目标检测的Tricks | 【Trick3】IoU loss与focal loss(包含一些变体介绍)

简介: 目标检测的Tricks | 【Trick3】IoU loss与focal loss(包含一些变体介绍)

这里介绍一下IoU loss与focal loss函数,之前的文章也有提及到,这里就不再过多的细说了。简单来说:

  • IoU loss:用来计算pred box与ground true之间的差异,用来边界框损失函数的计算;
  • focal loss:用来平衡正负样本不均衡的问题,由RetinaNet提出使用与One-Step目标检测算法上的一个技巧

关于这两部分的详细介绍可以见之前的博文:YOLOv4中的tricks概念总结——Bag of freebies

然后,后续有不少大佬对focal loss进行了变体,这里也简要记录一下。


1. IoU loss实现代码


关于边界框的回归损失,之前在yolov4中有总结了其归纳的“免费包”的概念,具体见:YOLOv4中的tricks概念总结——Bag of freebies,大概是进阶过程是:Smooth L1 loss、iou loss、giou loss、diou loss、ciou loss。这里不再对原理进行过多的介绍,直接贴上代码。


YOLOv3-SPP代码:

# iou loss、giou loss、diou loss、ciou loss的计算函数
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False):
     # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4
    """
    Args:
        box1: 预测框
        box2: 真实框
        x1y1x2y2: False
    Returns:
        box1和box2的IoU/GIoU/DIoU/CIoU
    """
    box2 = box2.t()
    # Get the coordinates of bounding boxes
    if x1y1x2y2:  # x1, y1, x2, y2 = box1
        b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]
        b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]
    else:  # transform from xywh to xyxy
        b1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0] + box1[2] / 2
        b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1] + box1[3] / 2
        b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0] + box2[2] / 2
        b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1] + box2[3] / 2
    # Intersection area
    inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \
            (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)
    # Union Area
    w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1
    union = (w1 * h1 + 1e-16) + w2 * h2 - inter
    iou = inter / union  # iou
    if GIoU or DIoU or CIoU:
        cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)  # 外接矩形的宽
        ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)  # 外接矩形的高
        if GIoU:  # Generalized IoU https://arxiv.org/pdf/1902.09630.pdf
            c_area = cw * ch + 1e-16  # 外围矩形的面积
            return iou - (c_area - union) / c_area  # GIoU
        if DIoU or CIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            # convex diagonal squared
            c2 = cw ** 2 + ch ** 2 + 1e-16   # 外接矩形的对角线距离(外接矩形的宽平方 + 外接矩形的高平方)
            # centerpoint distance squared
            # 两个框之间的中心点距离: [(b2x2+b2x1)/2 - (b1x2+b2x1)/2]^2 + [(b2y2+b2y1)/2 - (b1y2+b2y1)/2]^2
            rho2 = ((b2_x1 + b2_x2) - (b1_x1 + b1_x2)) ** 2 / 4 + ((b2_y1 + b2_y2) - (b1_y1 + b1_y2)) ** 2 / 4
            if DIoU:
                return iou - rho2 / c2  # DIoU
            elif CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                # CIoU同时考虑了重叠面积, 中心点之间的距离和长宽比. CIoU可以在BBox回归问题上获得更好的收敛速度和精度
                v = (4 / math.pi ** 2) * torch.pow(torch.atan(w2 / h2) - torch.atan(w1 / h1), 2)
                with torch.no_grad():
                    alpha = v / (1 - iou + v)
                return iou - (rho2 / c2 + v * alpha)  # CIoU
    return iou
# 损失计算函数  
def compute_loss(p, targets, model):   # predictions, targets, model
    ...
    # prediction subset corresponding to targets
    ps = pi[b, a, gj, gi]  
    # get prediction: xywh
    pxy = ps[:, :2].sigmoid()
    pwh = ps[:, 2:4].exp().clamp(max=1E3) * anchors[i]
    # predicted box
    pbox = torch.cat((pxy, pwh), 1)  
    # giou(prediction, target)
    giou = bbox_iou(pbox.t(), tbox[i], x1y1x2y2=False, GIoU=True)  
    lbox += (1.0 - giou).mean()  # giou loss
    ...


需要注意:

  • 理论上: CIoU Loss > DIoU Loss > GIoU Loss > IoU Loss > BCE Loss > L2 Loss。但是具体的做项目的时候,还是需要自己一个个的试试,可能不同的数据集得到的结果并不一样。


1.1 IoUloss变体——Alpha-IoU

paper:Alpha-IoU: A Family of Power Intersection over Union Losses for Bounding Box Regression

paperlink:https://arxiv.org/pdf/2110.13675.pdf


  • 前言:

