YOLOv10改进 | EIoU、SIoU、WIoU、DIoU、FocusIoU等二十余种损失函数

news2024/12/27 13:38:18

一、本文介绍

这篇文章介绍了YOLOv10的重大改进,特别是在损失函数方面的创新。它不仅包括了多种IoU损失函数的改进和变体,如SIoU、WIoU、GIoU、DIoU、EIOU、CIoU,还融合了“Focus”思想,创造了一系列新的损失函数。这些组合形式的损失函数超过了二十余种,每种都针对特定的目标检测挑战进行优化。文章会详细探讨这些损失函数如何提高YOLOv10在各种检测任务中的性能,包括提升精度、加快收敛速度和增强模型对复杂场景的适应性本文章主要是为了发最近新出的Inner思想改进的各种EIoU的文章服务,其中我经过实验在绝大多数下的效果都要比本文中提到的各种损失效果要好。 

 专栏回顾:YOLOv10改进系列专栏——本专栏持续复习各种顶会内容——科研必备 

本文代码地址: 文末提供完整代码块-包括EIoU、CIoU、DIoU等七种损失和其Focus变种


目录

一、本文介绍

 二、各种损失函数的基本原理 

2.1 交集面积和并集面积

2.2 IoU

2.3 SIoU

2.4 WioU

2.5 GIoU

2.6 DIoU

2.7 EIoU

2.8 CIoU

2.9 FocusLoss 

三、EIoU、SIoU、EIoU、FocusIoU等损失函数代码块

3.1 代码一

3.2 代码二 

四、添加EIoU、SIoU、EIoU、FocusIoU等损失函数到模型中

五、总结


 二、各种损失函数的基本原理 

2.1 交集面积和并集面积

在理解各种损失函数之前我们需要先来理解一下交集面积和并集面积,在数学中我们都学习过集合的概念,这里的交集和并集的概念和数学集合中的含义是一样的


2.2 IoU

论文地址:IoU Loss for 2D/3D Object Detectio

适用场景:普通的IoU并没有特定的适用场景

概念: 测量预测边界框和真实边界框之间的重叠度(最基本的边界框损失函数,后面的都是居于其进行计算)。


2.3 SIoU

论文地址:SIoU: More Powerful Learning for Bounding Box Regression

适用场景:适用于需要高精度边界框对齐的场景,如精细的物体检测和小目标检测。

概念: SIoU损失通过融入角度考虑和规模敏感性,引入了一种更为复杂的边界框回归方法,解决了以往损失函数的局限性,SIoU损失函数包含四个组成部分:角度损失、距离损失、形状损失和第四个未指定的组成部分。通过整合这些方面,从而实现更好的训练速度和预测准确性。


2.4 WioU

论文地址WIoU: Bounding Box Regression Loss with Dynamic Focusing Mechanism

适用场景:适用于需要动态调整损失焦点的情况,如不均匀分布的目标或不同尺度的目标检测。

概念:引入动态聚焦机制的IoU变体,旨在改善边界框回归损失。


2.5 GIoU

论文地址:GIoU: A Metric and A Loss for Bounding Box Regression

适用场景:适合处理有重叠和非重叠区域的复杂场景,如拥挤场景的目标检测。

概念: 在IoU的基础上考虑非重叠区域,以更全面评估边界框


2.6 DIoU

论文地址:DIoU: Faster and Better Learning for Bounding Box Regression

适用场景:适用于需要快速收敛和精确定位的任务,特别是在边界框定位精度至关重要的场景。

概念:结合边界框中心点之间的距离和重叠区域。


2.7 EIoU

论文地址:EIoU:Loss for Accurate Bounding Box Regression

适用场景:可用于需要进一步优化边界框对齐和形状相似性的高级场景。

概念:EIoU损失函数的核心思想在于提高边界框回归的准确性和效率。它通过以下几个方面来优化目标检测:

1. 增加中心点距离损失:通过最小化预测框和真实框中心点之间的距离,提高边界框的定位准确性。

2. 考虑尺寸差异:通过惩罚宽度和高度的差异,EIoU确保预测框在形状上更接近真实框。

