SENET通道注意力机制源代码+注释

本文介绍了一种将注意力机制应用于传统卷积神经网络(CNN)的方法,通过实现SENet(Squeeze-and-Excitation Networks)来提升模型性能。代码中展示了SENet的结构,包括全局平均池化、全连接层和sigmoid激活函数,用于计算权重并加权输入特征。实验中,SENet被应用到3通道的输入图像上,输出结果尺寸保持不变。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import torch
import torch.nn as nn


class SENET(nn.Module):
    def __init__(self, channel, r=0.5):  # channel为输入的维度, r为全连接层缩放比例->控制中间层个数
        super(SENET, self).__init__()
        # 全局均值池化
        self.global_avg_pool = nn.AdaptiveAvgPool2d(1)
        # 全连接层
        self.fc = nn.Sequential(
            nn.Linear(channel, int(channel * r)),  # int(channel * r)取整数   #通道压缩
            nn.ReLU(),          #relu激活函数进行激活 ()激励
            nn.Linear(int(channel * r), channel),     #展开
            nn.Sigmoid(),  #折算成0到1之间的权重
        )

    def forward(self, x):
        # 对x进行分支计算权重, 进行全局均值池化
        branch = self.global_avg_pool(x)   #前向传播先平均池化
        branch = branch.view(branch.size(0), -1)   #展开

        # 全连接层得到权重
        weight = self.fc(branch)    #经过全连接得到权重

        # 将维度为b, c的weight, reshape成b, c, 1, 1 与 输入x 相乘 即乘以权重
        hi, wi = weight.shape
        weight = torch.reshape(weight, (hi, wi, 1, 1))

        # 乘积获得结果
        scale = weight * x    #weight为权重 x为输入的  输出结果
        return scale
# alexnet1.add_module("linear",nn.Linear(1000 , 10))
alexnet1 = SENET(channel = 3) #通道数等于输入图片的通道数
print(alexnet1)
test1 = torch.ones(64, 3, 120, 120)  #输入64batch  3通道 120*120的图片

test1 = alexnet1 (test1)
print(test1.shape)   #输出无变化

本人尝试将注意力机制作为trick加入传统的CNN卷积神经网络进行优化,后面会陆续公布相应的代码和经验  未完待续...........

