为什么要把数据集分成训练集 验证集和测试集

模型与算力

讲清训练集、验证集、测试集各自的分工,以及划分数据时怎么做才不白费功夫,适合刚上手模型训练的读者。

很多人第一次跑模型就卡在这:训练准确率很好看,换一批数据就崩,于是反复调参数,却不知道问题出在数据划分上。这篇不背定义,而是把三种数据集的分工讲成一条流水线,给出划分比例、随机性、数据泄漏的排查顺序,以及什么情况下这套分法其实不适用。

很多人第一次跑模型都卡在同一个地方:训练的时候分数很好看,换一批没见过的数据立刻崩,于是回头疯狂调参数、加层数、换优化器,折腾几天也没起色。问题往往不在模型,而在数据怎么切。三种数据集不是走流程的形式主义,它们对应的是三件完全不同的事,搞混了,后面所有评估数字都不可信。

下面把这件事讲成一条流水线:每种数据集负责什么、比例怎么定、什么时候会悄悄泄漏、什么情况下这套分法其实不适用。最后给一份动手前的清单,照着做能省掉不少返工。

三种数据集不是重复劳动,是三件不同的事

训练集负责让模型见题、调整权重,它决定模型能学到什么。验证集负责在训练过程中做选择:挑超参、定训练轮次、决定什么时候早停。测试集负责在全部决定都做完之后,给一次不带偏见的成绩。三者的区别不在数据本身,而在「这次评估有没有被用来做决定」。

训练集
模型直接用来更新参数的那部分数据,模型可以反复看、反复记。
验证集
训练期间用来做选择的数据,你看它的结果去改超参、改轮次都算正常使用。
测试集
所有决定定完之后才碰一次,用来估计模型面对新数据时的表现。

一句话判断标准:凡是「根据结果做了一次决定」的那次评估,就不能再当成最终成绩。如果只有训练集,模型可以靠死记把分数刷上去;如果只有训练集加测试集,你会不自觉地拿测试集当验证集用,反复试到最后测试成绩也被你调脏了,等于白留。

比例没有标准答案,先按数据量和任务定档

网上流传的比例很多,但比例本身取决于你的数据量和任务类型。数据量大到几十万条以上时,验证集和测试集各留一小部分通常就够用,评估噪音小。数据量小的时候很尴尬:留得少,评估结果抖动大,一次好坏说明不了问题;留得多,训练数据不够,模型根本学不动。这时要在评估可信度和模型能学多少之间做取舍。

数据特征切分方式容易踩的坑
随机采样、样本独立随机切分,固定随机种子切完才发现重复样本分布在两边
类别不均衡按类别分层抽样某一类在验证集里一条都没有
日志、交易、传感器等按时间产生按时间切,过去训练、未来评估随机切分导致用未来预测过去
数据量极小只留训练集和验证集,用交叉验证每折都当真评估,计算量翻倍
  • 按时间顺序产生的数据不要随机切,要按时间切,用过去预测未来才符合真实使用场景。
  • 分类任务要保证每一类在三个集合里都出现,类别极不均衡时更要按类别分层抽样。
  • 切分前先固定随机种子,把划分结果存成文件,后续实验都用同一套切分,否则不同轮次的分数没法比。
  • 具体到你手上的数据量该切多少,可以到 模型训练(/training) 对一遍当时的通用做法,别照抄别人的百分比。

成绩虚高的头号嫌疑:数据泄漏排查顺序

训练分数高得离谱、验证分数也漂亮,一上线就崩,最常见的原因就是数据泄漏——模型在训练时以某种方式提前看到了答案。它不会报错,只会让所有数字变得好看,所以必须靠人工排查。按下面顺序查,能覆盖绝大多数情况。

  1. 先查重复同一条样本或高度相似的样本同时出现在训练集和验证集里,模型等于见过答案。去重要在划分之前做,划分之后再发现就得重切。
  2. 再查特征标签是由某个特征直接算出来的,或者归一化、缺失值填充等预处理在划分之前用了全量数据统计,都算泄漏。正确做法是预处理只在训练集上拟合,再套用到验证和测试。
  3. 再查时间用未来数据预测过去,线下分数再高,线上也一定掉。检查切分是否按时间顺序,特征里有没有包含预测时点之后才产生的信息。
  4. 最后查流程调参、选模型、选早停点如果反复看测试集,那测试集就已经变成第二个验证集了。回头看实验记录,测试集被看过几次。

什么情况下这套分法不适用

三分法是监督学习里最通用的做法,但它不是万能的。数据本来就极少的时候,硬留一个固定测试集可能让两边都不够用,这时候可以只留训练集和验证集,用交叉验证替代固定测试集,把每一折都当一次评估,代价是计算量成倍增加,而且最终结果需要在多折之间取平均来看。

  • 数据极少时,用交叉验证替代固定测试集,别硬切出一小块不具代表性的数据当最终成绩。
  • 做无监督任务、纯检索或纯生成类评测时,「测试集」往往换成一套固定问题或人工评分标准,逻辑接近但不完全一样。
  • 线上持续迭代的场景,测试集要定期换新,否则几轮之后它就退化成训练数据的一部分,参考价值越来越低。
  • 如果业务指标本身就是最终目标,训练侧的验证分数只能作为参考,最终还得看线上的实际表现。

动手前的五步清单

上面讲的是判断标准,落到操作上就是下面五步。顺序很重要,颠倒任何一步都可能让前面白做。

  1. 第一步:清洗再去重先去重、清洗,再划分,顺序不能反。划分之后才发现重复,只能重切一遍。
  2. 第二步:确定切分方式随机、分层还是按时间,取决于数据是独立采样、类别均衡还是按时间产生。
  3. 第三步:固定随机种子把划分结果存成文件,保证后续实验用同一套切分,否则不同轮次之间的分数没有可比性。
  4. 第四步:先只用训练集训练前先只用训练集跑一遍,确认模型能学动,再加入验证集做选择。别一上来就盯着测试集。
  5. 第五步:最后才碰测试集最后一次才碰测试集,并且记录下这次用了哪个版本的数据、看过几次结果。

如果你在挑训练环境或算力方案,可以先到 工具目录(/tools/speed-test) 看看各家方案的实测情况,再到 价格追踪(/price-watch) 核对当时的报价对比,按自己的数据量和迭代频率来选,而不是只看宣传。

下一步想把这些判断标准落到具体数据上,可以到模型训练页面对一遍当前通用做法,再回头看自己的切分和预处理流程有没有踩到泄漏。

常见问题

验证集和测试集到底差在哪,能不能只留一个?

差在「有没有被用来做决定」。验证集是训练过程中的裁判,你会根据它反复调整;测试集只在最后用一次,用来估计真实表现。只留一个的话,你最后拿到的成绩已经被自己的调试污染过,会偏乐观。

三个集合的比例是不是按固定百分比切就行?

没有通用数字。数据量大可以少留,数据量小则要留够才能看出差异,时间序列还得按时间切。切分前先想清楚你的数据量级、类别分布和是否有时序,再看站内训练板块的通用做法。

训练集分数高、测试集分数差,一定是数据划分的问题吗?

不一定。模型过大、训练轮次过多、数据量太少都可能造成这个现象,划分不合理只是其中一种。排查顺序是先看去重和泄漏,再看模型容量和训练轮次,最后才怀疑数据量。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。