AlexeyAB DarkNet YOLOv3 Loss计算全解析

先附上AlexeyAB大神版本的DarkNet:github

一、前言

        目前还没有对yolo loss计算方法讲的很明白的资料,尤其是loss计算中是如何选取正负样本和忽略样本的。因此在这里做出详细的解释。本文是基于AlexeyAB版本的DarkNet,对yolo loss的计算方法进行阐述的。

二、Yolov3 Loss Function

        想要弄清楚loss计算的方法,需要明确几个关键点。

        1.yolov3是有3个特征图,每个特征图分配3个anchor,对于416*416*3的输入,那么3个yolo层特征图尺寸为13*13、26*26、52*52(不考虑channel),因此最多会输出(13*13*3 + 26*26*3 + 52*52*3)= 10647个框。

        2.那么每个预测框是由x, y, w, h, confidence, c1, c2, ..., cn表示的,其中confidence是预测框的置信度,也就是这个预测框中是否存在目标的置信度;c1, c2, ..., cn是预测框中目标类别的置信度。因此,若数据包含80类目标,那么一个预测框的长度是(4 + 1 + 80)= 85,每个yolo层包含3个anchor,那么一个grid cell对应的通道数是(85 * 3)= 255,三个yolo层特征图对应的尺寸也就是13*13*255,26*26*255,52*52*255。

        3.这里的正负样本,指的是预测框,而不是图片。分正负样本的原因是,正负样本的loss计算方法是不一样的,负样本只计算obj loss,因为负样本的bbox和classes预测是没有意义的;而正样本需计算三个loss:box loss(x, y, w, h的loss), obj loss(框置信度loss), class loss(类别loss)。     

loss_{box}=\lambda _{coord}\sum_{i=0}^{S^{2}}\sum_{j=0}^{B}I_{i,j}^{obj}(2-w_{i}\times h_{i})[(x_{i}-\hat{x_{i}})^{2}+(y_{i}-\hat{y_{i}})^{2}+(w_{i}-\hat{w_{i}})^{2}+(h_{i}-\hat{h_{i}})^{2}]\\ \indent loss_{obj}=-\sum_{i=0}^{S^{2}}\sum_{j=0}^{B}I_{i,j}^{obj}log(C_{i})-\lambda _{noobj}\sum_{i=0}^{S^{2}}\sum_{j=0}^{B}I_{i,j}^{noobj}log(1-C_{i})\\ \indent loss_{cls}=-\lambda _{class}\sum_{i=0}^{S^{2}}\sum_{j=0}^{B}I_{i,j}^{obj}\sum_{c\in classes}^{}[\hat{p}_{i}(c)log(p_{i}(c))+(1-\hat{p}_{i}(c))log(1-(p_{i}(c))]\\ \indent loss_{total}=loss_{box}+loss_{obj}+loss_{cls}

        其中,带^的变量指的是标签真值,S代表的是yolo层特征图的长宽,B代表box anchor也就是每个yolo层负责的anchor的个数(通常为3),代表该预测框是否是正样本,是的话为1,否的话为0,代表该预测框是否是负样本,是的话为1,否的话为0,当然也存在这两个值都为0的时候,那就代表该预测框为忽略样本。

        yolov3中loss由三个部分组成:

        1.box loss:也就预测框x, y, w, h的误差,yolov3原版用MSE loss计算,后续AlexeyAB大神改为GIoU Loss、DIoU Loss、CIoU Loss,这几个就不在这里展开讲了。

        2.obj loss:预测框置信度误差,用BCE loss计算。

        3.class loss:预测框类别误差,用BCE loss对每个类别进行计算,这里有的小伙伴会有疑问,为什么不用softmax loss呢,这是因为yolov3的作者考虑到数据集中的某些类别是存在包含关系的,比如人和女人,也就是多标签分类问题,如果用softmax就只能预测1类了。

三、正负样本和忽略样本的选取

        讲正负样本如何选取之前,先看一下darnet中是如何进行loss计算的,bbuf同学在【AlexeyAB DarkNet框架解析】九,YOLOV3损失函数代码详解中已经将loss计算的大部分代码进行了注释,唯一不足是没有用中文总结loss计算的流程,这对于比较懒的小伙伴是不太友好的,因此在本节中,对darknet中loss的计算过程形成中文的总结,更直观的解释loss计算的流程。想看具体代码的小伙伴请点击上方的链接。


darknet中loss的计算过程(forward_yolo_layer 前向传播函数)

          1.计算所有预测框(第二节中提到的10674个框)的置信度与0的误差(默认所有框都是负样本,这么做是为了方便计算);再遍历每个预测框,将该预测框与每个gt框(就是一张图片上事先标注好的标签框)计算iou,若最大iou大于ignore_thresh阈值(yolov4中是0.7),那么将这个预测框的置信度误差置0(就是认为这个预测框肯定不是负样本,但可能是正样本,也可能是忽略样本)。

        2.遍历每个gt框,计算gt框与anchors(共9对,事先预置好的)中哪个iou最大,那么gt框中心点所在的grid cell的那个anchor就负责预测这个gt框,也就是认为这个位置的预测框就是正样本(无论这个位置的预测框预测出来的值是怎样的),这个位置的预测框与gt框计算3个loss:box loss(x, y, w, h的loss), obj loss(框置信度loss), class loss(类别loss)。 

        3.如果其他8个anchors中有与gt框计算的iou大于了iou_thresh(yolov4中是0.213)的anchor,那么gt框中心点所在的grid cell的该anchor也作为正样本,同样与gt框计算那三个loss。


正负样本和忽略样本定义

  • 正样本gt框所在grid cellgt框与anchors中iou最大的和大于iou_thresh阈值的anchor,也就是说,当anchors和gt框定下来了之后,负责预测这个gt框的预测框(也就是正样本的位置)也就定下来了,无论这个位置预测出的框是怎样的。
  • 负样本:不是正样本的框的所有预测框中,预测出来的框与gt框的iou小于等于ignore_thresh阈值的都是负样本。
  • 忽略样本不是正样本的框的所有预测框中,预测出来的框与gt框的iou大于ignore_thresh阈值的都是忽略样本。因为这些大于阈值的这些框,说明预测也是比较准确的,不能简单的当负样本处理。忽略样本是不参与loss计算的。

欢迎小伙伴讨论,如有错误,感谢指出!

你可能感兴趣的:(机器学习/深度学习,深度学习,目标检测,yolov3,darknet,loss计算)