目标检测通过Bounding box回归来预测来定位图像中的目标,早期的目标检测工作使用IoU作为定位损失。然而,当预测框与Ground truth不重叠时,IoU损失会出现梯度消失问题,导致收敛速度减慢,导致检测器不准确。这激发了几种改进的基于IoU的损失设计,包括GIoU、DIoU、CIoU。GIoU在IoU损失中引入惩罚项以缓解梯度消失问题,而DIoU和CIoU在惩罚项中考虑了预测框与Ground truth 之间的中心点距离和宽高比。


  • idea:

通过在现有的IoU Loss中引入power 变换,提出了一个新的IoU损失函数,称为α-IoU,用于精确的bbox回归和目标检测。α-IoU是基于IoU的现有损失的统一幂化。


  • α-IoU家族表达式:

其实α-IoU其实非常简单,在IOU及惩罚项表达式中进行了幂的运算

image.png


2. focal loss实现代码


由于之前介绍过RetinaNet的论文:《论文阅读笔记 | 目标检测算法——RetinaNet(focal loss、含与SSD,RCNN,YOLO的对比)》,这里直接贴上公式。


公式:

image.png

YOLOv3-SPP代码:


class FocalLoss(nn.Module):
    # Wraps focal loss around existing loss_fcn(), i.e. criteria = FocalLoss(nn.BCEWithLogitsLoss(), gamma=1.5)
    def __init__(self, loss_fcn, gamma=2, alpha=0.25):
        super(FocalLoss, self).__init__()
        self.loss_fcn = loss_fcn  # must be nn.BCEWithLogitsLoss()
        self.gamma = gamma   # 参数gamma
        self.alpha = alpha   # 参数alpha
        # reduction: 控制损失输出模式 sum/mean/none 这里定义的交叉熵损失BCE都是mean
        self.reduction = loss_fcn.reduction
        self.loss_fcn.reduction = 'none'  # 不知道这句有什么用?  required to apply FL to each element
    def forward(self, pred, true):
        loss = self.loss_fcn(pred, true)  # 普通BCE Loss
        # p_t = torch.exp(-loss)
        # loss *= self.alpha * (1.000001 - p_t) ** self.gamma  # non-zero power for gradient stability
        # TF implementation https://github.com/tensorflow/addons/blob/v0.7.1/tensorflow_addons/losses/focal_loss.py
        pred_prob = torch.sigmoid(pred)  # prob from logits 如果模型最后没有 nn.Sigmoid(),那么这里就需要对预测结果计算一次 Sigmoid 操作
        # ture=0,p_t=1-p; true=1, p_t=p
        p_t = true * pred_prob + (1 - true) * (1 - pred_prob)
        # ture=0, alpha_factor=1-alpha; true=1,alpha_factor=alpha
        alpha_factor = true * self.alpha + (1 - true) * (1 - self.alpha)
        modulating_factor = (1.0 - p_t) ** self.gamma
        # loss = focal loss(代入公式即可)
        loss *= alpha_factor * modulating_factor
        if self.reduction == 'mean': # 一般是mean
            return loss.mean()
        elif self.reduction == 'sum':
            return loss.sum()
        else:  # 'none'
            return loss


补充:这里代码中对公式进行了一定的改动,使得计算更加稳定

image.png


2.1 focal loss变体——Equalized Focal Loss

paper:Equalized Focal Loss for Dense Long-Tailed Object Detection


  • idea:

通过将一个类别相关的调制因子引入Focal Loss。具有两个解耦的动态因子(即聚焦因子和加权因子)的调制因子独立处理不同类别的正负不平衡。focusing factor根据硬正样本对应类别的不平衡程度,决定了对硬正样本的学习集中度。加权因子增加了稀有类别的影响,确保了稀有样本的损失贡献不会被频繁的样本所淹没。这两个因素的协同作用使EFL在长尾场景中应用一阶段检测器时,能够均匀地克服前景-背景不平衡和前景类别不平衡。这是是一种广义的Focal Loss形式,扩展了原始的Focal Loss,可以同时解决前景-背景不平衡和前景类别不平衡的问题。


  • 亮点:

主要解决目标检测的长尾分布问题,提出了基于单阶段的长尾目标检测的第一个解决方案。它简单而有效地超越了所有现有的方法。


  • 公式:

image.png

  • 简要分析:

