学习资源站

RT-DETR改进策略【损失函数篇】NWD损失函数,提高小目标检测精度_detr损失函数-

RT-DETR改进策略【损失函数篇】| NWD损失函数,提高小目标检测精度

一、本文介绍

本文记录的是 基于NWD的RT-DETR的损失函数改进方法研究 。目前的IoU-Loss在一些情况下不能提供梯度来优化网络,例如当预测边界框P和真实边界框G没有重叠(即 ∣ P ∩ G ∣ = 0 |P \cap G| = 0 P G = 0 ),或者P完全包含G或反之(即 ∣ P ∩ G ∣ = P |P \cap G| = P P G = P 或G),而这两种情况在微小物体检测中非常常见。 CIoU DIoU 虽然能处理上述两种情况,但它们基于IoU, 对微小物体的位置偏差很敏感 。而 本文的改进方法能够使模型解决这些问题,实现对小目标的精确检测



二、NWD设计原理

NWD损失函数 设计的原理及优势如下:

2.1 NWD计算原理

  • 首先将边界框建模为二维高斯分布,对于两个二维高斯分布 m u 1 = N ( m 1 , ∑ 1 ) mu_1 = N(m_1, \sum_1) m u 1 = N ( m 1 , 1 ) μ 2 = N ( m 2 , ∑ 2 ) \mu_2 = N(m_2, \sum_2) μ 2 = N ( m 2 , 2 ) ,其二阶Wasserstein距离定义为: W 2 2 ( μ 1 , μ 2 ) = ∥ m 1 − m 2 ∥ 2 2 + T r ( ∑ 1 + ∑ 2 − 2 ( ∑ 2 1 2 ∑ 1 ∑ 2 1 2 ) 1 2 ) W_2^2(\mu_1, \mu_2) = \parallel m_1 - m_2\parallel_2^2 + Tr(\sum_1 + \sum_2 - 2(\sum_2^{\frac{1}{2}}\sum_1\sum_2^{\frac{1}{2}})^{\frac{1}{2}}) W 2 2 ( μ 1 , μ 2 ) =∥ m 1 m 2 2 2 + T r ( 1 + 2 2 ( 2 2 1 1 2 2 1 ) 2 1 ) ,可简化为: W 2 2 ( μ 1 , μ 2 ) = ∥ m 1 − m 2 ∥ 2 2 + ∥ ∑ 1 1 2 − ∑ 2 1 2 ∥ F 2 W_2^2(\mu_1, \mu_2) = \parallel m_1 - m_2\parallel_2^2 + \parallel \sum_1^{\frac{1}{2}} - \sum_2^{\frac{1}{2}}\parallel_F^2 W 2 2 ( μ 1 , μ 2 ) =∥ m 1 m 2 2 2 + 1 2 1 2 2 1 F 2
  • 对于从边界框A = ( c x a , c y a , w a , h a ) (c x_a, c y_a, w_a, h_a) ( c x a , c y a , w a , h a ) 和B = ( c x b , c y b , w b , h b ) (c x_b, c y_b, w_b, h_b) ( c x b , c y b , w b , h b ) 建模的高斯分布 N a N_a N a N b N_b N b ,可进一步简化为: W 2 2 ( N a , N b ) = ∥ ( [ c x a , c y a , w a 2 , h a 2 ] T , [ c x b , c y b , w b 2 , h b 2 ] T ) ∥ 2 2 W_2^2(\mathcal{N}_a, \mathcal{N}_b) = \parallel ([c x_a, c y_a, \frac{w_a}{2}, \frac{h_a}{2}]^T, [c x_b, c y_b, \frac{w_b}{2}, \frac{h_b}{2}]^T)\parallel_2^2 W 2 2 ( N a , N b ) =∥ ([ c x a , c y a , 2 w a , 2 h a ] T , [ c x b , c y b , 2 w b , 2 h b ] T ) 2 2
  • W 2 2 ( N a , N b ) W_2^2(\mathcal{N}_a, \mathcal{N}_b) W 2 2 ( N a , N b ) 是距离度量,不能直接用作相似度量(即像IoU一样的值在0和1之间),所以使用其指数形式归一化,得到新的度量NWD: N W D ( N a , N b ) = e x p ( − W 2 2 ( N a , N b ) C ) NWD(\mathcal{N}_a, \mathcal{N}_b) = exp(-\frac{\sqrt{W_2^2(\mathcal{N}_a, \mathcal{N}_b)}}{C}) N W D ( N a , N b ) = e x p ( C W 2 2 ( N a , N b ) ) ,其中C是一个与数据集密切相关的常数,在实验中经验性地设置为AI - TOD的平均绝对大小,并取得了最佳性能,且在一定范围内是稳健的。
  • NWD损失函数 设计为: L N W D = 1 − N W D ( N p , N g ) \mathcal{L}_{NWD} = 1 - NWD(\mathcal{N}_p, \mathcal{N}_g) L N W D = 1 N W D ( N p , N g ) ,其中 N p N_p N p 是预测框P的高斯分布模型, N g N_g N g 是真实边界框G的高斯分布模型。

