项目篇(四)交叉验证

张开发
2026/4/10 20:31:55 15 分钟阅读

分享文章

项目篇(四)交叉验证
前面提到两种优化机器学习模型的方法一种是做各种特征工程让特征集更适合模型另一种是防止过拟合让模型不用“那么”精确。这两种方式的优化角度不同特征工程是从数据预处理的角度给出更高质量的数据而防止过拟合则是在模型训练的过程中控制模型的复杂度。其实除此之外我们还可以从模型的验证和评估环节入手来优化模型性能。一、交叉验证小数据集的资源复用在样本充足的情况下我们会随机将数据分为 3 个部分训练集、验证集和测试集。其中训练集用来训练模型验证集用来模型调优测试集用来评估模型性能。有标签的数据是非常难以获得的。本来就很有限的数据集还要被拆成训练集、测试集和验证集真是让人特别舍不得。而且我们知道数据集越大就越不容易出现过拟合的现象。那么我们如何利用较小的数据集从而达到较大数据集的效果呢这就需要交叉验证。交叉验证的基本思想是这样的将训练数据集分为 k 等份其中 k-1 份用作训练集单独的那一份用作验证集整个过程重复 k 次这也通常称作 k 折。这样就最大程度重复地使用了训练集中的数据每一个数据都既做了训练又做了测试从而在最大程度上提高模型性能的可信度。交叉验证虽然一直在用不同的数据拆分进行模型的拟合但它实际上并不是在试图训练出新的模型它只是我们对模型的一种评估方式而已。这种交叉验证具体实现起来有 4 个步骤1、随机清洗数据集将数据集分为训练集和测试集将测试集预留出来放在一边。2、将训练数据集分成 k 组这个 k 值一般是随机设定比如 3510实操中以 10 折居多。在这一步中我们挑其中 1 组作为验证集剩下的 k-1 组做训练集这个过程要重复 k 次。我们在这些训练集上拟合模型可以得到 k 个不同的模型。然后再在对应的验证集上对这些模型进行评估就能得到一系列模型的评估分数。最后我们把这些评估分数进行平均这个平均分数就是交叉验证的最终结果了。3、按照步骤 1、2对多个算法进行交叉验证比如可以针对线性回归、决策树、随机森林等算法。根据每个算法交叉验证的评估结果从中挑选效果最好的算法模型。4、使用测试集评估最终模型的分数。实现方法每个数据样本都有 1 次机会进入验证集中并用于训练模型 k-1 次。这样一来我们就拥有了更多的数据量。整个过程如下所示1KFold在交叉验证中训练集和验证集的拆分可以通过 sklearn.model_selection 中的 KFold 函数实现。在这个函数中有三个主要参数需要我们了解一下from sklearn.model_selection import KFold #导入K折工具 from sklearn.metrics import r2_score #导入R2分数评估工具 kf5 KFold(n_splits5, shuffleFalse) #5折验证 i 1 for train_index, test_index in kf5.split(df_LTV): X_train df_LTV.iloc[train_index].drop([年度LTV],axis1) #训练集X X_test df_LTV.iloc[test_index].drop([年度LTV],axis1) #验证集X y_train df_LTV.iloc[train_index][年度LTV] #训练集y y_test df_LTV.loc[test_index][年度LTV] #验证集y model_lr.fit(X_train, y_train) #训练模型 print(f第{i}折验证集R2分数{r2_score(y_test, model_lr.predict(X_test))}) i 1第1折验证集R2分数0.5143622747243847第2折验证集R2分数-0.16778272779470416第3折验证集R2分数0.23879516275929713第4折验证集R2分数0.2482389409435588第5折验证集R2分数0.030882999240072652cross_val_scoresklearn 还提供了更简单的方式我们不用进行上面的 KFold 拆分过程只用一个 cross_val_score 函数就能直接完成模型的 K 折拆分、训练和验证一次性得到交叉验证结果。from sklearn.model_selection import cross_val_score # 导入交叉验证工具 # from sklearn.metrics import mean_squared_error #平均绝对误差 model_lr LinearRegression() #线性回归模型 scores cross_val_score(model_lr, #线性回归 X_train, #特征集 y_train, #标签集 cv5, # 五折验证 scoring neg_mean_absolute_error) #平均绝对误差 for i, score in enumerate(scores): print(f第{i1}折验证集平均绝对误差 {-score})第1折验证集平均绝对误差3191.99882739第2折验证集平均绝对误差1402.45679102第3折验证集平均绝对误差1168.49187113第4折验证集平均绝对误差1546.15537555第5折验证集平均绝对误差1138.41271054二、网格搜索直到找到最优的参数一个复杂的机器学习模型有可能有一大堆超参数模型的性能很大程度上取决于超参数的值。什么超参数是最好的那可不一定因为针对不同的问题而言最佳的参数一直在变化而且基本上没有太多规律可循。scikit-learn 中有一个 GridSearchCV 工具中文叫做网格搜索堪称是辅助我们自动调参的神器它可以帮我们自动调参轻松找到模型的最优参数。第一步明确你选择的模型有哪些可调的参数这个你可以通过查看算法的说明文档来确定第二步把模型中各超参数不同取值的排列组合尽可能多地列出来第三步调用 GridSearchCV 工具把可能的排列组合都传进去。完成这三步后GridSearchCV 会在后台创建出一大堆的并行进程挨个执行各种超参数的组合同时还会使用交叉验证的方法名称中的 CV意思就是 cross validation来评估每个超参数组合的模型。最后GridSearchCV 会帮你选定哪个组合是给定模型的最佳超参数值。举例LTV 预测项目看看怎么用 GridSearchCV 选出随机森林模型比较好的参数组合在调用 GridSearchCV 调参之前我们首先找出随机森林回归模型中有哪些参数最好的方法还是去sklearn 官网查看我们知道随机森林是由多棵决策树集合而成的算法所以这些参数都和各决策树的生成和剪枝过程相关。上面这些参数我们并不一定要完全理解它们的作用因为我们的重点不是去详细了解每一个超参数而是让 GridSearchCV 自动找到对于我们当前任务合适的超参数组合。找出随机森林模型的参数后接下来我们需要在程序中定义一个字典对象列出各个超参数以及我们希望去尝试的值组合你可以参考下面的代码。在这段代码中我定义了 rfr_param_grid 字典对象并在字典中指定了一系列参数值的组合举例来说对于 n_estimators 这个参数我就选择了 100 和 300当然你也可以尝试任意其它的值。model_rfr RandomForestClassifier() # 随机森林模型 # 对随机森林算法进行参数优化 rf_param_grid {max_depth: [None], max_features: [3, 5, 12], min_samples_split: [2, 5, 10], min_samples_leaf: [3, 5, 10], bootstrap: [False], n_estimators :[100,300], criterion: [gini]}然后在要调用 GridSearchCV 来进行超参数搜索之前我们先看看 GridSearchCV 这个函数本身有什么需要设定的参数。下面我们来调用 GridSearchCV 这个函数from sklearn.model_selection import GridSearchCV # 导入网格搜索工具 model_rfr_gs GridSearchCV(model_rfr, param_grid rfr_param_grid, cv3, scoringr2, n_jobs 10, verbose 1) model_rfr_gs.fit(X_train, y_train) # 用优化后的参数拟合训练数据集在上述代码中我将 GridSearchCV 返回的最佳参数组合存储在了 rfr_gs 这个新的随机森林模型。然后系统就会自动计算每种超参数组合拟合出的模型的准确率 / 损失Fitting 3 folds for each of 432 candidates, totalling 1296 fits[Parallel(n_jobs10)]: Using backend LokyBackend with 10 concurrent workers.[Parallel(n_jobs10)]: Done 30 tasks | elapsed: 22.0s[Parallel(n_jobs10)]: Done 180 tasks | elapsed: 2.0min[Parallel(n_jobs10)]: Done 430 tasks | elapsed: 4.8min[Parallel(n_jobs10)]: Done 780 tasks | elapsed: 8.7min[Parallel(n_jobs10)]: Done 1230 tasks | elapsed: 12.6min[Parallel(n_jobs10)]: Done 1296 out of 1296 | elapsed: 13.2min finished经过 GridSearchCV 自动地换参、拟合并自动交叉验证评估后最佳参数组合实际上已经被选出了它就被存储在 model_rfr_gs 这个新的随机森林中我们可以直接用它来做预测。这里我们调用 model_rfr_gs 的 best_params_ 属性来看一下这个最优模型是由哪些超参数组合而成的print( 最佳参数组合:, model_rfr_gs.best_params_)最佳参数组合: {bootstrap: True, max_depth: 10, max_features: sqrt, min_samples_leaf: 2, min_samples_split: 2, n_estimators: 50}然后我们看看 GridSearchCV 模型的准确性。from sklearn.metrics import r2_score, median_absolute_error #导入Sklearn评估模块 print(训练集上的R平方分数-调参后的随机森林: %0.4f % r2_score(y_train, model_rfr_gs.predict(X_train))) print(测试集上的R平方分数-调参后的随机森林: %0.4f % r2_score(y_valid, model_rfr_gs.predict(X_valid)))输出训练集上的R平方分数-随机森林: 0.7729测试集上的R平方分数-随机森林: 0.6523

更多文章