Yolov3的损失函数分析

Yolov3的网络架构在网上资源很多,但是关于loss的计算方法,网上的资源相对零散,并且原文作者并没有给出明确的计算公式。因此,本文的目的是梳理一下yolov3损失函数的计算流程。

Yolov3网络结构

在这里插入图片描述
Yolov3采用了Darknet53的backbone(采用了Resnet的残差结构),其输出为3张不同尺度的特征图(采用了SSD的思想)。特征图越小,每个grid cell对应的感受野越大,对应大目标的检测。

拿上图中右下角 ( 255 ∗ 13 ∗ 13 ) (255*13*13) (2551313)的特征图为例, 13 ∗ 13 13*13 1313是特征图大小,255可以拆分为 3 ∗ ( 4 + 1 + 80 ) 3*(4+1+80) 3(4+1+80),3表示一个grid cell对应3个anchor,4表示anchor的中心坐标xy和宽高wh,1表示该anchor是否包含目标的置信度,80表示coco数据集的80个类别。

anchor的选择与yolov2一样,采用了kmeans的思想。不同的是这里的K值为9。聚类后,尺寸最大的三个框分配给特征图最小的(感受野大),用来检测大目标;最小的3个框分给特征图最大的(感受野小),用以检测小目标;剩下的3个框分给中间尺寸的特征图。

因此,yolov3的输出维度是 B a t c h ∗ 3 ∗ ( 4 + 1 + 80 ) ∗ ( 13 ∗ 13 + 26 ∗ 26 + 52 ∗ 52 ) Batch*3*(4+1+80)*(13*13+26*26+52*52) Batch3(4+1+80)(1313+2626+5252)

损失函数计算

我们可以得到骨干网络Darknet的输出,但要怎样计算损失函数呢?

通常我们将特征图后面的层,即用来进行检测并得到Darknet最终输出的层叫做Yolo层,因为前面有三种不同尺度的特征图,所以Darknet对应了三个不同的Yolo层,而最终的loss就是把这3个Yolo层计算出来的损失求和,再进行反向传播。

这里还是以 ( 255 ∗ 13 ∗ 13 ) (255*13*13) (2551313)的特征图为例,该特征图有 3 ∗ 13 ∗ 13 3*13*13 31313个bounding box,假设某张图像有t个object,那么选出对应的t个iou最大的bounding box作为正例,其他iou>0.5的框全部舍弃掉,剩下的作为负例。这里的iou只需要用到box的宽高,而不用框的中心坐标(与kmeans时的iou计算方式一致)。

首先根据pytorch的代码,Yolov3的损失函数主要包括3个部分:

(1)对于正例,计算bbox与GT之间的位置和大小差异,采用MSE损失函数;

(2)对于正例,计算80个类别维度与target的one-hot向量间的交叉熵损失;

(3)对于正例和负例,分别计算置信度与真实之间的交叉熵,并按照一定的比例系数加权求和。

Darknet的输出只是坐标的偏置,对xy来说需要先进行sigmoid操作映射到[0,1]区间,再加上当前grid cell左上角格点的坐标,同时也将GT的坐标也按照当前特征图尺度进行缩放,统一后计算出bbox和GT的中心坐标的MSE;

对wh来说,网络输出的值也是bbox宽高的一个偏置,需要取exp(保证wh为正值)再乘以初始的anchor的宽高。不过在训练过程中,网络的输出可以直接用来计算loss,此时需要将GT的宽高进行反解(先除以anchor的宽高,再取log),这样两者也统一到一起,计算loss即可。

对于置信度需要做sigmoid操作,约束到[0,1]的空间;对于每个类别的得分,也需要用sigmoid映射到[0,1]之间。

Yolov3损失函数的计算到这里就差不多结束了,我认为比较晦涩的就一个地方,就是偏置、尺度、坐标宽高这些的关系比较杂乱。不妥之处请指正。

参考:

https://segmentfault.com/a/1190000021794637

https://towardsdatascience.com/calculating-loss-of-yolo-v3-layer-8878bfaaf1ff

猜你喜欢

转载自blog.csdn.net/jackzhang11/article/details/107302575