Chapter 05
训练集、验证集、测试集的哲学;交叉验证与数据泄露防范
在机器学习中,模型的最终目标是泛化(Generalization):对从未见过的数据做出准确预测。如果我们用全部数据训练,再用同样的数据评估,就如同考试时把题目提前泄露给学生——分数会虚高,但真实能力被掩盖。因此,数据划分是机器学习流程中最基础、也最关键的一步。
| 数据集 | 占比(参考) | 用途 | 使用次数 |
|---|---|---|---|
| 训练集 (Training Set) | 60%-80% | 训练模型参数 | 反复使用 |
| 验证集 (Validation Set) | 10%-20% | 调参、选模型、早停 | 多次评估 |
| 测试集 (Test Set) | 10%-20% | 最终无偏估计 | 仅一次 |
测试集就像高考卷——你只能做一次。一旦你用测试集的结果来反向调整模型(如调参),测试集就"被污染"了,失去了衡量真实泛化能力的意义。
最简单的划分方式是随机划分(Random Split),通过随机抽样将数据分为训练集和测试集。scikit-learn 的 train_test_split 默认采用这种方式。然而,当目标变量的类别分布不均匀时,随机划分可能导致某一类别在训练集或测试集中比例失衡。
分层抽样(Stratified Sampling)则保证划分后每个子集中各类别的比例与原始数据集一致。例如,原始数据中"违约"客户占5%,分层抽样后训练集和测试集中违约比例仍约为5%。这在医学诊断、金融风控等不平衡场景中至关重要。
单次随机划分可能因"运气"导致评估结果波动。K折交叉验证(K-Fold Cross-Validation)将数据集分为K个子集(Fold),轮流用K-1个子集训练、剩余1个子集验证,最终取K次评估的平均值。
常见变体包括:
数据泄露指训练阶段"偷看"了测试阶段才能知道的信息,导致评估结果虚高。常见形式:
正确做法:所有预处理(缩放、特征选择、降维)必须只在训练集上拟合,然后变换应用到测试集。
设数据集 D 有 N 个样本,设定折数 K(通常取 5 或 10):
K 越大,每轮训练集越接近全量数据,偏差越小,但方差增大且计算量增加;K=5 和 K=10 是实践中常用的平衡点。
设类别 c 在全集中的比例为 p_c = n_c / N。分层抽样要求每折中类别 c 的比例近似 p_c。当 K 能整除各类别样本数时,可以实现严格分层;否则采用近似分配。
对于二分类问题,StratifiedKFold 在 scikit-learn 中的实现逻辑是:先将每个类别的样本排序并分块,再从每类中循环抽取样本到各折,确保每折的类别比例与总体一致。
单次划分的验证误差方差较大;K-Fold 通过平均降低了方差,但代价是 K 倍的计算量。留一法偏差最低,但方差可能较高(因为各训练集高度重叠),且计算成本极高。理解这一点有助于在不同数据规模和场景下选择合适的验证策略。
对于时间序列数据,标准的随机 K-Fold 会引入未来信息泄露——用未来的模式预测过去。TimeSeriesSplit 保证第 i 轮的训练集只包含验证集时间点之前的数据,模拟真实的"用过去预测未来"场景。
股票价格、信用违约预测具有强时间依赖性。使用标准随机划分会严重高估模型表现(因为模型"偷看"了未来价格走势)。正确的做法是按时间顺序划分训练/验证/测试窗口,如用 2019-2021 训练、2022 验证、2023 测试,并采用滚动窗口交叉验证(Rolling Window CV)持续评估模型在时间推移后的稳定性。
医学数据往往样本量小(如罕见疾病仅数百例)、类别极度不平衡(阳性率 < 1%)。留一法或分层 5-Fold 是常用选择。在基因组学中,同一患者的多个样本必须归入同一折(GroupKFold),避免同一患者的数据同时出现在训练集和测试集,导致模型学到患者特异性而非疾病特异性特征。
推荐系统的核心挑战是"用户-物品"交互矩阵极度稀疏。随机划分用户或物品需要确保训练集中出现过的用户/物品在测试集中也有合理分布。实践中常采用按用户划分(Leave-one-user-out)或按时间切分:用用户早期的点击行为训练,预测后期的兴趣。
A/B 测试是线上验证模型效果的黄金标准,但离线验证决定了哪些模型有资格上线。交叉验证帮助筛选出泛化能力强的候选模型;上线后,通过 A/B 测试将用户随机分流到对照组(旧模型)和实验组(新模型),比较核心指标(点击率、转化率),最终确认模型在真实环境中的增益。
某数据集共 1000 条记录,类别 A 占 70%,类别 B 占 30%。现需划分为训练集(70%)和测试集(30%)。若采用随机划分,测试集中类别 B 可能只有约 20%;若采用分层抽样,测试集中类别 B 仍保持约 30%。
当样本量减小到 100 条时,随机划分导致测试集类别比例严重偏离的概率为何显著增加?
小样本下随机抽样的方差更大。100条中B类仅30条,随机抽30条测试集时,B类数量服从超几何分布,标准差约为 √(30×70/100 × 70/99) ≈ 3.9,相对波动可达 ±13%。分层抽样通过强制比例约束消除了这一波动。
使用 5-Fold 交叉验证评估某分类器,各折准确率为 [0.82, 0.85, 0.80, 0.83, 0.81]。
计算平均准确率和标准差,并判断模型是否稳定。
均值 μ = (0.82+0.85+0.80+0.83+0.81)/5 = 0.822;标准差 σ ≈ 0.018。各折得分波动在 ±2% 以内,说明模型稳定性较好。若 σ > 0.05,则提示数据分布不一致或模型对某些子集过拟合。
某数据科学家在预测员工是否离职时,将"上月绩效评级"作为特征,并发现模型 AUC 高达 0.96。但上线后效果骤降。
分析可能的泄露来源,并给出正确的特征工程顺序。
"上月绩效评级"可能在员工提交离职申请后才由主管打分(带有 retrospective bias),即特征生成时间晚于标签定义时间,构成目标泄露。正确流程:(1) 按时间切分数据;(2) 只用离职时间点之前的信息构建特征;(3) 在训练集上拟合标准化器/编码器;(4) 变换测试集;(5) 评估。
你有一份 2020-2024 年的月度销售数据,需预测未来 3 个月的销售额。
如何设计训练/验证划分以真实评估模型能力?
采用滚动窗口验证:训练集逐步扩展,验证集始终紧跟训练集末端。例如:
最终测试集为 2024.10-2024.12,全程不可用于调参。