Mat*_*zar 6 python r scikit-learn r-caret gridsearchcv
考虑 3 个数据集训练/验证/测试。sklearnGridSearchCV()默认情况下选择具有最高交叉验证分数的最佳模型。在预测需要准确的现实环境中,这是选择最佳模型的可怕方法。原因是它应该如何使用:
模型的训练集以学习数据集
Val 设置用于验证模型在训练集中学到的内容并更新参数/超参数以最大化验证分数。
测试集 - 在未见过的数据上测试您的数据。
最后,在实时环境中使用模型并记录结果,看看结果是否足以做出决策。令人惊讶的是,许多数据科学家仅仅选择验证分数最高的模型,就冲动地在生产中使用他们训练过的模型。我发现gridsearch选择的模型严重过度拟合,并且在预测看不见的数据方面比默认参数做得更差。
我的做法:
手动训练模型并查看每个模型的结果(以某种循环方式,但效率不高)。这是非常手动且耗时的,但我得到的结果比gridsearch好得多。我希望这是完全自动化的。
为我想要选择的每个超参数绘制验证曲线,然后选择显示训练集和验证集之间差异最小的超参数,同时最大化两者(即训练= 98%,验证= 78%确实很糟糕,但训练= 72% ,val=70% 是可以接受的)。
正如我所说,我想要一种更好的(自动化)方法来选择最佳模型。
我正在寻找什么样的答案:
我想最大化训练集和验证集中的分数,同时最小化训练集和验证集之间的分数差异。考虑以下网格搜索算法的示例:有两种模型:
Model A: train score = 99%, val score = 89%
Model B: train score = 80%, val score = 79%
Run Code Online (Sandbox Code Playgroud)
B 型是一个更可靠的模型,我随时都会选择 B 型而不是 A 型。它不太适合,并且预测是一致的。我们知道会发生什么。然而,gridsearch将选择模型 A,因为 val 分数更高。我发现这是一个常见问题,并且在互联网上没有找到任何解决方案。人们往往过于关注在学校学到的东西,而没有真正考虑选择过度拟合模型的后果。我看到了关于如何使用sklearn和caret包中的gridsearch并让他们为您选择模型的冗余帖子,但没有看到如何实际选择最佳模型。
到目前为止,我的方法非常手动。我想要一种自动化的方式来做到这一点。
我目前所做的是这样的:
gs = GridSearchCV(model, params, cv=3).fit(X_train, y_train) # X_train and y_train consists of validation sets too if you do it this way, since GridSearchCV already creates a cv set.
final_model = gs.best_estimator_
train_predictions = final_model.predict(X_train)
val_predictions = final_model.predict(X_val)
test_predictions = final_model.predict(X_test)
print('Train Score:', accuracy_score(train_predictions, y_train)) # .99
print('Val Score:', accuracy_score(val_predictions, y_val)) # .89
print('Test Score:', accuracy_score(test_predictions, y_test)) # .8
Run Code Online (Sandbox Code Playgroud)
如果我看到类似上面的内容,我会排除该模型并尝试不同的超参数,直到获得一致的结果。通过手动拟合不同的模型并查看所有 3 个结果、验证曲线等......我可以决定最好的模型是什么。我不想手动执行此操作。我希望这个过程能够自动化。网格搜索算法每次都会返回过拟合模型。我期待听到一些答案。
另一个大问题是验证集和测试集之间的差异。由于许多问题都面临时间依赖性问题,我想知道一种可靠的方法来随着时间的推移测试模型的性能。按时间分割数据集至关重要;否则,我们就会出现数据泄露。我熟悉的一种方法是判别分析(拟合模型以查看模型是否可以预测示例来自哪个数据集:训练验证测试)。另一种方法是 KS / KL 测试并查看目标变量的分布,或循环遍历每个特征并比较分布。
我同意这样的评论:使用测试集来选择超参数可以消除对验证集(/folds)的需要,并使测试集分数不再代表未来的性能。您可以通过“在实时反馈上测试模型”来解决这个问题,所以这很好。
我什至会给出我取出测试集的场景 - 这是同样的问题。网格搜索算法选择验证得分最高的模型。它不考虑训练分数和验证分数之间的差异。差异应该接近 0。99% 的训练分数和 88% 的 val 分数不是一个好的模型,但网格搜索将采用 88% 的训练分数和 87% 的 val 分数。我会选择第二个模型。
现在,这是更容易理解的事情:除了原始性能之外,还有其他原因希望训练/测试分数差距较小。请参阅https://datascience.stackexchange.com/q/66350/55122。实际上sklearn,自 v0.20 以来确实适应了这一点:通过使用return_train_score=Trueandrefit作为消耗cv_results_并返回最佳索引的可调用函数:
refit :bool、str 或可调用,默认=True
...
如果在选择最佳估计器时除了最大分数之外还有其他考虑因素,则可以将 refit 设置为一个函数,该函数在给定 cv_results_ 的情况下返回所选的 best_index_。在这种情况下,将根据返回的 best_index_ 设置 best_estimator_ 和 best_params_,而 best_score_ 属性将不可用。
...
https://scikit-learn.org/stable/modules/ generated/sklearn.model_selection.GridSearchCV.html
当然,这要求您可以将查看分数及其差异的手动过程放入一个函数中,并且可能不承认像验证曲线这样的东西,但至少它是一些东西。