在这里插入图片描述

2.2 NWD优势

  • 尺度不变性 :与IoU相比, NWD 对边界框的尺度变化不敏感,更适合测量微小物体之间的相似性。
  • 对位置偏差的平滑性 :IoU对微小物体的位置偏差过于敏感,而 NWD 因位置偏差产生的变化更平滑,这表明在相同阈值下, NWD 有可能比IoU更好地区分正/负样本。
  • 能测量非重叠或相互包含边界框的相似性 :即使边界框没有重叠或重叠可忽略, NWD 也能测量它们之间的分布相似性。
  • 提供梯度 :根据上述介绍, NWD损失函数 ∣ P ∩ G ∣ = 0 |P \cap G| = 0 P G = 0 P ∩ G ∣ = P P \cap G| = P P G = P 或G的情况下都能提供梯度。

论文: https://arxiv.org/pdf/2110.13389
源码: https://github.com/jwwangchn/NWD


三、NWD的实现代码

NWD 的实现代码如下:

def wasserstein_loss(pred, target, eps=1e-7, constant=12.8):
    r"""`Implementation of paper `Enhancing Geometric Factors into
    Model Learning and Inference for Object Detection and Instance
    Segmentation <https://arxiv.org/abs/2005.03572>`_.
    Code is modified from https://github.com/Zzh-tju/CIoU.
    Args:
        pred (Tensor): Predicted bboxes of format (x_center, y_center, w, h),
            shape (n, 4).
        target (Tensor): Corresponding gt bboxes, shape (n, 4).
        eps (float): Eps to avoid log(0).
    Return:
        Tensor: Loss tensor.
    """

    center1 = pred[:, :2]
    center2 = target[:, :2]

    whs = center1[:, :2] - center2[:, :2]

    center_distance = whs[:, 0] * whs[:, 0] + whs[:, 1] * whs[:, 1] + eps #

    w1 = pred[:, 2]  + eps
    h1 = pred[:, 3]  + eps
    w2 = target[:, 2] + eps
    h2 = target[:, 3] + eps

    wh_distance = ((w1 - w2) ** 2 + (h1 - h2) ** 2) / 4

    wasserstein_2 = center_distance + wh_distance
    return torch.exp(-torch.sqrt(wasserstein_2) / constant)

四、添加步骤

4.1 修改ultralytics/utils/metrics.py

此处需要查看的文件是 ultralytics/utils/metrics.py

metrics.py 中定义了模型的损失函数和计算方法,我们想要加入新的损失函数就只需要将代码放到这个文件内即可

NWD 添加后如下:

在这里插入图片描述

4.2 修改ultralytics/utils/loss.py

ultralytics/utils/loss.py 在的引用中添加 wasserstein_loss ,然后在 BboxLoss函数 中修改如下代码,使模型调用此 wasserstein_loss 损失函数。

在这里插入图片描述


iou = bbox_iou(pred_bboxes[fg_mask], target_bboxes[fg_mask], xywh=False, CIoU=True)

loss_iou = ((1.0 - iou) * weight).sum() / target_scores_sum

在上方代码下方添加如下代码:

nwd = wasserstein_loss(pred_bboxes[fg_mask], target_bboxes[fg_mask])
iou_ratio = 0.3  #可调超参数,小目标可变低
nwd_loss = ((1.0 - nwd) * weight).sum() / target_scores_sum
loss_iou = iou_ratio * loss_iou + (1 - iou_ratio) * nwd_loss

在这里插入图片描述

此时再次训练模型便会使用 NWD 计算模型的损失函数。


五、成功运行截图

在这里插入图片描述