很多人卡在一个点上:手里一批数据,怎么切、切多少、切完之后为什么测试集分数好看但上线就不行。这篇不重复「训练和测试哪个重要」这类结论,而是从数据本身出发,讲清两类集合各自承担什么职责、划分时该按什么维度切、以及哪些做法会让测试集失去参考价值。读完你能给自己的项目定一套划分规则,并知道什么情况下这套规则不适用。
很多人卡在一个点上:手里一批数据,怎么切、切多少、切完之后为什么测试集分数好看但上线就不行。这篇不重复「训练和测试哪个重要」这类结论,而是从数据本身出发,讲清两类集合各自承担什么职责、划分时该按什么维度切、以及哪些做法会让测试集失去参考价值。
读完你能给自己的项目定一套划分规则,并知道什么情况下这套规则不适用。注意一点:本文不给具体比例数字,因为比例取决于你的数据量和任务类型,判断标准给到之后,具体数值建议到站内页面按当时的情况核对。
用途不同:一个用来改参数,一个用来判断能不能用
训练集参与梯度更新,模型会记住它的统计规律甚至噪声;测试集不参与任何迭代,只回答「这份模型在没见过的东西上表现如何」。这两件事的性质完全不同:前者是学习材料,后者是验收标准,混在一起用就失去意义。
- 训练集分数高不代表能用,测试集分数才是决策依据;反过来,测试集分数不能用来反推该调什么参数。
- 常见错误是把测试集当成第二个训练集,看到测试集差就回去改模型再测同一批数据,测几次之后它就不再是测试集了。
- 如果只是想知道模型有没有收敛、要不要提前停,那是验证集的活,和测试集不要混用。
- 测试集的作用是回答「能不能上线」,不是「还能怎么改」,所以它跑的次数越少、结论越可信。
| 对比项 | 训练集 | 测试集 |
|---|---|---|
| 是否参与参数更新 | 参与 | 不参与 |
| 主要用途 | 拟合规律、调权重 | 判断泛化能力、是否可上线 |
| 跑的次数 | 可以反复跑 | 越少越好,关键节点才跑 |
| 改动方式 | 可以清洗、增强、重采样 | 一旦定版尽量不动 |
| 分数含义 | 学习效果 | 对外承诺的参考 |
划分方式不同:训练集怎么切,测试集就得怎么切
划分要按「和线上真实分布一致」的维度切,比如按时间切、按用户切、按设备切,而不是随手随机抽。时间序列类任务尤其不能随机打乱:用未来数据训练、过去数据测试,结果会虚高,上线必崩。
- 先定切分维度问清楚线上新数据是什么形态:新用户、新时间段还是新设备。按这个维度切,把它写进项目文档,全组统一。
- 处理同源样本同一来源的样本(同一篇文档切出的多个片段、同一张图的不同裁剪)要么全进训练集要么全进测试集,否则算泄漏。用文本指纹或哈希去查重叠。
- 做分布对照切完后对比两边的类别比例、长度分布、语种比例,偏差大就重新分层抽样,不要凑合。
类别比例、长度分布、语种比例尽量在两边保持一致。切完先做一遍分布对照,这一步花不了多少时间,但能挡掉后面很难查的一类问题。如果你的项目已经在跑,可以到站内 /tools/speed-test 做一次推理耗时测算,确认测试环节的资源开销是否可承受。
常见误区与一份自查清单
下面这几条是最常见的坑,按顺序自查一遍,基本能覆盖大部分「测试分数虚高」的场景。
- 泄漏:测试集里的信息以任何形式出现在训练过程中,包括被用来选特征、选超参、挑数据清洗口径。
- 切了但没用上:留出一份测试集却从没跑过,等于白留;建议固定一份、写上版本号、只在关键节点跑。
- 只切一次就完事:数据在增长、标注口径在变,测试集需要定期复审,看它是否还代表当前业务分布。
- 分布漂移:上线一段时间后测试集不再代表新数据,此时测试集分数只能当历史参考,不能当当下结论。
- 口径不一致:训练脚本和测试脚本用了不同的清洗规则,分数差异其实来自预处理,不是模型。
给你的项目定一套可执行的划分规则
- 确定切分维度时间 / 用户 / 随机三选一,写在项目文档里,全组统一。选完在注释里写清理由。
- 按比例初切并分层类别不均衡时做分层抽样,保证每类在两边都有代表。具体比例参考自己的数据量,不要照搬别人的数字。
- 做泄漏检查查重复样本、查同源样本是否跨集、查测试数据有没有进过训练脚本的读取路径。三步都过再往下走。
- 跑基线并测算开销跑一遍基线,同时到站内 /models/deploy 做一次显存与耗时测算,确认测试环节的资源开销可承受。
- 冻结测试集把测试集冻结成带版本的文件,记录切分脚本与随机种子。后续新增数据只进训练集,测试集另行扩版。
| 动作 | 验证方式 | 不通过的信号 |
|---|---|---|
| 切分维度确定 | 文档里有明确记录 | 不同人切法不一样 |
| 分布对照 | 两边统计量接近 | 某一类只出现在一边 |
| 泄漏检查 | 同源样本不跨集 | 查重时发现重叠 |
| 测试集冻结 | 有版本号与随机种子 | 换台机器跑分数就变 |
比例怎么定、资源开销多少算合理,这类跟规模强相关的数字,建议到站内 /price-watch 或 /rankings 核对当时的实测数据,别直接抄别人项目里的数值。
什么情况下这套思路不适用
上面这套流程的前提是「有稳定分布、数据量够切」。下面几种情况硬套反而会拖慢节奏,需要换思路。
- 探索阶段或数据量极小(几十条)时,硬留一份测试集会让两边都不够用,更实际的做法是交叉验证。
- 一次性调研任务、只想知道某个开源模型大概行不行,可以直接用公开榜单数据,不必自己切;但要清楚公开集可能已被训练过。
- 如果业务本身没有稳定分布(每天数据形态都在变),固定测试集的意义有限,重心应放在持续采样和线上监控。
- 做的是纯生成类、没有客观标签的任务,测试集只能靠人工抽样评估,这时规则要改成「评估集 + 评分标准」,而不是分数对照。
常见问题
训练集和测试集一般按什么比例分?
没有固定答案,取决于数据总量和任务。数据多时测试集占比可以小一些,数据少时留太多会导致训练不够。关键是测试集要大到分数稳定、不会因为多加几条样本就大幅波动。具体数字可以到站内 /training 页面看当时的说明,再结合自己的样本量定。
测试集分数比训练集低很多,是哪里出问题了?
先分清两种情况:如果差距随着训练持续扩大,通常是过拟合,需要减容量、加正则或加数据;如果一开始就差很多,更可能是划分有问题,比如训练集和测试集分布不一致,或者存在同源样本跨集导致的泄漏。按上面的泄漏检查清单逐项排查,优先查重复数据和切分维度。
验证集和测试集能不能用同一份数据?
不建议。验证集是拿来反复调的,你会根据它的反馈改模型、改超参,它的分数会随着你的调整被间接「污染」;测试集要是同一份,最后报出的分数就是乐观偏差。稳妥做法是三分开:训练、验证调参、测试只在最终评估跑一次。数据实在太少时,可以明确标注这是验证结果而非最终结论。