4.2 数据切分、交叉验证与泄漏:评估集要模拟模型将面对的未知
模型在随机切分上表现近乎完美。你检查样本后发现,同一任务被日志拆成几十行,训练集和测试集各有一部分;模型只是认出了任务 ID 和固定模式。数据从未真正“未知”。
切分不是固定的 60/20/20 配方。它是一场部署模拟:模型未来要面对新记录、新时间、新队伍还是新站点,决定了隔离单位。
本课目标
- 给 training、validation/CV 和 test 分配不同职责;
- 根据独立、分组、时间和空间结构选择切分;
- 把 preprocessing、feature selection 和 calibration 放入正确边界;
- 识别反复查看测试集造成的适应性过拟合。
1. 三类数据职责
- training:拟合模型和预处理参数;
- validation/CV:选择特征、算法、超参数、阈值和停止点;
- test:方案冻结后估计整个选择流程的泛化表现。
如果根据 test 结果改变模型、特征或论文叙事,test 已参与选择。需要新 holdout、nested CV 或诚实标注结果偏乐观。
固定百分比不是目标。样本小可用交叉验证,时间变化快可能用多个 rolling windows,测试集还要足够覆盖关键群体与罕见失败。
2. 随机切分的适用条件
随机行切分近似假设样本可交换,且部署目标与当前分布相似。分类可 stratify label 以减少类别比例波动,但:
- 不保证所有重要交叉群体平衡;
- 不处理同一实体重复;
- 不模拟未来漂移;
- 不能修复选择偏差。
随机种子只保证某次伪随机过程可复现,不证明结果稳健。可重复多次切分报告分布。
3. Group split
同一用户、设备、队伍、病人或文档的多行高度相关,应按泛化目标把完整 group 放在同一 fold。
from sklearn.model_selection import GroupKFold
cv = GroupKFold(n_splits=5)
for train_idx, valid_idx in cv.split(X, y, groups=team_id):
assert set(team_id[train_idx]).isdisjoint(team_id[valid_idx])若一人属于多个家庭/站点,group 定义可能重叠,需要连接分量或更高层隔离。只按单个字段 group 可能仍有泄漏。
4. 时间切分
预测未来时,训练应早于验证。Rolling/expanding window 可评估多个时期:
train Jan–Mar → validate Apr
train Jan–Apr → validate May
train Jan–May → validate Jun还要设置:
- label maturation:训练样本标签已完整观察;
- feature/label gap:防止重叠窗口泄漏;
- embargo:金融等重叠事件场景隔离邻近期;
- late-arriving data:历史回放只使用当时可用版本。
简单按时间排序后切最后 20%,仍可能把同一事件的未来修订泄漏进训练特征。
5. 空间与站点泛化
如果模型要部署到未见堡垒,测试应留出整个堡垒;若只在已有堡垒预测未来,则可在每个堡垒内按时间切。两种问题不同,应分别评估。
地理邻近会造成空间相关。留出相邻网格的随机点可能过于容易,可采用区域 block 和缓冲带。
6. Preprocessing 必须在 fold 内 fit
会从数据学习参数的步骤都属于模型选择过程:
- imputation、scaling、encoding;
- feature selection、PCA;
- target encoding;
- resampling/SMOTE;
- calibration 和 threshold selection。
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
pipeline = Pipeline([
("impute", SimpleImputer(strategy="median")),
("scale", StandardScaler()),
("model", LogisticRegression(max_iter=1000)),
])交叉验证 pipeline,每折会重新 fit 前处理。先对全表标准化/筛选再 CV,即使没直接看 label,也让验证折影响转换;目标编码和监督选择泄漏更严重。
7. 重采样只能在训练折
对少数类 oversampling、undersampling 或 synthetic sampling 应在每个训练 fold 内做。先 SMOTE 再切分会让一个原样本及其合成邻居跨 fold,显著乐观。
评估集应保留部署时自然分布。若业务会改变采样/筛选,还需用权重或单独目标分布评估。
8. Nested cross-validation
同一组 CV folds 既选超参数又报告最佳分数,会产生选择乐观。Nested CV:
- inner loop 选择 pipeline 和超参数;
- outer loop 评估整个选择过程。
成本较高,但小数据、候选多且需要可靠比较时很重要。最终模型可在全部开发数据上按选定流程重训,独立 test 仍只使用一次。
9. 数据去重不能跨越 test 边界偷看
先对全数据做近重复检测可能利用 test 内容来修改 training。正确流程取决于目标:
- 全局来源层去除真正重复采集,可在切分前,规则与原因要固定;
- 语义近重复/相似图像应先分 group,再按 group 切;
- 根据 test 表现发现并删除“麻烦样本”属于污染。
版本、哈希、来源 ID 和去重簇应保留以审计。
10. Test set 的操作纪律
访问者与用途受限
评估脚本和主指标预先冻结
只返回必要聚合,避免逐样本反复调试
每次访问记录模型、数据和理由
测试后变更必须重新建立评估边界
测试分布与部署变化时重新取样测试集不是永恒标准。随着团队反复公开 benchmark 成绩,组织知识也会对它过拟合。
常见误区
- 拆成三份就没有泄漏:切分单位和所有 fit 步骤同样重要。
- stratify 解决分布问题:它只约束指定标签比例。
- 随机种子固定就可靠:可能只是复现一次偶然切分。
- test 只看不训练所以可多看:人的选择也会过拟合。
练习
- 对重复任务日志比较行随机和 GroupKFold 分数。
- 为 30 天 label window 设计时间 split 与 gap。
- 演示全数据 feature selection 与 fold 内选择的差异。
- 为测试集建立访问日志和“何时需要新 test”规则。
小结
评估可信度来自隔离真实未知,而不是文件名叫 test.csv。时间、实体、空间和所有数据学习步骤都要与部署目标一致。
下一课用学习曲线和误差分解诊断欠拟合、过拟合与分布变化,并选择对症控制。