CBAM注意力机制结构图自绘版:从原理到实现的全方位解析

1次阅读
没有评论

共计 2038 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

背景痛点:为什么需要注意力机制?

在传统 CNN 模型中,卷积核对所有空间位置和通道的特征进行无差别处理。这种方式存在两个明显缺陷:

  1. 特征选择低效 :背景噪声与关键特征被同等对待
  2. 计算资源浪费 :对不重要的特征区域分配了相同计算量

通过可视化热力图可以发现,模型往往在无关区域产生高激活值。这正是 CBAM(Convolutional Block Attention Module)要解决的核心问题。

CBAM 双重注意力机制解析

通道注意力模块

CBAM 注意力机制结构图自绘版:从原理到实现的全方位解析

数学过程:

$$
M_c(F) = \sigma(MLP(AvgPool(F)) + MLP(MaxPool(F)))
$$

其中:
– $F$ 为输入特征图 $\mathbb{R}^{C×H×W}$
– $MLP$ 采用降维比为 $r$ 的瓶颈结构
– $\sigma$ 是 Sigmoid 函数

空间注意力模块

计算表达式:

$$
M_s(F) = \sigma(f^{7×7}([AvgPool(F); MaxPool(F)]))
$$

关键点:
– 方括号表示通道拼接
– $f^{7×7}$ 是 7×7 卷积核
– 输出空间权重矩阵 $\mathbb{R}^{1×H×W}$

PyTorch 完整实现

import torch
import torch.nn as nn

class CBAM(nn.Module):
    def __init__(self, channels, reduction_ratio=16):
        super().__init__()
        # 通道注意力
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)
        self.mlp = nn.Sequential(nn.Linear(channels, channels // reduction_ratio),
            nn.ReLU(),
            nn.Linear(channels // reduction_ratio, channels)
        )
        # 空间注意力
        self.conv = nn.Conv2d(2, 1, kernel_size=7, padding=3)

    def forward(self, x):
        # 通道注意力
        avg_out = self.mlp(self.avg_pool(x).squeeze(-1).squeeze(-1))
        max_out = self.mlp(self.max_pool(x).squeeze(-1).squeeze(-1))
        channel_weights = torch.sigmoid(avg_out + max_out).unsqueeze(-1).unsqueeze(-1)
        x = x * channel_weights

        # 空间注意力
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        spatial_weights = torch.sigmoid(self.conv(torch.cat([avg_out, max_out], dim=1)))
        return x * spatial_weights

集成到 ResNet 的实战示例

class ResBlock_CBAM(nn.Module):
    def __init__(self, in_channels):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels, in_channels, 3, padding=1)
        self.conv2 = nn.Conv2d(in_channels, in_channels, 3, padding=1)
        self.cbam = CBAM(in_channels)
        self.relu = nn.ReLU()

    def forward(self, x):
        residual = x
        x = self.relu(self.conv1(x))
        x = self.conv2(x)
        x = self.cbam(x)  # 插入 CBAM 模块
        return self.relu(x + residual)

实验对比数据

在 CIFAR-10 测试集上的效果对比:

模型 准确率 参数量 GFLOPs
ResNet-18 93.2% 11.2M 0.56
ResNet-18+CBAM 94.7% 11.3M 0.58

关键发现:
1. 仅增加 0.1% 参数量即获得 1.5% 精度提升
2. 计算开销增长控制在 3% 以内

避坑指南

  1. 维度匹配问题
  2. 通道数变化时需重新初始化 CBAM 模块
  3. 空间注意力要求输入高宽≥7(因 7×7 卷积)

  4. 超参数调优建议

  5. 降维比 $r$ 通常取 8 -32
  6. 初始学习率降低为原值的 0.1 倍

  7. 部署注意事项

  8. 导出 ONNX 时需处理广播操作
  9. 量化时注意 Sigmoid 函数的精度损失

开放思考方向

  1. 动态调整降维比 $r$ 的可行性
  2. 空间注意力能否替换为动态卷积
  3. 在 Transformer-CNN 混合架构中的应用潜力

通过自绘结构图可以更直观理解:通道注意力像 ” 特征选择器 ”,空间注意力像 ” 区域聚焦镜 ”。建议读者尝试用 matplotlib 绘制各层权重热力图,这对理解模型行为非常有帮助。

正文完
 0
评论(没有评论)