<think>好的,我现在需要帮助用户了解SENet通道注意力机制的原理和实现方法。首先,我得回顾一下自己之前整理的相关资料和引用内容。 用户提供的引用中,提到SE注意力机制通过自动学习特征通道的重要程度,并赋予权重,使网络关注重要通道。引用[1]和[2]都强调了SE模块通过全连接网络根据损失函数来学习权重,而不是手动分配。引用[3]说明注意力机制的自适应特性,而引用[4]提供了原始论文的链接,可能需要参考。 首先,我需要解释SENet的核心思想,即Squeeze-and-Excitation结构。这里应该分步骤说明Squeeze和Excitation两个操作。Squeeze阶段使用全局平均池化压缩空间信息,生成通道描述符。Excitation阶段通过全连接层学习通道间的依赖关系,生成权重。这部分需要结合数学公式,比如使用$z_c = \frac{1}{H \times W} \sum_{i=1}^H \sum_{j=1}^W u_c(i,j)$这样的公式表示全局平均池化,然后用$s = \sigma(W_2 \delta(W_1 z))$表示全连接层和激活函数的过程。 接下来,要说明如何将这些权重应用到原始特征图上,即每个通道乘以对应的标量权重。这部分可能需要一个公式,如$\tilde{u}_c = s_c \cdot u_c$。 然后,实现方法部分需要提供代码示例。用户提到使用PyTorch或TensorFlow,所以需要选择其中一种框架。考虑到引用[2]中提到了Pytorch的完整代码,可能优先用PyTorch。代码部分要包括Squeeze操作(全局平均池化)、Excitation操作(两个全连接层,中间有ReLU和Sigmoid激活),以及最后的scale操作。需要确保代码符合用户给的格式,比如使用代码块,并正确缩进。 在应用场景部分,需要结合引用[3]提到的自适应注意力,说明SE模块可以插入到各种CNN结构中,如ResNet、Inception等,提升图像分、目标检测等任务的性能。同时,引用[2]提到虽然增加了参数,但性价比高,这里可以强调SE模块的轻量级和有效性。 最后,生成相关问题时要围绕SE模块的原理、实现细节、与其他注意力机制的区别、优化方法等展开,确保问题有针对性,帮助用户深入理解。 需要注意用户要求所有行内数学公式用$...$,独立公式用$$...$$,并且正确使用LaTeX语法。同时,回答要结构清晰,分步骤解释原理,代码示例正确,引用标识自然添加在段落末尾。比如在提到SE模块的核心思想时,引用[1]和[2],在讨论应用场景时引用[3]。 现在需要检查是否有遗漏的要点,比如是否解释了为什么SE模块有效,或者不同框架的实现差异。此外,确保回答中没有使用Markdown格式,除了代码块。代码示例需要正确展示SENet中SE模块的实现,可能包括初始化部分、前向传播中的步骤。 总结来说,回答的结构应该是:原理分步骤解释(Squeeze、Excitation、Scale),PyTorch实现代码,应用场景,相关问题。每个部分都需引用对应的资料,并正确使用公式和代码格式。</think>### SENet通道注意力机制原理分步解析 SENet(Squeeze-and-Excitation Network)的核心是通过**通道注意力机制**动态调整特征通道的权重,增强重要通道并抑制冗余信息。其核心结构分为三个阶段: #### 1. Squeeze(压缩) 通过全局平均池化(Global Average Pooling)将特征图$u \in \mathbb{R}^{C \times H \times W}$压缩为通道描述符$z \in \mathbb{R}^C$,公式为: $$ z_c = \frac{1}{H \times W} \sum_{i=1}^H \sum_{j=1}^W u_c(i,j) $$ 这一步将空间维度$H \times W$压缩为1个标量,保留通道$C$的全局信息[^1][^2]。 #### 2. Excitation(激励) 利用两个全连接层学习通道间非线性关系,生成权重向量$s \in \mathbb{R}^C$: $$ s = \sigma(W_2 \cdot \delta(W_1 \cdot z)) $$ 其中: - $W_1 \in \mathbb{R}^{\frac{C}{r} \times C}$为降维层,$r$是压缩比(通常$r=16$) - $\delta$是ReLU激活函数 - $W_2 \in \mathbb{R}^{C \times \frac{C}{r}}$为升维层 - $\sigma$是Sigmoid函数,将权重归一化到$[0,1]$[^2][^4] #### 3. Scale(缩放) 将学习到的权重$s_c$与原始特征图逐通道相乘: $$ \tilde{u}_c = s_c \cdot u_c $$ 最终输出$\tilde{u} \in \mathbb{R}^{C \times H \times W}$实现了通道级别的特征重标定[^3]。 --- ### PyTorch实现代码 ```python import torch import torch.nn as nn class SEBlock(nn.Module): def __init__(self, channel, reduction=16): super(SEBlock, self).__init__() self.avg_pool = nn.AdaptiveAvgPool2d(1) self.fc = nn.Sequential( nn.Linear(channel, channel // reduction), nn.ReLU(inplace=True), nn.Linear(channel // reduction, channel), nn.Sigmoid() ) def forward(self, x): b, c, _, _ = x.size() y = self.avg_pool(x).view(b, c) # Squeeze y = self.fc(y).view(b, c, 1, 1) # Excitation return x * y.expand_as(x) # Scale ``` --- ### 应用场景与特点 1. **轻量级增强**:SE模块仅增加约2%的计算量,但能显著提升ImageNet分准确率(ResNet-50错误率从23.21%降至22.85%) 2. **即插即用**:可嵌入ResNet的残差块、Inception模块等结构中 3. **多任务适用**:广泛用于图像分、目标检测(如Faster R-CNN)、语义分割等场景[^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小馨馨的小翟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值