1.注意力机制
我们可以通过眼睛看到各种各样的事物,感知世界上的大量信息;可以让自己免受海量信息的干扰,是因为人的选择能力,可以选择重要的信息,而忽视不重要信息。同样,希望网络也具有这种能力,从而在网络中引入了注意力机制。注意力机制,是对输入进行加权再输出,希望网络关注到的地方给较大的权重,不希望网络注意的地方给较小的权重。
2.空间注意力
当输入的大小为(256,256,3)时,输出为(256,256,1)的空间注意力机制的PyTorch实现代码如下所示:
import torch
import torch.nn as nn
class SpatialAttention(nn.Module):
def __init__(self, in_channels, kernel_size=7):
super(SpatialAttention, self).__init__()
padding = kernel_size // 2
self.conv = nn.Conv2d(in_channels, 1, kernel_size, padding=padding, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
# x: [batch_size, channels, height, width]
# channel-wise pooling
x_mean = torch.mean(x, dim=1, keepdim=True) # [batch_size, 1, height, width]
# convolution
x_conv = self.conv(x_mean) # [batch_size, 1, height, width]
# sigmoid
x_sigmoid = self.sigmoid(x_conv) # [batch_size, 1, height, width]
# apply attention
x_attention = x * x_sigmoid.expand_as(x) # [batch_size, channels, height, width]
# reduce channel dimension to 1
x_attention = torch.mean(x_attention, dim=1, keepdim=True) # [batch_size, 1, height, width]
return x_attention
其中,使用torch.mean对特征图进行平均池化操作,从而将通道数从输入的3降到1。因为对于每个像素位置,通过空间注意力机制得到的权重都是一样的,因此对不同通道的结果进行平均化是合理的。
3.通道注意力
以下是一个简单的通道注意力的代码实现:
import torch
import torch.nn as nn
class ChannelAttention(nn.Module):
def __init__(self, in_channels, reduction_ratio=16):
super(ChannelAttention, self).__init__()
# 通过全局平均池化层来计算通道维度上的平均值
self.avg_pool = nn.AdaptiveAvgPool2d(1)
# 通过一个线性层,将平均池化后的特征图进行降维,输出维度为 (in_channels/reduction_ratio, 1, 1)
self.fc = nn.Sequential(
nn.Linear(in_channels, in_channels // reduction_ratio),
nn.ReLU(inplace=True),
nn.Linear(in_channels // reduction_ratio, in_channels),
nn.Sigmoid()
)
def forward(self, x):
# 获取输入x的尺寸
batch_size, num_channels, H, W = x.size()
# 计算通道维度上的平均值
x_pool = self.avg_pool(x)
# 将通道维度上的平均值进行展平
x_pool = x_pool.view(batch_size, num_channels)
# 将展平后的特征图输入到全连接层中,得到每个通道上的权重系数,输出维度为 (batch_size, num_channels)
x_fc = self.fc(x_pool)
# 将通道维度上的权重系数进行扩展,扩展为与输入特征图相同的维度 (batch_size, num_channels, H, W)
x_fc = x_fc.view(batch_size, num_channels, 1, 1)
x_fc = x_fc.expand_as(x)
# 将原始特征图与通道权重系数相乘,得到加权后的特征图
x = x * x_fc
# 返回加权后的特征图在通道维度上求和,得到输出特征图,维度为 (batch_size, 1, 1, num_channels)
x = x.sum(dim=1, keepdim=True)
return x
4. 混合注意力机制
在混合注意力机制中,通道注意力和空间注意力可以通过串联、或者并联的方式进行组合。
混合注意力机制的代表模型是:卷积注意力模块(Convolutional Block Attention Module,CBAM),它包括通道注意力模块CAM、和空间注意力模块SAM。
CBAM的模型结构如下,它对输入的特征图,首先进行通道注意力模块处理;得到的结果,再经过空间注意力模块处理,最后得到调整后特征。