深度理解yolov3损失函数

本文深入剖析YOLOv3的损失函数,包括bbox、obj和class三部分。损失函数涉及BCE和GIoU计算,以及在PyTorch实现中的差异。对于lbox,使用GIoU衡量框的准确性;lobj通过BCEWithLogitsLoss计算置信度损失;lcls则依据设定模式计算分类损失。文章详细解释了各个部分的代码实现,并给出了不同模式下的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

深度理解yolov3损失函数

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

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

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

\begin{aligned} lbox &= \lambda_{coord}\sum_{i=0}^{S^2}\sum_{j=0}^{B}1_{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] \\ lcls &= \lambda_{class}\sum_{i=0}^{S^2}\sum_{j=0}^{B}1_{i,j}^{obj}\sum_{c\in classes}p_i(c)log(\hat{p_i}(c)) \\ lobj &= \lambda_{noobj}\sum_{i=0}^{S^2}\sum_{j=0}^{B}1_{i,j}^{noobj}(c_i-\hat{c_i})^2+\lambda_{obj}\sum_{i=0}^{S^2}\sum_{j=0}^{B}1_{i,j}^{obj}(c_i-\hat{c_i})^2 \\ loss &= lbox + lobj + lcls \end{aligned}

           

其中:

S:代表grid size,S^2代表 13×13,26×26,52×52

B:box

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

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

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

                                             BCE(\hat{c_i},c_i)=-\hat{c_i}\times log(c_i)-(1-\hat{c_i})\times log(1-c_i)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

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

1.lbox部分                                                                                                                                                                                                                                                                                                                                                                                                                   

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

  简单来说其IoU公式如下:

                                                      IoU=\frac{|A\cap B|}{|A\cup B|}                                                                                                                                                                                                                                                                                                                                                   

而GIoU公式如下:

                                                      GIoU=IoU-\frac{|A_c-U|}{|A_c|}                                                                                                                                                                                                                                                                                                                                     

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

    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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

 

 

参考链接:https://www.cnblogs.com/pprp/p/12590801.html

 

### YOLOv8损失函数详解 #### 组成部分 YOLOv8采用了一个多组件构成的综合损失函数来优化模型性能。此损失函数由三个主要部分组成: - **目标检测损失**:这部分负责识别图像中是否存在对象以及预测边界框的位置准确性[^1]。 - **目标分类损失**:用于区分不同类别的物体,确保每个预测出来的区域都能被正确地标记为其所属类别。 - **目标定位损失**:专注于提高边界框坐标的精度,使得预测框能够更精确地包围住实际的目标位置。 #### 工作原理 对于每一个网格单元格内的候选框而言,在训练过程中会计算上述三种类型的误差,并通过加权求和形成最终的整体损失值。具体来说: - 对于存在真实对象的情况(即正样本),将会同时考虑所有三项损失;而对于不存在任何对象的地方(负样本),则只涉及目标检测损失项以减少误报率。 为了更好地平衡各项之间的贡献度并加快收敛速度,通常会对各个分量赋予不同的权重系数。此外,还会引入一些额外机制如IoU(Intersection over Union)改进版GIoU或DIoU等作为辅助指标加入到整体框架之中,从而进一步提升模型的表现效果。 ```python import torch.nn.functional as F def compute_loss(predictions, targets): # 假设predictions和targets已经过预处理 obj_loss = ... # 计算目标检测损失 cls_loss = F.cross_entropy(...) # 使用交叉熵计算分类损失 loc_loss = smooth_l1_loss(...) # 使用平滑L1损失计算定位损失 total_loss = lambda_obj * obj_loss + lambda_cls * cls_loss + lambda_loc * loc_loss return total_loss ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值