引言:

CBAM(Convolutional Block Attention Module)是一种轻量级的注意力机制模块,用于增强卷积神经网络的特征提取能力。在YOLO(You Only Look Once)目标检测框架的骨干网络中,CBAM模块通过通道注意力和空间注意力的双重机制,显著提升了模型对重要特征的关注能力。

    CBAM在YOLO中的应用优势

  • 特征增强:CBAM模块通过动态调整通道和空间权重,使YOLO骨干网络更关注目标物体的关键特征,抑制背景噪声。

  • 轻量化设计:CBAM的计算开销较小,适合嵌入YOLO的实时检测框架,几乎不影响推理速度。

  • 性能提升:实验表明,添加CBAM模块的YOLO变体(如YOLOv5-CBAM)在COCO等数据集上mAP提升约1-2%

YOLO26主要功能

  • DFL 移除
    分布式焦点损失(DFL)模块虽然有效,但常常使导出复杂化并限制了硬件兼容性。YOLO26 完全移除了 DFL,简化了推理过程,并拓宽了对边缘和低功耗设备的支持。

  • 端到端无NMS推理
    与依赖NMS作为独立后处理步骤的传统检测器不同,YOLO26是原生端到端的。预测结果直接生成,减少了延迟,并使集成到生产系统更快、更轻量、更可靠。

  • ProgLoss + STAL
    改进的损失函数提高了检测精度,在小目标识别方面有显著改进,这是物联网、机器人、航空影像和其他边缘应用的关键要求。

  • MuSGD Optimizer
    一种新型混合优化器,结合了SGDMuon。灵感来自 Moonshot AI 的Kimi K2,MuSGD 将 LLM 训练中的先进优化方法引入计算机视觉,从而实现更稳定的训练和更快的收敛。

  • CPU推理速度提升高达43%
    YOLO26专为边缘计算优化,提供显著更快的CPU推理,确保在没有GPU的设备上实现实时性能。

由于YOLO26n在轻量化和边缘部署优势明显,所以改变骨干架构会使性能降低,且在轻量化方面提升不大

一,准备

电脑要有conda环境,且部署ultralytics的YOLO26系列https://docs.ultralytics.com/zh/这是官方链接。

CBAM代码(CBAM.py)

import torch
import torch.nn as nn
import torch.nn.functional as F

