注意力机制——Squeeze-and-Excitation Networks(SENet)

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),再根据实验结果进行适当调整。

猜你喜欢

转载自blog.csdn.net/weixin_50752408/article/details/129583914
今日推荐