参数Yj是第j类的Focusing Factor,它在Focal Loss中起着与Y起类似的作用。一个大Y将大大减少大多数阴性样本的损失贡献,从而提高阳性样 本的影响,这里Yj=Yb+Yvj。其中Yvj=s(1-gj),gj值较大表示第j类 (例如频繁) 是训练平衡,这样Y总值就会较小,不需要过度平衡;但较小值表示类别(例如罕见)是训练不平衡,因为Y总值就会较大,表示需要平衡一下;超参数s是决定EFL中Yvj上限的缩放因子。但即使使用了Focusing Factor Yj仍然有 2 个障碍损失的性能,于是作者提出了Weighting Factor,通过重新平衡不同类别的损失贡献来缓解上述问题。与Focusing Factor相似为罕见类别分配了一个较大的权重因子值,以提高其损失贡献,同时保持频繁类别的权重因子接近于1;而对于类别常见的就分配一个较小的权重因子值,以减少他的损失贡献,其实思想上本质还是一样的。


2.2 focal loss变体——cyclical focal loss

paper:CYCLICAL FOCAL LOSS


  • idea:

提出一种新颖的cyclical focal loss,并证明它是比交叉熵 softmax 损失或focal loss更通用的损失函数,为平衡、不平衡或长尾数据集提供了卓越的性能。


  • 公式:

image.png

image.png


参考资料:

https://zhuanlan.zhihu.com/p/457257320

https://zhuanlan.zhihu.com/p/452207890

目录
相关文章
|
弹性计算 算法 安全
SSH学习(一)- 概念了解
整体上对SSH协议进行一个概括了解。
809 3
|
11月前
|
计算机视觉
YOLOv11改进策略【小目标改进】| 2024-TOP 自适应阈值焦点损失(ATFL)提升对小目标的检测能力
YOLOv11改进策略【小目标改进】| 2024-TOP 自适应阈值焦点损失(ATFL)提升对小目标的检测能力
1707 11
YOLOv11改进策略【小目标改进】| 2024-TOP 自适应阈值焦点损失(ATFL)提升对小目标的检测能力
|
10月前
|
Java Linux 定位技术
Minecraft配置文件参数说明(JAVA服务器篇)
Minecraft JAVA版服务器启动后会生成server.properties配置文件,位于minecraft_server/根目录下。该文件包含多项关键设置,如游戏模式(gamemode)、最大玩家数(max-players)、难度(difficulty)等。此文档详细说明了各配置项的功能与默认值,帮助用户高效管理服务器环境。
2168 60
|
11月前
|
Serverless 计算机视觉
YOLOv11改进策略【小目标改进】| Shape-NWD:融合改进,结合Shape-IoU和NWD 更好地适应小目标特性
YOLOv11改进策略【小目标改进】| Shape-NWD:融合改进,结合Shape-IoU和NWD 更好地适应小目标特性
1814 9
|
11月前
|
机器学习/深度学习 资源调度 算法
YOLOv11改进策略【损失函数篇】| 引入Soft-NMS,提升密集遮挡场景检测精度,包括GIoU-NMS、DIoU-NMS、CIoU-NMS、SIoU-NMS、 EIou-NMS
YOLOv11改进策略【损失函数篇】| 引入Soft-NMS,提升密集遮挡场景检测精度,包括GIoU-NMS、DIoU-NMS、CIoU-NMS、SIoU-NMS、 EIou-NMS
4034 6
|
11月前
|
关系型数据库 决策智能
YOLOv11改进策略【损失函数篇】| Slide Loss,解决简单样本和困难样本之间的不平衡问题
YOLOv11改进策略【损失函数篇】| Slide Loss,解决简单样本和困难样本之间的不平衡问题
1528 6
|
机器学习/深度学习 算法 PyTorch
深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU、WIOU损失函数分析及Pytorch实现
这篇文章详细介绍了多种用于目标检测任务中的边界框回归损失函数,包括IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU和WIOU,并提供了它们的Pytorch实现代码。
3223 1
深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU、WIOU损失函数分析及Pytorch实现
|
存储 人工智能 安全
从梦想到现实:十年见证AI自动化漏洞修复的演变
2014年,我怀揣着利用科技创造更安全数字世界的梦想,提出了通过云平台自动化修复第三方网站漏洞的构想。十年后的2024年,随着AI技术的崛起,这一梦想已成为现实。如今,用户只需简单注册并安装插件,AI系统就能自动检测、修复漏洞,整个过程高效、智能。AI不仅提升了系统的可靠性和效率,还具备自我学习能力,使安全防护更加主动。未来,我将继续用AI探索更多可能,推动技术的发展,不断完善这个充满智慧与安全的数字世界。
317 3
从梦想到现实:十年见证AI自动化漏洞修复的演变
|
机器学习/深度学习 数据采集 存储
数据集
【7月更文挑战第10天】数据集
1994 1
|
机器学习/深度学习 计算机视觉
YOLOv8改进 | 损失函数篇 | QualityFocalLoss质量焦点损失(含代码 + 详细修改教程)
YOLOv8改进 | 损失函数篇 | QualityFocalLoss质量焦点损失(含代码 + 详细修改教程)
2583 2