4、数据划分策略:训练集、验证集、测试集的划分方法

数据划分是模型验证框架的第一道关口,也是决定后续所有评估指标是否可信的基石。如果划分方式不当,即使使用了最先进的交叉验证算法或最精细的监控仪表盘,得到的性能结论也可能严重偏离真实部署场景。本章将系统讲解留出法、K 折交叉验证、分层采样、时间序列切分等核心策略,并针对数据泄露、随机种子管理、类别不平衡等高频问题给出可落地的操作规范。

数据划分策略全景图 原始数据集 D = {(x₁,y₁)...(xₙ,yₙ)} 留出法 (Hold-out) 训练 70% | 验证 15% | 测试 15% K 折交叉验证 K=5 或 10,分层采样 时间序列切分 前向链 / 滚动窗口 关键操作 • 随机打乱后按比例切分 • 固定随机种子保证可复现 • 验证集用于调参 • 测试集仅用一次 • 类别不平衡需分层 • 小样本慎用(方差大) K 折流程 ① 数据随机分为 K 份 ② 每轮取 1 份做验证 ③ 其余 K-1 份做训练 ④ 重复 K 次取平均 ⑤ 最终模型用全量训练 ⑥ 测试集保持独立 前向链切分 • 训练集时间必须早于验证集 • 禁止随机打乱 • 滚动窗口:固定窗口滑动 • 扩展窗口:逐步累积历史 • 需考虑季节性和趋势 • 防止未来信息泄露

4.1 核心原理:为什么划分方式决定模型可信度

数据划分的本质是模拟模型在未见数据上的表现。训练集负责拟合参数,验证集用于模型选择与超参数调优,测试集则扮演“最终考官”的角色。三者必须严格隔离,任何跨越边界的“信息流动”都会导致评估结果虚高。例如,若在训练前用全量数据做特征缩放,测试集的均值/方差信息已经泄露到训练过程中,最终测试指标将无法反映真实泛化能力。

从概率视角看,我们希望测试误差 E_test 能够无偏估计泛化误差 E_gen。留出法在数据充足时(如 >10 万条)表现稳定,但在小样本场景下,单次划分的方差可能非常大——不同随机种子可能产生 5% 以上的 AUC 波动。交叉验证通过多次划分取平均,显著降低了这种方差,但计算成本也随之上升。时间序列数据则打破了独立同分布假设,必须保持时间顺序,否则模型会“偷看未来”。

核心原则:测试集只能使用一次。如果反复用同一测试集评估不同模型,实际上测试集已经变成了验证集,最终指标会偏向过拟合的模型。

4.2 留出法(Hold-out)与分层采样

留出法是最直观的划分方式:将数据集按比例随机切分为训练集、验证集、测试集。常见比例为 60/20/20 或 70/15/15。对于中小规模数据(< 5 万条),建议训练集占比不低于 70%,否则模型可能欠拟合;对于大规模数据(> 100 万条),训练集占比可适当降低至 90% 以上,因为验证集和测试集只需足够评估即可。

分层采样(Stratified Sampling)是留出法的重要改进。当分类任务存在类别不平衡时(如欺诈检测中正样本仅占 1%),简单随机划分可能导致验证集或测试集中正样本数量极少甚至为零。分层采样保证每个子集中各类别比例与原始数据集一致。回归任务中则可采用分位数分层,确保不同数值区间的样本均匀分布。

场景推荐划分比例说明
小样本(< 1 万条)60/20/20 或 70/15/15训练集占比高,避免欠拟合;使用分层采样
中等规模(1 万~10 万条)70/15/15 或 80/10/10验证集和测试集各 1 万条左右即可稳定评估
大规模(> 100 万条)90/5/5 或 98/1/1测试集 5 万条已足够;节省训练时间
类别极不平衡(< 1% 正样本)分层采样 + 70/15/15确保验证/测试集中正样本 ≥ 30 条

4.3 K 折交叉验证:小样本的可靠选择

K 折交叉验证将数据均分为 K 份,每次取其中 1 份作为验证集,其余 K-1 份作为训练集,重复 K 次后取平均性能。K 的典型取值为 5 或 10。K=10 时偏差更低,但计算量增加一倍;K=5 在计算效率和稳定性之间取得较好平衡。对于深度学习等耗时任务,可考虑 K=3 或使用单次验证集。

操作流程:

  1. 将数据随机打乱,按分层采样分为 K 份;
  2. 对于每一折 i:使用第 i 份作为验证集,其余 K-1 份合并为训练集;
  3. 在训练集上训练模型,在验证集上计算评估指标(如准确率、F1、AUC);
  4. 计算 K 次指标的平均值和标准差;
  5. 最终模型使用全部数据重新训练,测试集保持独立未使用。

交叉验证的另一个变体是重复 K 折(Repeated K-Fold),即多次执行 K 折并取平均,进一步降低随机性影响。例如 5×2 交叉验证(5 次重复的 2 折)常用于算法比较。

