CBAM注意力机制与自注意力机制的本质区别及实战应用

1次阅读
没有评论

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

image.webp

CBAM 注意力机制与自注意力机制的本质区别及实战应用

概念区分与数学原理

CBAM(Convolutional Block Attention Module)和自注意力机制(Self-Attention)是两种完全不同的注意力机制:

  • CBAM
  • 由通道注意力(Channel Attention)和空间注意力(Spatial Attention)两个子模块组成
  • 通道注意力公式(基于全局平均 / 最大池化):
    M_c(F) = \sigma(MLP(AvgPool(F)) + MLP(MaxPool(F)))
  • 空间注意力公式(基于卷积操作):

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

  • 自注意力机制

  • Transformer 架构的核心组件
  • 计算过程(Q/K/ V 变换):
    Attention(Q,K,V) = softmax(\frac{QK^T}{\sqrt{d_k}})V

常见误用与性能影响

  1. 计算资源浪费案例
  2. 在 CNN 架构中误用自注意力会导致:

    • 计算复杂度从 O(n) 飙升到 O(n²)
    • 小分辨率特征图上出现过度平滑现象
  3. 模型性能下降实例

  4. 在 ImageNet 分类任务中测试表明:
    • 错误替换 CBAM 为自注意力会使 top- 1 准确率下降 3 -5%
    • 推理速度降低 40% 以上

PyTorch 实现详解

通道注意力模块

class ChannelAttention(nn.Module):
    def __init__(self, in_planes, ratio=8):
        super().__init__()
        # [B,C,H,W] -> [B,C,1,1] 两种池化方式
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)

        # 共享参数的 MLP(实际用 1x1 卷积实现)self.fc1 = nn.Conv2d(in_planes, in_planes//ratio, 1, bias=False)
        self.relu = nn.ReLU()
        self.fc2 = nn.Conv2d(in_planes//ratio, in_planes, 1, bias=False)

    def forward(self, x):
        avg_out = self.fc2(self.relu(self.fc1(self.avg_pool(x))))
        max_out = self.fc2(self.relu(self.fc1(self.max_pool(x))))
        return torch.sigmoid(avg_out + max_out)  # [B,C,1,1]

空间注意力模块

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super().__init__()
        # 经验表明 7x7 卷积在多数场景效果最佳
        self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False)

    def forward(self, x):
        # 沿通道维度做平均 / 最大池化 [B,C,H,W]->[B,1,H,W]
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out = torch.max(x, dim=1, keepdim=True)[0]
        concat = torch.cat([avg_out, max_out], dim=1)  # [B,2,H,W]
        return torch.sigmoid(self.conv(concat))  # [B,1,H,W]

ResNet 集成示例

class CBAM_ResBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, 3, stride, 1)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.conv2 = nn.Conv2d(out_channels, out_channels, 3, 1, 1)
        self.bn2 = nn.BatchNorm2d(out_channels)

        self.channel_att = ChannelAttention(out_channels)
        self.spatial_att = SpatialAttention()

    def forward(self, x):
        residual = x
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))

        # CBAM 处理(注意顺序:先通道后空间)out = self.channel_att(out) * out
        out = self.spatial_att(out) * out

        return F.relu(out + residual)

实验对比分析

CIFAR-10 测试结果

模型类型 参数量 (M) FLOPs(G) 准确率 (%)
ResNet-18 11.2 0.56 93.5
+CBAM 11.3 0.57 94.8
+Self-Attention 12.1 1.02 92.3

注意力热图可视化

CBAM 注意力机制与自注意力机制的本质区别及实战应用
– CBAM 能同时增强关键通道和空间区域
– 自注意力在低分辨率特征上出现过度聚焦

工程实践指南

  1. BN 层协同技巧
  2. 应将 CBAM 模块放在 BN 层之后
  3. 避免在注意力权重应用前做 ReLU 激活

  4. 多分辨率适配方案

  5. 空间注意力卷积核应随输入尺寸调整:
    kernel_size = min(7, input_size//2)  # 保证感受野合理 
  6. 通道注意力不受分辨率影响

  7. 初始化策略

  8. 将最终 sigmoid 前的卷积层权重初始化为 0
  9. 可使训练初期等效于原始网络

延伸思考

在视频理解任务中,可以考虑:
1. 增加时间维度的 3D 卷积注意力
2. 在 LSTM 单元中嵌入 CBAM 机制
3. 跨帧的特征通道相关性分析

期待读者在实践中探索更多可能性,也欢迎分享您的改进方案。

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