011、检测模型精度上不去?先把标注质量查一遍:错标、漏标、框偏移的排查方法

011、检测模型精度上不去?先把标注质量查一遍:错标、漏标、框偏移的排查方法 011、检测模型精度上不去先把标注质量查一遍错标、漏标、框偏移的排查方法去年有个项目客户给了一堆工业质检数据我调了半个月的YOLOv8mAP卡在0.65死活上不去。换backbone、调anchor、加数据增强能试的都试了结果还不如人家baseline。后来实在没辙拉了一整天的标注文件出来看发现标注框歪得离谱——有的框把背景全包进去了有的只框了目标的一半。改完标注mAP直接跳到0.82。那之后我养成了一个习惯模型训不动先查标注。标注问题比你想的常见很多团队拿到数据就开训觉得标注是标注员的事。但标注质量对检测模型的影响比模型结构、超参数都大。一个错标样本可能在训练时产生几十甚至上百个错误梯度更新。尤其是小目标、密集场景、遮挡情况标注稍微偏一点模型就学歪了。我见过最夸张的案例一个行人检测数据集标注员把“人”和“影子”全标上了模型学到最后看到地上的影子就兴奋。还有一次某个类别只有200个样本其中30个框偏移超过50%模型对这个类别的召回率直接崩到0.1。错标类别标错了模型就学歪了错标是最致命的问题。一个“猫”被标成“狗”模型就会在猫的位置上学习“狗”的特征。如果错标比例超过5%模型基本就废了。怎么查写个脚本把每个类别的标注框可视化出来按类别分组看。别只看单张图要批量看。我习惯的做法是随机抽1000张图把标注框画上去然后按类别排序快速翻一遍。如果某个类别的框里出现大量其他类别的物体那就是错标。代码里可以加个统计每个类别的标注框数量、平均面积、长宽比。如果某个类别的平均面积突然比同类小很多大概率是标错了——比如把“汽车”标成了“自行车”。# 这里踩过坑别只统计数量要结合面积和长宽比defcheck_label_quality(ann_file):importjsonwithopen(ann_file)asf:datajson.load(f)# 按类别统计cls_stats{}forannindata[annotations]:cat_idann[category_id]bboxann[bbox]# [x, y, w, h]areabbox[2]*bbox[3]aspect_ratiobbox[2]/max(bbox[3],1)ifcat_idnotincls_stats:cls_stats[cat_id]{count:0,areas:[],ratios:[]}cls_stats[cat_id][count]1cls_stats[cat_id][areas].append(area)cls_stats[cat_id][ratios].append(aspect_ratio)# 输出异常类别forcat_id,statsincls_stats.items():avg_areanp.mean(stats[areas])avg_rationp.mean(stats[ratios])# 别这样写if avg_area 100: 这种硬阈值不靠谱# 应该和同类别的其他样本比ifstats[count]10:# 检查是否有面积异常小的样本small_samples[aforainstats[areas]ifaavg_area*0.3]iflen(small_samples)stats[count]*0.1:print(f类别{cat_id}有{len(small_samples)}个面积异常小的框建议检查)漏标模型学不到的东西永远检测不到漏标比错标更隐蔽。错标至少还有个框漏标是完全没有标注。模型在训练时看到这个物体会把它当成背景学习“这个特征背景”。等到推理时模型看到同样的物体就会认为它是背景。怎么查最直接的方法用训练好的模型去预测训练集把预测结果和标注结果对比。如果模型在某个区域预测出高置信度的框但标注里没有那大概率是漏标。我写过一个工具把预测框和标注框画在同一张图上预测框用红色标注框用绿色。如果某个区域只有红色框没有绿色框那就是漏标候选。# 这里踩过坑别用模型自己的预测结果去查漏标模型可能已经学歪了# 应该用另一个独立训练的模型或者用预训练模型deffind_missing_labels(model,dataset,threshold0.5):missing_candidates[]forimg,targetsindataset:predsmodel.predict(img)forpredinpreds:ifpred[confidence]threshold:# 检查是否有标注框覆盖这个预测框matchedFalsefortintargets:ioucompute_iou(pred[bbox],t[bbox])ifiou0.3:# 别用0.5漏标的框可能和标注框有部分重叠matchedTruebreakifnotmatched:missing_candidates.append((img,pred))returnmissing_candidates另一个技巧看类别分布。如果某个类别的样本数明显少于预期或者某个场景下的样本数异常少很可能是漏标了。比如“夜间行人”只有10个样本但“白天行人”有1000个那夜间场景大概率漏标严重。框偏移框歪了模型就学歪了框偏移是最常见的问题。标注员手一抖框就偏了。偏移5%以内还能忍超过10%基本就废了。怎么查看标注框的边界是否紧贴目标。我写过一个脚本计算每个标注框内像素的梯度分布。如果框内边缘梯度集中在框的边界附近说明框标得准如果梯度集中在框内部说明框可能偏大了如果梯度集中在框外部说明框偏小了。# 这里踩过坑别用简单的边缘检测要结合目标本身的纹理特征defcheck_bbox_alignment(image,bbox):x,y,w,hbbox# 取框内区域cropimage[y:yh,x:xw]# 计算梯度grad_xcv2.Sobel(crop,cv2.CV_64F,1,0,ksize3)grad_ycv2.Sobel(crop,cv2.CV_64F,0,1,ksize3)grad_magnp.sqrt(grad_x**2grad_y**2)# 计算框边界附近的梯度强度border_gradnp.mean(grad_mag[0:2,:])np.mean(grad_mag[-2:,:])\ np.mean(grad_mag[:,0:2])np.mean(grad_mag[:,-2:])# 计算框内部的梯度强度inner_gradnp.mean(grad_mag[2:-2,2:-2])# 如果边界梯度远小于内部梯度说明框可能偏大了ifborder_gradinner_grad*0.5:return框可能偏大# 如果边界梯度远大于内部梯度说明框可能偏小了ifborder_gradinner_grad*3:return框可能偏小return正常另一个更直观的方法看标注框的长宽比分布。如果某个类别的长宽比集中在几个离散值上说明标注员可能用了固定的模板没有根据实际目标调整。比如“汽车”的长宽比应该在1.2到2.0之间如果全是1.5那肯定有问题。批量排查的实用工具手动一张张看太慢我整理了一套批量排查流程统计异常样本计算每个标注框的置信度用预训练模型预测看标注框和预测框的IoUIoU低于0.5的标出来。聚类分析把标注框的坐标、面积、长宽比做聚类离群点大概率有问题。时序对比如果数据是按时间采集的看标注质量随时间的变化。标注员疲劳时标注质量会下降。交叉验证让两个标注员标同一批数据对比差异。差异大的样本就是问题样本。# 这里踩过坑别用单一指标要综合判断defbatch_check(ann_file,img_dir,model):# 1. 加载标注# 2. 用模型预测# 3. 计算每个标注框的IoU# 4. 找出IoU低的样本# 5. 可视化输出pass# 具体实现略核心思路如上修复标注的实操建议发现问题后怎么修错标直接改类别ID。如果错标比例高建议重新标注。漏标用模型预测结果作为候选人工确认后加入标注。框偏移用模型预测的框作为参考人工微调。或者用分割模型先分割出目标再取外接矩形。别想着一次性全修完。先修影响最大的错标优先其次是漏标最后是框偏移。修完一批训一个模型看看效果再决定要不要继续修。个人经验标注质量这件事永远不要相信“标注员说标好了”。我见过太多团队数据标注花了几个月结果模型训出来效果不好最后发现是标注问题。与其花时间调模型不如先花两天把标注查一遍。一个实用的建议在项目开始前先让标注员标100张图你亲自检查一遍把标准定好。等标注员标完第一批数据再抽检一次。这样能避免后期大规模返工。另一个建议标注规范里要写清楚“模糊目标怎么标”“遮挡目标怎么标”“小目标怎么标”。这些边界情况最容易出问题。最后标注质量检查应该是一个持续的过程不是一次性的。每次模型训完看看哪些样本预测错了分析一下是模型的问题还是标注的问题。很多时候你会发现模型预测错的地方标注本身就有问题。模型精度上不去别急着换网络结构先把标注查一遍。这可能是性价比最高的优化手段。