很多人第一次跑模型,卡在同一个问题上:数据到底该切成几份、每份干什么用。切错了,模型看着很好,一上新数据就崩。这篇不堆术语,按「谁负责学、谁负责挑、谁负责判」把三集的职责讲清楚,并给出一套可执行的划分与自查步骤,让你拿到手就能改自己手上的数据集。
很多人第一次跑模型,卡在同一个问题上:手上这份数据到底该切成几份、每份干什么用。切错了,模型在训练时看着挺好,一上新数据就崩。这篇不堆术语,按「谁负责学、谁负责挑、谁负责判」把三集的职责讲清楚,并给出一套可以照着做的划分与自查步骤。看完你就能回头改自己手上的数据集。
先说一句定心的话:训练集、验证集、测试集不是三个必须都有的东西,而是一套分工。分工清不清楚,决定了你报出来的数字可不可信。下面每一节都给判断标准和动作,不讲空话。
三集到底各管什么:用一句话记住分工
把三集想成一场考试。训练集是平时的练习题,模型靠它见题、改参数;验证集是模拟考,用来在训练过程中挑超参数、决定什么时候停;测试集是最终交卷,只在最后评估用一次。关键不在名字,而在于你实际怎么用它们。
- 训练集
- 模型真正用来学参数的那部分数据,见得多、改动也最多
- 验证集
- 训练过程中当考官,用来选超参数、判断过拟合、决定早停
- 测试集
- 封存到最后,只跑一次,用来给出「大概什么水平」的结论
验证集不是必选项。如果只是内部试水、不做对外结论,可以先只分训练和验证。但只要你打算说「上线后大概什么水平」,就必须留出没被动过的测试集。反过来说,一旦你用测试集反复调参,测试集就悄悄变成了验证集,最终指标会虚高,这时的数字对外基本没有参考价值。
- 先问自己:这次结论要给谁看?只给自己看,训练+验证就够;要给外部看,就必须有独立测试集
- 再问:调参阶段我有没有偷看测试集?偷看过一次,测试集就不再干净
- 最后问:三份数据是不是来自同一批样本的重复?是的话,先把去重做掉再谈划分
划分顺序:先切测试集,再切验证集
顺序这件事很多人做反了。正确做法是:先按比例切出一份测试集并封存,再从剩下的数据里切验证集。如果反过来先切验证集,剩下的数据可能已经把测试集要用的那部分混进去,分布就不干净了。
- 第一步:先去重、再检查标签把重复样本和近重复样本清掉,同时确认标签没有明显错标。这一步不做,后面切得再规范也白搭。
- 第二步:先切测试集并封存按任务类型选切分方式,切出测试集后就当成它不存在,训练调参阶段完全不碰。
- 第三步:从剩余数据切验证集剩下的数据里再切出一份验证集,用于训练过程中的模型选择。
- 第四步:记录每集的分布把每集的样本数、类别占比、切分方式和随机种子记下来,否则下次复现不出来。
还有一个容易忽略的点:划分要在任何清洗、特征工程之前做。如果先对全量数据做了标准化、补缺或编码,再切分,同一批数据的信息会跨集泄漏。正确顺序是先切分,再各自处理,互不干扰。
比例怎么定:看数据量和任务类型
比例没有标准答案,但判断标准是有的:数据多,验证集和测试集只要保证「够统计」就行,比例可以压得很小;数据少,比例再大也撑不住,只能靠交叉验证。关键不是某个固定数字,而是每份集合里样本够不够支撑你下的结论。
| 数据类型 | 切分方式 | 判断标准 |
|---|---|---|
| 普通平衡数据 | 随机抽签 | 每集各类别占比接近即可 |
| 类别不平衡 | 分层抽样 | 小类不能整类落进某一个集 |
| 时间序列 | 按时间前后切 | 用早的预测晚的,不能随机打乱 |
| 分组结构(同一用户多条) | 按组切分 | 同一组的样本只能出现在一个集里 |
类别不平衡的任务别用随机切分。随机切很容易让某个小类整类落进测试集,或者训练集里根本没有这个小类,模型等于没见过就上考场。用分层抽样可以保证每集里各类别占比接近。具体比例不用记死,可以到 /ai-dict/category/basics 对照基础概念,再按自己的数据量试算。
时间序列类数据不能随机打乱,必须按时间前后切:用早的数据训练,用晚的数据验证和测试。随机切会引入未来信息,模型在评估时看起来很好,上线后完全对不上。这是新手最常踩的坑之一。
最常见的三个坑:泄漏、调参污染、指标好看
划分做完了不代表就干净。下面三个坑最常出现,而且它们都会让指标虚高,让人误以为模型没问题。每次跑完实验,按这三个方向过一遍。
- 泄漏:同一条样本或它的近重复出现在两个集合里,模型等于提前见过题;处理办法是做严格去重,按用户或按文档分组切分
- 调参污染:看着测试集指标反复换超参数、换模型,这等于把测试集当验证集用了;对策是调参阶段完全不看测试集
- 指标好看:训练集效果好测试集差,通常是过拟合;反过来三集都差,多半是数据或标注问题,不是模型不够大
判断泄漏最直接的办法是查重叠:把训练集和验证集、测试集按样本 ID 或关键字段做个交集,看有没有同一条数据同时出现。有交集就是泄漏,先解决它,再谈模型效果。这一步花不了多少时间,但能省下后面大量的排查。
怎么快速自查
- 查重叠按样本 ID 或关键字段求交集,训练集和验证集、测试集之间不应该有交集。
- 查分布对比各集的类别占比,差距明显就说明切分方式有问题。
- 查调参记录翻一遍实验记录,确认调参阶段有没有人看过测试集指标。
- 查指标落差看训练集和测试集的指标差距,差距大先怀疑过拟合或泄漏,别急着换更大的模型。
一套能直接照做的划分流程
把前面几节的内容收成一条流水线。下面六步按顺序做完,基本能覆盖大多数入门项目。每一步都写了怎么验证,照着做就行。
- 去重并确认标签质量清理重复样本和明显错标,确认标签口径一致。
- 按任务类型决定切分方式普通数据随机切,不平衡数据分层,时间序列按时间切,分组数据按组切。
- 先切测试集并封存切完就当它不存在,调参阶段完全不碰。
- 从剩余数据切验证集用于训练过程中的模型选择和早停判断。
- 记录每集的样本量和类别分布写进实验记录,包含切分方式和随机种子。
- 训练只用验证集,最后跑一次测试集调参全程只看验证集,最终评估只跑一次测试集并记录结果。
把每集的样本数、切分方式、随机种子写进实验记录,这件事容易被省掉。省掉的代价是下次别人复现不出来,或者你自己过两周也说不清当时怎么切的。记录本身就是流程的一部分。
什么时候用交叉验证,什么时候别用
交叉验证是把训练数据分成若干折,轮换着当验证集,用多轮结果的平均来降低单次划分的偶然性。它不是万能的,用错地方反而会误导结论。判断标准还是数据量和结构。
- 数据量小、想要更稳的评估时用交叉验证,能降低单次划分的偶然性
- 数据量大、单次训练成本高时不必交叉验证,固定一份验证集更省算力
- 交叉验证只替代验证环节,不替代测试集;对外报结果仍然要有独立测试集
- 时间序列和强分组结构的数据,普通随机交叉验证会破坏结构,需要按时间或按组做交叉
不适用的情况要记牢:时间序列和强分组结构的数据,普通随机交叉验证会把未来信息或同组信息混进来,评估结果不可信。这类数据要用按时间前后切或按组切的交叉方式。拿不准自己的数据属于哪种,可以到 /tools/speed-test 之类站内工具页看看有没有适合的辅助工具。
训练中还要不要再切一份「开发集」
开发集和验证集在很多项目里其实是同义词。差别在于团队规模:如果调参和评估由不同人负责,可以再单独留一份只给评估方看的集合,避免调参的人顺手把评估数据也看了。小团队没必要堆太多集合,数据本来就不够分,切太碎每一份的统计意义都会下降。
判断标准很简单:多一份集合能带来更可信的结论就用,只是让流程更复杂就省掉。数据集切几份从来不是目标,让最后的结论可信才是。别为了流程好看,把数据切到每一份都不够用。
三集的本质不是三个文件夹,而是三道防线:学、挑、判,各不相干。下一步想对照基础概念和常见任务的切分方式,可以去站内资料库核对当时的说明;如果你在用中转站跑实验,也建议先把模型选择和数据划分这两件事分开看,别让接口层的波动污染你的评估结论。→
常见问题
验证集和测试集有什么区别,能不能只留一个?
验证集在训练过程中反复使用,用来选超参数和决定什么时候停;测试集只在最后用一次,用来估计真实表现。只留一个的话,你调参时看的那个集就既是验证集又是测试集,最后报出的数字会偏乐观。数据实在少,可以先用交叉验证代替验证集,但测试集仍建议单独留一份。
三集的比例按多少分比较合适?
没有固定答案,取决于数据总量和任务。数据多的时候验证集和测试集只要够统计就行,比例可以压小;数据少的时候比例再大也撑不住,更适合用交叉验证。类别不平衡要用分层抽样,时间序列要按时间切。建议先记录每集样本量和类别分布,再判断够不够用,站内 /ai-dict/category/basics 可以对照基础概念。
为什么我的模型训练集效果好,测试集效果很差?
这通常说明模型把训练数据记住了而不是学到了规律,也就是过拟合。常见诱因是数据量小、模型相对任务太大、训练轮数过多,或者训练集和测试集分布本来就不一致。排查顺序是:先确认有没有数据泄漏,再看训练和验证两条曲线是否分叉,然后考虑加正则、减轮数或补数据。
划分数据集之前要不要先做归一化或特征工程?
要先划分再处理。归一化的均值方差、编码的类别表这些只能从训练集算出来,然后套用到验证集和测试集。如果先对全量数据做处理再切分,验证和测试的信息就提前渗进了训练过程,评估结果会偏乐观。同理,去重也必须在切分之前完成。
时间序列数据能不能随机切分?
不能。随机切分会让模型在训练时看到未来的数据,评估结果严重失真。正确做法是按时间先后切:用较早的一段训练,中间一段验证,最后一段测试。如果要做交叉验证,用按时间滚动的窗口方式,而不是随机抽折。分组结构明显的数据比如同一用户的多次记录,也要按组切而不是按条切。