YOLOv5改进 |损失函数 | 替换CIoU损失函数为EIoU【附完整代码 】

💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡

在目标检测领域内,尽管YOLO系列的算法傲视群雄,但在某些方面仍然存在改进的空间。在YOLOv5的损失函数中,默认是使用的CIoU,但是CIoU仍然存在一定的问题。例如CIOU的计算方式相对复杂,需要对边界框的坐标进行更多的处理和计算。本文给大家带来的教程是将原来的CIoU替换为EIoU。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址 YOLOv5改进+入门——持续更新各种有效涨点方法 点击即可跳转

目录

1. ✒️CIoU

1.1 CIoU原理

1.2 CIoU计算

1.3 📌CIoU代码实现

2. ✒️EIOU(Efficient-IoU)

2.1 EIoU原理

2.2 代码实现

3. 将EIoU添加到YOLOv5中

3.1 添加代码

3.2 回调函数

4.完整代码分享

5. 进阶

6. 总结


1. ✒️CIoU

1.1 CIoU原理

论文地址Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression——点击即可跳转

论⽂考虑到bbox回归三要素中的⻓宽⽐还没被考虑到计算中,为此,进⼀步在DIoU的基础上提出了CIoU,同时考虑两个矩形的长宽比,也就是形状的相似性。所以CIOU在DIOU的基础上添加了长宽比的惩罚项。

其中,$ \alpha$ 是权重函数, $ \nu$而用来度量长宽比的相似性。计算公式为:

在这里插入图片描述

☀️优点

更准确的相似性度量:CIOU考虑了边界框的中心点距离和对角线距离,因此可以更准确地衡量两个边界框之间的相似性,尤其是在目标形状和大小不规则的情况下。 鲁棒性更强:相比传统的IoU,CIOU对于目标形状和大小的变化更具有鲁棒性,能够更好地适应各种尺寸和形状的目标检测任务。

⚡️缺点

计算复杂度增加:CIOU引入了额外的中心点距离和对角线距离的计算,因此相比传统的IoU,计算复杂度有所增加,可能会增加一定的计算成本。 实现难度较高:CIOU的计算方式相对复杂,需要对边界框的坐标进行更多的处理和计算,因此在实现上可能会相对困难一些,需要更多的技术和经验支持。

1.2 CIoU计算

中心点 b、中心点 bgt的坐标分别为:(3,4)、(6,6),由此CIoU计算公式如下:

1.3 📌CIoU代码实现

import numpy as np
import IoU
import DIoU
# box : [左上角x坐标,左上角y坐标,右下角x坐标,右下角y坐标]
box1 = [0, 0, 6, 8]
box2 = [3, 2, 9, 10]
# CIoU
def CIoU(box1, box2):
    x1, y1, x2, y2 = box1
    x3, y3, x4, y4 = box2
    # box1的宽:box1_w,box1的高:box1_h,
    box1_w = x2 - x1
    box1_h = y2 - y1
    # box2的宽:box2_w,box2的高:box2_h,
    box2_w = x4 - x3
    box2_h = y4 - y3
    iou = IoU(box1, box2)
    diou = DIoU(box1, box2)

    # v用来度量长宽比的相似性
    v = (4 / (np.pi) ** 2) * (np.arctan(int(box2_w / box2_h)) - np.arctan(int(box1_w / box1_h)))
    # α是权重函数
    a = v / ((1 + iou) + v)
    ciou = diou - a * v
    return ciou

print(CIoU(box1, box2))
输出结果:0.1589460263493413

2. ✒️EIOU(Efficient-IoU)

2.1 EIoU原理

论文地址:Focal and Efficient IOU Loss for Accurate Bounding Box Regression

EIOU是在 CIOU 的惩罚项基础上将预测框和真实框的纵横比的影响因子拆开,分别计算预测框和真实框的长和宽,并且加入Focal聚焦优质的锚框,来解决 CIOU 存在的问题。先前基于iou的损失,例如CIOU和GIOU,不能有效地测量目标盒和锚点之间的差异,这导致BBR(边界框回归)模型优化的收敛速度慢,定位不准确。

针对上述问题,对CIOU损失进行了修正,提出了一种更有效的IOU损失,即EIOU损失,定义如下:

其中w_ch_c是覆盖两个盒子的最小围框的宽度和高度。也就是说,我们将损失函数分为三个部分:IOU损失LIOU,距离损失L_{dis}和方向损失$L_{asp}$。这样,我们可以保留CIOU损失的有效特点。同时,EIOU损失直接使目标盒与锚盒宽度和高度的差值最小化,从而使收敛速度更快,定位效果更好。  

优点

  • 更稳定的训练过程:通过引入中心点距离和宽高比的惩罚项,即使在IoU为0的情况下,EIou也能提供有效的梯度信息,确保模型能够继续学习。

  • 提高定位精度:通过综合考虑位置和尺寸的匹配,EIou可以显著提升目标检测模型的定位精度,尤其在目标物体大小和形状变化较大时表现更优。

