交叉验证不是万能的模型性能“保险”,但它能帮你避开训练集过拟合带来的假安全感——关键在于选对策略、配对评估指标、并警惕数据泄露。

交叉验证不是万能的模型性能“保险”,但它能帮你避开训练集过拟合带来的假安全感——关键在于选对策略、配对评估指标、并警惕数据泄露。
用 cross_val_score 快速跑 baseline,但别只看平均值
它适合快速验证模型在不同折上的稳定性,但默认返回的是单指标数组,容易忽略方差。比如用 RandomForestClassifier 在 iris 上做 5 折 CV:
from sklearn.model_selection import cross_val_score from sklearn.ensemble import RandomForestClassifier from sklearn.datasets import load_iris <p>X, y = load_iris(return_X_y=True) scores = cross_val_score(RandomForestClassifier(), X, y, cv=5, scoring='accuracy')</p>
得到 [0.9667 1. 0.9333 0.9333 1. ],平均 0.9667 看似很好——但标准差 0.027 提示波动存在。实际项目中建议同时检查:
-
scoring参数必须显式指定,比如'f1'或'roc_auc',否则分类任务默认用'accuracy',回归任务用'r2',容易误判 - 如果数据有类别不平衡,
'accuracy'会失真,换成'f1_weighted'或'average_precision' - 传入的
cv可以是整数(如5),也可以是StratifiedKFold(n_splits=5, shuffle=True, random_state=42),后者能保证每折的类别比例一致
手动控制 cross_val_predict 获取预测结果,用于后续分析
当你需要每个样本的预测概率、混淆矩阵或特征重要性归因时,cross_val_predict 比 cross_val_score 更有用——它返回与原始 X 长度一致的预测向量,但注意:它不等于“把模型 fit 一次再 predict”,而是每折独立训练+预测,避免数据重复使用。
常见陷阱:
- 不能直接拿
cross_val_predict的输出去算feature_importances_,因为每次 fold 训练的树结构不同,importance 不可叠加 - 若用
scoring='neg_log_loss',cross_val_score返回负值,需加负号还原;而cross_val_predict不受此影响 - 对时间序列数据,必须用
TimeSeriesSplit,否则未来信息会泄露到训练折中
自定义 CV splitter 时,get_n_splits 和 split 方法缺一不可
比如你想按用户 ID 分组做留一用户验证(Leave-One-Group-Out),就得确保分组变量不参与模型训练,且每折训练集和测试集完全隔离:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
from sklearn.model_selection import GroupKFold
groups = [...] # 每个样本对应的 group id
gkf = GroupKFold(n_splits=3)
for train_idx, test_idx in gkf.split(X, y, groups):
X_train, X_test = X[train_idx], X[test_idx]
y_train, y_test = y[train_idx], y[test_idx]
关键点:
-
groups必须和X、y长度一致,类型可以是 int 或 str,但不能是嵌套结构 -
GroupKFold不打乱顺序,所以shuffle参数无效;如需随机分组,得自己重排groups向量 - 如果某 group 样本数少于折数(如 2 个用户做 3 折 CV),
split会抛出ValueError: Cannot have number of splits n_splits=3 greater than the number of members in groups
多标签或多输出场景下,cross_val_score 默认不支持,得改用 cross_val_predict + 手动评分
sklearn 的 cross_val_score 内部调用 estimator.score(),而多数多输出模型(如 MultiOutputRegressor)没实现该方法,会报错 AttributeError: 'MultiOutputRegressor' object has no attribute 'score'。
解决办法是绕过 scoring,用 cross_val_predict 得到预测后,用 sklearn.metrics 中的函数逐指标计算:
- 对每个输出列单独调用
mean_squared_error(y_true[:, i], y_pred[:, i]) - 若用
MultiOutputClassifier,可用accuracy_score或hamming_loss,但注意hamming_loss越小越好,而accuracy_score是越接近 1 越好 - 不要把多输出 flatten 成一维再评分,会破坏输出维度语义
真正难的不是调用哪个函数,而是想清楚:你验证的到底是模型结构、超参选择,还是数据划分方式本身?CV 结果波动大时,优先检查标签分布、特征缩放一致性、以及是否意外把测试信息编码进了特征工程步骤里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










