别急着调参数:YOLO检测效果不好时,应该按照什么顺序排查?
完成螺丝检测Demo的数据采集和标注后我很快开始了第一次YOLO模型训练。原本以为只要数据集准备完成模型训练结束后就能得到一个比较理想的检测结果。但实际测试时我发现模型存在不少问题有些螺丝没有被检测出来有些相似型号会被错误分类螺丝密集排列时还会出现漏检。看到这些结果后我最开始的想法是继续调参数增加训练轮数调整学习率更换更大的模型修改置信度阈值调整数据增强强度。但经过几次训练后模型效果并没有明显改善。后来我才逐渐意识到在工业视觉项目中模型效果不好时最先应该检查的通常不是参数而是任务定义、图像质量、数据分布和标注质量。如果前面的环节存在问题后面无论怎样调参都只能在错误的数据基础上反复训练。因此在后续项目中我逐渐形成了一套比较固定的 YOLO 问题排查流程。一、先不要笼统地说“模型效果不好”很多人在模型训练结束后会直接给出一个结论这个模型效果不太好。但“效果不好”其实并不是一个具体的问题。在开始排查之前首先要明确模型到底出现了什么错误。通常可以分为以下几类。1. 漏检图像中明明存在目标但模型没有检测出来。例如在螺丝计数项目中一张图里实际有 20 颗螺丝模型只检测出了 18 颗那么缺少的两颗就是漏检。漏检通常会直接影响数量统计结果。如果系统要求根据螺丝数量判断是否缺料那么只漏掉一颗就可能导致整次检测结果错误。常见原因包括目标在图像中占用的像素太少螺丝之间发生遮挡或重叠金属表面反光导致局部纹理丢失训练集中缺少类似场景标注数据中存在漏标置信度阈值设置过高输入图像缩放后小目标特征被进一步压缩。2. 误检图像中本来不是目标的区域却被模型识别成了目标。例如夹具被识别成螺丝金属反光区域被识别成螺丝头背景中的圆形结构被模型错误检测两颗重叠螺丝之间的区域被重复识别。误检通常和以下因素有关缺少纯背景图片背景纹理和目标过于相似标注框中包含了过多背景训练场景过于单一置信度阈值设置过低。3. 类别混淆模型能够检测出目标但预测的类别不正确。在多类别螺丝识别项目中这类问题尤其常见。不同型号的螺丝可能只在长度、螺帽形状、螺纹结构或者局部尺寸上存在细微差别。如果这些特征在图像中不够明显模型就很容易将 A 型号识别成 B 型号。类别混淆通常和以下因素有关类别之间外观差异太小类别定义本身不够清晰某些类别样本数量不足图像分辨率无法体现关键差异关键特征被遮挡类别标签存在错标。4. 重复检测同一个目标被多个检测框重复识别。这类问题通常需要检查NMS 阈值是否合理两个预测框的重叠程度目标是否出现严重遮挡后处理代码是否正确模型输出解析是否存在问题。只有先判断问题属于哪一种后续的排查才有方向。二、第一步确认任务定义是否合理在检查数据和模型之前还需要先确认一个容易被忽略的问题这个任务是否真的适合按照当前方式进行目标检测例如在螺丝混料识别项目中需要提前明确以下规则相互重叠的螺丝是否必须全部识别只露出一部分的螺丝是否计数位于图像边缘、目标不完整的螺丝是否参与判断两种外观非常相似的螺丝能否仅通过当前拍摄角度区分混料判断依据是“出现其他类别”还是“数量和类别同时满足条件”同一颗螺丝出现不同姿态时是否仍然属于同一个类别如果这些规则没有提前统一那么数据标注人员、算法人员和现场使用人员可能会对同一张图片得出不同结论。例如一颗螺丝只有一半位于图像中标注人员认为它不完整因此没有标注算法人员认为只要出现就应该检测现场人员又希望它能够计入数量。这种情况下模型很难学到稳定的判断标准。所以工业项目首先要制定的不是训练参数而是检测规则和标注规范。三、第二步检查原始图像质量确认任务定义后我通常会先检查原始图片而不是马上打开训练曲线。因为对于工业视觉项目来说图像质量往往决定了模型能够达到的上限。这个项目使用的是海海机器人 500 万像素工业相机。虽然相机分辨率并不低但相机像素高并不代表目标特征一定清晰。真正需要关注的是目标在最终图像中到底占了多少像素。1. 检查目标尺寸假设原始图像分辨率较高但训练时统一缩放到 640×640。如果某颗螺丝在原始图像中本身就很小经过缩放后可能只剩下几十个像素。此时螺纹、螺帽和长度差异都会被进一步压缩。因此需要检查最小目标的宽度和高度是多少缩放到训练尺寸后还剩多少像素不同类别的关键差异能否保留是否需要提高训练输入尺寸是否需要调整相机工作距离或镜头焦距。2. 检查对焦工业相机安装完成后需要确认整个检测区域是否都处于清晰范围内。如果图像中心清晰但边缘模糊那么位于边缘的目标就更容易漏检。需要重点观察螺丝边缘是否清晰螺纹结构是否能够分辨图像四角是否失焦不同高度的目标能否同时保持清晰相机或工件振动是否造成运动模糊。3. 检查曝光和反光螺丝属于金属零件表面容易产生高亮反光。如果局部区域过曝原本应该存在的纹理和边缘可能会完全消失。模型看到的就不再是完整螺丝而是一片接近纯白的区域。除了过曝还需要检查欠曝。当整体亮度过低时深色螺丝和背景可能无法形成足够对比。这时需要从成像端进行优化例如调整曝光时间调整光源角度使用漫射光使用环形光或穹顶光调整相机增益必要时考虑偏振方案。在工业视觉中相机、镜头和光源并不是模型之外的独立部分它们共同决定了模型最终拿到什么样的数据。如果前端成像质量很差后端模型通常很难完全补救。四、第三步检查标注质量确认图像质量没有明显问题后下一步是检查标注。相比训练参数标注质量对模型结果的影响通常更加直接。1. 检查是否存在漏标漏标指图像中存在目标但对应目标没有标注框。这是目标检测任务中非常严重的问题。因为在训练过程中没有被标注的真实目标会被模型当作背景。如果漏标数量较多模型就会收到互相矛盾的训练信号在某些图片中这种外观是螺丝在另一些图片中相同外观却被当作背景。最终模型很容易出现漏检。对于密集排列的螺丝图片漏标尤其常见。因为目标数量多、相互遮挡人工标注时很容易遗漏其中一颗。2. 检查是否存在错标错标主要包括两种情况第一种是类别错误。例如A 型号螺丝被错误标注成 B 型号。对于本来就外观相似的类别少量错标也可能明显增加类别混淆。第二种是目标区域错误。例如标注框只框住了螺丝头标注框没有包含完整螺丝标注框包含了相邻螺丝的一部分标注框偏离了真实目标。3. 检查标注框是否统一目标检测的标注框不一定要追求极端贴合但必须保持规则一致。不能在同一个数据集中出现以下情况有些框紧贴目标有些框包含大量背景有些框标完整螺丝有些框只标螺帽有些遮挡目标被标注有些相似遮挡目标又没有标注。模型并不知道哪一种标注方式才是正确的它只能从数据中寻找规律。标注标准越混乱模型学习难度越大。4. 制定遮挡目标的标注规则对于螺丝重叠场景需要提前制定统一规则。例如可见面积超过一定比例时进行标注严重遮挡且无法判断类别时不标注位于图像边缘但仍能确认类别时继续标注两颗螺丝相互重叠时分别标注无法区分类别的目标不强行标注为某一类。具体规则可以根据项目要求调整但必须保证整个数据集执行同一套标准。五、第四步检查数据集分布标注没有明显问题后还需要检查数据集的分布是否合理。很多数据集看起来图片数量不少但真正有效的信息非常有限。例如采集了 2000 张图片但这些图片可能都是同一个背景同一种摆放方式同一个曝光参数同一个目标数量同一种光照状态相邻时间连续拍摄的高度相似图片。这种数据集虽然数量多但场景覆盖不足模型很容易过拟合。1. 检查类别是否均衡假设一个数据集中A 类螺丝有 5000 个B 类螺丝有 3000 个C 类螺丝只有 300 个。那么 C 类通常更容易出现漏检和误分类。需要分别统计每个类别的图片数量标注框数量单张图中的目标数量不同姿态数量遮挡样本数量反光样本数量密集排列样本数量。不能只看总图片数量。2. 检查困难样本是否足够工业现场真正容易出问题的通常不是标准样本而是困难样本。在螺丝检测中困难样本主要包括螺丝相互重叠螺丝紧密排列螺丝位于图像边缘金属表面强反光局部阴影不同方向和角度背景出现相似结构少数类别和相似类别。如果训练集中大部分都是排列整齐、光照均匀、目标完整的图片那么模型在标准测试图片上可能表现很好但到了真实现场就容易失败。3. 检查是否有负样本负样本是指不包含目标的背景图片或者包含容易被误识别结构的图片。例如空托盘夹具金属垫片圆形孔洞局部强反光与螺丝外观相似的零件。适当加入负样本可以帮助模型学习“什么不是螺丝”降低误检率。4. 检查训练集和验证集是否存在数据泄漏如果一段连续采集的视频被拆成图片然后相邻帧分别进入训练集和验证集那么训练集和验证集中的图片可能几乎完全相同。这种情况下验证指标可能看起来很好但并不能代表模型具有真正的泛化能力。更合理的划分方式是按照不同采集批次不同日期不同工件批次不同光照状态不同摆放场景进行划分而不是简单随机打乱所有图片。六、第五步分析指标而不是只看总mAP数据检查完成后才进入训练结果分析。很多人训练 YOLO 后首先关注的是 mAP。但在工业项目中只看一个总体 mAP 往往不够。1. PrecisionPrecision 表示模型预测出来的目标中有多少是真正正确的。可以简单理解为模型说“这里有螺丝”时有多大概率是真的。Precision 较低通常意味着误检较多。2. RecallRecall 表示实际存在的目标中有多少被模型成功检测出来。可以理解为图像中所有真实螺丝模型找回来了多少。Recall 较低通常意味着漏检较多。在螺丝计数项目中我会更加关注 Recall因为漏掉一颗螺丝就会直接导致计数错误。不过这并不代表 Precision 不重要。如果误检出一个不存在的目标同样会影响最终数量。因此实际项目需要在 Precision 和 Recall 之间寻找平衡。3. 分类别查看指标总体 mAP 可能会掩盖某些类别的问题。例如A 类检测效果很好B 类检测效果很好C 类效果非常差。由于 A 类和 B 类样本数量更多最终总体指标仍然可能比较高。因此需要分别查看每个类别的PrecisionRecallAP误检数量漏检数量。4. 查看混淆矩阵对于多类别螺丝识别混淆矩阵非常重要。它可以帮助判断哪两个类别最容易混淆某个类别是否经常被识别为背景某个类别是否大量吸收其他类别类别混淆是否具有固定规律。如果 A 类经常被识别成 B 类不一定要立即修改网络结构。首先应该回到原始图片中查看A 和 B 的关键区别是什么当前拍摄角度能否看到这个区别图像分辨率是否足够两个类别是否存在错标样本数量是否均衡。5. 不要只看训练曲线训练损失持续下降不代表模型一定能够正常交付。验证指标很高也不代表所有工业场景都能稳定检测。除了曲线和指标还必须查看实际预测图片尤其是失败样本。工业项目最终交付的不是一个漂亮的 mAP而是稳定可靠的检测结果。七、第六步逐张分析错误样本当模型出现问题时最有效的方法之一就是将所有错误图片单独保存并分类。通过这种方式可以逐渐看出模型错误是否具有规律。例如漏检是否主要集中在强反光场景类别混淆是否只发生在某两个型号之间小目标是否普遍检测困难图像边缘目标是否更容易被忽略误检是否总是出现在同一种夹具上。如果模型错误具有明显规律那么优化方向通常已经比较清楚。八、第七步有针对性地补充数据发现问题后不能只是继续随机采集大量图片。有效的数据补充应该围绕模型错误进行。例如如果强反光场景漏检应该补充不同反光位置不同曝光程度不同螺丝姿态不同光源亮度局部过曝但仍可识别的样本。如果密集排列时漏检应该补充不同数量的密集排列不同重叠程度不同方向组合部分遮挡目标紧贴的场景。如果两个类别经常混淆应该重点采集能够体现二者差异的图片。例如两种螺丝主要区别在螺帽那么就要确保螺帽区域清晰螺帽没有严重反光不同角度下仍能体现区别两个类别样本数量相对均衡。如果背景容易误检应该补充对应背景负样本而不是继续增加标准螺丝图片。数据补充不是继续随机拍照而是根据模型错误有针对性地增加困难样本。九、第八步最后再调整训练参数只有完成前面的检查后才应该开始系统调参。此时调参才是有依据的而不是盲目尝试。可以重点检查以下内容。1. 输入图像尺寸如果目标较小提高训练和推理输入尺寸可能有帮助。但输入尺寸越大通常会带来训练速度下降推理耗时增加显存占用增加TensorRT 部署成本提高。因此需要根据目标尺寸和实时性要求进行权衡。2. 模型大小更大的模型通常具有更强的特征提取能力但不一定能解决所有问题。如果类别区分特征在原始图像中根本不存在更换更大的模型也无法创造出这些特征。同时大模型还可能带来推理速度下降部署资源增加过拟合风险提高。3. 训练轮数训练轮数太少可能导致模型尚未收敛但训练轮数并不是越多越好。需要结合训练损失验证损失PrecisionRecallmAP实际预测结果共同判断。如果训练集指标持续提高而验证集指标开始下降说明模型可能出现过拟合。4. 数据增强Mosaic、MixUp、随机缩放、旋转、亮度变化等数据增强能够提升泛化能力但增强强度需要符合真实工业场景。例如现场螺丝不会发生严重透视变形就没有必要使用过强的透视增强。如果增强后的图片已经明显偏离真实成像分布反而可能干扰模型学习。5. 置信度阈值和NMS阈值这两个参数属于推理后处理参数。降低置信度阈值通常可以提高 Recall但也可能增加误检。提高置信度阈值通常可以减少误检但可能增加漏检。NMS 阈值则会影响重叠检测框的保留情况。因此阈值不能只根据单张图片调整而应该在完整测试集上进行统计。十、部署后还要检查训练与推理是否一致有时模型在 Python 中测试效果正常但导出 ONNX、转换 TensorRT 并集成到 C 上位机后检测结果明显下降。这时问题不一定出在模型本身还要检查部署流程。常见问题包括图像通道顺序错误RGB 和 BGR 混用图像归一化方式不一致Resize 和 Letterbox 处理不一致输入尺寸不一致输出张量解析错误坐标映射回原图时计算错误置信度计算方式不一致NMS 实现不同FP16 或 INT8 转换带来精度变化C端与Python端使用了不同阈值。因此在部署前后应该使用同一批图片分别进行对比测试。建议至少对比预处理后的输入数据模型原始输出检测框坐标类别编号置信度NMS 后的最终结果。只有确认 Python、ONNX、TensorRT 和 C 各阶段结果基本一致才能排除部署实现问题。