【YOLO改进】换遍IoU损失函数之WIoU Loss(基于MMYOLO)

WIoU损失函数

设计原理

WIoU的引入

在目标检测任务中,预测框与真实框之间的相似度是一个重要的评估指标。传统的IoU(Intersection over Union)损失函数虽然能够直观地反映出目标检测结果与真实情况之间的匹配程度,但在某些情况下存在局限性,例如当预测框与真实框不相交时,IoU损失函数无法进行优化。为了解决这些问题,研究人员提出了WIOU损失函数,通过引入权重因子进行加权计算,使得损失函数在目标检测任务中具有更广泛的适用性。

WIOU损失函数的设计原理基于交并比(Intersection over Union)的概念,即预测框与真实框之间的交集面积与并集面积之比。为了使得损失函数在预测结果与真实结果完全一致时取得最小值为0,在两者差异较大时取得较大的值,WIOU损失函数采用了以下设计思路:

  1. 计算预测框与真实框之间的交集面积和并集面积。
  2. 引入权重因子,对不同类别的目标进行不同程度的加权。
  3. 计算加权后的交并比,并将其补集取负数作为损失函数的值。

通过引入权重因子,WIOU损失函数可以更加灵活地处理不同类别的目标,解决了类别不平衡问题。同时,由于WIOU损失函数基于交并比的概念进行设计,因此它具有尺度不变性,不受目标尺度和形状变换的影响,这使得WIOU损失函数适用于各种不同尺度和形状的目标检测任务。

计算步骤

WIOU损失函数的计算步骤如下:

  1. 计算预测框与真实框之间的交集面积(W_overlap)和并集面积(W_union)。
  2. 引入一个小常数eps(用于避免除0错误),通常取一个很小的正数。
  3. 计算加权后的交并比(WIOU),公式为:(W_overlap + eps) / (W_union + eps)。
  4. 将加权后的交并比的补集取负数作为损失函数的值(WIOULoss),公式为:1 - (W_overlap + eps) / (W_union + eps)。

WIoU计算的源代码

import math

import torch
from torch import nn


