CBAM 注意力机制

13 阅读4分钟

CBAM(Convolutional Block Attention Module)是一种轻量级的通用注意力模块,它通过顺序结合通道注意力空间注意力机制,使卷积神经网络能够自适应地强调重要特征并抑制不必要特征,从而显著提升模型性能。

🔍 CBAM 的核心原理

CBAM 包含两个关键子模块,它们依次对输入特征图进行细化。

  1. 通道注意力模块:确定“关注什么”

    • 目标:评估每个特征通道的重要性。例如,在识别猫的任务中,该模块会学习到“耳朵纹理”或“眼睛形状”对应的特征通道比“背景颜色”通道更为关键。

    • 操作

      • 信息聚合:对输入特征图同时进行全局平均池化全局最大池化,得到两个不同的通道描述符。平均池化捕捉整体上下文信息,而最大池化能捕获更显著的局部特征,两者结合使信息更全面。
      • 权重学习:将两个池化结果分别送入一个共享的多层感知机(MLP) (通常由两个卷积层构成,中间包含一个降维比率为 r的瓶颈结构以节省参数),然后将它们的输出相加。
      • 权重应用:最终通过 Sigmoid 激活函数生成0到1之间的通道注意力权重 Mc​,并与原始特征图逐通道相乘,完成对特征通道的缩放。
  2. 空间注意力模块:确定“在哪里关注”

    • 目标:评估特征图中每个空间位置的重要性,定位关键区域。

    • 操作

      • 信息聚合:对经过通道注意力细化后的特征图,在通道维度上分别进行平均池化最大池化,并将结果拼接在一起,形成对空间信息的有效描述。
      • 权重学习:使用一个标准卷积层(通常为7x7卷积)对拼接后的特征进行卷积操作,以融合空间上下文信息。
      • 权重应用:同样通过 Sigmoid 函数生成空间注意力权重 Ms​,其形状为 [B, 1, H, W]。该权重会与特征图逐位置相乘,突出重要空间区域。

CBAM 的完整流程是通道注意力优先,空间注意力后续,即 F′=Ms​(Mc​(F)⊗F)⊗(Mc​(F)⊗F)。研究表明,这种顺序通常能获得最佳效果。

⚙️ PyTorch 实现示例

以下是一个简洁的 CBAM 模块的 PyTorch 实现代码,展示了其核心结构:

import torch
import torch.nn as nn

class ChannelAttention(nn.Module):
    def __init__(self, in_channels, reduction=16):
        super().__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)
        self.mlp = nn.Sequential(
            nn.Conv2d(in_channels, in_channels // reduction, 1, bias=False),
            nn.ReLU(),
            nn.Conv2d(in_channels // reduction, in_channels, 1, bias=False)
        )
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avg_out = self.mlp(self.avg_pool(x))
        max_out = self.mlp(self.max_pool(x))
        channel_weights = self.sigmoid(avg_out + max_out)
        return x * channel_weights  # 广播机制自动应用权重

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super().__init__()
        padding = kernel_size // 2
        self.conv = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        combined = torch.cat([avg_out, max_out], dim=1)
        spatial_weights = self.sigmoid(self.conv(combined))
        return x * spatial_weights  # 广播机制自动应用权重

class CBAM(nn.Module):
    def __init__(self, in_channels, reduction=16, kernel_size=7):
        super().__init__()
        self.channel_attention = ChannelAttention(in_channels, reduction)
        self.spatial_attention = SpatialAttention(kernel_size)

    def forward(self, x):
        x = self.channel_attention(x)  # 先应用通道注意力
        x = self.spatial_attention(x) # 再应用空间注意力
        return x

🚀 如何集成到CNN中及应用效果

CBAM 的即插即用特性使其能够轻松集成到各种主流卷积神经网络(如 ResNet、MobileNet 等)的任一卷积块之后。例如,在 ResNet 的残差块中,CBAM 模块通常被添加在最后一个卷积层之后、残差连接之前。

集成 CBAM 后,模型在多项任务中表现出性能提升:

  • 图像分类:在 ImageNet 等数据集上,基线模型的分类错误率显著降低。
  • 目标检测:在 MS COCO 和 VOC 数据集上,检测模型的精度得到提高。
  • 语义分割:有助于模型更精确地定位物体边界。

可视化研究(如 Grad-CAM)表明,引入 CBAM 的网络能够更准确地聚焦于目标物体的关键部位。

💎 总结

CBAM 的核心优势在于其双重注意力机制轻量级设计。它不仅考虑了特征通道的重要性,还关注了特征的空间位置,从而更全面地优化特征表示。由于其参数少、计算开销低且易于集成,CBAM 已成为提升卷积神经网络性能的实用且有效的工具。