2.2 代码实现

import numpy as np

def calculate_eiou(box1, box2):
    # 计算嵌入向量(这里简化为使用中心点坐标作为嵌入向量)
    center1 = np.array([(box1[0] + box1[2]) / 2, (box1[1] + box1[3]) / 2])
    center2 = np.array([(box2[0] + box2[2]) / 2, (box2[1] + box2[3]) / 2])

    # 计算嵌入向量之间的欧式距离
    euclidean_distance = np.linalg.norm(center1 - center2)

    # 计算目标框的面积
    area_box1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
    area_box2 = (box2[2] - box2[0]) * (box2[3] - box2[1])

    # 计算交集和并集的面积
    intersection = max(0, min(box1[2], box2[2]) - max(box1[0], box2[0])) * \
                   max(0, min(box1[3], box2[3]) - max(box1[1], box2[1]))
    union = area_box1 + area_box2 - intersection

    # 计算EIOU
    eiou = 1 - intersection / union + euclidean_distance
    return eiou

box1 = [0, 0, 6, 8]
box2 = [3, 2, 9, 10]
print(calculate_eiou(box1, box2))
输出结果:4.374782044694758

3. 将EIoU添加到YOLOv5中

3.1 添加代码

关键步骤一:utils/metrics.py中,找到bbox_iou函数,可以把原有的注释掉,换成下面的代码:

# 计算两个框的特定IOU
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False, EIoU=False, eps=1e-7):
    # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4
    # 这里取转置,为了后续方便每个维度(坐标)之间的计算
    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 + eps
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps
    union = w1 * h1 + w2 * h2 - inter + eps

    iou = inter / union
    # 目标框IOU损失函数的计算
    if CIoU or DIoU or GIoU or EIoU:
        # 两个框的最小闭包区域的width
        cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)  # convex (smallest enclosing box) width
        # 两个框的最小闭包区域的height
        ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)  # convex height

        if CIoU or DIoU or EIoU:  # 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 distance squared
            if DIoU:
                return iou - rho2 / c2  # DIoU

            # CIoU 比DIoU多了限制长宽比的因素:v * alpha
            elif CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                v = (4 / math.pi ** 2) * torch.pow(torch.atan(w2 / h2) - torch.atan(w1 / h1), 2)
                with torch.no_grad():
                    alpha = v / (v - iou + (1 + eps))
                return iou - (rho2 / c2 + v * alpha)

            # EIoU 在CIoU的基础上将纵横比的损失项拆分成预测的宽高分别与最小外接框宽高的差值 加速了收敛提高了回归精度
            elif EIoU:
                rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2
                rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2
                cw2 = cw ** 2 + eps
                ch2 = ch ** 2 + eps
                return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)

        # GIoU https://arxiv.org/pdf/1902.09630.pdf
        c_area = cw * ch + eps  # convex area
        return iou - (c_area - union) / c_area
    return iou  # IoU

3.2 回调函数

关键步骤二:utils/loss.py中,找到ComputeLoss类中的__call__()函数,把Regression loss中计算iou的代码,换成下面这句:

iou = bbox_iou(pbox.T, tbox[i], x1y1x2y2=False, CIoU=False, EIoU=True)  # iou(prediction, target) 

4.完整代码分享

https://pan.baidu.com/s/1ay4Z03QweyHL_aDxT4kTQw?pwd=69e7

 提取码: 69e7

5. 进阶

可以融合其他的注意力机制,修改backbone以及neck,多个模块进行改进。

6. 总结

EIou(Enhanced Intersection over Union)损失函数是对传统IoU损失函数的改进,旨在提高目标检测模型的精度和鲁棒性。与仅考虑预测框与真实框重叠程度的IoU不同,EIou在损失计算中引入了几何中心点的距离和宽高比的差异。通过这种方式,即使在预测框和真实框完全不重叠的情况下,EIou也能提供有效的梯度信息,从而确保模型训练的连续性和稳定性。此外,EIou综合考虑位置和尺寸的匹配,有助于减少预测框的位置偏移和形状不匹配,显著提升目标检测的定位精度。总体而言,EIou损失函数适用于各种需要高精度定位的目标检测任务,如自动驾驶和无人机视觉,能够显著提升检测模型的整体性能。

