YOLO11 改进 – 注意力机制 _ EMA (Efficient Multi-Scale Attention) 高效多尺度注意力:跨空间学习与多分支协同增强特征表征,优化多尺度目标检测

前言

本文介绍了高效多尺度注意力(EMA)模块及其在YOLOv11中的结合应用。现有注意力机制在通道维度缩减时可能影响深度视觉表示,EMA模块通过结合通道和空间信息、采用多尺度并行子网络结构等创新点,实现了高效的多尺度注意力机制。其基本原理包括通道和空间注意力结合、多尺度并行子网络设计等。在多个流行基准数据集上的实验表明,该模块能有效提高特征表示能力。我们将EMA集成进YOLOv11,实验证明改进后的模型在目标检测任务中性能优越,具有广泛应用前景。

文章目录: YOLOv11改进大全:卷积层、轻量化、注意力机制、损失函数、Backbone、SPPF、Neck、检测头全方位优化汇总

专栏链接: YOLOv11改进专栏

文章目录

[TOC]

介绍

摘要

通道与空间注意力机制在众多计算机视觉任务中展现出卓越性能,能够生成更为清晰的特征表征,然而通过通道维度缩减来建模跨通道关系可能对深度视觉表征的提取产生负面影响。针对此问题,本文提出了一种新颖高效的多尺度注意力(EMA)模块,该模块着重于保持各通道信息的完整性同时降低计算复杂度。具体实现中,我们将部分通道重新调整至批次维度,并将通道维度划分为多个子特征组,确保空间语义特征在各特征组内均匀分布。在技术细节上,除了在各并行分支中对全局信息进行编码以实现通道权重的重新校准外,两个并行分支的输出特征还通过跨维度交互机制进行进一步聚合,从而有效捕获像素级的成对关系。为验证所提出方法的有效性,我们在图像分类与目标检测任务上开展了系统的消融研究与实验验证,采用包括CIFAR-100、ImageNet-1k、MS COCO及VisDrone2019在内的多个权威基准数据集进行性能评估,实验结果充分证明了该多尺度注意力模块的优越性能。

创新点

  1. 高效的多尺度注意力机制 :EMA模块提出了一种高效的多尺度注意力机制,能够同时捕获通道和空间信息,并在不增加太多参数和计算成本的情况下有效地提高特征表示能力。

  2. 通道维度重塑 :EMA模块通过将部分通道重塑为批量维度,将通道维度分组为多个子特征,从而使空间语义特征在每个特征组内得到良好分布,提高了特征的表达能力。

  3. 并行子网络设计 :EMA模块采用了并行子网络设计,有助于捕获跨维度的交互作用和建立维度间的依赖关系,提高了模型对长距离依赖关系的建模能力。

  4. 性能优越 :EMA模块在目标检测任务中表现出色,相较于传统的注意力模块(如CA和CBAM),EMA在保持模型尺寸和计算效率的同时,取得了更好的性能表现,证明了其在提升模型性能方面的有效性和高效性。

  5. 适用性广泛 :EMA模块的模型尺寸适中,适合在移动终端上部署,并且在各种计算机视觉任务中都表现出色,具有广泛的应用前景和实际意义。

文章链接

论文地址: 论文地址

代码地址: 代码地址

基本原理

EMA(Efficient Multi-Scale Attention)模块是一种新颖的高效多尺度注意力机制,旨在提高计算机视觉任务中的特征表示效果。 EMA注意力模块通过结合通道和空间信息、采用多尺度并行子网络结构以及优化坐标注意力机制,实现了更加高效和有效的特征表示,为计算机视觉任务的性能提升提供了重要的技术支持。

  1. 通道和空间注意力的结合 :EMA模块通过将通道和空间信息相结合,实现了通道维度的信息保留和降低计算负担。这种结合有助于在特征表示中捕捉跨通道关系,同时避免了通道维度的削减,从而提高了模型的表现效果。

  2. 多尺度并行子网络 :EMA模块采用多尺度并行子网络结构,其中包括一个处理1x1卷积核和一个处理3x3卷积核的并行子网络。这种结构有助于有效捕获跨维度交互作用,建立不同维度之间的依赖关系,从而提高特征表示的能力。

  3. 坐标注意力(CA)的再审视 :EMA模块在坐标注意力(CA)的基础上进行了改进和优化。CA模块通过将位置信息嵌入通道注意力图中,实现了跨通道和空间信息的融合。EMA模块在此基础上进一步发展,通过并行子网络块有效捕获跨维度交互作用,建立不同维度之间的依赖关系。

  4. 特征聚合和交互 :EMA模块通过并行子网络的设计,有助于实现特征的聚合和交互,从而提高模型对长距离依赖关系的建模能力。这种设计避免了更多的顺序处理和大规模深度,使模型更加高效和有效。

