YOLOv8目标检测创新改进与实战案例专栏
专栏目录: YOLOv8有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例
专栏链接: YOLOv8基础解析+创新改进+实战案例
介绍
摘要
最近,基于MLP的视觉骨干网络开始出现。与CNN和视觉Transformer相比,具有较少归纳偏差的MLP架构在图像识别中表现出竞争力。其中,采用直接空间移位操作的空间移位MLP(S2-MLP)比包括MLP-mixer和ResMLP在内的早期工作取得了更好的性能。最近,使用较小的补丁和金字塔结构,Vision Permutator(ViP)和Global Filter Network(GFNet)在性能上超过了S2-MLP。本文中,我们改进了S2-MLP视觉骨干网络。我们在通道维度上扩展特征图,并将扩展后的特征图分成若干部分,对分割部分进行不同的空间移位操作。同时,我们利用分割注意力操作融合这些分割部分。此外,类似于其他方法,我们采用了较小尺度的补丁并使用金字塔结构来提升图像识别的准确性。我们将改进后的空间移位MLP视觉骨干网络称为S2-MLPv2。使用55M参数,我们的中型模型S2-MLPv2-Medium在ImageNet-1K基准测试中使用224 × 224的图像,在没有自注意力和外部训练数据的情况下实现了83.6%的top-1准确率。
文章链接
论文地址:论文地址
代码地址:代码地址
基本原理
分割注意力模块概述
分割注意力(Split Attention)模块旨在融合来自不同操作的多个特征图。这个模块在ResNeSt网络中首次提出,并被Vision Permutator等模型采用,用于增强特征图的表现能力。
具体实现步骤
特征图的平均计算:
- 假设有 $k$ 个大小为 $n \times c$ 的特征图$[X_1, X_2, \cdots, X_K]$,其中$(n$) 是patches的数量, $c$ 是通道数。
- 首先,计算这些特征图的平均值:
$$ a = \sum_{k=1}^{K} 1X_k $$
其中, $1 \in \mathbb{R}^n$ 是一个全1的行向量。
通过MLP生成注意力权重:
- 计算得到的平均值 (a) 会经过一系列的MLP层生成注意力权重:
$$ \hat{a} = \sigma(aW_1)W_2 $$
其中,$\sigma$ 是GELU激活函数,$$W_1 \in \mathbb{R}^{c \times \bar{c}}\) 和 \(W_2 \in \mathbb{R}^{\bar{c} \times Kc}$$ 是MLP层的权重矩阵,$\hat{a} \in \mathbb{R}^{Kc}$ 是输出。
- 计算得到的平均值 (a) 会经过一系列的MLP层生成注意力权重:
计算注意力矩阵:
- 输出 (\hat{a}) 会被重塑为矩阵 (\hat{A} \in \mathbb{R}^{K \times c}),然后通过softmax函数计算得到注意力矩阵:
$$ \bar{A} = \text{softmax}(\hat{A}) $$
其中,(\bar{A} \in \mathbb{R}^{K \times c})。
- 输出 (\hat{a}) 会被重塑为矩阵 (\hat{A} \in \mathbb{R}^{K \times c}),然后通过softmax函数计算得到注意力矩阵:
生成注意力特征图:
- 通过将每个特征图与注意力矩阵进行逐元素乘法,生成加权后的特征图 (\hat{X}):
$$ \hat{X}[i, :] = \sum_{k=1}^{K} X_k[i, :] \odot \bar{A}[k, :] $$
其中,(\odot) 表示逐元素乘法。
- 通过将每个特征图与注意力矩阵进行逐元素乘法,生成加权后的特征图 (\hat{X}):
yolov8代码
class S2Attention(nn.Module):
# S2注意力模块,整合空间位移和分割注意力
def __init__(self, channels=512):
super().__init__()
# 定义MLP层
self.mlp1 = nn.Linear(channels, channels * 3)
self.mlp2 = nn.Linear(channels, channels)
self.split_attention = SplitAttention()
def forward(self, x):
b, c, w, h = x.size()
x = x.permute(0, 2, 3, 1) # 调整维度顺序
x = self.mlp1(x) # 通过MLP层扩展特征
x1 = spatial_shift1(x[:, :, :, :c]) # 应用第一种空间位移
x2 = spatial_shift2(x[:, :, :, c:c * 2]) # 应用第二种空间位移
x3 = x[:, :, :, c * 2:] # 保留原始特征的一部分
x_all = torch.stack([x1, x2, x3], 1) # 堆叠特征
a = self.split_attention(x_all) # 应用分割注意力
x = self.mlp2(a) # 通过另一个MLP层缩减特征维度
x = x.permute(0, 3, 1, 2) # 调整维度顺序回原始
return x
task与yaml配置
详见: https://blog.csdn.net/shangyanaf/article/details/140472196