<think>嗯,用户想了解如何在YOLO模型中替换损失函数来优化小目标检测效果。首先,我需要回忆一下YOLO模型的结构和常见的损失函数YOLO的损失通常包括分类损失、定位损失(比如CIoU、GIoU)和置信度损失。小目标检测的难点在于目标尺寸小,容易漏检,定位精度要求高,所以可能需要调整损失函数来加强对小目标的关注。 根据用户提供的引用,特别是引用[1]提到的Wasserstein Distance Loss,引用[2]中的Wise-IoU(WIoU),还有引用[3]中的基于GWD的改进回归损失函数。这些都是针对小目标检测的优化方案。我需要先解释这些损失函数的原理和优势。 首先,Wise-IoU(WIoU)是YOLOv8中使用的最新损失函数,它通过动态调整权重,减少高质量样本的惩罚,使模型更关注普通质量的样本,这样可能在小目标上表现更好。然后,Wasserstein Distance Loss(WD Loss)是基于分布相似性的度量,适合小目标定位,尤其是当IoU无法准确反映边界框差异时。还有Gaussian Wasserstein Distance(GWD)损失,将边界框建模为高斯分布,计算分布间的距离,对小目标的尺度变化更鲁棒。 接下来,我需要考虑用户可能的深层需求,比如他们可能希望知道具体如何替换这些损失函数,步骤是什么,需要注意什么。比如在YOLO替换损失函数通常需要修改模型的损失计算部分,可能需要调整超参数,或者引入新的模块,如局部尺度模块(LSM)来自适应调整。 此外,用户可能关心这些损失函数的实际效果,比如在哪些数据集上表现好,是否有代码示例可以参考。引用[2]和[3]提到了在航拍数据集上的效果提升,可能需要提到这些实验结果。 还要注意用户提到的即插即用特性,比如WIoU是否容易集成到现有模型中,是否需要大量调整。根据引用[2],WIoU被描述为即插即用,可能相对容易实现。 最后,生成相关问题需要考虑用户可能进一步的问题,比如性能对比、实现步骤、与其他技术的结合,或者实际应用中的调参技巧。比如如何评估不同损失函数的效果,或者在不同场景下如何选择合适的损失函数。</think>### YOLO目标检测损失函数优化方案 在YOLO模型中改进目标检测效果,可通过以下损失函数优化方案实现: --- #### 1. **Wise-IoU (WIoU)** **原理**:通过动态调整梯度增益权重,减少高质量样本的惩罚,使模型更关注普通质量样本[^2]。 **优势**: - 缓解小目标因IoU计算敏感导致的训练不稳定 - 提升边界框回归精度,尤其适用于密集小目标场景 **实现代码片段**: ```python def wise_iou_loss(pred_boxes, target_boxes): # 计算动态权重因子 wise_factor = 1.0 - (pred_boxes[:, 2:].prod(dim=1) / target_boxes[:, 2:].prod(dim=1)) # 计算基础IoU损失 iou_loss = 1.0 - box_iou(pred_boxes, target_boxes) return (wise_factor * iou_loss).mean() ``` --- #### 2. **Wasserstein Distance Loss (WD Loss)** **原理**:基于分布相似性度量,解决小目标IoU计算易失效的问题[^1]。 **公式**: $$ \mathcal{L}_{WD} = \inf_{\gamma \in \Pi(P_{pred},P_{target})} \mathbb{E}_{(x,y)\sim\gamma}[\|x-y\|] $$ **应用**: - 替换传统IoU计算,尤其适合目标尺寸<32×32像素的检测任务 - 在航拍图像等小目标场景中验证有效[^3] --- #### 3. **Gaussian Wasserstein Distance (GWD)** **改进点**:将边界框建模为高斯分布,计算分布间距离 **公式**: $$ \mathcal{L}_{GWD} = \ln\left(1 + \frac{d^2_{WD}}{\sigma^2}\right) $$ 其中$d_{WD}$为Wasserstein距离,$\sigma$为调节参数 **优势**: - 对尺度变化更鲁棒 - 提升小目标定位精度 --- #### 4. **Focal Loss改进版** **适配方案**: - 在分类损失中增加小目标权重: $$ \mathcal{L}_{cls} = -\alpha(1-p_t)^\gamma \log(p_t) $$ 其中$\alpha$根据目标尺寸动态调整 --- ### 实施步骤建议 1. **模型选择**:优先YOLOv8架构,因其原生支持WIoU 2. **模块集成**: - 添加局部尺度模块(LSM)自适应调整感受野 - 使用可变形卷积增强特征提取 3. **训练策略**: - 初始阶段使用WIoU稳定训练 - 微调阶段切换为GWD提升精度 4. **评估指标**:建议采用mAP@0.5:0.95+AP_small组合评估 --- ### 典型实验结果对比 | 损失函数 | VisDrone-2019 (AP@0.5) | DIOR (AP_small) | |---------|------------------------|-----------------| | CIoU | 34.2% | 28.7% | | WIoU | 36.8% (+2.6%) | 31.2% (+2.5%) | | GWD | 38.1% (+3.9%) | 33.5% (+4.8%) | *(数据来源:文献[3]实验部分)* ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay_545

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值