YOLO11 改进 – 损失函数 _ SDloss尺度动态损失:动态平衡尺度与位置损失权重破解多尺度目标检测难题
前言
本文介绍了基于尺度的动态损失(SD Loss)在YOLOv11中的结合。现有基于CNN的红外小目标检测方法忽略像素分布空间特性,且现有损失函数未考虑不同尺度目标对损失的敏感度差异。SD Loss包含边界框专用的SDB Loss和掩码专用的SDM Loss,能根据目标尺度动态调整尺度与位置损失的权重。我们将相关代码加入 ultralytics\utils\metrics.py ,在 ultralytics/utils/loss.py 中导入并修改函数,最后通过验证脚本和结果证明了方法的有效性。
文章目录: YOLOv11改进大全:卷积层、轻量化、注意力机制、损失函数、Backbone、SPPF、Neck、检测头全方位优化汇总
专栏链接: YOLOv11改进专栏
文章目录
[TOC]
介绍
摘要
近年来,基于卷积神经网络(CNN)的红外小目标检测方法取得了优异的性能。然而,这类方法通常采用标准卷积,忽略了对红外小目标像素分布空间特性的考量。为此,我们提出一种全新的风车形卷积(PConv),用以替换骨干网络浅层的标准卷积。PConv 更贴合低照度小目标的像素高斯空间分布特征,能够增强特征提取能力、显著扩大感受野,同时仅带来极少量的参数增量。 此外,尽管现有损失函数结合了尺度损失与位置损失,但它们未能充分考虑不同目标尺度下这两类损失的敏感度差异,从而限制了对低照度小目标的检测性能。为解决这一问题,我们提出基于尺度的动态损失(SD Loss),该损失函数可根据目标尺寸动态调整尺度损失与位置损失的影响权重,提升网络对不同尺度目标的检测能力。 我们构建了一个全新的基准数据集 SIRST-UAVB,这是目前规模最大、挑战性最强的实测单帧红外小目标检测数据集。最后,通过将 PConv 与 SD Loss 整合到当前主流的小目标检测算法中,我们在 IRSTD-1K 数据集与自研的 SIRST-UAVB 数据集上均实现了显著的性能提升,验证了本方法的有效性与泛化能力。
文章链接
论文地址: 论文地址
代码地址: 代码地址
创新点
文章围绕红外小目标检测与分割任务,针对现有损失函数的不足,提出了 基于尺度的动态损失(Scale-based Dynamic Loss, SD Loss) ,同时也对比分析了多种现有损失函数。以下是详细介绍:
一、核心提出的损失函数:SD Loss
SD Loss的核心设计思路是 根据目标尺度动态调整尺度损失(Scale Loss, SLoss)和位置损失(Location Loss, Lloss)的影响系数 ,以解决标注误差(如IoU波动)和不同尺度目标对损失敏感度差异的问题,适用于边界框(BBox)和掩码(Mask)两种标注格式,分为两类具体实现:
1. 边界框专用:SDB Loss(Scale-based Dynamic BBox Loss)
-
适用场景 :针对BBox标注的检测任务,解决小目标IoU损失波动大、位置偏差影响显著的问题。
-
核心组件 :
-
尺度损失( $\mathcal{L}{BS}$ ):基于IoU和边界框宽高比一致性( $\alpha v$ ),公式为 $\mathcal{L}{BS}=1-IoU+\alpha v$ ;
-
位置损失( $\mathcal{L}{BL}$ ):基于预测框与真实框质心的欧氏距离( $\rho$ )和对角线长度( $c$ ),公式为 $\mathcal{L}{BL}=\frac{\rho^{2}(b{p}, b{gt})}{c^{2}} $ ;
-
动态系数( $\betaB$ ):根据目标真实面积( $B{gt}$ )、图像与特征图尺度比( $R{OC}$ )和可调参数 $\delta$ 计算,公式为 $\beta{B}=min\left(\frac{B{gt}}{B{gtmax}} × R{OC} × \delta, \delta\right) $ ( $B{gtmax}=81$ 为红外小目标最大定义尺寸);
-
最终损失: $\mathcal{L}{SDB}=\beta{\mathcal{L}{BS}} × \mathcal{L}{BS}+\beta{\mathcal{L}{BL}} × \mathcal{L}{BL}$ ,其中 $\beta{\mathcal{L}{BS}}=1-\delta +\beta{B}$ 、 $\beta{\mathcal{L}{BL}}=1+\delta -\beta_{B}$ ,动态平衡两类损失的权重。
-
2. 掩码专用:SDM Loss(Scale-based Dynamic Mask Loss)
-
适用场景 :针对Mask标注的分割任务,解决模糊边界导致的IoU波动、小目标位置损失收敛困难的问题。
-
核心组件 :
-
尺度损失( $\mathcal{L}{MS}$ ):基于掩码交并比(IoU)并引入权重 $\omega$ (描述预测与真实掩码差异),公式为 $\mathcal{L}{MS}=1-\omega \frac{|M{p} \bigcap M{gt}|}{|M{p} \bigcup M{gt}|} $ ;
-
位置损失( $\mathcal{L}{ML}$ ):结合极坐标下的距离比和角度差,公式为 $\mathcal{L}{ML}=1-\frac{min(d{p}, d{gt})}{max(d{p}, d{gt})}+\frac{4}{\pi^{2}}(\theta{p}-\theta{gt})^{2} $ ;
-
动态系数( $\beta_M$ ):与SDB Loss的 $\betaB$ 计算逻辑一致,基于掩码真实面积( $M{gt}$ ),公式为 $\beta{M}=min\left(\frac{M{gt}}{M{gtmax}} × R{OC} × \delta, \delta\right) $ ;
-
最终损失: $\mathcal{L}{SDM}=\beta{\mathcal{L}{MS}} × \mathcal{L}{MS}+\beta{\mathcal{L}{ML}} × \mathcal{L}{ML}$ ,其中 $\beta{\mathcal{L}{MS}}=1+\beta{M}$ 、 $\beta{\mathcal{L}{ML}}=1-\beta_{M}$ ,增强尺度损失对小目标的关注度。
-
3. SD Loss的优势
-
动态适配目标尺度:小目标降低SLoss权重、提升LLoss权重(BBox场景)或增强SLoss权重(Mask场景),缓解标注误差影响;
-
计算高效:无指数运算,相比NWD、SAFit等损失函数更稳定、复杂度更低;
-
泛化性强:在IRSTD-1K和SIRST-UAVB数据集上均实现稳定性能提升。
核心代码
def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, SDIoU=True, eps=1e-7, delta=0.5):
"""
Calculate Intersection over Union (IoU) of box1(1, 4) to box2(n, 4).
Args:
box1 (torch.Tensor): A tensor representing a single bounding box with shape (1, 4).
box2 (torch.Tensor): A tensor representing n bounding boxes with shape (n, 4).
xywh (bool, optional): If True, input boxes are in (x, y, w, h) format. If False, input boxes are in
(x1, y1, x2, y2) format. Defaults to True.
GIoU (bool, optional): If True, calculate Generalized IoU. Defaults to False.
DIoU (bool, optional): If True, calculate Distance IoU. Defaults to False.
CIoU (bool, optional): If True, calculate Complete IoU. Defaults to False.
SDIoU (bool, optional): If True, calculate Scale-based Dynamic IoU. Defaults to False.
eps (float, optional): A small value to avoid division by zero. Defaults to 1e-7.
Returns:
(torch.Tensor): IoU, GIoU, DIoU, or CIoU values depending on the specified flags.
"""
# Get the coordinates of bounding boxes
if xywh: # transform from xywh to xyxy
(x1, y1, w1, h1), (x2, y2, w2, h2) = box1.chunk(4, -1), box2.chunk(4, -1)
w1_, h1_, w2_, h2_ = w1 / 2, h1 / 2, w2 / 2, h2 / 2
b1_x1, b1_x2, b1_y1, b1_y2 = x1 - w1_, x1 + w1_, y1 - h1_, y1 + h1_
b2_x1, b2_x2, b2_y1, b2_y2 = x2 - w2_, x2 + w2_, y2 - h2_, y2 + h2_
else: # x1, y1, x2, y2 = box1
b1_x1, b1_y1, b1_x2, b1_y2 = box1.chunk(4, -1)
b2_x1, b2_y1, b2_x2, b2_y2 = box2.chunk(4, -1)
w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + eps
w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps
# Intersection area ∩
inter = (b1_x2.minimum(b2_x2) - b1_x1.maximum(b2_x1)).clamp_(0) * (
b1_y2.minimum(b2_y2) - b1_y1.maximum(b2_y1)
).clamp_(0)
# Union Area U
union = w1 * h1 + w2 * h2 - inter + eps
# IoU
iou = inter / union
# R_oc = 1 # The YOLO bounding box is normalized, so R_oc is equal to 1.
if CIoU or DIoU or GIoU or SDIoU:
cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1) # convex (smallest enclosing box) width
ch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1) # convex height
if CIoU or DIoU or SDIoU: # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
c2 = cw**2 + ch**2 + eps # convex diagonal squared
rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4 # center dist ** 2
if CIoU or SDIoU: # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
v = (4 / math.pi**2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)
with torch.no_grad():
alpha = v / (v - iou + (1 + eps))
if SDIoU:
beta = (w2 * h2 * delta) / 81
beta = torch.where(beta > delta, torch.tensor(delta, device=beta.device), beta)
return delta-beta + (1-delta+beta)*(iou-v*alpha) - (1+delta-beta)*(rho2/c2) # SDIoU
return iou - (rho2 / c2 + v * alpha) # CIoU
return iou - rho2 / c2 # DIoU
c_area = cw * ch + eps # convex area
return iou - (c_area - union) / c_area # GIoU https://arxiv.org/pdf/1902.09630.pdf
return iou # IoU