作者做施工安全App,mAP50=0.51达标但实际漏检防护背心,根因是指标评估维度与业务需求错配,复盘数据清洗、训练集平衡等工程细节。
我在开发 GroundCheck,一款面向建筑安全管理员的离线优先现场检查应用。我们早期的一个重要赌注是设备端危险检测——一个完全运行在手机上的 YOLO 模型,无需互联网,在你拍照的瞬间就能识别出缺失的安全帽和安全背心。在这方面没有竞争对手;其他所有产品都是云端检测,一旦失去信号就会失灵,而在工地现场信号中断是家常便饭。
这讲述的是一个看起来很漂亮、实际上却问题重重的指标,以及如何发现真相的故事——外加一次被与模型无关的事情搅乱了两次的训练过程。
我们的第一个真正的模型,用一个 10 类分类体系训练(安全帽、背心、口罩、锥桶等),达到了 0.510 mAP50。这超过了我们的内部基准线 0.50。模型上线,功能宣布完成,转战下一个任务。
然后我用一张简单的测试照片跑了一下——六个建筑工人,标准的工地场景,有些戴着安全帽,都穿着高可视背心。模型找到了零件背心。不是"低置信度",是零。它还幻觉出一个本来没戴帽子的人戴着安全帽。
对于一个安全应用来说这是很糟糕的表现,直接推翻了我训练日志里那个"0.510,超过目标"的数字。发生了什么?
mAP50 是一个很容易被误导的指标,如果你只看宏平均的话。我们的 0.510 是跨 10 个类平均的,而这些类底层的实际表现差异巨大:
一个在安全帽和护面罩上表现出色的模型可以把一个坏掉的背心检测器拉到一个看起来不错的平均值。这个数字没有错——只是它没有回答我真正关心的问题:"这对最重要的那些类有效吗?"
教训:单一的聚合指标是一个总结,不是定论。如果你的类不是大致同等简单且同等重要,在相信标题数字之前先看各类分解——如果可以的话,用真实样本跑一下模型并亲眼看看。那个零背心失败我用三十秒就用自己的眼睛发现了;然而在那个本应精确测量这件事的指标里,它是无形的。
做了两个改动:我删除了两个类(NO-安全背心/NO-口罩),它们的训练数据太少,永远不可能训练好——应用现在从"检测到一个人且没有背心框与之重叠"来推断"没穿背心",而不是直接尝试检测 absence,这被发现是一个比它本来需要难得多的学习问题。然后我专门去找了三个新的开源数据集来加强表现不足的类,大致将最差类的验证量增加了两倍。
重新训练。相同的架构(YOLOv8s),相同的目标:超过 0.510,而且这次,验证那些真正重要的类。
这部分与模型无关,全都是关于在偶尔会有其他想法的硬件上运行长时间训练任务的事。有两个问题出错,但它们根本不是 ML 问题:
首先,机器在训练中途重启了(无关的维护),在计划的 200 个 epoch 中杀死了第 134 个 epoch 的进程。可以恢复——检查点能在 kill 后存活,只需从 last.pt 恢复。
其次,更有趣:我专门写来处理此类崩溃的自动恢复脚本有一个 bug。yolo detect train resume=True model=<checkpoint> 应该在中断的地方精确继续。在我的环境里,它静默地没有——它退回 Ultralytics 内置的 4 图玩具数据集而不是我真正的 32,000 图训练集,并愉快地报告成功。没有错误,没有警告。只是一次训练运行悄悄地做着没用的工作,直到我注意到损失曲线看起来干净得可疑才发现。
我之所以 catch 到它是因为进程数看起来不对——一个训练任务应该只有一个 Python 进程,但我看到的是二十五个。顺着这条线追查发现是参数解析器静默地丢弃了我的数据集配置并替换成了自己的默认值。
真正有效的修复:不再信任"智能"恢复,而是每次都做一个平淡的、 boring 的、明确指定的重启——拼写出每一个参数,在走开之前验证日志显示的是我真实的数据集路径,不要依赖一个本应为你推断一切的 flag。boring 且经过验证,永远好过 clever 且静默,当一个后台进程悄悄地失败而不是大声失败时。
重新训练的模型在第 177 个 epoch 左右 plateau 在 0.682 mAP50,仍未达到 0.80 的 stretch goal。我尝试了一个简短的"继续"运行——从最终权重热启动一个新的 40 epoch pass,希望再捞几分。
它让事情变得更糟,立刻且持续——精确度每个 epoch 都在下降。在一个已经过了 178 个 epoch 收敛的模型上重置完整的学习率计划冲击太大;不是微调,而是开始遗忘。一旦趋势明确,在 4 个 epoch 后 kill 掉它,保留原始检查点。有时训练过程的正确做法——就像很多优化问题一样——是认识到你已经找到了一个好的停止点,进一步的调整更可能伤害而不是帮助。
与之前相同的两个检查,只是这次正确地执行了:
在完整验证集上的各类 mAP50:

测试照片。与之前相同的六个工人。这次:正确检测到 4 件可见背心,正确检测到所有 3 顶佩戴的安全帽,正确标记了裸露的头部。不完美——仍有几件背心被漏掉,置信度分数是中等而不是很高——但这是一个真实的、可见的修复。之前悄无声息坏掉的那些类现在真正可用了。
两个不 glamorous 的习惯让这次重新训练免于两次交付一个坏掉的检测器:拒绝在没看各类分解的情况下相信单一的聚合指标,以及拒绝在没有检查具体是否真的做了它声称做的事情的情况下相信自动化恢复机制。两者都不令人兴奋。但它们正是安全功能是否真正有效和只是在没人 double-check 的仪表盘里看起来有效之间的区别。
GroundCheck 是一款面向建筑安全管理员的离线优先检查应用,围绕设备端 AI 危险检测构建,零连接即可工作——因为工地不总是有信号,安全检查不应该等待云端 API。
对于进一步的行动,你可以考虑屏蔽这个人或举报滥用。