class IouLoss(nn.Module):
    ''' :param monotonous: {
            None: origin
            True: monotonic FM
            False: non-monotonic FM
        }'''
    momentum = 1e-2
    alpha = 1.7
    delta = 2.7

    def __init__(self, ltype='WIoU', monotonous=False):
        super().__init__()
        assert getattr(self, f'_{ltype}', None), f'The loss function {ltype} does not exist'
        self.ltype = ltype
        self.monotonous = monotonous
        self.register_buffer('iou_mean', torch.tensor(1.))

    def __getitem__(self, item):
        if callable(self._fget[item]):
            self._fget[item] = self._fget[item]()
        return self._fget[item]

    def forward(self, pred, target, ret_iou=False, **kwargs):
        self._fget = {
            # pred, target: x0,y0,x1,y1
            'pred': pred,
            'target': target,
            # x,y,w,h
            'pred_xy': lambda: (self['pred'][..., :2] + self['pred'][..., 2: 4]) / 2,
            'pred_wh': lambda: self['pred'][..., 2: 4] - self['pred'][..., :2],
            'target_xy': lambda: (self['target'][..., :2] + self['target'][..., 2: 4]) / 2,
            'target_wh': lambda: self['target'][..., 2: 4] - self['target'][..., :2],
            # x0,y0,x1,y1
            'min_coord': lambda: torch.minimum(self['pred'][..., :4], self['target'][..., :4]),
            'max_coord': lambda: torch.maximum(self['pred'][..., :4], self['target'][..., :4]),
            # The overlapping region
            'wh_inter': lambda: torch.relu(self['min_coord'][..., 2: 4] - self['max_coord'][..., :2]),
            's_inter': lambda: torch.prod(self['wh_inter'], dim=-1),
            # The area covered
            's_union': lambda: torch.prod(self['pred_wh'], dim=-1) +
                               torch.prod(self['target_wh'], dim=-1) - self['s_inter'],
            # The smallest enclosing box
            'wh_box': lambda: self['max_coord'][..., 2: 4] - self['min_coord'][..., :2],
            's_box': lambda: torch.prod(self['wh_box'], dim=-1),
            'l2_box': lambda: torch.square(self['wh_box']).sum(dim=-1),
            # The central points' connection of the bounding boxes
            'd_center': lambda: self['pred_xy'] - self['target_xy'],
            'l2_center': lambda: torch.square(self['d_center']).sum(dim=-1),
            # IoU
            'iou': lambda: 1 - self['s_inter'] / self['s_union']
        }

        if self.training:
            self.iou_mean.mul_(1 - self.momentum)
            self.iou_mean.add_(self.momentum * self['iou'].detach().m
### YOLO损失函数中的加权IoU (WIoU) 在目标检测领域,交并比(Intersection over Union, IoU)是一种广泛使用的度量方法,用于评估预测边界框与真实边界框之间的重叠程度。然而,在某些情况下,简单的IoU可能无法充分反映不同大小物体的重要性差异。因此,提出了加权IoU(Weighted IoU, Wiou),通过引入权重来调整不同尺寸的目标对总损失的影响。 #### 加权IoU的定义 Wiou的核心思想是在计算IoU的基础上加入一个权重项,该权重通常基于目标的真实边界框面积或其他特征属性。具体来说,对于两个边界框 \(A\) 和 \(B\): \[ \text{IoU}(A, B) = \frac{\text{Area of Overlap}}{\text{Area of Union}} \] 而加权IoU则可以表示为: \[ \text{WIoU}(A, B) = w(A, B) \cdot \left(1 - \text{IoU}(A, B)\right) \] 其中,\(w(A, B)\) 是一个权重函数[^2],可以根据实际需求设计。常见的实现方式是以目标的真实边界框面积作为权重依据,即较大的目标具有更高的权重。 #### 实现细节 以下是Wiou的一个典型Python实现示例,假设输入为目标的真实边界框和预测边界框坐标列表: ```python import torch def bbox_iou(box1, box2, eps=1e-7): """ 计算两个边界框的IoU """ 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] inter_rect_x1 = torch.max(b1_x1, b2_x1) inter_rect_y1 = torch.max(b1_y1, b2_y1) inter_rect_x2 = torch.min(b1_x2, b2_x2) inter_rect_y2 = torch.min(b1_y2, b2_y2) clip_mask = ((inter_rect_x1 < inter_rect_x2) * (inter_rect_y1 < inter_rect_y2)).float() inter_area = torch.clamp(inter_rect_x2 - inter_rect_x1 + 1, min=0) * \ torch.clamp(inter_rect_y2 - inter_rect_y1 + 1, min=0) * clip_mask b1_area = (b1_x2 - b1_x1 + 1) * (b1_y2 - b1_y1 + 1) b2_area = (b2_x2 - b2_x1 + 1) * (b2_y2 - b2_y1 + 1) union_area = b1_area + b2_area - inter_area + eps iou = inter_area / union_area return iou def wiou_loss(pred_boxes, true_boxes, weight_func=None): """ 计算加权IoU损失 """ if weight_func is None: # 默认使用真实框面积作为权重 def default_weight_func(true_box): area = (true_box[..., 2] - true_box[..., 0]) * (true_box[..., 3] - true_box[..., 1]) return area.unsqueeze(-1).clamp(min=1e-6) weight_func = default_weight_func weights = weight_func(true_boxes) ious = bbox_iou(pred_boxes, true_boxes) loss = weights * (1.0 - ious) return loss.mean() # 使用示例 pred_boxes = torch.tensor([[10., 10., 20., 20.]]) # 预测框 true_boxes = torch.tensor([[15., 15., 25., 25.]]) # 真实框 loss = wiou_loss(pred_boxes, true_boxes) print(f"WIoU Loss: {loss.item()}") ``` 上述代码实现了基本的Wiou损失计算逻辑,并允许自定义权重函数。默认情况下,权重由真实边界框的面积决定。 #### 应用场景 Wiou特别适用于处理多尺度目标检测问题,因为其可以通过赋予大目标更高权重的方式改善模型对大型物体的学习效果。此外,它还可以与其他改进IoU损失(如SIoU、EIou等)结合使用,进一步提升性能。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值