目录
[SE-Inception and SE-ResNet](#SE-Inception and SE-ResNet)
论文地址
摘要
卷积神经网络建立在卷积运算的基础上,它通过在局部感受野内将空间和通道信息融合在一起来提取信息特征。为了提高网络的表示能力,最近的几种方法已经显示了增强空间编码的好处。在这项工作中,我们专注于通道关系,并提出了一种新颖的架构单元,我们将其称为"挤压和激励"(SE)块,它通过显式建模通道之间的相互依赖性来自适应地重新校准通道方面的特征响应。我们证明,通过将这些块堆叠在一起,我们可以构建在具有挑战性的数据集上具有极好的泛化能力的 SENet 架构。至关重要的是,我们发现 SE 模块能够以最小的额外计算成本为现有最先进的深度架构带来显着的性能改进。 SENets 构成了我们 ILSVRC 2017 分类提交的基础,该分类提交赢得了第一名,并将 top-5 错误率显着降低至 2.251%,与 2016 年获胜条目相比相对提高了约 25%。
我们通过引入一个新的架构单元(我们将其称为"挤压和激励"(SE)块)来研究架构设计的另一个方面 - 通道关系。我们的目标是通过显式建模网络卷积特征通道之间的相互依赖性来提高网络的表示能力。为了实现这一目标,我们提出了一种允许网络执行特征重新校准的机制,通过该机制它可以学习使用全局信息来选择性地强调信息丰富的特征并抑制不太有用的特征。
SE结构图
模型结构
SE 构建块的基本结构如图所示。对于任何给定的变换 Ftr : X → U, X ∈ RH′×W ′×C′ , U ∈ RH×W ×C ,,我们可以构建相应的 SE 块来执行特征重新校准。特征 U 首先通过挤压操作,该操作聚合跨空间维度 H × W 的特征图以生成通道描述符。该描述符嵌入了通道特征响应的全局分布,使得来自网络的全局感受野的信息能够被其较低层利用。接下来是激励操作,其中通过基于通道依赖性的自门机制为每个通道学习特定于样本的激活,控制每个通道的激励。然后对特征图 U 进行重新加权以生成 SE 块的输出,然后可以将其直接馈送到后续层中。
代码实现
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)
class SEConv(nn.Module):
# channel attentive convolution
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True, reduction=16): # ch_in, ch_out, kernel, stride, padding, groups
super().__init__()
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
self.bn = nn.BatchNorm2d(c2)
self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
self.se = SELayer(c2, reduction)
def forward(self, x):
residual = x
out = self.bn(self.conv(x))
out = self.se(out)
out += residual
return self.act(out)
class SEBottleneck(nn.Module):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = SEConv(c1, c_, 1, 1)
self.cv2 = SEConv(c_, c2, 3, 1, g=g)
self.add = shortcut and c1 == c2
def forward(self, x):
return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
以上代码添加在 ultralytics\nn\modules\block.py文件中
Squeeze
为了解决利用通道依赖性的问题,我们首先考虑输出特征中每个通道的信号。每个学习过滤器都使用局部感受野进行操作,因此变换输出 U 的每个单元都无法利用该区域之外的上下文信息。在感受野尺寸较小的网络较低层中,这个问题变得更加严重。为了缓解这个问题,我们建议将全局空间信息压缩到通道描述符中。这是通过使用全局平均池化生成通道统计数据来实现的。
Excitation
为了利用挤压操作中聚合的信息,我们接下来进行第二个操作,旨在完全捕获通道方面的依赖关系。为了实现这一目标,该函数必须满足两个标准:首先,它必须是灵活的(特别是,它必须能够学习通道之间的非线性交互),其次,它必须学习非互斥关系,因为我们将就像确保允许强调多个通道而不是单热激活。
SE-Inception and SE-ResNet
将 SE 块应用于 AlexNet和 VGGNet非常简单。 SE 块的灵活性意味着它可以直接应用于标准卷积之外的变换。为了说明这一点,我们通过将 SE 块集成到具有复杂设计的现代架构中来开发 SENet。对于非残差网络,例如Inception网络,通过将变换Ftr作为整个Inception模块来构造SE块。通过对架构中的每个此类模块进行此更改,我们构建了一个 SE-Inception 网络。此外,SE 块足够灵活,可以在残差网络中使用。图 3 描述了 SEResNet 模块的架构。这里,SE块变换Ftr被视为残差模块的非恒等分支。挤压和激励都在与恒等分支求和之前起作用。可以通过遵循类似的方案来构建与 ResNeXt、Inception-ResNet、MobileNet和 ShuffleNet集成的更多变体。
原始 Inception 模块和 SE-Inception 模块的架构
原始 Residual 模块和 SE-ResNet 模块的架构
yaml文件编写
# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C3SE, [256, False]]
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 18 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 21 (P5/32-large)
- [[16, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
完整代码分享
https://download.csdn.net/download/m0_67647321/88894601
总结
SE注意力机制,这是一种新颖的架构单元,旨在通过使其能够执行动态通道特征重新校准来提高网络的表示能力。大量的实验证明了 SENet 的有效性,它在多个数据集上实现了最先进的性能。此外,它们还提供了对先前架构在通道特征依赖性建模方面的局限性的一些见解,我们希望这对于需要强区分性特征的其他任务可能有用。最后,SE 块引起的特征重要性可能有助于相关领域,例如用于压缩的网络修剪。