我是正确使用 GridSearch 还是需要使用所有数据进行交叉验证?

数据挖掘 Python 交叉验证 训练 网格搜索
2022-02-18 10:46:11

我正在使用一个包含 400 个观察值、34 个特征和相当多的异常值的数据集,其中一些是极端值。鉴于我的数据的性质,这些需要在模型中。

我首先对我的数据进行 75-25 的拆分,然后将这 25% 放在一边。

在训练集上,我使用了 GridSearchCV 和 10 次折叠和 7 次重复的 RepeatedKFold,这返回了我的 best_estimator 结果,当我们进入 .cv_results_ 时,我们看到它是 mean_test_score 指标。然后我将其称为我的“交叉验证分数”。然后,使用这个模型拟合,我在测试集上运行它作为 grid.score(X_test, y_test) 并将其称为我的测试分数。


def rf(df, score):

    X_train, X_test, y_train, y_test = train_test(df)

    params = {'n_estimators': [400, 700, 1000],
              'max_features': ['sqrt', 'auto'],
              'min_samples_split': [2, 3],
              'min_samples_leaf': [1, 2, 3],
              'max_depth': [50, 100, None],
              'bootstrap': [True, False]
}

    scorers = {'RMSE': make_scorer(rmse, greater_is_better=False),
               'MAE': make_scorer(mean_absolute_error, greater_is_better=False),
               'R2': make_scorer(r2_score)}

    cv = RepeatedKFold(n_splits=10, n_repeats=7)


    grid = GridSearchCV(estimator=RandomForestRegressor(random_state=random.seed(42)),
                              param_grid=params, 
                              verbose=1, 
                              cv=cv, 
                              n_jobs =-1, 
                              scoring=scorers, 
                              refit = score)

    grid = grid.fit(X_train, y_train)    

    print('Parameters used:', grid.best_params_)

    if score  == 'RMSE':
        print('RMSE score on train:', round(-1*grid.best_score_,4))
        print('RMSE score on test: ', round(-1*grid.score(X_test, y_test),4))

    elif score == 'R2':
        print('R Squared score on train:', round(grid.best_score_,4))
        print('R Squared score on test: ', round(grid.score(X_test, y_test),4))

    elif score == 'MAE':
        print('MAE score on train:', round(-1*grid.best_score_,4))
        print('MAE score on test: ', round(-1*grid.score(X_test, y_test),4))

当我将指标设置为 RMSE(最重要的指标)时,它会输出以下内容:

火车上的
RMSE 分数:8.489 测试中的 RMSE 分数:5.7952

我做对了吗?我可以认为这种差异可以接受吗?以随机森林为例,如果我故意忽略网格搜索参数并将我的 min_leaf_node 设置为 10 左右,我的 RMSE 会一直上升到 12,但它在 CV 分数和我的测试数据之间变得非常相似。我在使用 SVR 和 MLP 算法时遇到了类似的结果。

这是我论文的一部分,现在我的主管告诉我应该使用我所有的数据进行交叉验证,我认为这是不正确的。

我的结论是,鉴于模型中的异常值,如果没有更多的观察,结果会出现差异,但是我不知道这个结论是否正确,或者我在这里做错了什么。

在异常值较少的有点相似的数据集中运行我的模型可以使结果彼此更接近。

火车上的
RMSE 分数:5.9731 测试中的 RMSE 分数:6.9164

1个回答

据我所知,您的程序是正确的。您正确地将数据拆分为训练/测试,然后仅使用训练数据来找到最佳超参数。使用在交叉验证中找到的所有训练数据和超参数,您将在测试集上评估您的最终模型。

事实上,异常值和数据集的大小是验证和测试之间存在巨大差异的最可能原因。基本上,如果在您对数据进行初始拆分后,这些异常值中的大多数都落在测试集中,那么您的测试集分数很可能会大于您的验证分数。另一方面,如果这些异常值在您的训练集中,您会期望相反的情况。这是因为,无论您的训练集中有哪些数据用于任何随机分区,无论您做什么,这些异常值观察都不太可能被很好地预测,并且由于您的数据集的大小非常小,这些异常值将严重影响您的误差估计(特别是对于由于平方而对异常值非常敏感的 RMSE)。

无论哪种方式,如果您想诚实,请仅将测试集分数报告为您的最终估计。

在我的测试集分数差异很大的情况下(通常是由于小数据集和大量异常值),我强烈建议按照您的描述重复整个模型构建过程,但每次使用不同的种子(即每次将整个数据集拆分为不同种子的训练/测试)。这样做直到你没有耐心或者你对模型性能的估计中的差异足够小。也许从这些重复中形成自举置信区间,以便为您提供有关模型性能变化程度的信息。