问题描述
我正在学习机器学习,但遇到了无法解释的不匹配问题。
我有一个网格可以根据 gridsearchcv 返回的准确度计算最佳模型。
model=sklearn.neighbors.KNeighborsClassifier()
n_neighbors=[3,4,5,6,7,8,9]
weights=['uniform','distance']
algorithm=['auto','ball_tree','kd_tree','brute']
leaf_size=[20,30,40,50]
p=[1]
param_grid = dict(n_neighbors=n_neighbors,weights=weights,algorithm=algorithm,leaf_size=leaf_size,p=p)
grid = sklearn.model_selection.gridsearchcv(estimator=model,param_grid=param_grid,cv = 5,n_jobs=1)
SGDgrid = grid.fit(data1,targetd_simp['VALUES'])
print("SGD Classifier: ")
print("Best: ")
print(SGDgrid.best_score_)
value=SGDgrid.best_score_
print("params:")
print(SGDgrid.best_params_)
print("Best estimator:")
print(SGDgrid.best_estimator_)
y_pred_train=SGDgrid.best_estimator_.predict(data1)
print(sklearn.metrics.confusion_matrix(targetd_simp['VALUES'],y_pred_train))
print(sklearn.metrics.accuracy_score(targetd_simp['VALUES'],y_pred_train))
我得到的结果如下:
SGD Classifier:
Best:
0.38694539229180525
params:
{'algorithm': 'auto','leaf_size': 20,'n_neighbors': 8,'p': 1,'weights': 'distance'}
Best estimator:
KNeighborsClassifier(leaf_size=20,n_neighbors=8,p=1,weights='distance')
[[4962 0 0]
[ 0 4802 0]
[ 0 0 4853]]
1.0
可能这个模型高度过拟合。我仍然要检查它,但这不是问题的问题。
所以,基本上,如果我理解正确,gridsearchcv 正在为交叉验证中的一个块找到 0.3869(相当差)的最佳准确度分数,但最终的混淆矩阵是完美的,以及它的准确度最终矩阵。这对我来说没有多大意义......理论上如此糟糕的模型表现如何?
我还在 gridsearchcv 中添加了 scoring = 'accuracy'
以确保返回的值实际上是准确的,并且返回的值完全相同。
我在这里遗漏了什么?
解决方法
您所描述的行为很正常,在意料之中。您应该知道 GridSearchCV
有一个默认设置为 true 的参数 refit
。它触发以下内容:
使用在整个数据集上找到的最佳参数重新拟合估计器。
这意味着 best_estimator_
返回的估算器已针对您的整个数据集(在您的情况下为 data1
)进行了改装。因此,估计器在训练期间已经看到了数据,并且预期在其上表现得特别好。您可以使用以下示例轻松重现这一点:
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
X,y = make_classification(random_state=7)
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=42)
search = GridSearchCV(KNeighborsClassifier(),param_grid={'n_neighbors': [3,4,5]})
search.fit(X_train,y_train)
print(search.best_score_)
>>> 0.8533333333333333
print(accuracy_score(y_train,search.predict(X_train)))
>>> 0.9066666666666666
虽然这不像你的情况那么令人印象深刻,但它仍然是一个明确的结果。在交叉验证期间,模型针对未用于训练模型的一个折叠进行验证,因此针对模型之前未见过的数据进行验证。然而,在第二种情况下,模型在训练期间已经看到了所有数据,预计模型在这些数据上的表现会更好。
为了更好地感受真实的模型性能,您应该使用包含模型之前未见过的数据的保持集:
print(accuracy_score(y_test,search.predict(X_test)))
>>> 0.76
如您所见,该模型在这些数据上的表现要差得多,并向我们表明以前的指标都有些过于乐观了。该模型实际上并没有很好地概括。
总而言之,您的结果并不令人惊讶,并且有一个简单的解释。分数的高差异令人印象深刻,但仍然遵循相同的逻辑,实际上只是过度拟合的明确指标。