Почему такая большая разница в точности при применении критерия Джини и энтропии?
Всем привет. Продолжаю потихоньку изучать ML и добрался до известного дата-сета 'Wine'. И упёрся в следующий момент: если я использую энтропию в качестве критерия вместо критерия Джини, то точность падает на 4-10%. На примере кода
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn import tree
from sklearn import metrics
from sklearn.metrics import classification_report,confusion_matrix
dataset = load_wine()
X_train, X_test, y_train, y_test = train_test_split(dataset.data, dataset.target, test_size=0.322, random_state = 42)
dt_wine = tree.DecisionTreeClassifier()
dt_wine = dt_wine.fit(X_train,y_train)
y_pred = dt_wine.predict(X_test)
test_accuracy= metrics.accuracy_score(y_test, y_pred)
print("Accuracy: ", '%.2f'% (test_accuracy*100),"%")
Accuracy: 94.83 % но если запускаю
dt_wine = tree.DecisionTreeClassifier(criterion='entropy')
то Accuracy 84.48
Я пробовал играть с данными, но всё равно энтропия показывает результаты хуже чем Джинни. Это энтропия не подходит к данному дата сету или она действительно хуже чем критерий Джинни в большинстве вариантов? Или это я что-то неправильно сделал (например точность посчитал)? Теорию читал и не нашёл никаких предпосылок для столь больших отличий.
Ответы (1 шт):
Если вы хотите воспроизводимые результаты обучения модели, то всегда используйте параметр random_state, иначе вы можете получить разные результаты на абсолютно тех же датасетах.
Пример - два раза запускаем один и тот же код (одни и те же датасеты):
In [29]: %paste
dt_wine = tree.DecisionTreeClassifier()
dt_wine = dt_wine.fit(X_train,y_train)
y_pred = dt_wine.predict(X_test)
test_accuracy= metrics.accuracy_score(y_test, y_pred)
print("Accuracy: ", '%.2f'% (test_accuracy*100),"%")
## -- End pasted text --
Accuracy: 96.55 %
In [30]: %paste
dt_wine = tree.DecisionTreeClassifier()
dt_wine = dt_wine.fit(X_train,y_train)
y_pred = dt_wine.predict(X_test)
test_accuracy= metrics.accuracy_score(y_test, y_pred)
print("Accuracy: ", '%.2f'% (test_accuracy*100),"%")
## -- End pasted text --
Accuracy: 94.83 %
Точность предсказаний уменьшилась во втором случае. Для того, чтобы этого избежать надо использовать параметр random_state:
По поводу выбора критерия - если бы один критерий был бы всегда лучше другого, то наверное не имело бы смысла оставлять тот критерий, который всегда дает худший результат. ;)
Критерий является одним их гиперпараметров модели, который можно и нужно настраивать (GridSearchCV, RandomizedSearchCV, hyperopt, etc.)
Если вы используете алгоритмы, основанные на деревьях решений, то я бы советовал использовать Decision Tree Ensembles алгоритмы - они гораздо устойчивее к переобучению и почти всегда дают лучшие результаты, по сравнению с использованием единичных деревьев.
Пример для ваших данных:
In [52]: from sklearn.ensemble import RandomForestClassifier
In [53]: rf = RandomForestClassifier(random_state=123)
In [54]: rf.fit(X_train, y_train)
Out[54]:
RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
criterion='gini', max_depth=None, max_features='auto',
max_leaf_nodes=None, max_samples=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=100,
n_jobs=None, oob_score=False, random_state=123,
verbose=0, warm_start=False)
In [55]: y_pred2 = rf.predict(X_test)
In [56]: metrics.accuracy_score(y_test, y_pred2)
Out[56]: 1.0