3. 结合最小封闭框尺寸:将损失函数与包含预测框和真实框的最小封闭框的尺寸相结合,从而使得损失更加敏感于对象的尺寸和位置。

EIoU损失函数在传统IoU基础上增加了这些考量,以期在各种尺度上都能获得更精确的目标定位,尤其是在物体大小和形状变化较大的场景中。


2.8 CIoU

论文地址:CIoU:Enhancing Geometric Factors in Model Learning

适用场景:适合需要综合考虑重叠区域、形状和中心点位置的场景,如复杂背景或多目标跟踪。

概念:综合考虑重叠区域、中心点距离和长宽比。


2.9 FocusLoss 

论文地址:Focal Loss for Dense Object Detection

适用场景:适用于需要高精度边界框对齐的场景,如精细的物体检测和小目标检测。 

Focal Loss由Kaiming He等人在论文《Focal Loss for Dense Object Detection》中提出,旨在解决在训练过程中正负样本数量极度不平衡的问题,尤其是在一些目标检测任务中,背景类别的样本可能远远多于前景类别的样本。

Focal Loss通过修改交叉熵损失,增加一个调整因子这个因子降低了那些已经被正确分类的样本的损失值,使得模型的训练焦点更多地放在难以分类的样本上。这种方式特别有利于提升小目标或者在复杂背景中容易被忽视的目标的检测性能。简而言之,Focal Loss让模型“关注”(或“专注”)于学习那些对提高整体性能更为关键的样本。


三、EIoU、SIoU、EIoU、FocusIoU等损失函数代码块

3.1 代码一

此代码块块的基础版本来源于Github的开源版本,我在其基础上将Inner的思想加入其中形成了各种Inner的思想同时融合各种改良版本的损失函数形成对应版本的InnerIoU、InnerCIoU等损失函数。

import numpy as np
import torch, math

class WIoU_Scale:
    ''' monotonous: {
            None: origin v1
            True: monotonic FM v2
            False: non-monotonic FM v3
        }
        momentum: The momentum of running mean'''
    
    iou_mean = 1.
    monotonous = False
    _momentum = 1 - 0.5 ** (1 / 7000)
    _is_train = True

    def __init__(self, iou):
        self.iou = iou
        self._update(self)
    
    @classmethod
    def _update(cls, self):
        if cls._is_train: cls.iou_mean = (1 - cls._momentum) * cls.iou_mean + \
                                         cls._momentum * self.iou.detach().mean().item()
    
    @classmethod
    def _scaled_loss(cls, self, gamma=1.9, delta=3):
        if isinstance(self.monotonous, bool):
            if self.monotonous:
                return (self.iou.detach() / self.iou_mean).sqrt()
            else:
                beta = self.iou.detach() / self.iou_mean
                alpha = delta * torch.pow(gamma, beta - delta)
                return beta / alpha
        return 1

