1 简介
注意力机制使神经网络能够准确地专注于与输入的相关元素,它已成为改善深度神经网络性能的重要组成部分。
在计算机视觉研究中,主要有两种广泛使用的注意力机制:空间注意力和通道注意力,它们分别用于捕获像素级成对关系和通道依赖性。尽管将它们融合在一起可能会比其单独的实现获得更好的性能,但这将不可避免地增加计算开销。
本文提出了一个有效的Shuffle Attention(SA)模块来解决此问题,该模块采用Shuffle单元有效地结合了两种类型的注意力机制。具体而言,SA首先将通道维分组为多个子特征,然后再并行处理它们。然后,对于每个子特征,SA利用Shuffle Unit在空间和通道维度上描绘特征依赖性。之后,将所有子特征汇总在一起,并采用“channel shuffle”运算符来启用不同子特征之间的信息通信。
所提出的SA模块既有效又高效,例如,针对ResNet50的SA的参数和计算分别为300vs25.56M和2.76e-3GFLOP与4.12GFLOP,并且性能提升在1.34%以上。
在常用基准上的大量实验结果(包括用于分类的ImageNet-1k,用于目标检测的MS COCO和实例分割)表明,所提出的SA通过获得较高的精度而具有较低的模型复杂性,从而明显优于当前的SOTA方法。
2 前人工作
2.1 Multi-branch architectures
CNN的多分支架构经过了多年的发展,越来越精确和快速。多分支架构背后的原则“Split-Transform-Merge”,这减轻了数百层网络的训练困难问题。
InceptionNet系列是成功的多分支架构,其中每个分支都精心配置了定制的卷积核,以便聚合更多信息丰富的特征。
ResNet也可以看作是两个分支网络,其中一个分支是Identity Mapping。
SKNets和ShuffleNet系列都遵循了InceptionNets的思想,有多个分支的各种卷积核,但至少在2个重要方面有所不同。
SKNets利用自适应选择机制实现神经元自适应感受野大小;ShuffleNets进一步将“channel split”和“channel shuffle” 操作合并为单个element-wise操作,以在速度和精度之间做出权衡。
2.2 Grouped Features
特性分组学习可以追溯到AlexNet,他的动机是将模型分配到更多的GPU资源上。AlexNet并指出卷积组可以学习更好的特征表示。
Mobilenet和ShuffleNet将每个channel视为一个组,并对这些组内的空间关系进行建模。而胶囊网络将每组神经元建模为一个胶囊,其中活性胶囊中的神经元活动代表了图像中特定实体的各种属性。而SGE开发胶囊并将通道维度划分为多个子特征,学习不同的语义。
2.3 Attention mechanisms
注意力机制对信息最丰富的特征表达分配权重更大,同时抑制无用的特征表达权重。Self-Attention方法将图像中所有位置的加权和计算在一个位置的上下文。SE-Net通过使用2个FC层建模Channel之间的关系。ECA-Net采用一维卷积生成Channel权值,显著降低了SE的模型复杂度。非局部(non-local,NL)模块通过计算特征图中每个空间点之间的相关矩阵来生成一个注意力图。CBAM、GCNet和SGE将空间注意力和通道注意力组合,而DANet通过将不同分支的2个注意力模块相加,自适应地将局部特征和它们的全局特征结合起来。
3 Shuffle Attention
本文提出的SA模块将输入特征映射分组,并使用Shuffle单元将通道注意力和空间注意力整合为每组一个块。然后,对所有子特征进行聚合,并利用“channel shuffle”算子实现不同子特征之间的信息通信。SA模块的总体架构如图所示:
3.1 Feature Grouping
对于给定的特征映射,其中C、H、W分别表示通道数、spatial高度和宽度,SA首先沿着通道方向将X分成G组,比如,,,其中每个子特征在训练过程中逐渐捕获一个特定的语义特征响应。然后,通过注意力模块为每个子特征生成相应的重要性系数。具体来说,在每个注意力单元的开始,的输入沿着通道方向分为2个分支,即。
Figure 2中,一个分支采用Channel的位置图产生通道注意力Map,而另一分支是利用的关系特性生成一个空间注意力Map,所以该模型可以同时专注于“What”和“Where”。
3.2 Channel Attention
完全捕获通道依赖关系的典型案例就是是利用SE Block。但是会带来太多的参数,不利于设计一个更轻量级的注意力模块。此外,它不适合通过执行尺寸为k的一维卷积(如ECA)来生成Channel权值,因为k往往非常大。
为了改进,本文提供了一种替代方案,首先通过简单地使用全局平均池化(GAP)来嵌入全局信息,以生成的Channel Feature,这可以通过通过空间方向收缩来进行计算:
此外,还创建了一个紧凑的特性,以便为精确和自适应选择提供指导。这是通过一个简单的门控机制与sigmoid 激活实现的。然后,Channel注意力的最终输出可以由下式获得:
其中,,用于缩放和移动s。
3.3 Spatial Attention
与Channel Attention不同,Spatial Attention关注的是“Where”,是Channel Attention的补充。首先,对使用Group Norm(GN)以获得spatial-wise statistics。然后,采用增强的表示。Spatial Attention的最终输出由下式获得:
其中,,。然后将2个分支连接起来,使通道的数量与输入的通道数量相同。
3.4 Aggregation
完成以上操作之后,所有的子特性都被聚合。最后,类似于ShuffleNet v2采用了一个通道shuffle操作符,使跨群组的信息沿着通道维度流动。
SA模块的最终输出大小为X,这使得SA很容易与经典的Backbone架构集成。注意和GN超参数只是SA中引入的参数。单个SA模块中,每个分支的通道数为。因此,总参数(通常G为32或64),与整个网络的数百万个参数相比微不足道。
3.5 SA模块的PyTorch复现
import torch import torch.nn as nn from torch.nn.parameter import Parameter class sa_layer(nn.Module): """Constructs a Channel Spatial Group module. Args: k_size: Adaptive selection of kernel size """ def __init__(self, channel, groups=64): super(sa_layer, self).__init__() self.groups = groups self.avg_pool = nn.AdaptiveAvgPool2d(1) self.cweight = Parameter(torch.zeros(1, channel // (2 * groups), 1, 1)) self.cbias = Parameter(torch.ones(1, channel // (2 * groups), 1, 1)) self.sweight = Parameter(torch.zeros(1, channel // (2 * groups), 1, 1)) self.sbias = Parameter(torch.ones(1, channel // (2 * groups), 1, 1)) self.sigmoid = nn.Sigmoid() self.gn = nn.GroupNorm(channel // (2 * groups), channel // (2 * groups)) @staticmethod def channel_shuffle(x, groups): b, c, h, w = x.shape x = x.reshape(b, groups, -1, h, w) x = x.permute(0, 2, 1, 3, 4) # flatten x = x.reshape(b, -1, h, w) return x def forward(self, x): b, c, h, w = x.shape x = x.reshape(b * self.groups, -1, h, w) x_0, x_1 = x.chunk(2, dim=1) # channel attention xn = self.avg_pool(x_0) xn = self.cweight * xn + self.cbias xn = x_0 * self.sigmoid(xn) # spatial attention xs = self.gn(x_1) xs = self.sweight * xs + self.sbias xs = x_1 * self.sigmoid(xs) # concatenate along channel axis out = torch.cat([xn, xs], dim=1) out = out.reshape(b, -1, h, w) out = self.channel_shuffle(out, 2) return out