Scikit-learn 中 KNN 分类器中的网格搜索参数和交叉验证数据集

Grid Search parameter and cross-validated data set in KNN classifier in Scikit-learn

我正在尝试使用 SciKit-Learn 执行我的第一个 KNN 分类器。我一直在关注用户指南和其他在线示例,但有几件事我不确定。为此 post 让我们使用以下

X = 数据 Y = 目标

1) 在我读过的大多数机器学习介绍页面中,似乎都说你想要一个训练集、一个验证集和一个测试集。据我了解,交叉验证允许您结合训练集和验证集来训练模型,然后您应该在测试集上对其进行测试以获得分数。然而,我在论文中看到,在很多情况下,你可以只对整个数据集进行交叉验证,然后将 CV 分数报告为准确性。我知道在理想情况下你会想要测试单独的数据,但如果这是合法的,我想交叉验证我的整个数据集并报告这些分数

2) 所以开始这个过程

我定义我的 KNN 分类器如下

knn = KNeighborsClassifier(algorithm = 'brute')

我搜索最好的 n_neighbors 使用

clf = GridSearchCV(knn, parameters, cv=5)

现在如果我说

clf.fit(X,Y)

我可以使用

检查最佳参数
clf.best_params_

然后我可以得到一个分数

clf.score(X,Y)

但是 - 据我了解,这还没有交叉验证模型,因为它只给出 1 个分数?

如果我看到了 clf.best_params_ = 14 我可以继续

knn2 = KNeighborsClassifier(n_neighbors = 14, algorithm='brute')
cross_val_score(knn2, X, Y, cv=5)

现在我知道数据已经过交叉验证,但我不知道使用 clf.fit 找到最佳参数然后使用 cross_val_score 与新的 knn 模型是否合法?

3) 我知道 'proper' 方法如下

拆分为 X_train、X_test、Y_train、Y_test、 缩放训练集 -> 将变换应用于测试集

knn = KNeighborsClassifier(algorithm = 'brute')
clf = GridSearchCV(knn, parameters, cv=5)
clf.fit(X_train,Y_train)
clf.best_params_

然后我可以得到一个分数

clf.score(X_test,Y_test)

在这种情况下,是否使用最佳参数计算得分?


我希望这是有道理的。我一直试图在没有 posting 的情况下尽可能多地找到,但我已经到了我认为获得一些直接答案会更容易的地步。

在我的脑海中,我试图使用整个数据集获得一些交叉验证的分数,但也使用网格搜索(或类似的东西)来微调参数。

提前致谢

  1. 是的,您可以对整个数据集进行 CV,这是可行的,但我仍然建议您至少将数据分成 2 组,一组用于 CV,一组用于测试。

  2. .score 函数应该 return 根据 documentation 的单个 float 值,这是 [=12] 的分数=](这是你在给定的 X,Y

  3. 上拟合你的 GridSearchCV 得到的得分最高的估计量
  4. 如果您发现最好的参数是 14,您可以继续在您的模型中使用它,但如果您给它更多的参数,您应该设置所有参数。 (- 我这么说是因为你没有给出你的参数列表)是的,再次检查你的简历是合法的,以防万一这个模型是否和它应该的一样好。

希望这能让事情变得更清楚:)

如果数据集很小,您可能没有 train/test 拆分的奢侈。人们通常仅根据交叉验证来估计模型的预测能力。在上面的代码中,GridSearchCV 在拟合模型 (clf.fit(X, y)) 时执行 5 折交叉验证,方法是将训练集拆分为内部训练集 (80%) 和验证集 (20%)。

您可以通过 clf.cv_results_ 访问包括验证分数在内的模型性能指标。您要查看的指标包括 mean_test_score(在您的情况下,每个 n_neighbor 应该有 1 个分数)。您可能还想打开 'mean_train_score' 以了解模型是否过度拟合。请参阅下面的示例代码以了解模型设置(注意 knn 是一种非参数 ML 模型,它对特征的规模很敏感,因此人们经常使用 StandardScaler 对特征进行归一化):

    pipe = Pipeline([
        ('sc', StandardScaler()),     
        ('knn', KNeighborsClassifier(algorithm='brute')) 
    ])
    params = {
        'knn__n_neighbors': [3, 5, 7, 9, 11] # usually odd numbers
    }
    clf = GridSearchCV(estimator=pipe,           
                      param_grid=params, 
                      cv=5,
                      return_train_score=True) # Turn on cv train scores
    clf.fit(X, y)

快速提示:样本数的平方根通常是 n_neighbor 的不错选择,因此请确保将其包含在 GridSearchCV 中。希望这对您有所帮助。