def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, SIoU=False, EIoU=False, WIoU=False, Focal=False, alpha=1, gamma=0.5, scale=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 xywh:  # 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
    if scale:
        self = WIoU_Scale(1 - (inter / union))

    # IoU
    # iou = inter / union # ori iou
    iou = torch.pow(inter/(union + eps), alpha) # alpha iou
    if CIoU or DIoU or GIoU or EIoU or SIoU or WIoU:
        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 EIoU or SIoU or WIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            c2 = (cw ** 2 + ch ** 2) ** alpha + eps  # convex diagonal squared
            rho2 = (((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4) ** alpha  # center dist ** 2
            if CIoU:  # 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_ciou = v / (v - iou + (1 + eps))
                if Focal:
                    return iou - (rho2 / c2 + torch.pow(v * alpha_ciou + eps, alpha)), torch.pow(inter/(union + eps), gamma)  # Focal_CIoU
                else:
                    return iou - (rho2 / c2 + torch.pow(v * alpha_ciou + eps, alpha))  # 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 = torch.pow(cw ** 2 + eps, alpha)
                ch2 = torch.pow(ch ** 2 + eps, alpha)
                if Focal:
                    return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2), torch.pow(inter/(union + eps), gamma) # Focal_EIou
                else:
                    return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2) # EIou
            elif SIoU:
                # SIoU Loss https://arxiv.org/pdf/2205.12740.pdf
                s_cw = (b2_x1 + b2_x2 - b1_x1 - b1_x2) * 0.5 + eps
                s_ch = (b2_y1 + b2_y2 - b1_y1 - b1_y2) * 0.5 + eps
                sigma = torch.pow(s_cw ** 2 + s_ch ** 2, 0.5)
                sin_alpha_1 = torch.abs(s_cw) / sigma
                sin_alpha_2 = torch.abs(s_ch) / sigma
                threshold = pow(2, 0.5) / 2
                sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)
                angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - math.pi / 2)
                rho_x = (s_cw / cw) ** 2
                rho_y = (s_ch / ch) ** 2
                gamma = angle_cost - 2
                distance_cost = 2 - torch.exp(gamma * rho_x) - torch.exp(gamma * rho_y)
                omiga_w = torch.abs(w1 - w2) / torch.max(w1, w2)
                omiga_h = torch.abs(h1 - h2) / torch.max(h1, h2)
                shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4) + torch.pow(1 - torch.exp(-1 * omiga_h), 4)
                if Focal:
                    return iou - torch.pow(0.5 * (distance_cost + shape_cost) + eps, alpha), torch.pow(inter/(union + eps), gamma) # Focal_SIou
                else:
                    return iou - torch.pow(0.5 * (distance_cost + shape_cost) + eps, alpha) # SIou
            elif WIoU:
                if Focal:
                    raise RuntimeError("WIoU do not support Focal.")
                elif scale:
                    return getattr(WIoU_Scale, '_scaled_loss')(self), (1 - iou) * torch.exp((rho2 / c2)), iou # WIoU https://arxiv.org/abs/2301.10051
                else:
                    return iou, torch.exp((rho2 / c2)) # WIoU v1
            if Focal:
                return iou - rho2 / c2, torch.pow(inter/(union + eps), gamma)  # Focal_DIoU
            else:
                return iou - rho2 / c2  # DIoU
        c_area = cw * ch + eps  # convex area
        if Focal:
            return iou - torch.pow((c_area - union) / c_area + eps, alpha), torch.pow(inter/(union + eps), gamma)  # Focal_GIoU https://arxiv.org/pdf/1902.09630.pdf
        else:
            return iou - torch.pow((c_area - union) / c_area + eps, alpha)  # GIoU https://arxiv.org/pdf/1902.09630.pdf
    if Focal:
        return iou, torch.pow(inter/(union + eps), gamma)  # Focal_IoU
    else:
        return iou  # IoU

3.2 代码二 

代码块二此处是使用Focus时候需要修改的代码,如果不适用则不需要修改下面的代码,因为利用Focus机制时候返回的类型是元组所以需要额外的处理。 

        if type(iou) is tuple:
            if len(iou) == 2:
                # Focus Loss 时返回的是元组类型,进行额外处理
                loss_iou = ((1.0 - iou[0]) * iou[1].detach() * weight).sum() / target_scores_sum
            else:
                loss_iou = (iou[0] * iou[1] * weight).sum() / target_scores_sum

        else:
            # 正常的损失函数
            loss_iou = ((1.0 - iou) * weight).sum() / target_scores_sum


四、添加EIoU、SIoU、EIoU、FocusIoU等损失函数到模型中

4.1 修改一

第一步我们需要找到如下的文件ultralytics/utils/metrics.py,找到如下的代码,下面的图片是原先的代码部分截图的正常样子,然后我们将整个代码块一将下面的整个方法(这里这是部分截图)内容全部替换


4.2 修改二

第二步我们找到另一个文件如下->"ultralytics/utils/loss.py",我们找到如下的代码块,将代码块二替换其中的第74行,

同时在上面的第73行(我说的我图片这里的不一定代表你那里,替换成如下的形式),按照下面代码设置即可!

        # 想用那个对应的设置为True即可,比如我想用EIoU,那么我只需要把EIoU设置为True,那么此时就是EIoU!
                           xywh=False, GIoU=False, DIoU=False, CIoU=True, EIoU=False, SIoU=False, WIoU=False, Focal=False, ratio=0.75)


