数据集 训练集 测试集 验证集划分

模型与算力

给做数据准备的工程师讲数据集划分的常用方法、比例取舍与踩坑点,附可照做的操作顺序。

跑微调或训练前,多数人卡在同一个地方:手上一批数据,到底怎么切成训练、验证、测试三份,切完心里没底。切错了,验证分数很好看,上线就崩,还查不出原因。这篇不讲概念定义,只讲怎么切、切完怎么自查、什么情况下常规切法不适用,让你在动手前就能把坑避开。

跑微调或训练前,多数人卡在同一个地方:手上一批数据,到底怎么切成训练、验证、测试三份,切完心里没底。切错了,验证分数很好看,上线就崩,还查不出原因。这篇不讲概念定义,只讲怎么切、切完怎么自查、什么情况下常规切法不适用,让你在动手前就能把坑避开。

下面按「先想清楚为什么切三份 → 再选切法 → 处理来源泄漏 → 卡住预处理顺序 → 最后定比例和验收」的顺序走。每一节都给你能直接照做的动作和判断标准,不铺垫概念。

三份数据各自干什么,为什么不能省

训练集用来更新参数,模型直接看过;验证集只在调参和选轮次时用,不参与梯度更新;测试集全程不看,只在最后验收一次。这三件事对应三种不同的决策,混在一起就没法判断模型是真的学到了,还是只是记住了。

  • 训练集:模型直接见过,参数更新只依赖它;
  • 验证集:用来决定什么时候停、选哪组超参,见过但不参与梯度更新;
  • 测试集:只在最后验收一次,提前看就等于把测试集变成了验证集,分数失去参考意义。

只切两份会出问题:只切训练加测试时,你没有任何中立依据决定什么时候停;只切训练加验证时,最后没法给出可信的对外结论。所以三份不是形式要求,是流程决定的。

常用切法:随机、分层、按时间、按实体

切法不是越复杂越好,而是要看你的数据里有没有「不能被打散」的结构。下面四种是实际工作中最常用的,选错一种,后面的分数基本没法信。

切法适用场景什么时候别用
随机切分样本独立同分布、数据量足够样本少、类别极不均衡时容易切出分布不均的两份
分层切分分类任务,尤其少数类样本少回归任务或标签连续时没有明确层可依
按时间切分时序预测、推荐、风控样本本身没有时间先后关系,硬切反而浪费数据
按实体切分同一用户、文档、会话有多条记录实体本身就是被预测对象、且片段互相独立时

随机切分最省事,适合样本独立同分布、且数据量足够的场景;样本少时容易切出分布不均的两份。分层切分按类别比例切,分类任务里少数类样本少时必须用,否则验证集里可能一个正例都没有。按时间切分是训练用早的、验证测试用晚的,时序预测、推荐、风控这类场景只用这一种,随机切会泄漏未来信息。按实体切分是同一用户、同一文档、同一患者的样本必须整组进同一份,否则模型记的是实体而不是规律。

判断标准很简单:先问一句「我的样本之间有没有隐藏的组结构」。有组结构就先按组切,组内再谈随机还是分层;没有组结构再考虑随机或分层。

同一来源的数据要被一起切走

典型泄漏:同一段文本的不同切片、同一张图的不同增强版本、同一通对话的多轮记录,被随机分到训练和验证两边。后果是先出现验证分数异常高、上线明显掉档,再回头查数据才发现问题。

  1. 标来源 ID给每条样本补一个来源 ID(文档 ID、用户 ID、会话 ID),这一步做完先别急着切。
  2. 按 ID 去重排序把来源 ID 去重后排序,检查有没有一个 ID 对应多条样本、且这些样本被分到不同集合。
  3. 按 ID 切分再组内分配先切来源 ID,再把每个 ID 下的样本整组放进对应集合,不要先切样本再回头合并。
  4. 切完复查用脚本查训练/验证/测试三份之间来源 ID 的交集,交集必须为空才算过。

什么情况下不适用:如果你的任务本身就是同一实体的不同片段互相独立预测(比如逐句分类),可以放宽,但要写进实验记录里说明,别默认别人也知道。

先切分,再做统计和预处理

归一化、编码、词表构建、缺失值填充这些步骤,统计量只能从训练集算出来,再套用到验证和测试。把全量数据一起做标准化,等于把验证集和测试集的分布信息提前灌进了训练流程,分数会偏乐观。

# 思路示意,不是完整脚本;先切分,再只对训练集 fit
train, val, test = split_by_id(all_data)
scaler.fit(train[features])          # 只在训练集上算统计量
train_x = scaler.transform(train[features])
val_x   = scaler.transform(val[features])
test_x  = scaler.transform(test[features])
  • 类别不平衡的过采样、合成样本,只在训练集上做;
  • 不要在切分前对全量做增强,增强等于造出跨集合的同源样本;
  • 自查动作:把预处理脚本里所有 fit 类调用挨个过一遍,确认输入只有训练集。

比例怎么定,切完怎么验收

比例不是固定的。数据量越大,验证和测试占比可以越小;数据量很小的时候,考虑交叉验证而不是硬切一份出来。经验上先保证验证集里每一类都有足够样本数,再看测试集能不能撑起一次像样的评估,最后剩下的给训练。

检查项怎么看不通过怎么办
来源 ID 是否跨集合取三份交集,必须为空回到按来源 ID 重切,别手动删样本凑
标签分布差异三份的类别占比逐类对比差异大的类做分层,或在验证集里补样本
特征/长度分布偏移看训练与验证的分位数是否相近先查预处理顺序,再考虑分层或重切
测试集使用记录确认测试集只被评估过一次已多次看过就把这版测试集降级为验证集

切完做三项检查:来源 ID 有没有跨集合重复、各集合的标签分布差多少、文本长度或特征分布有没有明显偏移。前两项查的是数据划分本身,第三项查的是预处理有没有越界。三项全过再进训练,不要边训边补检查。

比例和划分后的分布对照,可以到 /training 与 /models/deploy 核对当时的说明口径,别照搬别人的数字;具体数值随数据规模和任务变化,以站内页面当时的说明为准。

下一步如果你正在挑训练环境或对照不同方案的落地成本,先去 /tools/speed-test 把当前环境的实际表现测一遍,再回来定划分比例,顺序反了容易白调一轮。

常见问题

训练集、验证集、测试集按什么比例分比较合适?

没有通用答案。先看验证集每类样本够不够,测试集能不能支撑一次完整评估,剩下的给训练。数据少就别硬切,改用交叉验证。具体比例参考站内 /training 的说明,并结合你任务的数据量决定,别直接抄别人的数。

验证集和测试集能不能用同一份数据?

不建议。一旦你根据验证集分数反复调配置,这份数据就参与了决策,再用它做最终验收会偏乐观。真要做最终结论,测试集必须在整个调参过程里一次都没看过,只在最后一次跑。

按时间切分是不是一定比随机切分好?

只在数据本身有时序或因果关系的场景下更好,比如推荐、风控、销量预测。如果样本之间确实互相独立,随机切分更省数据。判断依据是:用未来的数据预测过去,在你的业务里是否成立。

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