训练集与测试集划分全指南:避开过拟合与数据泄露的坑 📅 发布时间:2026/9/16 20:21:32 👁 浏览次数: 很多新手都会遇到一种特别诡异的场景训练过程中损失值降得很漂亮验证集上的指标也说得过去结果一到测试集上就原形毕露。你以为是模型过拟合正则化、Dropout、早停轮番上阵折腾半天也没多大改善。其实问题往往不在模型而在你对训练数据集和测试数据集的理解与操作上。这个系列写到第10篇终于到了我认为整个AI入门阶段最容易被轻视、却又最容易埋雷的环节。很多教程会把训练集、测试集当成一个理所当然的概念划分完就开训但实际做项目时你会发现数据集的构建方式、划分策略、使用边界几乎决定了你最终模型的上限。这篇文章我会把训练集和测试集从原理到实操掰开揉碎讲清楚包括怎么采集清洗数据、几种划分策略分别适用什么场景、测试集污染是怎么悄悄发生的以及如何用测试结果反过来指导数据迭代。内容适合正在用YOLO、分类网络或任何监督学习框架训练自己数据集的人无论你是刚入门的小白还是已经跑通几个开源项目的进阶玩家这篇都能帮你少踩几个大坑。1. 训练集和测试集到底在解决什么问题1.1 一个直观但容易误导的类比很多人喜欢把训练集比作习题册把测试集比作期末考试卷。这个类比基本方向没错但有一个关键点被忽略考试的目的是检验你学会了知识而不是检验你背下了某道题的答案。如果习题册和考卷用的是同一批题目你考了满分也不能说明能力只能说明记忆力好。模型训练也是这个道理。训练集是让模型去学的数据测试集是检验它学没学会的数据。如果两者混在一起或者划分不干净模型就可能不是在学习规律而是在背答案。这就是所谓的过拟合——表面上训练指标非常好一到真实场景就崩。我以前带过一个实习生训练一个二分类模型拿到的准确率高达99%。结果部署到线上面对真实用户数据准确率直接掉到72%。后来排查发现他把整个数据集做了增强处理之后才划分训练测试集导致测试集里出现了大量和训练集几乎重复的增强图片。模型的好成绩完全是背答案背出来的。1.2 为什么不能简单套用固定比例网上随便一搜最常见的数据集划分建议就是7:3或者8:2。这个经验值有一定道理但如果你真在任何场景下都套用大概率会出问题。划分比例真正要权衡的是两方面训练集越大模型见到的样本越丰富学得越充分但测试集也不能太小否则评估结果不稳定你对模型真实水平的判断就不可靠。给你一个直观的例子假设你只有100张图片按8:2划分测试集只有20张。这20张里哪怕只有一张被误分准确率就掉了5个百分点。你用这个结果去判断模型好坏误差范围大得离谱。但如果你的数据集有100万张图片哪怕只拿出5%做测试集也有5万张评估结果就非常稳定。我的建议是样本量很小的时候先别急着留固定的测试集优先考虑交叉验证后面会细讲样本量足够大时测试集也未必需要绝对比例很大够用就行。关键是要让测试集的样本量能支撑你对模型做可靠判断。1.3 验证集训练集和测试集之间不可或缺的第三者严格来说一个完整的训练流程会涉及三个数据集合训练集、验证集、测试集。很多人会在入门阶段忽略验证集直接把训练集当验证集用这是另一个常见的坑。三个集合的分工是这样的训练集用来更新模型的参数权重。验证集用来做模型选择、调超参数、判断何时早停。测试集只在最终评估时使用一次用来模拟模型面对完全未见过的数据时的表现。用考试类比训练集是日常作业验证集是模拟考测试集才是真正的高考。你可以根据模拟考成绩调整复习策略但如果你根据高考成绩去调整复习方向那显然是来不及的而且这行为本身就不合理。实际操作中很多人会拿测试集反复调参今天测一下改改学习率明天测一下换换网络结构测了十几次终于调出了一个好结果然后宣布模型精度很高。这本质上已经是在拿测试集当验证集用了最终的测试结果严重虚高放到真实场景一定会打折。正确做法是用训练集训练用验证集调参模型定型后再用测试集做一次最终体检。2. 如何构建一份能真正训练出好模型的数据集2.1 数据量多少张才够没有标准答案但有经验值不管是YOLO目标检测还是图像分类被问到最多的问题就是我到底要准备多少张图片这个问题的标准答案只有一个看任务复杂度。但如果你需要一些可参考的经验值我可以给你一组我自己实践下来还算靠谱的基准。对于图像分类任务如果类别之间的差异非常明显比如猫和狗、汽车和自行车每个类别有500张以上原始图片配合合理的数据增强通常能训练出一个可用的模型。如果类别差异细微比如不同品种的狗、不同型号的零件每个类别建议准备2000张以上。对于目标检测任务因为每个目标还需要精确的标注框复杂度更高一般来说每个类别至少要有1000个标注实例各种尺度、角度、遮挡情况都要覆盖到。这里要引入一个核心概念数据集的多样性比绝对数量更重要。你有1万张几乎一模一样的猫的照片不如有1000张不同背景、不同光线、不同姿态、不同遮挡程度的猫的照片。模型真正学到的是类别之间的边界而这个边界是靠各种变化条件下的样本共同支撑起来的。2.2 数据清洗把脏数据挡在训练之前很多开源数据集直接下载下来就能用但自己构建数据集时最花时间的往往不是采集而是清洗。这里说的清洗包括三类工作。第一类是去除错误样本。标注框对不齐、类别标错、同一张图里目标被遮挡超过一半导致标注框严重偏离——这些样本不但让模型学不到正确特征还会干扰训练稳定性。检查方法很简单但很耗时用标注工具逐张过一遍或者用训练好的模型辅助预标注后再人工修正。第二类是处理重复和近重复样本。从视频里抽帧的话连续几十帧可能只有微小的位置变化。这些高度相似的样本本质上等效于一个样本反复出现还会让模型对特定帧产生过拟合。抽帧时建议每隔N帧抽一次或者按帧间差异度去重。第三类是类别平衡问题。真实场景的数据往往呈现长尾分布少数类别拥有大量样本大部分类别样本稀少。直接拿这种数据训练模型会严重偏向头部的类别。处理方法有三种对少数类别过采样重复采样或做增强、对多数类别欠采样、或者在损失函数上给少数类别更高权重。我的经验是先做欠采样去掉一些冗余的多数类样本再对少数类做有针对性的增强效果通常比单纯靠损失函数权重更好。2.3 数据增强一条必须画在训练集内部的线数据增强是扩充数据集的利器尤其在小数据集上几乎能翻倍提升模型表现。但这里有一条铁律增强只能应用在训练集上测试集必须保持原始数据的分布。很多入门资源会把数据增强讲成一种提升模型泛化能力的手段但很少有人提醒增强后的图片和原始图片在像素层面存在很强的相关性。如果在划分训练测试集之前就做了增强增强后的图片很可能同时出现在训练集和测试集里这会导致测试结果虚高。我前文提到的实习生案例里就是先用了随机翻转、随机裁剪、色彩抖动做了5倍增强然后再划分数据集。测试集里充满训练集图片的变体模型相当于提前见过了考试题。正确的做法是先把原始数据按策略划分为训练集和测试集再在训练流程中实时对训练集做增强也就是在线增强。例如YOLO系列训练时使用的Mosaic、MixUp、HSV扰动等都是实时作用在训练数据上的不会污染测试集。2.4 标注质量决定模型能力上限的隐形因素如果说数据是模型的天花板那标注质量就是支撑这个天花板的柱子。标注不准确的数据轻则让模型收敛变慢重则让模型学到错误模式。我见过一个比较典型的例子一个项目要检测流水线上的瓶盖缺陷标注时把瓶盖表面轻微划痕和瓶盖正常归为一类的边界搞得非常模糊不同标注员的判断标准还不统一。训练出来的模型在测试集上表现尚可但上线后几乎每天都有漏检或者误报因为生产环境中的光线、角度变化让那些模糊边界问题集中暴露了出来。所以如果条件允许建议至少让两个人独立标注同一批样本然后计算标注一致性比如用Cohens Kappa系数或者检测场景下对比IoU不一致的地方再让第三个人复核。这会很费时间但对数据集质量带来的提升是值得的。即便你一个人做标注也要给自己定一套明确的标注规范什么情况算遮挡、什么程度算缺陷、类别边界在哪里然后严格执行。3. 数据集划分的三种策略按场景选不是按习惯选3.1 随机划分最常用但未必最适合你随机划分就是直接把全量数据随机打散后按比例切分。实现简单代码一行就能搞定。但在有些场景下随机划分会给你一个虚假的信心。最典型的就是视频抽帧数据。假设你要做一个车辆检测模型从一段城市道路监控视频里抽了5000帧作为数据集。如果随机划分训练集和测试集那么测试集里会有大量和训练集高度相似的连续帧。比如视频第100帧在训练集第99帧和第101帧很可能就在测试集里。三帧画面上车辆位置只移动了几个像素背景几乎一样。模型在测试集上的表现当然会很好但换个路段、换个时间可能立刻原形毕露。这种问题的本质是样本不独立。视频帧之间存在强时序相关性随机划分破坏了训练集和测试集要来自独立分布这一前提。3.2 按视频序列或时间戳划分评估泛化能力的正解如果你的数据天然带有时间或序列属性比如视频帧、股票K线、传感器时序数据正确的做法是按序列切分而不是按单帧随机切分。具体操作上你可以把整个视频序列按时间切成两段前80%的帧作为训练集后20%的帧作为测试集。或者按视频ID划分如果有多个不同场景的视频确保同一个视频的所有帧只会出现在其中一个集合里。这样做的好处是测试集里的样本和训练集样本不再存在直接的邻居关系考验的是模型真正学到了目标物体的通用特征而不是记住了某个特定画面的背景信息。代价是测试难度变大了指标通常会比随机划分低几个点——但这才更接近模型上线的真实表现。如果你在用Scikit-learn可以用GroupShuffleSplit这类支持组划分的工具按视频ID分组切分。如果用的是PyTorch或自定义流程手动按组切也不复杂核心就是保证分组逻辑在划分前就确定好。3.3 按场景或域划分检验模型的真实鲁棒性还有一种更严苛的划分方式让训练集和测试集来自不同的数据分布。比如训练集里全是白天晴天的街景测试集里放夜间、雨天、雾天的图像。或者训练集来自A城市的道路测试集来自B城市的道路。这种划分策略不会让模型指标好看甚至会很难看但它能回答一个关键问题我的模型能不能在真实场景中落地这本质上是在做领域泛化能力的检验。如果你做的项目要部署到不可控的真实环境我非常建议用这种方式多测几次。哪怕最终指标不够理想你也知道了模型的短板在哪里它是对光照变化敏感还是对背景环境变化敏感抑或对不同角度拍摄的目标敏感。带着这些信息再去补充数据远比盲目堆样本量高效得多。3.4 小数据集的保底方案K折交叉验证当你的数据量很小留出固定测试集太奢侈时K折交叉验证几乎是唯一靠谱的选择。做法是把数据分成K份常用5或10每次取其中1份作为验证集其余K-1份作为训练集训练K次每次验证集都不同最终把K次验证结果取平均。这样每个样本都参与过训练也参与过验证对模型真实水平的估计更稳定。使用交叉验证时有两点提示。第一如果数据不独立比如来自同一视频序列分组时仍然要按组逻辑切分比如GroupKFold不能直接随机分K份否则问题依旧。第二交叉验证适合在小数据集上做模型选型和参数调优等确定了最终模型和超参数后再用全部数据重新训练一次供部署使用。4. 测试集污染的几种常见路径你以为你测了其实你在骗自己4.1 信息泄露测试集绝对不能参与任何决策测试集污染这个词听起来很专业说穿了就一句话测试集中的任何信息包括数据本身、数据分布、评估结果都不能反过来影响你的建模决策。实际项目里最常见的污染路径有三个。第一种是拿测试集反复调超参数。很多人在训练时发现指标不理想就改一下学习率、换一下网络深度然后立刻在测试集上测。每测一次测试集的信息就泄露一次。测几十次之后模型可能已经在隐式地记住了测试集的分布特征。这时候测试集作为未知数据的模拟意义就消失了。第二种是在测试集上做观察后处理。比如发现测试集里某个类别经常被误分就针对性地调整分类阈值甚至后处理规则。这依然是让测试集影响了你的决策。第三种更加隐蔽用整个数据集做标准化或归一化。如果你的归一化参数均值和方差是全量数据算出来的那测试集的信息已经悄悄流入了训练流程。正确做法是只在训练集上计算归一化参数然后用这些参数去转换验证集和测试集。4.2 先增强后切分很多视频教程最爱犯的错我前面反复提到这一点因为它实在是太常见了。不少教程为了让效果看起来更好会先对整个数据集做增强扩充然后才划分训练测试集。这样确实能把测试集指标做得非常漂亮但本质上模型在测试集上看到的大部分图片都是训练集图片的换皮版本评估结果严重失真。一个判断方法很简单在测试集上随机挑几张增强后的图片看看能不能在训练集里找到对应的原图。如果能找到那这个划分方案就有问题。4.3 标注风格不一致测试集标注和训练集标注来自不同的人标注质量对测试结果的影响比很多人想象中大。如果训练集和测试集是不同的人标注的而两人的标注风格差异明显比如一个人喜欢把检测框画得紧一些另一个人画得松一些那模型在测试集上的mAP可能会受到额外干扰。处理思路有两种一种是在划分前统一标注风格由同一个人或同一套规则复核全量标注另一种是用IoU阈值适当的后处理比如NMS参数调整来消化标注风格差异但这属于治标不治本。最稳妥的办法还是在数据划分前制定清晰的标注规范并在全量数据上执行同一套标准。4.4 数据去重遗漏互联网数据集的经典陷阱很多人会选择从互联网上爬图片来构建数据集。这时候一个特别容易踩的坑是重复样本同一张图片可能被不同网站以不同文件名、不同尺寸保存爬下来之后如果不做去重它可能既出现在训练集又出现在测试集。处理办法是在划分前做感知哈希Perceptual Hash去重或者更简单一点用图片文件的MD5值先做一层去重再用相似度计算做第二层去重。如果数据量比较大可以先粗后细MD5去掉完全相同的再用感知哈希去掉视觉上几乎一样的。5. 用测试集做评估的正确姿势指标怎么选、结果怎么读5.1 别让准确率骗了你从精度、召回率到F1分类任务中最常用的指标是准确率Accuracy但它有一个致命缺陷在类别不平衡时严重失真。假设99%的样本是A类1%是B类模型全部预测为A类准确率是99%看起来非常好可这个模型对B类完全无效。正确做法是同时关注精确率Precision、召回率Recall和两者的调和平均F1值。精确率回答的是模型预测为正类的样本里有多少预测对了召回率回答的是所有真实的正类样本里模型找回来了多少。实际场景里精确率和召回率往往此消彼长。以缺陷检测为例如果你更在意漏检正类没有被找出来就优先提高召回率如果你更在意误报把正常品判为缺陷就优先提高精确率。具体需要通过调整分类阈值来平衡这时候绘制的PR曲线Precision-Recall Curve能帮你直观地看到不同阈值下的权衡。5.2 目标检测场景mAP不是唯一的答案如果你在用YOLO或Faster R-CNN这类检测模型官方输出的指标里最显眼的是mAP。但mAP只是参考它不是全部。我建议你看评估结果时分三步走。第一步看不同IoU阈值下的AP变化。mAP0.5和mAP0.5:0.95是两种常见口径。前者只要求预测框和真实框有50%的重叠就算正确后者要求更严格从50%到95%的多个阈值取平均。如果你的mAP0.5不错但mAP0.5:0.95很差说明你的定位精度不够框的位置大体对但不够精细。第二步按类别看AP。mAP是所有类别的平均但平均数字好看不代表每个类别都好。很可能某一个大类别的AP很高拉高了平均值另一个稀缺类别的AP低得吓人。按类别拆开才能发现模型的偏科问题。第三步结合PR曲线看置信度阈值。测试集上的PR曲线可以告诉你哪些类别容易混淆以及不同置信度阈值下精度和召回率的实际情况。这对接下来的阈值设定和后处理策略非常重要。5.3 从测试结果反推数据问题测试集不只是用来打分的测试集最容易被低估的价值是诊断功能。当测试结果不理想时不要急着调模型结构先回到数据层面检查几件事。如果整体指标差先看测试集里是否有训练集覆盖不到的新场景、新角度、新光照条件这往往意味着你的训练集多样性不够。如果某个类别指标特别差先数一下这个类别在训练集中有多少样本如果严重不足优先补这个类别的数据。如果误报严重去看看误报样本长什么样很可能是背景干扰或者类别边界定义模糊导致。我自己的习惯是每次测试集评估结束后把错误样本按类别、按原因分组保存截图整理成一份错误分析文档。这份文档比测试报告本身更有价值它能直接指导下一轮的数据迭代方向。5.4 测试集客观性一旦模型定型尽量只测一次最后再强调一个原则性问题测试集只应该在你认为模型已经定型后使用一次。如果测完发现还有提升空间可以回去改模型、补数据但测试集本身不应该成为你反复迭代的目标。如果你在测试集上反复测试并持续改进最终你得到的模型其实已经间接拟合了测试集。这个时候测试集的评估结果只是最后一次实验的记录而不是模型泛化能力的无偏估计。这就像一个学生反复做同一套模拟卷做到最后每次都满分但这并不能证明他掌握了所有知识点只能证明他把这套卷子背熟了。实际操作中我一般会把数据集拆成训练集、验证集、测试集三部分后把测试集锁起来——平时完全不去碰它只在最终评估时解开。如果模型要发布或者要做技术决策时再用测试集做最终检验。回到我开头提到的那个现象——训练和验证表现很好测试集上一测就崩。现在你应该知道这种情况大概率不是模型的锅而是数据集操作流程出了问题。要么是划分策略不对随机划分了有序列相关性的数据要么是信息泄露增强数据混进了测试集、全量标准化、用测试集调参要么是数据本身有问题标注风格不一致、类别分布恶劣。我自己做了这么多年AI项目最大的体会是大部分人愿意在模型结构上花时间研究各种网络、各种注意力机制却不太愿意认真打磨数据。但实战中你最终会发现模型结构带来的提升可能只有一两个百分点而数据集的质量、划分的严谨程度动辄就是十个点以上的差距。尤其是当你开始用真实业务数据替代公开数据集做训练时训练集和测试集的管理就直接决定了项目能不能从实验室精度走到线上可用。下一次当你准备训练自己的数据集时从采集、清洗、标注一路走到划分每一步都多问一句这一步操作会不会让测试集不再干净如果答案是否定的那你的测试结果就值得信任。后续这个系列我会接着讲数据标注工具的选择、以及如何用测试集的评估结果快速定位数据问题如果你也正在被数据集折腾可以先从这篇文章里的几个检查点入手排查一遍。