news 2026/7/5 11:31:09

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/6/23 16:57:06

实现关系型数据库需要完成的任务

一、目的猜测关系型数据库服务器的实现需要完成哪些主要任务。二、实现关系型数据库要完成的任务1、服务端和客户端的TCP通信协议实现。兼容加密和明文两种TCP连接方式。客户端发给服务端的命令只能是SQL语句。服务端回复的数据包分为:"普通结果包"和&quo…

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

BRAM与外部存储器在通信模块中的协同工作:全面讲解

BRAM与DDR的“双剑合璧”:通信模块中的存储协同实战解析你有没有遇到过这样的场景?设计一个10Gbps以太网桥接器,数据流如潮水般涌来。你刚把一帧报文写进DDR,下一帧就已经到了FIFO入口——而此时CPU还在为上一个中断忙得焦头烂额。…

作者头像 李华
网站建设 2026/7/1 22:01:52

基于Django的本地健康宝微信小程序系统【源码文末联系】

基于Django的本地健康宝微信小程序系统 三个角色(管理员,用户,医护人员) 效果如下: 登录页面疫苗信息管理页面论坛分类页面新闻资讯页面用户首页面疫苗信息页面交流论坛页面地图页面研究背景 在信息技术飞速发展和智能…

作者头像 李华
网站建设 2026/6/23 19:29:38

适用于远程教学的proteus8.16下载安装教程操作指南

手把手教你搭建远程电子实验环境:Proteus 8.16 安装全解析你有没有遇到过这样的情况?学生在家上《单片机原理》课,老师讲得头头是道,可一到动手环节——“老师,我装不上 Proteus!”、“仿真打不开&#xff…

作者头像 李华
网站建设 2026/7/2 12:24:58

AI初创团队必备:PyTorch-CUDA-v2.6镜像标准化开发环境

AI初创团队必备:PyTorch-CUDA-v2.6镜像标准化开发环境 在人工智能研发一线摸爬滚打过的工程师都懂,真正卡住项目进度的往往不是模型设计本身,而是那个看似简单却总出问题的环节——“环境装好了吗?” 设想一下:新同事…

作者头像 李华