秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡
专栏目录 :《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有50+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进——点击即可跳转
深度是深度神经网络的特征。但更多的深度意味着更多的顺序计算和更高的延迟。这就引出了一个问题——能否构建高性能的“非深度”神经网络?我们展示了这是可能的。为此,我们使用并行子网络,而不是一层接一层地堆叠。这有助于有效减少深度,同时保持高性能。通过利用并行子结构,我们首次展示了一个深度仅为12的网络。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
专栏地址:YOLOv8改进——更新各种有效涨点方法——点击即可跳转
目录
1. 原理
2. 将ParNetAttention添加到YOLOv8中
2.1 ParNetAttention代码实现
2.2 更改init.py文件
2.3 添加yaml文件
2.4 在task.py中进行注册
2.5 执行程序
3. 完整代码分享
4. GFLOPs
5. 进阶
6. 总结
1. 原理
论文地址:NON-DEEP NETWORKS——点击即可跳转
官方代码:官方代码仓库——点击即可跳转
ParNetAttention的主要原理在于其独特的并行子网络结构。下面是一些关键点:
-
非深度设计:ParNet(Parallel Networks)通过使用并行子网络代替传统的逐层堆叠结构,显著减少了网络的深度。典型的ParNet只有12层,但在ImageNet、CIFAR10和CIFAR100等竞争性基准上表现出色。
-
并行子网络:在ParNet中,层级不是顺序连接的,而是并行排列的。这种设计允许减少网络深度,同时保持高准确性。并行子网络之间没有连接,只有在开始和结束时才进行连接。
-
效率与性能:由于并行子结构,ParNet可以有效地在多个处理器之间并行化,超越了传统的深度网络(如ResNet)的速度和准确性。尽管引入了处理单元之间的通信延迟,但ParNet仍能实现高效的并行处理。
-
扩展性:ParNet可以通过增加宽度、分辨率和分支数量来有效扩展,同时保持深度恒定。实验表明,ParNet的性能不会饱和,随着计算量的增加,可以实现更高的性能。
-
SSE模块:ParNet块由三个并行分支组成:1×1卷积、3×3卷积和Skip-Squeeze-and-Excitation (SSE)模块。训练完成后,1×1和3×3卷积可以融合在一起,以实现更快的推理。SSE分支增加了感受野,同时不影响深度。
总之,ParNet通过并行子网络设计,实现了在保持较低深度的同时,依然具有竞争力的性能和高效的计算能力。
2. 将ParNetAttention添加到YOLOv8中
2.1 ParNetAttention代码实现
关键步骤一: 将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/block.py中,并在该文件的__all__中添加“ParNetAttention”
class ParNetAttention(nn.Module):def __init__(self, channel=1024, out_channel=1024):super().__init__()self.sse = nn.Sequential(nn.AdaptiveAvgPool2d(1),nn.Conv2d(channel, out_channel, kernel_size=1),nn.Sigmoid())self.conv1x1 = nn.Sequential(nn.Conv2d(channel, out_channel, kernel_size=1),nn.BatchNorm2d(out_channel))self.conv3x3 = nn.Sequential(nn.Conv2d(channel, out_channel, kernel_size=3, padding=1),nn.BatchNorm2d(out_channel))self.silu = nn.SiLU()def forward(self, x):b, c, _, _ = x.size()x1 = self.conv1x1(x)x2 = self.conv3x3(x)x3 = self.sse(x) * xy = self.silu(x1 + x2 + x3)return y
ParNet处理图片的主要流程涉及多个并行子结构,每个子结构都有不同的卷积和特征提取模块。以下是其处理图片的主要步骤:
-
输入图像:输入图像首先经过初始的卷积层,用于基本的特征提取和降采样。
-
并行子网络结构:
-
并行分支:图像特征被送入多个并行的分支,每个分支包含不同的卷积操作。主要的分支包括1×1卷积、3×3卷积和Skip-Squeeze-and-Excitation (SSE)模块。
-
1×1卷积:这一分支主要用于减少特征维度和线性组合特征。
-
3×3卷积:这一分支用于提取更复杂的特征,并增加感受野。
-
Skip-Squeeze-and-Excitation (SSE)模块:这一分支通过通道注意机制提升特征表示能力。
-
-
特征融合:
-
并行分支的输出在最后进行融合。融合方式可以是简单的加和操作或其他复杂的融合策略,以集成不同分支提取到的特征。
-
-
全局池化与全连接层:
-
融合后的特征图经过全局平均池化,减少特征图的尺寸,并生成固定长度的特征向量。
-
全局池化后的特征向量被送入全连接层,用于最终的分类或回归任务。
-
-
输出:
-
最终的全连接层输出分类结果或其他任务的结果(如检测、分割等)。
-
通过上述流程,ParNet能够在保持较低深度的同时,实现高效的特征提取和高准确性的图像处理。其核心在于并行子网络结构,这使得网络能够在多个处理器之间并行执行,提高计算效率并减少延迟。
2.2 更改init.py文件
关键步骤二:修改modules文件夹下的__init__.py文件,先导入函数
然后在下面的__all__中声明函数
2.3 添加yaml文件
关键步骤三:在/ultralytics/ultralytics/cfg/models/v8下面新建文件yolov8_PA.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, ParNetAttention, [ 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, ParNetAttention, [ 1024 ] ] # ParNetAttention https://arxiv.org/abs/2110.07641- [ [ 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
max_channels: 1024 # max_channels# YOLOv8s
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
max_channels: 1024 # max_channels# YOLOv8l
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
max_channels: 512 # max_channels# YOLOv8m
depth_multiple: 0.67 # model depth multiple
width_multiple: 0.75 # layer channel multiple
max_channels: 768 # max_channels# YOLOv8x
depth_multiple: 1.33 # model depth multiple
width_multiple: 1.25 # layer channel multiple
max_channels: 512 # max_channels
2.4 在task.py中进行注册
关键步骤四:在task.py的parse_model函数中进行注册,
2.5 执行程序
关键步骤五:在ultralytics文件中新建train.py,将model的参数路径设置为yolov8_PA.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_PA.yaml') # build from YAML and transfer weights# Train the model
model.train(batch=16)
🚀运行程序,如果出现下面的内容则说明添加成功🚀
3. 完整代码分享
https://pan.baidu.com/s/1I7VfQa6NRgAAgSO_vwGG3g?pwd=ugu5
提取码:ugu5
4. GFLOPs
关于GFLOPs的计算方式可以查看:百面算法工程师 | 卷积基础知识——Convolution
未改进的YOLOv8nGFLOPs
改进后的GFLOPs
5. 进阶
可以结合损失函数或者卷积模块进行多重改进
6. 总结
ParNetAttention的主要原理是通过引入并行子网络结构来替代传统深度网络的逐层堆叠设计,以显著减少网络深度并提升计算效率。具体来说,ParNetAttention在处理图像时,将输入特征图分配到多个并行分支,这些分支分别进行1×1卷积、3×3卷积和Skip-Squeeze-and-Excitation (SSE)模块处理。通过这种并行计算方式,网络能够有效提取多样化的特征,并在最后融合这些特征以生成最终的输出。这个并行结构不仅加快了计算速度,还通过有效的特征融合提升了模型的表现,同时允许在宽度和分支数量上进行扩展,保持较低深度的同时实现高效、精确的图像处理。