SE
Squeeze-and-Excitation Networks。
通过全局平均池化,先降维再升维的变换,使用sigmoid函数实现特征的重标定,给通道赋值不同的权重,最后再将权重加载到输入中。
class SELayer(nn.Module):
def __init__(self, channel, reduction=16):
super(SELayer, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Sequential(
nn.Linear(channel, channel // reduction, bias=False),
nn.ReLU(inplace=True),
nn.Linear(channel // reduction, channel, bias=False),
nn.Sigmoid()
)
def forward(self, x):
b, c, _, _ = x.size()
y = self.avg_pool(x).view(b, c)
y = self.fc(y).view(b, c, 1, 1)
return x * y.expand_as(x)
SE模块和残差模块结合,一般放在残差分支,和输入相加之前,可以对残差分支学习到的特征进行加权调整,从而增强高级特征的表达能力。
class SEBasicBlock(nn.Module):
expansion = 1
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
base_width=64, dilation=1, norm_layer=None,
*, reduction=16):
super(SEBasicBlock, self).__init__()
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3,stride=stride, padding=1)
self.bn1 = nn.BatchNorm2d(planes)
self.relu = nn.ReLU(inplace=True)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,stride=1, padding=1)
self.bn2 = nn.BatchNorm2d(planes)
self.se = SELayer(planes, reduction)
self.downsample = downsample
self.stride = stride
def forward(self, x):
residual = x
out = self.relu(self.bn1(self.conv1(x)))
out = self.se(self.bn2(self.conv2(out))) #use SE
if self.downsample is not None:
residual = self.downsample(x)
out += residual
out = self.relu(out)
return out
ECA
Effificient Channel Attention for Deep Convolutional Neural Networks。
作者经过实验研究表明,SENet中降维对通道的注意力预测带来了副作用,提出了一种不降维的局部跨通道交互策略,使用一维卷积替代了SENet中的MLP。
class ECALayer(nn.Module):
"""Constructs a ECA module.
Args:
channel: Number of channels of the input feature map
k_size: Adaptive selection of kernel size
"""
def __init__(self, channel, k_size=3):
super(eca_layer, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding=(k_size - 1) // 2, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
# x: input features with shape [b, c, h, w]
b, c, h, w = x.size()
# feature descriptor on the global spatial information
y = self.avg_pool(x) # [b, c, 1, 1]
# Two different branches of ECA module
y = y.squeeze(-1).transpose(-1, -2) # [b, c, 1] => [b, 1,c]
y = self.conv(y) # [b, 1,c]
y = y.transpose(-1, -2).unsqueeze(-1) # [b, c, 1] => [b, c, 1, 1]
# Multi-scale information fusion
y = self.sigmoid(y)
return x * y.expand_as(x)
CA
Coordinate attention for efficient mobile