使用Stratified K折交叉验证中最优折训练最终模型是否合规?
问题解答:能否选取K折交叉验证中表现最优的折训练最终模型?
这种做法完全不合规,会导致模型严重过拟合,泛化能力大幅下降,具体原因和正确做法如下:
核心问题:数据泄露与交叉验证的本质
- 数据泄露:你用K折验证的结果来选择训练子集,相当于把验证集的信息间接传递给了最终模型。最优折的优秀表现可能只是该折数据的特殊性(比如样本分布刚好适配当前模型),而非模型的真实泛化能力。用这个子集训练的模型,在真实未知数据上的表现会远差于交叉验证的平均得分。
- 交叉验证的目的:K折交叉验证是用来评估超参数的泛化能力,帮你从网格搜索中选出最优超参数组合,而不是用来挑选“最好的训练数据片段”。当你确定了最优超参数后,应该用全部可用训练数据来训练最终模型,这样才能让模型学习到数据的完整分布。
你的代码的正确修改方式
不需要保存各折的训练/测试数据,直接用全部数据训练最终模型:
from sklearn.metrics import confusion_matrix, roc_auc_score, roc_curve, auc, precision_recall_curve from sklearn.model_selection import StratifiedKFold from sklearn.linear_model import LogisticRegression # 交叉验证评估超参数(这里你已经确定了C=0.009等参数) kf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) cv_score = [] i = 1 for train_index, test_index in kf.split(X, y): print(f'{i} of KFold {kf.n_splits}') X_train, X_test = X.loc[train_index], X.loc[test_index] y_train, y_test = y.loc[train_index], y.loc[test_index] lr = LogisticRegression(C=0.009, penalty='l2', solver='newton-cg').fit(X_train, y_train) score = roc_auc_score(y_test, lr.predict_proba(X_test)[:, 1]) precision, recall, thresholds = precision_recall_curve(y_test, lr.predict_proba(X_test)[:, 1]) auc_precision_recall = auc(recall, precision) print(f'ROC AUC score : {score}') print(f'auc_precision_recall : {auc_precision_recall}') cv_score.append(score) i += 1 # 用全部数据训练最终模型 final_lr = LogisticRegression(C=0.009, penalty='l2', solver='newton-cg').fit(X, y)
补充建议
如果想要提升模型的稳定性和泛化能力,可以考虑模型融合:保留K折训练的所有模型,对未知数据的预测结果取平均(概率值平均)。这种方式能利用多个模型的多样性,降低单模型的过拟合风险,效果通常优于单拎最优折训练的模型。
内容的提问来源于stack exchange,提问作者Romain LOMBARDI
相关产品推荐
相关产品推荐

