模型上板之前①:别急着换模型,精度不够可能根本不是模型的问题
系列:模型上板之前——视觉数据工程实战
摘要
视觉模型精度不够时,很多人的第一反应是换模型、调参数、提高输入分辨率。但实际项目里,问题往往来自数据:场景覆盖不足、困难样本缺失、标签不统一、负样本不足,甚至训练集和验证集存在数据泄漏。本文从常见 Bad Case 出发,聊聊为什么在改模型之前,应该先看看数据。
1. 精度不够,第一反应一定要换模型吗?
做目标检测时,常见的优化路径大概是:
这些方法当然都有效。
但真实项目中,我现在更习惯先做一件事:
把模型预测错误的图片全部翻出来看一遍。
因为很多问题并不是“模型不会”,而是:
训练数据根本没教过它。
例如:
模型现象 | 更应该先检查什么 |
|---|---|
远距离漏检严重 | 远距离训练数据够不够 |
小目标 Recall 很低 | 小目标样本比例 |
夜间性能明显下降 | 暗光数据是否不足 |
某种背景频繁误检 | 是否缺困难负样本 |
A、B 类别总是混淆 | 标签定义是否合理 |
验证集很好,现场很差 | 是否存在数据泄漏 |
模型结构只是问题的一部分。
更完整一点,可以理解为:
而实际工程中,最后两项经常被低估。
2. 数据很多,不代表数据覆盖足够
假设我们已经采了 5000 张目标图片。
乍一看不少。
但仔细统计:
而模型真正部署之后,经常面对:
那模型效果不好其实并不奇怪。
所以相比单纯统计:
一共有多少张图片?
我更关注:
真实部署场景到底覆盖了多少?
例如同一个目标至少应该考虑:
距离;
角度;
光照;
背景;
遮挡;
目标尺寸。
数据量不等于数据覆盖度。
5000 张高度重复的数据,未必比 2000 张覆盖充分的数据更有价值。
3. FN:漏检,先看是不是缺对应数据
模型漏检,也就是 FN,常见在:
小目标;
远距离;
遮挡;
模糊;
暗光;
复杂背景。
比如小目标检测很差。
很多人第一反应是:
加 P2 检测层?
可以。
但建议先统计训练集的小目标占比。
例如:
目标尺寸 | 数量 | 占比 |
|---|---|---|
大目标 | 9000 | 45% |
中目标 | 10400 | 52% |
小目标 | 600 | 3% |
如果小目标只有 3%,那模型小目标效果差,首先很可能是数据问题。
这时候最直接的办法可能不是改网络,而是:
补小目标数据。
4. FP:模型为什么总把背景当目标?
另一个常见问题是误检。
例如把这些东西检测成目标:
一个很容易忽略的问题是:
训练数据是不是几乎每张图里都有目标?
如果是这样,模型见过很多:
但很少见:
所以目标检测不仅需要正样本,也需要:
Hard Negative
例如模型经常把某种地面反光识别成液体,那么下一轮可以专门加入:
整个过程其实很简单:
这已经是一个最基本的数据闭环。
5. 两个类别总混淆,也可能不是模型的问题
假设:
先别急着增加分类能力。
建议先问三个问题。
① 图像上真的能稳定区分吗?
人在现实环境里知道两个物体是什么,不代表摄像头也能稳定看出来。
尤其在:
情况下,很多特征都会消失。
② 标签定义有没有重叠?
如果同一个目标:
那模型收到的监督信息本身就是矛盾的。
③ 业务真的需要区分吗?
如果最后:
那是不是一定需要分成三个模型类别?
这是实际项目里非常重要的一点:
标签不是越细越好,而应该服务于业务。
一个比较合理的过程是:
6. 验证集很好,现场却很差,要警惕数据泄漏
这种情况反而更加危险:
看起来非常漂亮。
但模型部署之后,实际效果却明显没有这么好。
这时候建议优先检查一个问题:
训练集和验证集是不是来自同一段视频?
假设原始视频名称为:
按照视频抽帧后,图片采用“视频名称 + 8 位帧序号”的方式命名:
如果直接对所有图片随机按照 8:2 划分训练集和验证集,就可能出现:
对于固定机位或者运动变化较慢的视频,相邻帧之间往往只有很小的变化:
可能只是目标移动了几个像素,背景、光照、拍摄角度几乎完全一致。
从模型角度来看:
这种情况下,验证指标自然会很好看,但它并不能真实反映模型面对新场景时的泛化能力。
更合理的方式:按照数据来源划分
对于视频抽帧得到的数据,不建议直接在图片级随机划分,而应该尽量按照:
视频;
场景;
采集日期;
采集批次;
采集设备;
进行隔离。
例如有多个独立视频:
可以划分为:
这样可以确保:
最终测试出来的指标可能没有随机划分那么漂亮,但通常更加可信。
对于真实部署项目来说:
一个略低但可信的指标,比一个因为连续帧泄漏得到的高指标更有价值。
7. 为什么我更喜欢看 Bad Case?
Precision、Recall、mAP、F1 都很重要。
但它们只能告诉我们:
模型效果怎么样。
Bad Case 才能进一步告诉我们:
为什么会这样。
例如:
Bad Case | 下一步数据动作 |
|---|---|
小目标漏检 | 补小目标 |
夜间漏检 | 补暗光 |
遮挡漏检 | 补遮挡 |
反光误检 | 补反光负样本 |
A/B 混淆 | 检查标签定义 |
某场景完全失效 | 补该场景数据 |
所以我现在更认可这样的模型迭代方式:
而不是:
8. 补数据,不应该只是“再采 5000 张”
假设第一版模型主要有三个问题:
下一批数据计划就不应该写:
再采 5000 张。
而应该写成:
这就是:
定向补数据
甚至可以把困难样本单独整理:
普通数据让模型知道:
正常目标长什么样。
Hard Case 则是在教模型:
最容易犯错的地方应该怎么办。
9. 那什么时候才应该换模型?
当然,数据不是万能的。
如果已经确认数据覆盖充分,仍然存在明显能力瓶颈,那就应该考虑模型本身。
例如:
输入分辨率不够
如果目标最终只有:
那再补数据也有上限。
需要考虑:
提高输入分辨率;
小目标检测层;
调整网络结构。
模型容量确实不够
场景复杂、类别多、尺度跨度大,小模型也可能真的到极限。
这时候再考虑:
但对于最终要部署到端侧设备上的模型,还有另外一个现实问题:
最终跑到 X5、J5 这类端侧平台上时,我们追求的并不是单纯的最高精度,而是:
之间的平衡。
所以在端侧项目里:
能通过数据解决的问题,通常值得优先通过数据解决。
10. 模型上板之前,我会先检查这些问题
如果模型精度不够,我现在通常会先检查:
数据是否覆盖真实部署场景;
小目标、暗光、遮挡、模糊是否充分;
是否存在大量连续重复帧;
是否有困难负样本;
标签标准是否统一;
类别是否真的可区分;
train / val 是否可能发生数据泄漏;
Bad Case 是否集中在几个固定场景。
如果这些问题还没有答案,我一般不会急着改模型。
因为很可能:
你正在用模型优化,解决一个数据问题。
写在最后
一个真正落地的视觉模型,并不是:
更接近:
所以我现在越来越觉得:
一个视觉模型真正开始变好,不是从换更大的网络开始,而是从知道自己为什么错开始。
下一篇继续聊整个链路更上游的问题:
《模型上板之前②:不要拿着相机乱拍,一套真正能用于训练的数据到底应该怎么采?》
下一篇会重点聊:
距离、角度、光照、背景、目标尺寸、正负样本,以及视频采集过程中最容易产生的无效数据。