深度理解yolov3损失函数

在yolov3中,loss分为三个部分:

  • 一个是xywh部分带来的误差,也就是bbox带来的loss
  • 一个是置信度带来的误差,也就是obj带来的loss
  • 最后一个是类别带来的误差,也就是class带来的loss

在代码中分别对应lbox,lobj,lcls,yolov3中使用的loss公式如下:

yolov5seg损失权重 yolov3损失函数多少 停止_git

           

其中:

S:代表grid size,

yolov5seg损失权重 yolov3损失函数多少 停止_损失函数_02

代表 13×13,26×26,52×52

B:box

   

yolov5seg损失权重 yolov3损失函数多少 停止_yolov5seg损失权重_03

:如果在i,j处的box有目标,其值为1,否则为0     

yolov5seg损失权重 yolov3损失函数多少 停止_深度学习_04

:如果在i,j处的box没有目标,其值为1,否则为0 

     BCE(binary cross entropy)具体计算公式如下:

                                             

yolov5seg损失权重 yolov3损失函数多少 停止_yolov3_05

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

以上是论文中yolov3对应的损失函数分析,对应框架为darknet。而pytorch版本的yolov3改动比较大,分成三个部分进行具体分析:

1.lbox部分                                                                                                                                                                                                                                                                                                                                                                                                                   

  在U版yolov3中,使用的是GIOU,具体讲解见GIOU讲解链接                                                                                                                                                                                                                                                                                                                               

  简单来说其IoU公式如下:

                                                     

yolov5seg损失权重 yolov3损失函数多少 停止_深度学习_06

                                                                                                                                                                                                                                                                                                                                                   

而GIoU公式如下:

                                                     

yolov5seg损失权重 yolov3损失函数多少 停止_深度学习_07

                                                                                                                                                                                                                                                                                                                                     其中

yolov5seg损失权重 yolov3损失函数多少 停止_yolov3_08

代表两个框最小闭包区域面积,也就是同时包含了预测框和真实框的最小框的面积。

    yolov3中提供了IoU,GIoU,DIoU和CIoU等计算方式,以GIoU为例:

if GIoU:  # Generalized IoU https://arxiv.org/pdf/1902.09630.pdf
    c_area = cw * ch + 1e-16  # convex area
    return iou - (c_area - union) / c_area  # GIoU

  可以看到代码和GIoU公式是一致的,再来看一下lbox计算部分:

giou = bbox_iou(pbox.t(), tbox[i],
				x1y1x2y2=False, GIoU=True) 
lbox += (1.0 - giou).sum() if red == 'sum' else (1.0 - giou).mean()

    可以看到box的loss是1-giou的值。

2.lobj部分

      lobj代表置信度,即该bounding box中是否含有物体的概率。在yolov3代码中obj loss可以通过arc来指定,有两种模式:

     如果采用default模式,使用BCEWithLogitsLoss,将obj loss和cls loss分开计算:

BCEobj = nn.BCEWithLogitsLoss(pos_weight=ft([h['obj_pw']]), reduction=red)
if 'default' in arc:  # separate obj and cls
    lobj += BCEobj(pi[..., 4], tobj)  # obj loss
    # pi[...,4]对应的是该框中含有目标的置信度,和giou计算BCE
    # 相当于将obj loss和cls loss分开计算

    如果采用BCE模式,使用的也是BCEWithLogitsLoss,计算对象是所有的cls loss:

BCE = nn.BCEWithLogitsLoss(reduction=red)
elif 'BCE' in arc:  # unified BCE (80 classes)
    t = torch.zeros_like(pi[..., 5:])  # targets
    if nb:
        t[b, a, gj, gi, tcls[i]] = 1.0 # 对应正样本class置信度设置为1
        lobj += BCE(pi[..., 5:], t)#pi[...,5:]对应的是所有的class

3.lcls部分

      如果是单类的情况,cls loss=0

      如果是多类的情况,也分两个模式:

      如果采用default模式,使用的是BCEWithLogitsLoss计算class loss。

BCEcls = nn.BCEWithLogitsLoss(pos_weight=ft([h['cls_pw']]), reduction=red)
# cls loss 只计算多类之间的loss,单类不进行计算
if 'default' in arc and model.nc > 1:
    t = torch.zeros_like(ps[:, 5:])  # targets
    t[range(nb), tcls[i]] = 1.0 # 设置对应class为1
    lcls += BCEcls(ps[:, 5:], t)  # 使用BCE计算分类loss

     如果采用CE模式,使用的是CrossEntropy同时计算obj loss和cls loss。

CE = nn.CrossEntropyLoss(reduction=red)
elif 'CE' in arc:  # unified CE (1 background + 80 classes)
    t = torch.zeros_like(pi[..., 0], dtype=torch.long)  # targets
    if nb:
    t[b, a, gj, gi] = tcls[i] + 1 # 由于cls是从零开始计数的,所以+1
    lcls += CE(pi[..., 4:].view(-1, model.nc + 1), t.view(-1))
    # 这里将obj loss和cls loss一起计算,使用CrossEntropy Loss

 以上三个部分总结下来就是下图:

yolov5seg损失权重 yolov3损失函数多少 停止_git_09