模型在自己电脑上跑出训练集和验证集都很漂亮,一上线或一换测试集就掉一大截,这是最常见的「假好」。这篇不解释概念,直接给一套排查顺序:先判断是不是泄漏和划分问题,再看分布与标注,最后才是模型侧的过拟合与调参。每一步都写清看什么、改什么、什么情况下这套判断不适用。
模型在自己电脑上跑,训练集和验证集准确率都很漂亮,一换测试集或者一上线就掉一大截,这是最常见的假好现象。它不代表模型彻底没救,而是说明你看到的分数有一部分是幻觉。这篇不讲概念,直接按顺序排查:先看是不是泄漏和划分姿势不对,再看分布与标注,最后才轮到模型侧的过拟合和调参。
排查要有顺序,因为代价差别很大。数据侧的问题改划分和预处理就能解决,模型侧调参往往要重训,如果顺序搞反,你会在调参上浪费大量时间,而根因一直没动。下面每一步都写清看什么、改什么,以及什么情况下这套判断不适用。
先看清是什么缺口:三种高根本不是一回事
训练高、验证低是经典过拟合,方向明确。训练高、验证也高、只有测试低,才是本篇重点,这两类要分开看。判断前先把三条曲线的数值摆在一起,别只盯着测试那一个数字。
- 确认测试集是独立的第三份数据,还是从验证集里临时切的,或者干脆从训练集里漏出来的;划分方式不同,结论完全不同。
- 差距按绝对百分点看,同时看测试集样本量。只有几十条样本时,错几条带来的波动本身就很大,别急着归因。
- 记录评估口径。类别不平衡时准确率会骗人,先补一份混淆矩阵或分类型指标再下结论。
- 先复现训练时的评估脚本,再换一个评估脚本跑同一份数据,排除脚本本身的口径差异。
| 现象组合 | 最可能的解释 | 先查什么 |
|---|---|---|
| 训练高、验证低 | 过拟合 | 正则、早停、模型复杂度 |
| 训练高、验证高、测试低 | 泄漏、划分或分布问题 | 切分方式、预处理顺序、分布对照 |
| 训练低、验证低、测试也低 | 欠拟合或标签噪声 | 特征、标注质量、样本量 |
| 三条都高但上线差 | 线上线下口径不一致 | 线上输入清洗与截断逻辑 |
第一嫌疑:泄漏与划分姿势不对
按样本随机切分是最常见的坑。同一张图的不同裁剪、同一用户的多次行为、同一段文本的相邻片段,被随机分到训练和测试两侧,等于变相泄漏。模型在训练时见过近似答案,测试时自然分数虚高,换一份真正干净的数据就露馅。
- 按实体分组切分以用户、设备、文档、会话为单位切分,保证同一实体的样本只出现在一侧。验证方式是统计训练集和测试集在实体维度上有没有交集。
- 时序数据按时间切用过去的数据训练,用之后的数据测试,不能随机打乱。验证方式是检查测试集时间戳是否全部晚于训练集。
- 预处理只在训练集上拟合归一化、缺失值填充、特征筛选、目标编码,都要先切分再在训练集上拟合,然后应用到验证和测试。验证方式是检查这些步骤的代码位置是否在切分之后。
- 重采样只动训练集过采样和欠采样同样只在训练集上做,否则测试集分布被人为改动,评估结果不可信。
把上面几条列成清单逐条核对,多数测试掉分能在这步找到根因。不适用的情况:如果模型本身是时序预测或推荐系统,按实体的分组规则需要针对业务再定义,通用的按用户分组不一定合适,得结合数据生成过程判断。
第二嫌疑:分布、标注与线上口径
测试集和训练集本来就可能有分布差异。采集时间、渠道、设备、人群变化,都会让同一模型在两个集合上表现不同。先做基础分布对照,再看标注质量,最后核对线上口径。
| 对照项 | 怎么看 | 差异大的含义 |
|---|---|---|
| 类别比例 | 统计两侧各类占比 | 评测口径不可比,先重采样或分层评估 |
| 缺失率 | 按字段统计两侧缺失比例 | 清洗逻辑不一致,或采集渠道不同 |
| 数值分布 | 对关键特征做分位数对照 | 存在漂移,模型换环境会掉分 |
| 文本长度 | 统计长度分布与截断比例 | 线上截断与离线不一致 |
标注质量要抽查。测试集若复用旧标注,或由不同的人标注,标准漂移会直接体现为掉分。抽几十条人工复核,比调参有用得多。另外,线上口径和离线口径不一致也常被误当成测试集问题:线上输入经过清洗、截断、改写,离线测试用的是原始文本,结论自然对不上。
第三嫌疑:模型侧的过拟合与修复动作
排除前两类之后,才轮到模型本身。训练轮数过多、参数过多、特征过多,都会让模型记住噪声而不是规律。修复动作按代价从低到高排,别一上来就换模型。
- 加正则:权重衰减、Dropout、树模型的深度与叶子数限制,先从这些低成本手段试起。
- 早停:以验证集为准,别偷看测试集。早停的监控指标要和最终评估指标一致。
- 数据增强或补数据:样本量不够时,补数据的收益通常比调超参更稳。
- 类别不平衡时调整损失权重,而不是简单重采样,避免改变数据本身的分布结构。
- 调参纪律:所有选择只看验证集,测试集留到最后跑一次,跑完就不再回头改参数。
不适用的情况:如果模型刚刚换过版本,评估脚本也刚改过,先固定一个可复现的基线再谈过拟合,否则前后的比较没有意义。另外,如果验证集本身也是从训练集里随机切出来的,它对过拟合的指示作用有限,优先把划分方式改对。
收尾核对清单:改完之后怎么确认真的修好了
修完之后不能只看测试集分数变好了。要同时确认三条线合理,并且这套评估流程以后还能重复。下面这份清单建议直接贴到项目文档里。
- 固定划分文件固定随机种子,把切分结果落盘保存,保证每次评估用的是同一份测试集,避免结果来回漂。
- 三条线一起看训练、验证、测试三条线都要合理。测试高但验证低同样不正常,可能意味着测试集本身有泄漏或口径问题。
- 留一份最终测试集把一份从未参与任何决策的数据留作最终判定,上线前只跑一次,跑完不再用它调参。
- 上线后做监控输入分布、预测分布、分类型指标定期对账,掉分时按数据、口径、模型的顺序查,别一上来就重训。
需要换算、成本或模型规格参考时,去站内对应页面核对当时的数字,别用本文的定性描述替代实际数据。评测方法和数据划分相关的更多资料,可以在站内指南中心按关键词找。
下一步如果你正在对比不同模型或中转服务的实际表现,站内的工具目录和可信度检测页面能帮你把评测口径对齐,避免拿不可比的数据下结论。→常见问题
训练集和验证集准确率都很高,只有测试集低,一定是过拟合吗?
不一定。典型过拟合是训练高、验证就低;如果验证也高只有测试低,更常见的是泄漏、划分方式不当或测试集分布不同。排查顺序建议是数据泄漏→划分与预处理顺序→分布与标注→最后才看模型,直接调正则往往解决不了问题。
验证集高测试集低,能不能干脆不用验证集,直接按测试集调参?
那等于把测试集变成了验证集,你会得到一个对这批数据过拟合、上线仍然掉分的模型。正确做法是验证集用来做所有选择,测试集只在定稿时跑一次;如果测试集反复参与决策,就该重新划一份从未看过的最终测试集。
样本量很小的时候,测试集掉几个点正常吗?
小样本上几个样本的错误就能造成明显百分比波动,先算一下置信区间或做多次划分平均,再判断是否真有差距。样本太少时,与其纠结单次分数,不如用交叉验证的均值与方差来看模型是否稳定,具体评估口径可参考站内测评相关页面。