4.3 修改三

修改完上面的第二步,我们需要找到如下文件"ultralytics/utils/tal.py",在这个文件中我们找到如下的代码块,我这里已经修改完了,这里的使用保持和修改二一致(这里不要开启Focus的如果步骤二开启这里也不要开启)


五、总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv10改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~),如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1908602.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

充分利用视觉信息多问多答合成数据,提升多模态大模型数学推理能力

©PaperWeekly 原创 作者 | 史文浩 单位 | 电子科技大学 论文题目: Math-LLaVA: Bootstrapping Mathematical Reasoning for Multimodal Large Language Models 论文链接: https://arxiv.org/abs/2406.17294 开源链接: https://github.c…

鸿蒙开发HarmonyOS NEXT (三) 熟悉ArkTs (上)

一、自定义组件 1、自定义组件 自定义组件,最基础的结构如下: Component struct Header {build() {} } 提取头部标题部分的代码,写成自定义组件。 1、新建ArkTs文件,把Header内容写好。 2、在需要用到的地方,导入…

Django 新增数据 create()方法

1,添加模型 Test/app11/models.py from django.db import modelsclass Book(models.Model):title models.CharField(max_length100)author models.CharField(max_length100)publication_date models.DateField()price models.DecimalField(max_digits5, decim…

后门攻击检测指南--windowsLinuxweb

免责声明:本文仅做技术交流与学习... 目录 Win d o w s - 后 门 - 常 规 & 权 限 维 持& 内 存 马 Lin u x - 后 门 - 常 规 & 权 限 维 持 & R o o t kit& 内 存 马 关于Rootkit的检测: web层面-后门--内存马 Win d o w s - 后 门 - 常 规…

构建LangChain应用程序的示例代码:58、如何使用 Nomic 的新嵌入模型构建和部署一个检索增强生成(RAG)应用

Nomic 嵌入模型 Nomic 发布了一个新的嵌入模型,在长上下文检索方面表现出色(8k上下文窗口)。 本教程将介绍使用 Nomic 嵌入构建和部署(通过 LangServe)RAG 应用的过程。 注册 获取您的 API 令牌,然后运行: ! nomic login然后使用您生成的 API 令牌运行 ! nomic login <…

vue-使用Worker实现多标签页共享一个WebSocket

文章目录 前言一、SharedWorker 是什么SharedWorker 是什么SharedWorker 的使用方式SharedWorker 标识与独占 二、Demo使用三、使用SharedWorker实现WebSocket共享 前言 最近有一个需求&#xff0c;需要实现用户系统消息时时提醒功能。第一时间就是想用WebSocket进行长连接。但…

WordPress开发进群V2主题源码,多种引流方法,引私域二次变现

WordPress开发进群V2主题源码&#xff0c;多种引流方法&#xff0c;引私域二次变现 全新前端UI界面&#xff0c;多种前端交互特效让页面不再单调&#xff0c;进群页面群成员数&#xff0c;群成员头像名称&#xff0c;每次刷新页面随机更新不重复&#xff0c;最下面评论和点赞也…

产品经理-交互设计动手实践(11)

业内有很多画交互的工具&#xff0c;这里不过多介绍&#xff0c;互联网公司最常用的工具是Axure,墨刀,蓝湖,小瀑 它是一个专业的快速原型设计工具&#xff0c;使用它能够快速创建线框图、流程图、原型和规格说明文档。 它能快速、高效地创建原型&#xff0c;同时支持多人协作设…

Java进阶----继承

继承 一.继承概述 继承是可以通过定义新的类&#xff0c;在已有类的基础上扩展属性和功能的一种技术. 案例&#xff1a;优化 猫、狗JavaBean类的设计 狗类&#xff1a;Dog 属性&#xff1a;名字 name&#xff0c;年龄 age 方法&#xff1a;看家 watchHome()&#xff0c;Gett…

机器学习统计学基础 - 最大似然估计

最大似然估计&#xff08;Maximum Likelihood Estimation, MLE&#xff09;是一种常用的参数估计方法&#xff0c;其基本原理是通过最大化观测数据出现的概率来寻找最优的参数估计值。具体来说&#xff0c;最大似然估计的核心思想是利用已知的样本结果&#xff0c;反推最有可能…

自定义类TMyLabel继承自QLabel ,实现mouseDoubleClickEvent

自定义类TMyLabel &#xff0c;继承自QLabel TMyLabel 中重新实现了 event 方法&#xff0c;重写了mouseDoubleClickEvent 发射信号 在主窗体中放入TMyLabel组件&#xff0c;将TMyLabel mouseDoubleClickEvent 信号&#xff0c; 绑定到实现方法do_doubleClick()槽函数 TMy…

知识付费系统3.0整站源码知识付费网课平台网创资源付费带自动采集同步插件

程序说明&#xff1a; 1.修复更新到最新版本 2.自动采集插件重写 3.关闭采集授权域名直接对接 4.更新插件主动请求同步资源 5.带自动采集插件 原始功能 支持分类替换 将主站同步过来的文章分类进行替换 支持自定义文章作者&#xff08;选择多个作者则同步到的文章作者将会随机分…

已解决 javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法,亲测有效!!!

已解决 javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 一、问题分析 二、报错原因 三、解决思路 四、解决方法 五、总结 博主v&#xff1a;XiaoMing_Java 博主v&#x…

Desktop docker 部署 WordPress

Desktop Docker 部署 WordPress 之前都是在Linux里面玩的&#xff0c;今天看到别人在windwos下安装docker&#xff0c;一时兴起装了一个试试&#xff0c;效果一般&#xff0c;很吃硬盘空间和内存。 首先在docker官方下载桌面版&#xff0c;安装下一步一直到完成。 安装完docke…

C++初阶:从C过渡到C++的入门基础

✨✨所属专栏&#xff1a;C✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ C发展历史 C的起源可以追溯到1979年&#xff0c;当时BjarneStroustrup(本贾尼斯特劳斯特卢普&#xff0c;这个翻译的名字不同的地⽅可能有差异)在⻉尔实验室从事计算机科学和软件⼯程的研究⼯作。⾯对项⽬中复…

ubantu安装k8s集群服务

进行主机优化配置 参考&#xff1a; 修改主机名称 hostnamectl set-hostname k8s-node03 关闭swap分区 swapoff -a #临时关闭 sed -i /\/swap/s/^/# /etc/fstab #永久关闭 增加主机解析 cat >> /etc/hosts << EOF 10.1.60.119 k8s-master01 10.1.60.12…

ArcGIS:探索地理信息系统的强大功能与实际应用

ArcGIS是一款功能强大的地理信息系统&#xff08;GIS&#xff09;软件&#xff0c;由Esri公司开发。它广泛应用于各个领域&#xff0c;包括城市规划、环境保护、资源管理、交通运输等。作为一名长期使用ArcGIS的用户&#xff0c;我深感这款软件在数据分析、地图制作和空间信息管…

ROS编译错误: fatal error: test_pkg/test_pkg.h: 没有那个文件

在ROS安装完毕后编译ros工作空间&#xff0c;出现了以下错误: 解决方法: 删除工作空间&#xff0c;重建再重新编译

Android EditText+ListPopupWindow实现可编辑的下拉列表

Android EditTextListPopupWindow实现可编辑的下拉列表 &#x1f4d6;1. 可编辑的下拉列表✅步骤一&#xff1a;准备视图✅步骤二&#xff1a;封装显示方法✅步骤三&#xff1a;获取视图并监听 &#x1f4d6;2. 扩展上下箭头✅步骤一&#xff1a;准备上下箭头icon图标✅步骤二&…

基于stm32开发的红外循迹小车

本项目算是接触32来开发的第一个小项目了&#xff0c;虽然前期用51写过一个循迹小车&#xff0c;以为直接转到32会比较简单&#xff0c;结果还是花了大几天才把小车的参数完全调完&#xff0c;以此来记录下自己的学习历程&#xff08;注&#xff1a;循迹算法并未加入PID算法&am…