论文地址:https://arxiv.org/abs/1709.01507
pytorch实现:https://github.com/miraclewkf/SENet-PyTorch
主题思想
论文中心的思想是下列该图,其主要目的是有选择地注重信息有用的特征通道并抑制无用的特征通道,方法是给下图U中C个HxW的特征通道分配不同的权重,当然权重也是通过网络学习获得。这个思想有点类似生活中我们投票,你地位高那么你1票可以抵上普通人的5票,如果你地位过低只能算0.5票。论文中也提到这有关于注意力和门机制,由于本人不熟悉该NLP方面的知识,大家有兴趣可以参考:https://www.jianshu.com/p/e14c6a722381

代码实现
论文作者表示可以灵活地将SE block整合到现有的网络模型。以ResNet-18作为基础网络,在ResNet的BasicBlock基础上添加Squeeze和Excitation操作得到的上图SE block。其中squeeze操作采用平均池化,对应上图的Fsq方法,excitation操作包括两个全连接层和激活函数,对应上图Fex。上图中得到1x1xC的tensor不同颜色表示C个不同的权重,表示特征选择后的每个特征通道的重要性,然后与先前特征U上的逐个通道相乘,完成在通道维度上的对原始特征的重标定。


代码实现为
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, inplanes, planes, stride=1, downsample=None):
super(BasicBlock, self).__init__()
self.conv1 = conv3x3(inplanes, planes, stride)
self.bn1 = nn.BatchNorm2d(planes)
self.relu = nn.ReLU(inplace=True)
self.conv2 = conv3x3(planes, planes)
self.bn2 = nn.BatchNorm2d(planes)
self.downsample = downsample
self.stride = stride
if planes == 64:
self.globalAvgPool = nn.AvgPool2d(56, stride=1)
elif planes == 128:
self.globalAvgPool = nn.AvgPool2d(28, stride=1)
elif planes == 256:
self.globalAvgPool = nn.AvgPool2d(14, stride=1)
elif planes == 512:
self.globalAvgPool = nn.AvgPool2d(7, stride=1)
self.fc1 = nn.Linear(in_features=planes, out_features=round(planes / 16))
self.fc2 = nn.Linear(in_features=round(planes / 16), out_features=planes)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
residual = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None:
residual = self.downsample(x)
original_out = out
out = self.globalAvgPool(out)
out = out.view(out.size(0), -1)
out = self.fc1(out)
out = self.relu(out)
out = self.fc2(out)
out = self.sigmoid(out)
out = out.view(out.size(0), out.size(1), 1, 1)
out = out * original_out
out += residual
out = self.relu(out)
return out
以一张224x224的彩色图片为例,其一个SE block维度变化的流程图为下图红框区域。

额外的参数量
相对于原来的模型,现在网络中新增的参数量主要是两个全连接层。第一个FC首先将特征维度降低到输入的 1/16,然后经过 ReLu 激活后再通过第二个FC层升回到原来的维度。这样做比直接用一个全连接层的好处在于:1)具有更多的非线性,可以更好地拟合通道间复杂的相关性;2)极大地减少了参数量和计算量。其中1/16也是一个超参数r,下图为不同r下的错误率和参数量。

全连接层其参数量为输入通道数乘以输出通道数,上述SE block有两个全连接层,第一个降维的FC维度为Cx(C/r),第二个升维的FC维度为(C/r)xC,故一个SE block新增的参数量为2xCx(C/r)。若网络中有S个stage,每个stage有Ns个SE block,那么总共新增的参数量为下图公式:

从公式5可以看出,增加的参数量和通道C关系很大,而网络越到高层,其feature map的通道数越多,也就是C越大,因此大部分增加的参数都是在高层。同时作者通过实验发现即便去掉最后一个stage的SE block,对模型的影响也非常小(<0.1% top-1 error),因此如果你对参数量的限制要求很高,倒是可以这么做,毕竟具体在哪些stage,哪些block中添加SE block都是自由定义的。
下图两张图可以看出使用SE block在计算成本上的增加可以忽略不计,但是错误率却有显著的下降,尤其是ResNet-101在添加SE block后比原先更深的ResNet-152错误还要低,添加SE block显然是一个明智的选择。

