news 2026/4/18 9:54:39

Day 50 CBAM 注意力机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day 50 CBAM 注意力机制

1.1 什么是 CBAM?
CBAM (Convolutional Block Attention Module) 是一种能够集成到任何卷积神经网络架构中的注意力模块。

1.2 核心目标
通过学习的方式,自动获取特征图在通道和空间维度上的重要性
对特征图进行自适应调整,增强重要特征,抑制不重要特征
提升模型的特征表达能力和性能
简单来说,CBAM 就像是给模型装上了"智能眼镜",让模型能够更精准地看到图像中关键的部分。

1.3 CBAM 的组成
CBAM 由两个主要部分组成:

  • 通道注意力模块(Channel Attention):分析"哪些通道的特征更关键"
  • 空间注意力模块(Spatial Attention):定位"关键特征在图像中的具体位置"
1.4 CBAM vs SE 注意力
  • SE 通道注意力的局限:仅关注"哪些通道重要",未考虑"重要信息在空间中的位置"
  • CBAM 的突破:二者结合,让模型同时学会"关注什么"和"关注哪里"
1. 第一步:通道注意力(Channel Attention Module, CAM)

核心目标:判断「哪些通道的特征更重要」。比如在识别猫的任务中,「猫耳朵」「猫爪子」对应的通道特征比「背景纹理」对应的通道特征更重要。

工作流程(超简化版)

  1. 对特征图[C, H, W]全局池化,把每个通道的H×W大小的特征,压缩成1 个数值,得到一个[C, 1, 1]的向量(这个向量代表了每个通道的「全局重要性」)。
    • 这里用了两种池化:全局平均池化(GAP)和全局最大池化(GMP),目的是获取更全面的信息。
  2. 把这两个池化后的向量,输入一个简单的两层神经网络(MLP),分别得到两个[C, 1, 1]的权重向量。
  3. 把两个权重向量相加,再经过一个sigmoid函数(把数值压缩到 0~1 之间),得到最终的通道注意力权重
  4. 把这个权重和原来的特征图相乘—— 重要通道的特征会被放大,不重要的会被削弱。
2. 第二步:空间注意力(Spatial Attention Module, SAM)

核心目标:判断「特征图的哪些空间位置更重要」。还是识别猫的任务,特征图里「猫所在的位置」比「背景位置」更重要。

工作流程(超简化版)

  1. 把第一步通道注意力处理后的特征图[C, H, W],在通道维度做池化:计算每个空间位置(每个H×W点)的平均值和最大值,得到两个[1, H, W]的特征图。
  2. 把这两个特征图拼接在一起,变成[2, H, W]
  3. 用一个3×3 的卷积层对拼接后的特征图降维,把通道数从 2 变回 1,得到[1, H, W]的特征图。
  4. 经过sigmoid函数得到空间注意力权重(0~1 之间)。
  5. 把这个权重和第一步处理后的特征图相乘—— 重要空间位置的特征会被放大,不重要的会被削弱。
3. 最终输出

经过「通道注意力 → 空间注意力」两步处理后,得到的特征图就是被注意力机制增强后的特征,可以直接传入下一个卷积块继续训练。

三、CBAM 的优势:为啥大家都爱用?

  1. 轻量级:参数量极少,几乎不会增加模型的计算负担,适合嵌入各种 CNN 模型(比如 ResNet、MobileNet)。
  2. 即插即用:不需要修改原网络的主体结构,直接加在卷积块的末尾或开头就行。
  3. 双维度注意力:同时关注「通道」和「空间」两个维度,比只做单维度注意力的效果更好。

四、小白友好的总结

CBAM 就像一个「特征筛选器」:

  • 先筛选有用的特征种类(通道注意力),再筛选有用的特征位置(空间注意力);
  • 让模型把精力集中在关键信息上,从而提升识别、分类等任务的准确率。
