秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡
专栏目录:《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进
卷积神经网络(CNN)通过收集复杂对象的分层和不同部分的语义子特征来生成特征表示。这些子特征通常在每个层的特征向量中以分组形式分布,代表各种语义实体。然而,这些子特征的激活往往受到相似模式和噪声背景的空间影响,导致错误的定位和识别。一个空间组增强(SGE)模块可以为每个语义组中每个空间位置生成一个注意力因子,从而调整每个子特征的重要性,以便每个组可以自主地增强其学习的表达并抑制可能的噪声。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
专栏地址:YOLOv8改进——更新各种有效涨点方法——点击即可跳转
目录
1. 原理
2. 将SGE添加到YOLOv8中
2.1 代码实现
2.2 更改init.py文件
2.3 新增yaml文件
2.4 注册模块
2.5 执行程序
3. 完整代码分享
4.GFLOPs
5. 进阶
6. 总结
1. 原理
论文地址:Spatial Group-wise Enhance: Improving Semantic Feature Learning in Convolutional Networks——点击即可跳转
官方代码:官方代码仓库——点击即可跳转
空间分组增强 (SGE) 模块旨在通过解决特征图中的空间错位和噪声来改进卷积神经网络 (CNN) 中的语义特征学习。以下是 SGE 模块的主要原理和机制:
分组特征:
-
特征沿卷积特征图的通道维度分组。这意味着将特征图分成几个组,每个组包含通道的子集。
注意机制:
-
在每个组中,根据全局特征和局部特征之间的相似性生成注意掩码。全局特征是组内所有特征的平均值,局部特征是该组内特定空间位置的特征。
-
注意掩码用于缩放每个空间位置的特征向量,增强重要特征并抑制噪声。这有助于确保语义特征在图像的空间维度上分布良好且稳健。
轻量级设计:
-
SGE 模块的设计具有计算效率,几乎不需要额外的参数或计算。这是通过使用点积和归一化等简单操作来生成注意掩码来实现的。
归一化和缩放:
-
计算基于相似性的系数(注意分数)后,对其进行归一化,以确保不同样本之间的缩放一致。这涉及减去平均值并除以每个组内系数的标准差。
-
然后使用可学习的参数对归一化的分数进行缩放和移位,确保网络可以在训练期间灵活调整 SGE 模块的影响。
性能提升:
-
事实证明,SGE 模块可以提高各种 CNN 架构在图像识别任务上的性能。它可以提高 ImageNet 基准测试中的 Top-1 准确率,并提高 COCO 基准测试中物体检测任务的平均准确率 (AP)。
总体而言,SGE 模块增强了每个组内语义特征的空间分布,从而使 CNN 中的特征表示更加准确和稳健。
2. 将SGE添加到YOLOv8中
2.1 代码实现
关键步骤一:将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/block.py中,并在该文件的__all__中添加“SpatialGroupEnhance”
from torch.nn import init
class SpatialGroupEnhance(nn.Module):
def __init__(self, groups=8):
super().__init__()
self.groups = groups
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.weight = nn.Parameter(torch.zeros(1, groups, 1, 1))
self.bias = nn.Parameter(torch.zeros(1, groups, 1, 1))
self.sig = nn.Sigmoid()
self.init_weights()
def init_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
init.kaiming_normal_(m.weight, mode='fan_out')
if m.bias is not None:
init.constant_(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
init.constant_(m.weight, 1)
init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
init.normal_(m.weight, std=0.001)
if m.bias is not None:
init.constant_(m.bias, 0)
def forward(self, x):
b, c, h, w = x.shape
x = x.view(b * self.groups, -1, h, w) # bs*g,dim//g,h,w
xn = x * self.avg_pool(x) # bs*g,dim//g,h,w
xn = xn.sum(dim=1, keepdim=True) # bs*g,1,h,w
t = xn.view(b * self.groups, -1) # bs*g,h*w
t = t - t.mean(dim=1, keepdim=True) # bs*g,h*w
std = t.std(dim=1, keepdim=True) + 1e-5
t = t / std # bs*g,h*w
t = t.view(b, self.groups, h, w) # bs,g,h*w
t = t * self.weight + self.bias # bs,g,h*w
t = t.view(b * self.groups, 1, h, w) # bs*g,1,h*w
x = x * self.sig(t)
x = x.view(b, c, h, w)
return x
SGE 模块的核心思想是在每个特征组内部进行空间增强,以提升特征学习的精度和鲁棒性。 具体步骤如下:
-
特征分组: 将特征图沿通道维度分成多个组,每个组包含代表特定语义的子特征。
-
全局特征提取: 对每个组内的所有特征进行全局平均池化,得到一个全局特征向量,代表该组学习的语义信息。
-
注意力权重生成: 计算全局特征向量与组内每个位置的特征向量之间的相似度,生成注意力权重向量。相似度越高,注意力权重越大。
-
特征增强: 将注意力权重向量通过 sigmoid 函数进行非线性变换,并与原始特征向量相乘,得到增强后的特征向量。 SGE 模块的优点:
-
轻量级: 仅引入少量参数,几乎没有额外的计算量。
-
高效: 有效提升特征学习的精度和鲁棒性,尤其是在识别具有高级语义的区域时。
-
可解释性强: 通过可视化注意力权重,可以直观地理解每个组学习的语义信息。
SGE 模块在图像分类和目标检测任务中都取得了显著的性能提升,证明了其在实践中的有效性。
2.2 更改init.py文件
关键步骤二:修改modules文件夹下的__init__.py文件,先导入函数
然后在下面的__all__中声明函数
2.3 新增yaml文件
关键步骤三:在 \ultralytics\ultralytics\cfg\models\v8下新建文件 yolov8_SGE.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
# 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, 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, SpatialGroupEnhance, [ 512 ] ]
- [ -1, 1, Conv, [ 512, 3, 2 ] ]
- [ [ -1, 9 ], 1, Concat, [ 1 ] ] # cat head P5
- [ -1, 3, C2f, [ 1024 ] ] # 21 (P5/32-large)
- [ -1, 1, SpatialGroupEnhance, [ 1024 ] ]
- [ [ 15, 19, 23 ], 1, Detect, [ nc ] ] # Detect(P3, P4, P5)
温馨提示:因为本文只是对yolov8基础上添加模块,如果要对yolov8n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。
# YOLOv8n
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.25 # layer channel multiple
# YOLOv8s
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
# YOLOv8l
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
# YOLOv8m
depth_multiple: 0.67 # model depth multiple
width_multiple: 0.75 # layer channel multiple
# YOLOv8x
depth_multiple: 1.33 # model depth multiple
width_multiple: 1.25 # layer channel multiple
2.4 注册模块
关键步骤四:在parse_model函数中进行注册,在parse_model函数中添加下面内容
elif m is SpatialGroupEnhance:
c1, c2 = ch[f], args[0]
if c2 != nc: # if c2 not equal to number of classes (i.e. for Classify() output)
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, *args[1:]]
2.5 执行程序
在train.py中,将model的参数路径设置为yolov8_SGE.yaml的路径
建议大家写绝对路径,确保一定能找到
from ultralytics import YOLO
# Load a model
# model = YOLO('yolov8n.yaml') # build a new model from YAML
# model = YOLO('yolov8n.pt') # load a pretrained model (recommended for training)
model = YOLO(r'/projects/ultralytics/ultralytics/cfg/models/v8/yolov8_SGE.yaml') # build from YAML and transfer weights
# Train the model
model.train(device = [3], batch=16)
🚀运行程序,如果出现下面的内容则说明添加成功🚀
3. 完整代码分享
https://pan.baidu.com/s/1oy-hZrMjOPIScMxpQpCeFg?pwd=yfbe
提取码: yfbe
4.GFLOPs
关于GFLOPs的计算方式可以查看:百面算法工程师 | 卷积基础知识——Convolution
未改进的YOLOv8nGFLOPs
改进后的GFLOPs
5. 进阶
可以与其他的注意力机制或者损失函数等结合,进一步提升检测效果
6. 总结
空间分组增强 (SGE) 模块通过解决特征图中的空间错位和噪声问题,改进了卷积神经网络中的语义特征学习。它沿通道维度对特征进行分组,并在每个组中使用注意机制,根据全局特征和局部特征之间的相似性生成注意掩码。这些掩码增强了重要特征,同时抑制了噪声,确保了语义特征的稳健性和分布性。SGE 模块具有计算效率,只需要极少的附加参数,并使用可学习的参数对注意力分数进行归一化和缩放。这种方法提高了 CNN 在图像识别和物体检测任务上的性能,提高了准确率和精确度。