YOLOv10改进 | 注意力机制 | 轻量级的空间组增强模块SGE【全网独家】

秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转  


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


专栏目录:《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进


卷积神经网络(CNN)通过收集复杂对象的分层和不同部分的语义子特征来生成特征表示。这些子特征通常在每个层的特征向量中以分组形式分布,代表各种语义实体。然而,这些子特征的激活往往受到相似模式和噪声背景的空间影响,导致错误的定位和识别。我们提出了一个空间组增强(SGE)模块,该模块可以为每个语义组中每个空间位置生成一个注意力因子从而调整每个子特征的重要性,以便每个组可以自主地增强其学习的表达并抑制可能的噪声。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

 专栏地址YOLOv10入门 + 涨点——持续更新各种涨点方法

目录

1. 原理

2. 将SGE添加到YOLOv8中

2.1 代码实现

2.2 更改init.py文件

2.3 新增yaml文件

2.4 注册模块

2.5 执行程序

3. 完整代码分享

4.GFLOPs

5. 进阶

6. 总结


1. 原理

论文地址:Spatial Group-wise Enhance: Improving Semantic Feature Learning in Convolutional Networks——点击即可跳转

官方代码:官方代码仓库——点击即可跳转

空间分组增强 (SGE) 模块旨在通过解决特征图中的空间错位和噪声来改进卷积神经网络 (CNN) 中的语义特征学习。以下是 SGE 模块的主要原理和机制:

分组特征

  • 特征沿卷积特征图的通道维度分组。这意味着将特征图分成几个组,每个组包含通道的子集。

注意机制

  • 在每个组中,根据全局特征和局部特征之间的相似性生成注意掩码。全局特征是组内所有特征的平均值,局部特征是该组内特定空间位置的特征。

  • 注意掩码用于缩放每个空间位置的特征向量,增强重要特征并抑制噪声。这有助于确保语义特征在图像的空间维度上分布良好且稳健。

轻量级设计

  • SGE 模块的设计具有计算效率,几乎不需要额外的参数或计算。这是通过使用点积和归一化等简单操作来生成注意掩码来实现的。

归一化和缩放

  • 计算基于相似性的系数(注意分数)后,对其进行归一化,以确保不同样本之间的缩放一致。这涉及减去平均值并除以每个组内系数的标准差。

  • 然后使用可学习的参数对归一化的分数进行缩放和移位,确保网络可以在训练期间灵活调整 SGE 模块的影响。

性能提升

  • 事实证明,SGE 模块可以提高各种 CNN 架构在图像识别任务上的性能。它可以提高 ImageNet 基准测试中的 Top-1 准确率,并提高 COCO 基准测试中物体检测任务的平均准确率 (AP)。

总体而言,SGE 模块增强了每个组内语义特征的空间分布,从而使 CNN 中的特征表示更加准确和稳健。

2. 将SGE添加到YOLOv8中

2.1 代码实现

关键步骤一:将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/block.py中,并在该文件的__all__中添加“SpatialGroupEnhance”

from torch.nn import init

class SpatialGroupEnhance(nn.Module):
    def __init__(self, groups=8):
        super().__init__()
        self.groups = groups
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.weight = nn.Parameter(torch.zeros(1, groups, 1, 1))
        self.bias = nn.Parameter(torch.zeros(1, groups, 1, 1))
        self.sig = nn.Sigmoid()
        self.init_weights()

    def init_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                init.kaiming_normal_(m.weight, mode='fan_out')
                if m.bias is not None:
                    init.constant_(m.bias, 0)
            elif isinstance(m, nn.BatchNorm2d):
                init.constant_(m.weight, 1)
                init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                init.normal_(m.weight, std=0.001)
                if m.bias is not None:
                    init.constant_(m.bias, 0)

    def forward(self, x):
        b, c, h, w = x.shape
        x = x.view(b * self.groups, -1, h, w)  # bs*g,dim//g,h,w
        xn = x * self.avg_pool(x)  # bs*g,dim//g,h,w
        xn = xn.sum(dim=1, keepdim=True)  # bs*g,1,h,w
        t = xn.view(b * self.groups, -1)  # bs*g,h*w

        t = t - t.mean(dim=1, keepdim=True)  # bs*g,h*w
        std = t.std(dim=1, keepdim=True) + 1e-5
        t = t / std  # bs*g,h*w
        t = t.view(b, self.groups, h, w)  # bs,g,h*w

        t = t * self.weight + self.bias  # bs,g,h*w
        t = t.view(b * self.groups, 1, h, w)  # bs*g,1,h*w
        x = x * self.sig(t)
        x = x.view(b, c, h, w)
        return x

