【问题标题】:Accuracy score in K-nearest Neighbour Classifier not matching with GridSearchCVK-nearest Neighbor Classifier 中的准确度得分与 GridSearchCV 不匹配
【发布时间】:2021-08-30 18:47:25
【问题描述】:

我正在学习机器学习,但遇到了我无法解释的不匹配问题。

根据 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' 以确保返回的值实际上是准确的,并且它返回的值完全相同。

我在这里错过了什么?

【问题讨论】:

    标签: machine-learning scikit-learn gridsearchcv scoring


    【解决方案1】:

    您所描述的行为是相当正常的,是可以预料的。您应该知道GridSearchCV 有一个参数refit,默认设置为true。它会触发以下内容:

    使用在整个数据集上找到的最佳参数重新调整估计器。

    这意味着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
    

    如您所见,该模型在这些数据上的表现要差得多,这表明之前的指标都过于乐观了。该模型实际上并没有很好地概括。

    总之,您的结果并不令人惊讶,并且有一个简单的解释。分数的巨大差异令人印象深刻,但仍然遵循相同的逻辑,实际上只是过度拟合的明确指标。

    【讨论】:

      猜你喜欢
      • 2014-06-28
      • 2011-06-24
      • 2015-07-12
      • 2015-04-17
      • 2016-02-04
      • 2016-01-24
      • 2010-09-12
      • 1970-01-01
      • 2014-12-09
      相关资源
      最近更新 更多