原文地址
原文
论文阅读方法
三遍论文法
初识
在卷积操作中,提取局部特征的同时融合了通道间的特征。很多工作中也都主要关注空间维度上的注意力,而这篇文章要做的事情就是建模特征通道维度上的注意力,起到特征校准的功能(feature recalibration ):加强有用的特征 + 抑制无用的特征。
主要的操作如上图所示:先对特征图U进行全局编码得到1x1xC 维的特征(Squeeze),经过非线性变换得到通道级注意力权重(Excitation),利用它对特征图进行特征校准。
相知
Squeeze操作: 使用全局平均池化得到通道维特征(channel-wise statistics ),作者也指出可以使用更复杂的全局特征提取操作。
Excitation操作: 这一步的目的主要是对squeeze 得到的特征进一步提取,得到通道级别的依赖信息(channel-wise dependencies )。为了达到这个目的,作者指出需要满足两个条件:① 足够灵活(flexible ),能够提取通道间的非线性互信息;② 学会一种非排斥的关系,因为作者希望它能允许多个通道被激活,而不是one-hot 形式。
因此,作者使用了fc - relu - fc - sigmoid 的组合形式,其中在fc-relu-fc 会进行一个升降维操作D - D/r - D ,并通过实验证明r 取16时,权衡了准确率和复杂度。
sigmoid之后,每个通道的取值在(0,1)之间,相当于门控机制(注意力)
最后的融合操作就比较简单了,得到了通道级的权重注意力s ,进行像素级点乘即可。
结合到现有框架中 正文中主要展示了两种插入方式,一种是Inception这类非残差结构,另一种是以ResNet为代表的残差结构: 部分实验 在ImageNet上的效果对比,增加少许参数量的同时提升了性能。
在MobileNet和ShuffleNet这类轻量级网络中,也提升了不少性能。
其次比较有意思的是作者展示了不同类别的通道激活情况:在浅层模块中SE是类无关的激活形式,不同的类别激活形式相似(SE_2_3 , SE_3_4 ),而在深层模块中SE对于不同的类别激活情况不一样(SE_4_6 , SE_5_1 )。这也对应了CNN在浅层主要提取得到的是通用特征,而在深层才提取特定类相关的特征。而在最后两个Block中,SE_5_2 类似于残差连接(大多数激活值为1,少部分为0),SE_5_3 为输入分类器前的特征,不同类别表现形式一样,只是在幅度上有略微差别。
因此作者也提到,删除最后两个block的SE模块,在损失极小性能的情况下,节省计算量。
回顾
SE模块主要考虑了通道维度间的依赖关系,加强某些判别性特征,衰弱某些无用特征。经过时间的检验,SE模块现在已经大量应用在各个最新架构和场景中,即插即用的典范。
代码
class SEModule(nn.Module):
""" SE Module """
def __init__(self, in_channels, reduction_ratio=16):
super().__init__()
self.max_pool = nn.AdaptiveMaxPool2d((1,1))
self.mlp = nn.Sequential(
nn.Linear(in_channels, in_channels//reduction_ratio),
nn.ReLU(),
nn.Linear(in_channels//reduction_ratio, in_channels)
)
def forward(self, x):
avg_feat = self.mlp(self.avg_pool(x).flatten(1))
att_weight = torch.sigmoid(att_feat).unsqueeze(2).unsqueeze(3)
return x*att_weight
参考
[1] 最后一届ImageNet冠军模型:SENet
|