YOLOv5 目标检测训练完整实践
YOLOv5 目标检测训练完整实践
网上”YOLOv5 教程”一大堆,从环境搭建到训练到部署都有。但没人会告诉你:标注质量差到模型根本训不出来是什么体验?现场 GPU 跑得好好的模型到客户机房延迟 1.2 秒怎么破?这些”破事”才是真做项目时遇到的。这篇写这些。
项目起源:客户一句”能自动识别吗?”
这个项目不是从”我们想用 AI”开始的,是从客户一句”拍照不规范,能不能自动识别?“开始的。
背景:我们做的是燃气行业的巡检系统,巡检人员去现场拍调压箱、井盖这些设备,回来人工检查拍照是否符合规范。但人工检查不靠谱——拍糊了、角度不对、漏拍的情况太常见。客户希望自动识别。
当时我心里的第一反应是:”这个需求不靠谱,照片变化太多,AI 怎么可能都识别?”
后来发现——业务方对 AI 的预期和 AI 的真实能力之间,永远隔着一道鸿沟。这个项目就是学着怎么填这道鸿沟。
第一阶段:数据采集,差点死在起点
第一次数据清洗:扔掉了 40%
我们从客户的真实巡检照片里收集了 2 万张,准备训练。但第一轮数据清洗就让我震惊:
- 重复照片:同一个巡检员上传 5 张几乎一样的图
- 拍照失败:模糊、过曝、角度诡异的图占 30%+
- 无关图:有些图里压根没有设备
第一轮清洗后,2 万张图变成了 1.2 万张。当时团队有人说”数据不够了”——我说”再多采集”,结果质量更差。
教训 1:垃圾数据比没数据更可怕。2 万张里如果有 30% 是错的,模型就会学错。我们后来定了规矩:宁可少 5000 张图,不可放进 1000 张错图。
标注:3 个实习生 vs AI 工具
我天真地以为标注是个简单活——画个框,标个类别,难不成比写代码还难?
结果我错了。
第一次标注让 3 个实习生做,标注完成后我随机抽了 500 张复检,发现严重的标注不一致:
- 同一个设备,有人框”调压箱”,有人框”调压箱顶部”
- 边界框大小差异巨大(同一个井盖,框的面积差 5 倍)
- 漏标(背景里的设备有时候不标)
更糟的是,不同标注员之间没有”标准答案”对照。我们花了 2 周时间重新做:
- 写了一份《标注规范》(A4 纸 6 页,包括每种类别的定义、边界框规则、特殊情况处理)
- 双标注 + 仲裁:每个图两个标注员标,差异大的交给 senior 仲裁
- 随机抽检:每周抽 5% 复检
教训 2:标注看起来是”低技术活”,实际上是 AI 项目最贵的成本。我们这个项目 60% 的人力都花在标注上,不是训练上。
第二阶段:训练,踩过的几个”低级错误”
错误 1:训练集验证集分布不一致
我第一版训练,验证集是在同一批数据里随机切 20% 出来。结果 mAP 高得离谱(0.95+),但拿到现场一塌糊涂。
后来才发现:数据是按”上传批次”组织的,随机切会让”同一批上传的相似图片”分到不同集合,造成数据泄漏。改成”按批次切分”后,验证集 mAP 掉到 0.78——这才接近真实表现。
教训 3:验证集划分方式比模型本身更重要。这一点 AI 教程里很少强调,但生产环境里至关重要。
错误 2:负样本缺失,”无中生有”
第一版模型有个诡异现象:客户上传一张”拍糊的天空”图,模型硬生生框出来一个”调压箱”。
排查后发现:训练集里全是”有设备”的图,模型从没学过”没有设备”的情况。
补了一批”纯背景图”(巡检员拍的空地、墙面、天空)后,这个现象消失了。
教训 4:负样本和正样本同样重要。一个项目如果只看”目标存在”的样本,模型一定会”无中生有”。
错误 3:数据增强过度
为了”提升泛化能力”,我把 mosaic、HSV 变换、随机翻转全开了。结果训练集 mAP 0.92,验证集 0.85,现场表现 0.70。
后来把增强强度降下来,反而泛化能力提升了。
教训 5:数据增强不是越多越好。每种增强都会引入”业务场景里不可能出现的图”,比如 180° 翻转的调压箱(现实中不会有)。
第三阶段:部署——真正的噩梦
训练好模型只是开始,部署才是真正让我加班到凌晨 3 点的部分。
噩梦 1:现场 GPU 推理延迟 1.2 秒
实验室 GPU 跑得好好的模型,部署到客户机房(用的是我们推荐的中端 GPU),单张图推理延迟 1.2 秒。客户直接说”这没法用,巡检员没耐心等”。
排查路径:
- 检查 ONNX 是否转换成功 —— 成功
- 检查是否用了 FP16 —— 没有
- 检查预处理 pipeline —— 找到了:Python 端做 resize 的实现用了 PIL,速度慢
最后做了几件事:
- 切换到 OpenCV 预处理(快 5 倍)
- 启用 TensorRT + FP16
- 批处理(batching)单卡并行
- 输入分辨率降到 416x416(从 640x640)
延迟从 1.2s 降到 80ms。不是模型变了,是 pipeline 变了。
教训 6:推理性能优化 80% 在 pipeline,不在模型。换模型能省 20%,优化 IO/预处理/批处理能省 80%。
噩梦 2:边缘 NPU 转换,模型变成”砖头”
客户有些项目是边缘设备(华为 Atlas、寒武纪),NPU 算力比 GPU 弱很多。模型从 GPU 转 NPU 格式后,直接不识别了。
排查发现:NPU 编译工具链对某些算子(动态 shape、复杂 NMS)支持不完善。最后换了 NMS 简化版 + 静态 shape 才解决。
教训 7:NPU/GPU 不是”通用加速器”。每种硬件的算子支持范围不一样,转换前要查兼容性表。
噩梦 3:Android 离线推理,apk 体积爆炸
客户要求 Android 端能离线推理。模型转 TFLite 后是 14MB,再加上 NDK、依赖库,整个 apk 50MB+。客户”难以接受”。
最后做了:
- 模型 INT8 量化到 3.5MB
- 精简依赖,用 NCNN 而不是 TFLite
- apk 控制在 12MB
教训 8:移动端推理,模型大小是硬约束。先定大小,再倒推用什么模型架构、什么量化方式。
实际效果(不说假话)
项目上线后我们在 3 个客户项目里跑了半年。统计效果是这样的(不是”准确率 99%”,是真实情况):
- 明确场景(光照好、角度标准):识别准确率 90%+
- 复杂场景(夜间、雨天、角度刁钻):识别准确率 60-70%
- 客户最关心的”漏检”(有设备但没识别出来):漏检率约 5%
- 客户最反感的”误检”(没设备但识别成有):误检率约 8%
我没有写”准确率提升 30%”这种数字,因为没有 baseline 怎么对比?客户原来的人工检查准确率都没有严格统计,AI 怎么和它比?
给正在做类似项目的人
- 预算的 60% 留给数据和标注,别都花在模型上
- 训练和部署要同步考虑,别等模型训完才想部署
- 现场数据 比训练集重要 100 倍,能拿到现场数据立刻重新训练
- “准确率” 不要随便承诺,客户对 95% 和 99% 的体感差异远小于你的想象
- “多端部署” 别一上来就做,先把一个端做扎实,再扩展其他端
最后说一句不好听的:现在网上很多”YOLOv5 教程”教你 5 分钟训一个模型,但那不是 AI 落地。真正的落地是数据治理 + 工程化 + 业务理解 + 客户预期管理,缺一不可。