下图是结构,其中包括输入、特征重组、通道注意力和输出步骤。

  1. 输入阶段

    • 输入张量形状为 $(c, h, w)$ ,其中 (c) 为通道数,(h) 为高度,(w) 为宽度。
  2. 特征重组阶段

    • 输入张量被划分为 $(g$ ) 个组,每组包含 $(\frac{c}{g}) $ 个通道。重组后的张量形状为 $(g \times \text{batch size})$ 。
  3. 特征提取和聚合阶段

    • 特征通过 $((1 \times 1))$ 的卷积层和平均池化层提取并聚合。

    • 聚合后的特征通过一个 Sigmoid 激活函数进行处理,以生成通道权重。

  4. 通道注意力阶段

    • 特征被进一步通过 $((3 \times 3))$ 卷积层和平均池化层提取,得到每个通道的注意力权重。

    • 使用 Softmax 进行归一化处理,确保权重分布合理。

  5. 特征融合阶段

    • 提取到的特征通过矩阵乘法与原始特征进行融合,生成最终的通道注意力特征。

    • 最终特征通过 Sigmoid 激活函数处理,以生成像素级别的注意力图。

  6. 输出阶段

    • 经过以上处理后,生成的特征被重组为原始输入的形状 $((c, h, w))$ ,形成最终输出。

通过这些步骤,实现了对输入特征的多尺度注意力处理,增强了特征表示的辨识能力,同时降低了计算开销。

核心代码

import torch
from torch import nn

class EMA(nn.Module):
    def __init__(self, channels, c2=None, factor=32):
        super(EMA, self).__init__()
        self.groups = factor  # 分组数,默认为32
        assert channels // self.groups > 0  # 确保通道数能够被分组数整除
        self.softmax = nn.Softmax(-1)  # 定义 Softmax 层,用于最后一维度的归一化
        self.agp = nn.AdaptiveAvgPool2d((1, 1))  # 自适应平均池化,将特征图缩小为1x1
        self.pool_h = nn.AdaptiveAvgPool2d((None, 1))  # 自适应平均池化,保留高度维度,将宽度压缩为1
        self.pool_w = nn.AdaptiveAvgPool2d((1, None))  # 自适应平均池化,保留宽度维度,将高度压缩为1
        self.gn = nn.GroupNorm(channels // self.groups, channels // self.groups)  # 分组归一化
        self.conv1x1 = nn.Conv2d(channels // self.groups, channels // self.groups, kernel_size=1, stride=1, padding=0)  # 1x1卷积
        self.conv3x3 = nn.Conv2d(channels // self.groups, channels // self.groups, kernel_size=3, stride=1, padding=1)  # 3x3卷积

    def forward(self, x):
        b, c, h, w = x.size()  # 获取输入张量的尺寸:批次、通道、高度、宽度
        group_x = x.reshape(b * self.groups, -1, h, w)  # 将张量按组重构:批次*组数, 通道/组数, 高度, 宽度
        x_h = self.pool_h(group_x)  # 对高度方向进行池化,结果形状为 (b*groups, c//groups, h, 1)
        x_w = self.pool_w(group_x).permute(0, 1, 3, 2)  # 对宽度方向进行池化,并转置结果形状为 (b*groups, c//groups, 1, w)
        hw = self.conv1x1(torch.cat([x_h, x_w], dim=2))  # 将池化后的特征在高度方向拼接后进行1x1卷积
        x_h, x_w = torch.split(hw, [h, w], dim=2)  # 将卷积后的特征分为高度特征和宽度特征
        x1 = self.gn(group_x * x_h.sigmoid() * x_w.permute(0, 1, 3, 2).sigmoid())  # 结合高度和宽度特征,应用分组归一化
        x2 = self.conv3x3(group_x)  # 对重构后的张量应用3x3卷积
        x11 = self.softmax(self.agp(x1).reshape(b * self.groups, -1, 1).permute(0, 2, 1))  # 对 x1 进行自适应平均池化并应用Softmax
        x12 = x2.reshape(b * self.groups, c // self.groups, -1)  # 重构 x2 的形状为 (b*groups, c//groups, h*w)
        x21 = self.softmax(self.agp(x2).reshape(b * self.groups, -1, 1).permute(0, 2, 1))  # 对 x2 进行自适应平均池化并应用Softmax
        x22 = x1.reshape(b * self.groups, c // self.groups, -1)  # 重构 x1 的形状为 (b*groups, c//groups, h*w)
        weights = (torch.matmul(x11, x12) + torch.matmul(x21, x22)).reshape(b * self.groups, 1, h, w)  # 计算权重,并重构为 (b*groups, 1, h, w)
        return (group_x * weights.sigmoid()).reshape(b, c, h, w)  # 将权重应用于原始张量,并重构为原始输入形状

实验

脚本

import warnings
warnings.filterwarnings('ignore')
from ultralytics import YOLO

if __name__ == '__main__':
#     修改为自己的配置文件地址
    model = YOLO('/root/ultralytics-main/ultralytics/cfg/models/11/yolov11-EMA.yaml')
#     修改为自己的数据集地址
    model.train(data='/root/ultralytics-main/ultralytics/cfg/datasets/coco8.yaml',
                cache=False,
                imgsz=640,
                epochs=10,
                single_cls=False,  # 是否是单类别检测
                batch=8,
                close_mosaic=10,
                workers=0,
                optimizer='SGD',
                amp=True,
                project='runs/train',
                name='EMA',
                )

结果

THE END