Squeeze-and-Excitation Networks(SENet)是一种通道注意力模型,通过对每个通道进行权重调整,增强对于重要通道的关注度,从而提高了模型的表现力。
SENet的核心思想是“挤压-激励(squeeze-and-excitation)”模块。该模块由两个部分组成:
1.Squeeze操作:将每个通道的特征图压缩成一个数值,即全局平均池化(global average pooling),可以理解为对每个通道进行特征提取,得到该通道的重要性系数。
2.Excitation操作:根据Squeeze操作得到的通道重要性系数,对每个通道的特征图进行加权,即通过一个全连接层对重要性系数进行学习,得到一个权重向量,然后将该向量应用到原始的特征图上。
通过引入SE模块,SENet可以自适应地对不同通道进行加权,从而增强对于重要通道的关注度,提高模型的表现力。实验表明,在图像分类、物体检测、分割等任务上,SENet都能够取得更好的性能。
使用PyTorch实现SEModule的示例代码:
import torch
import torch.nn as nn
# 定义Squeeze-and-Excitation模块
class SEModule(nn.Module):
def __init__(self, channels, reduction):
super(SEModule, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.fc1 = nn.Linear(channels, channels // reduction)
self.relu = nn.ReLU(inplace=True)
self.fc2 = nn.Linear(channels // reduction, channels)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
b, c, _, _ = x.size()
y = self.avg_pool(x).view(b, c)
y = self.fc1(y)
y = self.relu(y)
y = self.fc2(y)
y = self.sigmoid(y).view(b, c, 1, 1)
return x * y
SEModule在SENet网络中添加实例:
class SENet(nn.Module):
def __init__(self, num_classes=1000, reduction=16):
super(SENet, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=2, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = nn.Sequential(
nn.Conv2d(64, 64, kernel_size=1, stride=1, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64, 256, kernel_size=3, stride=1, padding=1, bias=False),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
SEModule(256, reduction),
nn.Conv2d(256, 64, kernel_size=1, stride=1, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64, 256, kernel_size=3, stride=1, padding=1, bias=False),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
SEModule(256, reduction),
nn.Conv2d(256, 64, kernel_size=1, stride=1, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64, 256, kernel_size=3, stride=1, padding=1, bias=False),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
SEModule(256, reduction)
)
...
...
...
SEModule
中的第一个参数 in_channels
表示输入特征图的通道数,第二个参数 reduction
表示压缩比,用于控制注意力机制的复杂度,通常取小于等于输入通道数的正整数。在 Squeeze-and-Excitation 模块中,先通过一个全局平均池化层将输入特征图降维成一个一维向量,再通过一个全连接层将其映射到一个较小的向量,最后通过两个 nn.Sequential
模块分别实现了两个步骤:
- 先通过一个
nn.Linear
层将输入特征图的通道数降至in_channels // reduction
,再通过一个激活函数(通常是 ReLU)进行非线性变换。 - 再通过一个
nn.Linear
层将通道数恢复至in_channels
,并通过 Sigmoid 函数输出每个通道的权重系数,用于对输入特征图中不同通道的特征进行加权求和。
因此,在 SEModule(256, reduction)
中,in_channels
表示输入特征图的通道数,reduction
表示压缩比,用于控制注意力机制的复杂度。
在 SENet
中,reduction
通常被设置为 16 或 8,取决于输入特征图的通道数。如果输入特征图通道数较大,可以适当增加 reduction
的值,以控制注意力机制的计算复杂度,防止过拟合。相反,如果输入特征图通道数较小,可以适当降低 reduction
的值,以提高注意力机制的效果,增强模型的表达能力。实践中,reduction
的设置往往需要结合具体任务和数据集的特点进行调整,一般来说,可以先尝试使用默认的取值(如 16 或 8),再根据实验结果进行适当调整。