import torch import torch.nn as nn import torch.nn.functional as F # 第一步:实现通道注意力模块(CAM) class ChannelAttention(nn.Module): def __init__(self, in_channels, reduction_ratio=16): """ 参数说明(小白版): - in_channels: 输入特征图的通道数(比如ResNet的卷积块输出通道数是64/128等) - reduction_ratio: 压缩系数(默认16,目的是减少MLP的参数量,不用改) """ super(ChannelAttention, self).__init__() # 全局平均池化:[B, C, H, W] → [B, C, 1, 1] self.avg_pool = nn.AdaptiveAvgPool2d(1) # 全局最大池化:[B, C, H, W] → [B, C, 1, 1] self.max_pool = nn.AdaptiveMaxPool2d(1) # 两层MLP(全连接层):压缩通道数再还原,减少计算量 self.fc = nn.Sequential( # 第一层:把通道数从 C 压缩到 C//reduction_ratio nn.Linear(in_channels, in_channels // reduction_ratio, bias=False), nn.ReLU(inplace=True), # 激活函数,增加非线性 # 第二层:把通道数还原回 C nn.Linear(in_channels // reduction_ratio, in_channels, bias=False) ) # sigmoid函数:把数值压缩到0~1之间,作为注意力权重 self.sigmoid = nn.Sigmoid() def forward(self, x): """ 前向传播(核心逻辑): x: 输入特征图,形状 [B, C, H, W] """ # 平均池化 + MLP avg_out = self.fc(self.avg_pool(x).view(x.size(0), -1)) # [B, C] # 最大池化 + MLP max_out = self.fc(self.max_pool(x).view(x.size(0), -1)) # [B, C] # 两个结果相加 → [B, C] → 变形为 [B, C, 1, 1] out = avg_out + max_out out = self.sigmoid(out).view(x.size(0), x.size(1), 1, 1) # 注意力权重 × 原特征图(逐通道相乘) return x * out # 第二步:实现空间注意力模块(SAM) class SpatialAttention(nn.Module): def __init__(self, kernel_size=3): """ 参数说明: - kernel_size: 卷积核大小(默认3,必须是奇数,不用改) """ super(SpatialAttention, self).__init__() # 卷积层:把通道数从2(平均+最大池化)降为1 self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False) self.sigmoid = nn.Sigmoid() def forward(self, x): """ 前向传播: x: 通道注意力处理后的特征图,形状 [B, C, H, W] """ # 在通道维度做平均池化:[B, C, H, W] → [B, 1, H, W] avg_out = torch.mean(x, dim=1, keepdim=True) # 在通道维度做最大池化:[B, C, H, W] → [B, 1, H, W] max_out, _ = torch.max(x, dim=1, keepdim=True) # 拼接两个池化结果:[B, 2, H, W] out = torch.cat([avg_out, max_out], dim=1) # 卷积降维 + sigmoid → [B, 1, H, W](空间注意力权重) out = self.sigmoid(self.conv(out)) # 注意力权重 × 原特征图(逐空间位置相乘) return x * out # 第三步:组合通道+空间注意力,实现完整的CBAM class CBAM(nn.Module): def __init__(self, in_channels, reduction_ratio=16, kernel_size=3): super(CBAM, self).__init__() self.channel_att = ChannelAttention(in_channels, reduction_ratio) # 通道注意力 self.spatial_att = SpatialAttention(kernel_size) # 空间注意力 def forward(self, x): """ 完整CBAM前向传播:先通道注意力,再空间注意力 x: 输入特征图 [B, C, H, W] return: 增强后的特征图 [B, C, H, W] """ x = self.channel_att(x) # 第一步:通道注意力 x = self.spatial_att(x) # 第二步:空间注意力 return x # --------------- 测试代码:小白可以直接运行看效果 --------------- if __name__ == "__main__": # 模拟一个CNN的特征图:批量大小=2,通道数=64,高=32,宽=32 # (这个形状是CNN中很常见的,比如ResNet18的第一层卷积输出) fake_feature = torch.randn(2, 64, 32, 32) # 创建CBAM模块:输入通道数=64(和特征图通道数一致) cbam = CBAM(in_channels=64) # 用CBAM处理特征图 enhanced_feature = cbam(fake_feature) # 打印输入/输出形状(验证:形状不变,只是特征被增强) print(f"输入特征图形状: {fake_feature.shape}") print(f"输出特征图形状: {enhanced_feature.shape}")

@浙大疏锦行

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 8:09:36

通俗解释USB接口有几种命名规则

一根线的进化史:为什么USB接口越来越“难懂”?你有没有过这样的经历?买了一根号称“高速传输”的USB线,结果拷贝一个4K视频比蜗牛还慢;给笔记本连扩展坞时,发现明明插的是USB-C口,却无法输出视频…

作者头像 李华
网站建设 2026/4/18 8:01:04

北京大学国家发展研究院 经济学辅修 经济学原理课程笔记(第十五章 劳动力市场)

文章目录第十五课 劳动力市场劳动力是一种生产要素生产要素的定义派生需求劳动力的独特性劳动力质量的影响因素完全竞争企业对劳动力的需求基本假设:双重价格接受者决策逻辑的转换:从边际成本到边际产量劳动力市场的决策法则案例表格分析劳动力的需求曲线…

作者头像 李华
网站建设 2026/4/18 7:53:53

Agisoft Metashape Pro(3D摄影建模软件)

链接:https://pan.quark.cn/s/19a0d5b41286Agisoft Metashape是一款专业的三维模型设计软件。软件根据最新的多视图三维重建技术,可以对任意照片进行处理,无需控制点;也可以通过给予的控制点生成真实坐标的三维模型。操作简单&…

作者头像 李华
网站建设 2026/4/18 8:00:21

功率马力的大小

功率马力的大小 在描述电机功率大小时, 有时会出现马力、hp、匹等描述功率的大小. 马力的解释 马力, (Imperial Horsepower, HP), 是功率的英制单位, 由工程师詹姆斯瓦特提出. 18 世纪, 瓦特改良蒸汽机后, 需要向工厂主说明 “蒸汽机的动力相当于多少匹马”(当时主要动力源是…

作者头像 李华