SGE 模块的核心思想是在每个特征组内部进行空间增强,以提升特征学习的精度和鲁棒性。 具体步骤如下

  1. 特征分组: 将特征图沿通道维度分成多个组,每个组包含代表特定语义的子特征。

  2. 全局特征提取: 对每个组内的所有特征进行全局平均池化,得到一个全局特征向量,代表该组学习的语义信息。

  3. 注意力权重生成: 计算全局特征向量与组内每个位置的特征向量之间的相似度,生成注意力权重向量。相似度越高,注意力权重越大。

  4. 特征增强: 将注意力权重向量通过 sigmoid 函数进行非线性变换,并与原始特征向量相乘,得到增强后的特征向量。 SGE 模块的优点

  • 轻量级: 仅引入少量参数,几乎没有额外的计算量。

  • 高效: 有效提升特征学习的精度和鲁棒性,尤其是在识别具有高级语义的区域时。

  • 可解释性强: 通过可视化注意力权重,可以直观地理解每个组学习的语义信息。

SGE 模块在图像分类和目标检测任务中都取得了显著的性能提升,证明了其在实践中的有效性

2.2 更改init.py文件

关键步骤二:修改modules文件夹下的__init__.py文件,先导入函数

然后在下面的__all__中声明函数

2.3 新增yaml文件

关键步骤三:在 \ultralytics\ultralytics\cfg\models\v10下新建文件 yolov10_SGE.yaml并将下面代码复制进去

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv10 object detection model. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  b: [0.67, 1.00, 512]

backbone:
  # [from, repeats, module, args]
  - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 6, C2f, [256, True]]
  - [-1, 1, SCDown, [512, 3, 2]] # 5-P4/16
  - [-1, 6, C2f, [512, True]]
  - [-1, 1, SCDown, [1024, 3, 2]] # 7-P5/32
  - [-1, 3, C2fCIB, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]] # 9
  - [-1, 1, PSA, [1024]] # 10

# YOLOv10.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 6], 1, Concat, [1]] # cat backbone P4
  - [-1, 3, C2fCIB, [512, True]] # 13

  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 4], 1, Concat, [1]] # cat backbone P3
  - [-1, 3, C2f, [256]] # 16 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 13], 1, Concat, [1]] # cat head P4
  - [-1, 3, C2fCIB, [512, True]] # 19 (P4/16-medium)
  - [ -1, 1, SpatialGroupEnhance, [ 512 ] ]

  - [-1, 1, SCDown, [512, 3, 2]]
  - [[-1, 10], 1, Concat, [1]] # cat head P5
  - [-1, 3, C2fCIB, [1024, True]] # 22 (P5/32-large)
  - [ -1, 1, SpatialGroupEnhance, [ 1024 ] ]

  - [[16, 19, 22], 1, v10Detect, [nc]] # Detect(P3, P4, P5)

温馨提示:因为本文只是对yolov8基础上添加模块,如果要对yolov8n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。


# YOLOv10n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
max_channels: 1024 # max_channels
 
# YOLOv10s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
max_channels: 1024 # max_channels
 
# YOLOv10l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
max_channels: 512 # max_channels
 
# YOLOv10m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple
max_channels: 768 # max_channels
 
# YOLOv10x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple
max_channels: 512 # max_channels

2.4 注册模块

关键步骤四:在parse_model函数中进行注册,添加SpatialGroupEnhance,

elif m is SpatialGroupEnhance:
            c1, c2 = ch[f], args[0]
            if c2 != nc:  # if c2 not equal to number of classes (i.e. for Classify() output)
                c2 = make_divisible(min(c2, max_channels) * width, 8)
            args = [c1, *args[1:]]

2.5 执行程序

在train.py中,将model的参数路径设置为yolov8_SGE.yaml的路径

建议大家写绝对路径,确保一定能找到

from ultralytics import YOLO
 
# Load a model
# model = YOLO('yolov8n.yaml')  # build a new model from YAML
# model = YOLO('yolov8n.pt')  # load a pretrained model (recommended for training)
 
model = YOLO(r'/projects/ultralytics/ultralytics/cfg/models/v8/yolov8_SGE.yaml')  # build from YAML and transfer weights
 
# Train the model
model.train(device = [3], batch=16)

🚀运行程序,如果出现下面的内容则说明添加成功🚀

3. 完整代码分享

https://pan.baidu.com/s/1ZW9GSgV7349X5io_4o4iGw?pwd=rs2b

提取码: rs2b 

4.GFLOPs

关于GFLOPs的计算方式可以查看百面算法工程师 | 卷积基础知识——Convolution

未改进的YOLOv10l的GFLOPs

改进后的GFLOPs

5. 进阶

可以与其他的注意力机制或者损失函数等结合,进一步提升检测效果

6. 总结

空间分组增强 (SGE) 模块通过解决特征图中的空间错位和噪声问题,改进了卷积神经网络中的语义特征学习。它沿通道维度对特征进行分组,并在每个组中使用注意机制,根据全局特征和局部特征之间的相似性生成注意掩码。这些掩码增强了重要特征,同时抑制了噪声,确保了语义特征的稳健性和分布性。SGE 模块具有计算效率,只需要极少的附加参数,并使用可学习的参数对注意力分数进行归一化和缩放。这种方法提高了 CNN 在图像识别和物体检测任务上的性能,提高了准确率和精确度。

  • 28
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

kay_545

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

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

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

打赏作者

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

抵扣说明:

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

余额充值