注意:交叉验证的“验证集”用于模型选择,不能替代独立的测试集。如果使用交叉验证选择模型后,再用同一份数据评估最终模型,仍然存在信息泄露风险。正确做法是:先用交叉验证选择最优模型和超参数,然后固定该模型,在从未参与训练的测试集上做最终评估。

4.4 时间序列切分:保持时间顺序的强制约束

时间序列数据(如股票价格、传感器读数、日活用户量)具有时间依赖性和自相关性,随机打乱会破坏这种结构,导致模型“看到未来”。时间序列切分必须保证训练集时间早于验证集,验证集早于测试集。常用的两种方法:

  • 前向链(Forward Chaining):初始训练集为前 60% 数据,验证集为接下来 20%,测试集为最后 20%。后续可扩展为多轮滚动:训练集逐步扩大,验证集逐步后移。
  • 滚动窗口(Rolling Window):固定窗口大小(如 30 天),每次滑动一定步长(如 7 天),训练集始终为最近 30 天,验证集为接下来 7 天。适用于概念漂移明显的场景。

时间序列切分还需考虑季节性周期。例如预测电商日销售额,训练集应包含至少一个完整年度周期,否则模型无法学习季节性模式。验证集和测试集也应覆盖完整的季节周期,避免只在旺季或淡季评估。

经验:对于金融时间序列,建议使用“扩展窗口”而非“滚动窗口”,因为模型可以利用更多历史信息。但需监控概念漂移——如果市场结构发生根本变化,过长的历史数据反而会引入噪声。

4.5 案例拆解:信贷风控模型的数据划分实战

背景与约束:某消费金融公司开发申请评分卡模型,数据集包含 120 万条历史贷款申请记录,时间跨度为 2021 年 1 月至 2023 年 12 月。正样本(违约)占比 2.3%。业务要求:模型需在 2024 年 Q1 上线,且需通过监管审计,验证流程必须可复现。

初始现象:团队最初使用随机 70/15/15 划分,模型在测试集上 AUC 达到 0.87,但上线后实际表现 AUC 仅 0.72,坏账率明显高于预期。

分析判断:排查发现两个问题:① 随机划分导致训练集包含 2023 年下半年的数据,而测试集包含 2021 年数据,模型实际上“见过”更近期的样本,但部署时面对的是未来数据;② 2022 年信贷政策收紧,违约率分布发生变化,随机划分使训练集和测试集的分布不一致。

实际操作步骤:

  1. 改为时间序列切分:训练集为 2021.01~2022.12(约 80 万条),验证集为 2023.01~2023.06(约 20 万条),测试集为 2023.07~2023.12(约 20 万条);
  2. 在训练集内使用 5 折分层交叉验证选择模型超参数(如逻辑回归的正则化系数);
  3. 固定最优模型后,在验证集上做一次快速检查(确保 AUC > 0.80);
  4. 最终在测试集上评估,记录 AUC、KS、Lift 等指标;
  5. 保存所有随机种子和划分索引,供审计复核。

结果对比:时间序列切分后,测试集 AUC 降至 0.79,但上线后实际 AUC 为 0.77,差距从 15% 缩小到 2.5%。虽然评估指标“变差”了,但更接近真实部署表现。

风险与代价:时间序列切分导致训练数据减少(少了 2023 年数据),模型可能未学习到最新趋势。为缓解此问题,团队在模型上线后建立了月度重训练机制,每次用最近 24 个月数据重新训练。

复盘经验:对于有明确时间属性的数据,必须优先采用时间序列切分,即使随机划分的评估指标更好看。评估的目标不是追求高分,而是准确预测未来。

4.6 常见误区与总结复盘

误区后果正确做法
测试集被多次使用指标虚高,模型过拟合测试集测试集仅用一次,或使用嵌套交叉验证
数据预处理(如标准化)在划分前进行信息泄露,评估结果不可信先划分,再在训练集上拟合预处理器,然后应用到验证/测试集
时间序列数据随机打乱模型学习到未来信息,上线后崩溃严格按时间顺序切分
类别不平衡时未分层验证集可能无正样本,指标失真使用分层采样或 SMOTE 后再划分
小样本使用留出法评估方差大,结论不稳定使用 K 折交叉验证或 Bootstrap
忽略分组结构(如同一用户多条记录)同组数据同时出现在训练和验证集使用 GroupKFold 按用户 ID 分组

总结:数据划分不是简单的“切一刀”,而是需要根据数据特性、业务场景和模型用途综合设计。留出法适合大规模独立数据,交叉验证适合小样本和模型选择,时间序列切分是时序数据的唯一正确选择。无论采用哪种方法,都必须保证测试集的独立性,并记录所有划分参数以确保可复现性。在实际项目中,建议将数据划分代码封装为独立模块,输入原始数据和配置参数,输出训练/验证/测试集的索引,这样既便于审计,也方便后续重训练时保持一致。