测试集不能参与任何训练逻辑,因为会引发数据泄露,导致评估虚高、泛化能力误判;预处理须仅在训练集fit,测试集仅transform,推荐使用Pipeline强制隔离。

用 train_test_split 划分数据时,为什么测试集不能参与任何训练逻辑?
因为只要测试集的标签、特征或统计信息(比如均值、标准差)被用于模型拟合、参数选择或特征工程,就会造成数据泄露——模型间接“看到”了测试数据,导致评估结果虚高,无法真实反映泛化能力。
实操建议:
- 所有预处理(如
StandardScaler.fit_transform())必须只在训练集上调用fit和transform;对测试集仅调用transform - 避免在划分前做全局归一化或缺失值填充(例如
df.fillna(df.mean())),这等价于用全量数据估计分布 - 使用
sklearn.pipeline.Pipeline能强制隔离训练/测试流程,推荐作为默认做法
用 learning_curve 看训练集大小对性能的影响,怎么看拐点?
learning_curve 返回训练得分和验证得分随训练样本数变化的曲线。拐点不是指曲线变平,而是指验证得分停止上升、甚至开始下降,同时训练得分持续高于验证得分且差距拉大——这是过拟合的典型信号。
关键细节:
立即学习“Python免费学习笔记(深入)”;
- 横轴是训练样本数量(非比例),所以需注意数据量是否足够支撑观察趋势
- 默认使用 5 折交叉验证,若数据少,可设
cv=3避免单折失效;但cv=2不推荐,方差太大 - 当训练得分 ≈ 1.0 且验证得分卡在 0.7 左右不再提升,大概率是模型复杂度过高或特征噪声大
示例片段:
from sklearn.model_selection import learning_curve
train_sizes, train_scores, val_scores = learning_curve(
estimator=clf,
X=X_train, y=y_train,
train_sizes=[0.2, 0.4, 0.6, 0.8, 1.0],
cv=5, scoring='accuracy'
)
用 validation_curve 扫描超参时,训练分和验证分的 gap 多大算危险?
没有绝对阈值,但当验证得分比训练得分低 **10% 以上**(例如训练 0.95 → 验证 0.82),且该 gap 随超参增大而快速扩大,基本可判定为过拟合。反过来,如果两者都低(如都卡在 0.6),则是欠拟合。
常见误判点:
- 只看最高验证分对应的超参,忽略 gap 趋势:选一个稍低但 gap 小的参数,往往泛化更稳
- 扫描范围不合理:比如对
RandomForestClassifier.max_depth从 1 扫到 100,前几层可能全是欠拟合,最后几层突然崩塌,中间的“甜点”容易被跳过 - 未重采样:分类任务中若类别不均衡,
scoring='f1_weighted'比默认'accuracy'更能暴露问题
为什么 cross_val_score 单看平均分不够,还要看标准差?
标准差大(比如 0.85 ± 0.12),说明模型在不同数据子集上表现波动剧烈,很可能受个别难样本或数据划分方式影响严重——这不是稳定过拟合或欠拟合,而是模型鲁棒性差,常出现在小数据集或高方差模型(如深度树、kNN 小 k)上。
对比场景:
- 欠拟合模型:cv 得分低 + 标准差小(如 0.62 ± 0.03),说明它始终学不好,但很“老实”
- 过拟合模型:cv 得分中等偏高 + 标准差大(如 0.78 ± 0.11),说明它在某些折上死记硬背成功了,换一组就崩
- 理想情况:得分高 + 标准差小(如 0.89 ± 0.02),这时再结合 learning curve 确认是否还有提升空间
真正容易被忽略的是:即使 cross_val_score 看着不错,如果验证集上 classification_report 显示某类召回率接近 0,那它只是在 majority class 上“假装优秀”。


















