这种网格搜索方法正确吗?

数据挖掘 机器学习 scikit-学习 网格搜索
2022-03-10 05:34:42

我有一些数据说 100 万行,然后我将 200,000 放在一边(用于验证)并将剩余的 800,000 称为训练集(X),如下所示,所以它不是整个数据,剩余的 200k 是验证集. 我的问题是,下面的网格搜索可以吗?我的 roc 曲线非常高,比如 0.96。我怀疑是因为下面的内容,我是否应该在 x_train 和 y_train 上使用网格搜索,然后再进一步拆分 x_train 和 y_train 以在 pipeline.fit() 上使用?

X=pd.read_csv('data_subset.csv')

X=X.dropna()
Y=X['status'].values
X=X.drop(columns=['status'])

x_train, x_test, y_train, y_test = train_test_split(
    X, Y, stratify=Y, random_state=42, test_size=0.2)


model = lgb.LGBMClassifier(silent=True, subsample=0.8,colsample_bytree=0.2,objective='binary')


parameters={
    'learning_rate_grid_lgbm': [0.015, 0.001, 0.1],    
}

然后我对此数据运行网格搜索:

clf = GridSearchCV(model, parameters, cv=3, scoring='roc_auc') 
clf.fit(X, y) ### i.e. instead clf.fit(x_train,y_train)

model = clf.best_estimator_

pipeline = make_pipeline(model)

pipeline.fit(x_train, y_train) 
predictions = pipeline.predict_proba(x_test)[:, 1]
roc_auc_score(y_test, predictions)

我的困惑是,如果我必须在 gridsearch 上使用 x_train,我应该如何继续执行之后的步骤?

2个回答

您的超参数是根据整组示例选择的,因此测试集的信息会泄漏到模型中。因此,验证将过于乐观(正如您所怀疑的那样)。

可以修复的是:

clf.fit(X, y)

只需使用

clf.fit(x_train, y_train)

正如你已经建议自己的那样。在该行之后,无需更改任何内容。您正在将模型拟合到训练数据上,然后在(尚未见过的)测试数据上测试性能。

编辑:实际上,阅读 GridSearchCV 的文档甚至更糟(取决于您的 pipeline.fit 方法在后台如何工作):不仅是在整个集合上选择模型超参数,通过使用model = clf.best_estimator_,您的模型现在也是使用训练+测试集进行训练,这当然是一件坏事,并且会导致测试数据上的 roc 分数远高于实际看不见的数据。

如果您对 X 数据(包含 800k 样本)执行网格搜索交叉验证,则无需在拟合模型之前再进行一次 train_test_split,因为网格搜索 CV 策略已经进行了多次拆分(与 'cv' 参数一样多值,在此处查看),然后您使用模型从未见过的数据(即您提前放置的 200k 样本)进行验证。见下图,你的 800k 样本是你的绿色训练数据拆分成折叠,剩下的 200k 样本是你的蓝色测试数据

来源:https ://scikit-learn.org/stable/modules/cross_validation.html 在此处输入图像描述

实际上,在您的代码中,您正在进行拆分,但是稍后您将模型拟合到整个 (X, y) 集上,这对您的 train_test 拆分没有意义,还使用 ​​y_test 计算最终的 roc_auc_score 实际上是您用于训练的数据的一部分(即 (X, y) 数据集的一部分)。

基本上,您的示例的步骤可能是:

  1. 拆分您的数据集以留下 200k 进行最终验证,就像您所做的那样
  2. 对其余数据(800k 个样本)应用网格搜索交叉验证,无需再次拆分
  3. 使用 clf.best_estimator_ 对您的验证功能集进行预测,以计算最终的 ROC AUC

虽然不是绝对必要的,但您也可以检查值 clf.cv_results_['mean_test_roc_auc'] 和 clf.cv_results_['std_test_roc_auc'],其中有几个数组,对于每个可能的超参数组合(即尝试过的模型),你有平均值+std roc_auc 值以考虑模型的稳健性。