1.GAM注意力机制:
图像解析:
从整体上可以看出,GAM和CBAM注意力机制还是比较相似的,同样是使用了通道注意力机制和空间注意力机制。但是不同的是对通道注意力和空间注意力的处理。
2.CBAM注意力解析
CBAM = CAM + BAM
- 对于通道注意力的处理:
首先对输入特征图进行最大池化和平均池化,再经过MLP分别处理,最终经过Sigmoid激活。 - 对于空间注意力的处理
对特征图进行最大池化和平均池化后叠加在一起,再进行卷积,经过Sigmoid激活函数处理。
3.GAM改进
了解了CBAM,我们来看GAM是怎么处理CAM 和SAM的,同样是先通道后空间。
- CAM
对于输入特征图,首先进行维度转换,经过维度转换的特征图输入到MLP,再转换为原来的维度,进行Sigmoid处理输出。 - SAM
对于SAM,GAM主要使用了卷积处理,对于这里有点像SE注意力机制,先将通道数量减少,再将通道数量增加。首先通过卷积核为7的卷积缩减通道数量,缩小计算量,在经过一个卷积核为7的卷积操作,增加通道数量,保持通道数量的一致。最后经过Sigmoid输出。
4.GAM的pytorch实现
这里给出GAM的pytorch实现代码:代码可能跟官方有些差异,是看图复现的
"""
GAM 注意力机制:对CBAM注意力进行改进
先通道注意力,再空间注意力
"""
import torch
import torch.nn as nn
# 通道注意力
class Channel_Attention(nn.Module):
def __init__(self, in_channel, out_channel, ratio=4):
super(Channel_Attention, self).__init__()
self.fc1 = nn.Linear(in_channel, in_channel // ratio)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(in_channel // ratio, in_channel)
self.sig = nn.Sigmoid()
def forward(self, x):
# b, c, h, w = x.size()
input = x.permute(0, 3, 2, 1)
output = self.fc2(self.relu(self.fc1(input)))
output = output.permute(0, 3, 2, 1)
return output * x
# 空间注意力
class Spatial(nn.Module):
def __init__(self, in_channel, out_channel, ratio, kernel_size=7):
super(Spatial, self).__init__()
padding = kernel_size // 2
self.conv1 = nn.Conv2d(
in_channel, in_channel // ratio, kernel_size=7, padding=padding
)
self.bn = nn.BatchNorm2d(in_channel // ratio)
self.act = nn.ReLU()
self.conv2 = nn.Conv2d(
in_channel // ratio, in_channel, kernel_size=kernel_size, padding=padding
)
self.bn1 = nn.BatchNorm2d(in_channel)
self.sig = nn.Sigmoid()
def forward(self, x):
conv1 = self.act(self.bn(self.conv1(x)))
conv2 = self.bn1(self.conv2(conv1))
output = self.sig(conv2)
return x * output
class GAM(nn.Module):
def __init__(self,in_channel, out_channel, ratio = 4, kernel_size = 7):
super(GAM, self).__init__()
self.channel_attention = Channel_Attention(in_channel,out_channel,ratio)
self.spatial_attention = Spatial(in_channel,out_channel,ratio,kernel_size)
def forward(self, x):
input = self.channel_attention(x)
output= self.spatial_attention(input)
return output
input = torch.randn(1, 4, 24, 24).cuda()
model = GAM(4, 4).cuda()
output = model(input)
print(output)
print(output.size()) #torch.Size([1, 4, 24, 24])
# 20220928
为了提高计算机视觉任务的性能,人们研究了各种注意力机制。然而,以往的方法忽略了保留通道和空间方面的信息以增强跨维度交互的重要性。因此,本文提出了一种通过减少信息弥散和放大全局交互表示来提高深度神经网络性能的全局注意力机制。
本文引入了3D-permutation 与多层感知器的通道注意力和卷积空间注意力子模块。在CIFAR-100和ImageNet-1K上对所提出的图像分类机制的评估表明,本文的方法稳定地优于最近的几个注意力机制,包括ResNet和轻量级的MobileNet。
1简介
卷积神经网络已广泛应用于计算机视觉领域的许多任务和应用中。研究人员发现,CNN在提取深度视觉表征方面表现良好。随着CNN相关技术的改进,ImageNet数据集的图像分类准确率在过去9年里从63%提高到了90%。这一成就也归功于ImageNet数据集的复杂性,这为相关研究提供了难得的机会。由于它覆盖的真实场景的多样性和规模,有利于传统的图像分类、表征学习、迁移学习等研究。特别是,它也给注意力机制带来了挑战。
近年来,注意力机制在多个应用中不断提高性能,引起了研究兴趣。Wang等人使用编码-解码器residual attention模块对特征图进行细化,以获得更好的性能。Hu 等人分别使用空间注意力机制和通道注意力机制,获得了更高的准确率。然而,由于信息减少和维度分离,这些机制利用了有限的感受野的视觉表征。在这个过程中,它们失去了全局空间通道的相互作用。
本文的研究目标是跨越空间通道维度研究注意力机制。提出了一种“全局”注意力机制,它保留信息以放大“全局”跨维度的交互作用。因此,将所提出的方法命名为全局注意力机制(GAM)。
2相关工作
注意力机制在图像分类任务中的性能改进已经有很多研究。
SENet在抑制不重要的像素时,也带来了效率较低的问题。
CBAM依次进行通道和空间注意力操作,而BAM并行进行。但它们都忽略了通道与空间的相互作用,从而丢失了跨维信息。
考虑到跨维度交互的重要性,TAM通过利用每一对三维通道、空间宽度和空间高度之间的注意力权重来提高效率。然而,注意力操作每次仍然应用于两个维度,而不是全部三个维度。
为了放大跨维度的交互作用,本文提出了一种能够在所有三个维度上捕捉重要特征的注意力机制。
3GAM注意力机制
本文的目标是设计一种注意力机制能够在减少信息弥散的情况下也能放大全局维交互特征。作者采用序贯的通道-空间注意力机制并重新设计了CBAM子模块。整个过程如图1所示,并在公式1和2。给定输入特征映射,中间状态和输出定义为:
其中和分别为通道注意力图和空间注意力图;表示按元素进行乘法操作。
通道注意力子模块
通道注意子模块使用三维排列来在三个维度上保留信息。然后,它用一个两层的MLP(多层感知器)放大跨维通道-空间依赖性。(MLP是一种编码-解码器结构,与BAM相同,其压缩比为r);通道注意子模块如图2所示:
空间注意力子模块
在空间注意力子模块中,为了关注空间信息,使用两个卷积层进行空间信息融合。还从通道注意力子模块中使用了与BAM相同的缩减比r。与此同时,由于最大池化操作减少了信息的使用,产生了消极的影响。这里删除了池化操作以进一步保留特性映射。因此,空间注意力模块有时会显著增加参数的数量。为了防止参数显著增加,在ResNet50中采用带Channel Shuffle的Group卷积。无Group卷积的空间注意力子模块如图3所示:
Pytorch实现GAM注意力机制
import torch.nn as nn
import torch
class GAM_Attention(nn.Module):
def __init__(self, in_channels, out_channels, rate=4):
super(GAM_Attention, self).__init__()
self.channel_attention = nn.Sequential(
nn.Linear(in_channels, int(in_channels / rate)),
nn.ReLU(inplace=True),
nn.Linear(int(in_channels / rate), in_channels)
)
self.spatial_attention = nn.Sequential(
nn.Conv2d(in_channels, int(in_channels / rate), kernel_size=7, padding=3),
nn.BatchNorm2d(int(in_channels / rate)),
nn.ReLU(inplace=True),
nn.Conv2d(int(in_channels / rate), out_channels, kernel_size=7, padding=3),
nn.BatchNorm2d(out_channels)
)
def forward(self, x):
b, c, h, w = x.shape
x_permute = x.permute(0, 2, 3, 1).view(b, -1, c)
x_att_permute = self.channel_attention(x_permute).view(b, h, w, c)
x_channel_att = x_att_permute.permute(0, 3, 1, 2)
x = x * x_channel_att
x_spatial_att = self.spatial_attention(x).sigmoid()
out = x * x_spatial_att
return out
if __name__ == '__main__':
x = torch.randn(1, 64, 32, 48)
b, c, h, w = x.shape
net = GAM_Attention(in_channels=c, out_channels=c)
y = net(x)```
4实验
4.1 CIFAR-100
4.2 ImageNet-1K
4.3 消融实验
5参考
[1].Global Attention Mechanism: Retain Information to Enhance Channel-Spatial Interactions