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

9

我正在尝试使用SciKit-Learn执行我的第一个KNN分类器。我一直在遵循用户指南和其他在线示例,但有几件事我不确定。在此帖子中,让我们使用以下内容:

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找到最佳参数,然后使用新的knn模型进行交叉验证?

  1. 我理解应该按照以下方式进行:

将数据分为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)

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

我希望这有意义。我一直在尝试寻找尽可能多的信息而不必发布,但是我已经到了认为获取一些直接答案会更容易的地步。

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

2个回答

7
  1. 你可以对整个数据集进行交叉验证,这是可行的,但我仍建议您至少将数据分成两组,一组用于交叉验证,另一组用于测试。

  2. .score函数根据文档应返回单个float值,即给定X,Y上最佳评分估计器(从拟合您的GridSearchCV中得到的最高评分估计器)的分数。

  3. 如果您看到最佳参数为14,则可以在模型中继续使用它,但是如果您提供了更多参数,则应设置所有参数。 (-我之所以这样说是因为您没有提供参数列表)如果需要,可以再次检查您的CV,以确保该模型是否达到预期效果。

希望这能让事情更清晰 :)


所以,当我在第2点使用clf.score(X,Y)时,它实现了我想要的 - 使用所有数据的交叉验证分类器。如果我继续使用cross_val_score(knn2, X, Y, cv=5)和最佳参数(是的,只有一个),那么这将像您在第3点中指出的那样再次检查CV。 - browser
我的意思是,我的第二点和第三点都是合法的方法? - browser

7
如果数据集很小,您可能没有足够的资源进行训练/测试拆分。人们经常仅基于交叉验证来估计模型的预测能力。在上面的代码中,当您将训练集分成内部训练集(80%)和验证集(20%)时,GridSearchCV执行5折交叉验证来训练模型(clf.fit(X, y))。
您可以通过 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 中包含它。希望这对你有帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接