如何在 python 中使用交叉验证执行 GridSearchCV

Posted

技术标签:

【中文标题】如何在 python 中使用交叉验证执行 GridSearchCV【英文标题】:How to perform GridSearchCV with cross validation in python 【发布时间】:2019-08-31 10:43:35 【问题描述】:

我正在使用GridSearchCV 执行RandomForest 的超参数调整,如下所示。

X = np.array(df[features]) #all features
y = np.array(df['gold_standard']) #labels

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

param_grid =  
    'n_estimators': [200, 500],
    'max_features': ['auto', 'sqrt', 'log2'],
    'max_depth' : [4,5,6,7,8],
    'criterion' :['gini', 'entropy']

CV_rfc = GridSearchCV(estimator=rfc, param_grid=param_grid, cv= 5)
CV_rfc.fit(x_train, y_train)
print(CV_rfc.best_params_)

我得到的结果如下。

'criterion': 'gini', 'max_depth': 6, 'max_features': 'auto', 'n_estimators': 200

之后,我将调整后的参数重新应用到x_test,如下所示。

rfc=RandomForestClassifier(random_state=42, criterion ='gini', max_depth= 6, max_features = 'auto', n_estimators = 200, class_weight = 'balanced')
rfc.fit(x_train, y_train)
pred=rfc.predict(x_test)
print(precision_recall_fscore_support(y_test,pred))
print(roc_auc_score(y_test,pred))

但是,我仍然不清楚如何将GridSearchCV10-fold cross validation 一起使用(即不只是将调整后的参数应用于x_test)。即如下所示。

kf = StratifiedKFold(n_splits=10)
for fold, (train_index, test_index) in enumerate(kf.split(X, y), 1):
    X_train = X[train_index]
    y_train = y[train_index]
    X_test = X[test_index]
    y_test = y[test_index]

既然GridSearchCV 使用了crossvalidation,我们可以使用所有Xy 并得到最好的结果作为最终结果吗?

如果需要,我很乐意提供更多详细信息。

【问题讨论】:

您在问如果您进行交叉验证,是否可以将您的测试集用作 GridSearch 的一部分?这样做最终会提供一个有偏差的分类性能,高估你的 trianed 分类器的泛化能力。 Imo,您目前拥有的代码提供了对泛化能力的最佳估计。所以我不会改变任何东西。 【参考方案1】:

既然GridSearchCV使用了crossvalidation,我们可以使用所有的X和y并得到最好的结果作为最终结果吗?

不,您不应该调整您的超参数(通过GridSearchCV 或单个gridSearch()),因为模型会选择最适合测试数据的超参数。这种方法失去了测试数据的真正目的。该模型性能不可泛化,因为它在超参数调优期间已经看到了这些数据。

查看this 文档以更好地了解超参数调整和交叉验证。

文档中的一些图片:

【讨论】:

使用roc_auc_score(y_test, rfc.predict_proba(x_test)) 哦,很抱歉没有给出完整的答案。试试rfc.predict_proba(x_test)[:,1] 我假设第二类是正类,你需要auc_roc_score rfc.classes_ 会给出模型中类的顺序 当我运行rfc.classes_ 时,我得到了array([0, 1], dtype=int64)。其实1 是我的少数派。所以,如果我选择rfc.predict_proba(x_test)[:,1],我假设我正在选择我的少数族裔班级(我感兴趣的班级)。如果我错了,请告诉我。期待您的来信:)【参考方案2】:

在这种情况下,您不应执行网格搜索。

在内部,GridSearchCV 将提供给它的数据集拆分为各种 trainingvalidation 子集,并使用提供给它的超参数网格找到 在验证子集上给出最高分数的单组超参数

训练-测试拆分的重点是,在此过程完成后,对迄今为止模型未知的测试数据执行一个最终评分,以查看是否您的超参数已经过拟合验证子集。如果效果不错,那么下一步就是将模型投入生产/部署。

如果您在交叉验证执行网格搜索,那么您将拥有多个组超参数,每个超参数都在其网格搜索验证子上做得最好- 交叉验证拆分的子集。您无法将这些集合组合成一个连贯的超参数规范,因此您无法部署您的模型。

【讨论】:

非常感谢您的出色回答。一个快速的问题。如果我们正在写一篇研究论文,应该报告什么结果。是CV_rfc.best_score_ 还是CV_rfc.predict(x_test) 的值?期待您的回音。非常感谢:) @Emi 我会说这取决于您的确切用例。请注意,predict 将返回 预测,而不是单个分数。 在分类的情况下,是的,我想。您还可以查看其他指标,例如 f-score 等。实际上,在 Data Science 或 Cross Validated SE 网站上问这个问题可能会更好。 @Emi 实际上,您应该使用predict_proba 而不是predict,因为ROC-AUC 分数需要概率。 @Emi 那是因为predict_proba 产生了一个形状为(len(x), n_classes) 的数组。您可以使用[:1] 对数组进行切片。

以上是关于如何在 python 中使用交叉验证执行 GridSearchCV的主要内容,如果未能解决你的问题,请参考以下文章

在 scikit learn 中结合网格搜索和交叉验证

如何在 R 中使用 LibSVM 执行 10 折交叉验证?

如何在#ag-grid for React 中执行单元格验证

在 sklearn 中运行 10 倍交叉验证后如何运行 SVC 分类器?

在 KFold 交叉验证的情况下如何显示平均分类报告和混淆矩阵

应用分层10折交叉验证时如何在python中获取所有混淆矩阵的聚合