class CBAM(nn.Module):


    def __init__(self, in_channels, reduction_ratio=16, kernel_size=7):

        super(CBAM, self).__init__()

        #通道注意力模块
        # 全局平均池化分支
        self.channel_avg_pool = nn.AdaptiveAvgPool2d(1)  # [batch, channels, 1, 1]
        # 全局最大池化分支
        self.channel_max_pool = nn.AdaptiveMaxPool2d(1)  # [batch, channels, 1, 1]

        # 共享MLP
        self.channel_mlp = nn.Sequential(
            nn.Conv2d(in_channels, in_channels // reduction_ratio, kernel_size=1, bias=False),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels // reduction_ratio, in_channels, kernel_size=1, bias=False)
        )

        # 空间注意力模块
        self.spatial_conv = nn.Conv2d(
            in_channels=2,  # 输入为2个通道
            out_channels=1,  # 输出1个通道
            kernel_size=kernel_size,
            padding=kernel_size // 2,  # 保持输出空间尺寸与输入一致
            bias=False
        )

        self.spatial_sigmoid = nn.Sigmoid()  # 将输出压缩到0~1之间,作为空间权重

    def forward(self, x):

        # 通道注意力计算
        avg_pool = self.channel_avg_pool(x)  # [B, C, 1, 1]
        max_pool = self.channel_max_pool(x)  # [B, C, 1, 1]

        # MLP学习通道权重
        avg_out = self.channel_mlp(avg_pool)  # [B, C, 1, 1]
        max_out = self.channel_mlp(max_pool)  # [B, C, 1, 1]

        # 相加后通过sigmoid得到通道注意力权重,在0-1之间
        channel_att = F.sigmoid(avg_out + max_out)  # [B, C, 1, 1]

        # 特征图与通道权重逐通道相乘
        x = x * channel_att  # [B, C, H, W]

        # 空间注意力计算
        avg_pool_spatial = torch.mean(x, dim=1, keepdim=True)  # [B, 1, H, W]
        max_pool_spatial, _ = torch.max(x, dim=1, keepdim=True)  # [B, 1, H, W]

        # 拼接两个池化
        spatial_input = torch.cat([avg_pool_spatial, max_pool_spatial], dim=1)  # [B, 2, H, W]

        # 通过卷积和sigmoid得到空间注意力权重
        spatial_att = self.spatial_sigmoid(self.spatial_conv(spatial_input))  # [B, 1, H, W]

        # 特征图与空间权重逐元素相乘
        x = x * spatial_att  # [B, C, H, W]

        return x

二,将CBAM添加到骨干网络架构中

1,在初始化文件中注册CBAM

编辑 ultralytics/nn/modules/__init__.py,添加 CBAM 的导入和导出。

2,修改模型解析器以支持 CBAM

编辑 ultralytics/nn/tasks.py,找到 parse_model 函数,在模块映射字典中添加 CBAM

大约就在1600多行,vscode可以用Ctrl+F检索

3. 修改 YAML 配置文件

这里我直接在卷积下面加了三个CBAM,由于下面有SPPF,所以加下面没必要

找到YOLO26的yaml文件(cfg\models\26\yolo26.yaml)

# YOLO26n backbone with CBAM
backbone:
  # [from, repeats, module, args]
  - [-1, 1, Conv, [64, 3, 2]]           # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]          # 1-P2/4
  - [-1, 2, C3k2, [256, False, 0.25]]   # 2
  - [-1, 1, CBAM, [256]]                # 3 <- 插入 CBAM (P3 特征)
  - [-1, 1, Conv, [256, 3, 2]]          # 4-P3/8
  - [-1, 2, C3k2, [512, False, 0.25]]   # 5
  - [-1, 1, CBAM, [512]]                # 6 <- 插入 CBAM (P4 特征)
  - [-1, 1, Conv, [512, 3, 2]]          # 7-P4/16
  - [-1, 2, C3k2, [512, True]]          # 8
  - [-1, 1, CBAM, [512]]                # 9 <- 插入 CBAM (P5 特征)
  - [-1, 1, Conv, [1024, 3, 2]]         # 10-P5/32
  - [-1, 2, C3k2, [1024, True]]         # 11
  - [-1, 1, SPPF, [1024, 5, 3, True]]   # 12
  - [-1, 2, C2PSA, [1024]]              # 13

更新 Head 部分的连接索引

我们插入了三层 CBAM,分别位于原索引 2、4、6 之后。因此 P3 特征的输出由原索引 4 变成了索引 6(CBAM 输出),P4 特征由原索引 6 变成了索引 9,P5 特征仍由 C2PSA(索引 13)提供。

图上那两个C3K2有连接别的部分接口,所以在head部分改变检索

# YOLO26n head
head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 9], 1, Concat, [1]] # cat backbone P4
  - [-1, 2, C3k2, [512, True]] # 13

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

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

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 13], 1, Concat, [1]] # cat head P5
  - [-1, 1, C3k2, [1024, True, 0.5, True]] # 22 (P5/32-large)

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

解释:

  • P3 特征:由原索引 4 变为现索引 6(CBAM 输出层,精炼后的 P3)

  • P4 特征:由原索引 6 变为现索引 9(CBAM 输出层,精炼后的 P4)

  • P5 特征:由原索引 10 变为现索引 13(C2PSA 输出,未直接加 CBAM,但索引顺延)

三,检测图像验证

from ultralytics import YOLO
model = YOLO('yolo26-cbam.yaml')
model = YOLO("yolo26n.pt")
results = model('kl.jpg',save = True)

这里简单预测一个图,能跑就是没出问题

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