目标检测炼丹经验总结

最近因为工作原因系统地摸了一下目标检测,也在生产环境部署了一波。公司的数据当然是不能放出来的,记录一些心得帮后来人少走弯路吧。

结论放在最前:在torchvision官方的预训练模型里,fasterrcnn/maskrcnn指标比fcos更高,但在本文进行的所有实验中fcos显著强于其他模型,目前达到的效果:考虑类别的mAP 0.535,不考虑类别0.636。

实验说明:以下结论依赖公司内部训练数据,测试结果套用COCO API取得,报告mAP为mAP50(即预测和groundtruth的IoU匹配阈值取0.5),并非mAP50:95。我司使用的数据比COCO大很多也难很多,所以指标绝对值参考意义不大,看相对提升即可。

  1. 模型设计
    a. 骨干网络
    i. 骨干网络性能越强越好
    1. resnext > resnet > mobilenet。从论文看ViT > CNN,但我没有尝试。
    2. resnext50_32x4d效果优于resnet50,收敛也更快,可以无缝替换。mAP可以提升3pt左右。
      ii. 预训练模型能极大加快收敛。
      iii. 使用预训练模型时,冻结底层参数,相比完全放开效果更好。
    3. 以resnet50为例,一般冻结5个阶段中的前2个。
      b. 检测头,性能由弱到强,每一个改进都能大幅提升mAP
      i. 初版仿yolo v1方案:无fpn,骨干网络接一层卷积,mAP~0.06
      ii. faster rcnn原始设计:采用fpn,rpn head一层卷积,roi head两层mlp。mAP提升约8pt(0.06->0.14)
      iii. 改进的faster rcnn(torchvision中的fasterrcnn_resnet50_fpn_v2):rpn head两层卷积,roi head四层卷积+一层mlp。mAP相比c.i.1提升10pt(0.21->0.315)。
      iv. 仿照cascade rcnn:多个roi检测头级联,每个roi head都使用两层mlp。mAP相比iii提升7~10pt(0.315->0.415,还有更换骨干网络的影响)。
    4. 在级联结构下,使用更复杂的roi head会显著降低训练和收敛速度,同时精度提升并不明显。
      v. decoupled head:检测头由分类回归任务共享卷积层,改为每个任务各自卷积只共享feature map,理论支持是分类更关注语义回归更关注结构细节,二者共享卷积层会导致冲突。采用decoupled head的一阶段网络,mAP相比iv可提升11pt(0.415->0.523)。
      c. 损失函数
      i. focal loss:所有使用sigmoid或者softmax的地方都可以用focal loss作为上位替代,效果提升明显。由于能自适应调整难/易样本权重,有了focal loss可以很大程度上摆脱正负样本不均衡的问题,无需依赖平衡采样。
    5. 不做其他改动的情况下,faster rcnn中sigmoid和softmax都替换为focal loss,mAP可提升7pt(0.14->0.21)。
      ii. iou loss(giou、diou、ciou):论文中提到改进的iou loss相比L1loss可以加快收敛,但图搜数据上的实验并没有观察到收敛速度或精度的显著提升。
  2. 训练trick
    a. 学习率 & 优化器
    i. 采用逐步衰减的学习率有助于收敛到较好的结果,本文实验一般SGD迭代3轮,学习率0.005->0.003->0.001。相比不衰减的情况,最终mAP可提升3-5pt。
    1. 根据pytorch论坛中的讨论,多轮训练中采用SGD+余弦变化的学习率效果较好。因为时间有限,本文中并未尝试。
    2. Adam优化器占用内存更高,同时在训练集足够大的情况下相比SGD似乎并无优势。
      b. 平衡采样
      i. 如果采用sigmoid和softmax等损失函数,需要用平衡采样控制训练样本中的正负例个数,一般正例远少于负例,faster rcnn中取1:3。
      ii. 如果采用focal loss,则平衡采样不会带来明显收益。
      c. 正样本选择
      i. fcos中采用的基于centerness的样本选择方法,实践中证明效果优于faster rcnn、retinanet等采用的基于roi的样本选择方法,收敛更快、最终精度更好。在网络结构完全一致的情况下,mAP可提升约1pt(0.523->0.535)。
    3. 提出ATSS的论文《Bridging the Gap Between Anchor-based and Anchor-free Detection via Adaptive Training Sample Selection》中有关于这一问题的详细讨论。
    4. 目前yolox系列采用了另一种称作SimOTA的样本选择方法,更简单,效果更好。
  3. 生产部署
    pytorch模型转onnx,然后再根据后端(openvino或者tensorrt)转相应格式。这里的坑在于,pytorch中一些看似简单的操作(比如roialign或者nms)翻译到onnx可能十分复杂,还会出现一些很多余的条件分支,这些分支在tensorrt或者openvino中支持很差。
    这里有两种办法。利用mmdet + mmdeploy的话,官方已经实现好了所有段子,保证大部分后端框架上都可以正常运行,只要部署时候带上mmdeploy生成的动态连接库即可。如果不想做任何额外开发,只用原生pytorch的话,还是用单阶段模型吧各位,模型只保留原始输出,nms什么的放到外面去做,保证模型是静态的。现在的单阶段模型(比如yolo系列)精度已经很高了,部署方便,速度也快,省去许多麻烦。

你可能感兴趣的:(计算机视觉,目标检测,deep-learning,pytorch)