赞
踩
专栏目录: YOLO有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例
专栏链接: YOLO基础解析+创新改进+实战案例
YOLOv8是由Ultralytics开发的最先进的目标检测模型,推升了速度、准确性和用户友好性的界限。YOLO这一缩写代表“你只看一次”(You Only Look Once),通过在一次网络传递中同时预测所有边界框,提升了算法的效率和实时处理能力。相比之下,其他一些目标检测技术需要经过多个阶段或过程来完成检测。YOLOv8在流行的YOLOv5架构上进行了扩展,在多个方面提供了改进。YOLOv8模型与其前身的主要区别在于使用了无锚点检测,这加速了非极大值抑制(Non-Maximum Suppression, NMS)的后处理过程。YOLOv8能够以惊人的速度和精度识别和定位图像和视频中的物体,并处理图像分类和实例分割等任务。
下图是GitHub 用户 RangeKing 制作的YOLOv8网络架构的可视化结结构图。
这里的Neck和Head分开了
下图是另一个版本的网络架构图,这个版本并没有区分neck和head。 但本质上两张图是一样的
YOLOv8的网络结构主要由以下三个大部分组成:
Backbone部分负责特征提取,采用了一系列卷积和反卷积层,同时使用了残差连接和瓶颈结构来减小网络的大小并提高性能。该部分采用了C2f模块作为基本构成单元,与YOLOv5的C3模块相比,C2f模块具有更少的参数量和更优秀的特征提取能力。具体来说,C2f模块通过更有效的结构设计,减少了冗余参数,提高了计算效率。此外,Backbone部分还包括一些常见的改进技术,如深度可分离卷积(Depthwise Separable Convolution)和膨胀卷积(Dilated Convolution),以进一步增强特征提取的能力。
Neck部分负责多尺度特征融合,通过将来自Backbone不同阶段的特征图进行融合,增强特征表示能力。具体来说,YOLOv8的Neck部分包括以下组件:
Head部分负责最终的目标检测和分类任务,包括一个检测头和一个分类头:
除了上述结构外,YOLOv8还引入了一些新的优化技术,如:
这是架构中最基本的模块,包括Conv2d层、BatchNorm2d层和SiLU激活函数。
卷积是一种数学运算,涉及将一个小矩阵(称为核或滤波器)滑动到输入数据上,执行元素级的乘法,并将结果求和以生成特征图。“2D”在Conv2d中表示卷积应用于两个空间维度,通常是高度和宽度。
批归一化(BatchNorm2d)是一种在深度神经网络中使用的技术,用于提高训练稳定性和收敛速度。在卷积神经网络(CNN)中,BatchNorm2d层特定地对2D输入进行批归一化,通常是卷积层的输出。它通过在每个小批次的数据中标准化特征,使每个特征在小批次中的均值接近0、方差接近1,确保通过网络的数据不会太大或太小,这有助于防止训练过程中出现的问题。
SiLU(Sigmoid Linear Unit)激活函数,也称为Swish激活函数,是神经网络中使用的激活函数。SiLU激活函数定义如下:
[ SiLU ( x ) = x ⋅ σ ( x ) ] [ \text{SiLU}(x) = x \cdot \sigma(x) ] [SiLU(x)=x⋅σ(x)]
其中, σ ( x ) \sigma(x) σ(x)是Sigmoid函数,定义为:
[ σ ( x ) = 1 1 + e − x ] [ \sigma(x) = \frac{1}{1 + e^{-x}} ] [σ(x)=1+e−x1]
SiLU的关键特性是它允许平滑的梯度,这在神经网络训练过程中是有益的。平滑的梯度可以帮助避免如梯度消失等问题,这些问题会阻碍深度神经网络的学习过程。
在深度神经网络,尤其是残差网络(ResNet)中,Bottleneck Block(瓶颈块)是一种常用的模块设计。Bottleneck Block旨在通过引入瓶颈结构,减少计算复杂度和参数数量,同时保留模型的性能。以下是Bottleneck Block的详细介绍。
Bottleneck Block 典型地由三个卷积层(Conv2d)组成:
这些卷积层之间通常会插入 BatchNorm 和激活函数。一个 Bottleneck Block 还包括一个恒等映射(Identity Mapping)或一个卷积映射(Convolutional Mapping),用于实现残差连接。残差连接使得输入可以绕过中间卷积层,直接加到输出上,从而减轻梯度消失的问题。
假设输入张量为 X X X,输出张量为 Y Y Y。Bottleneck Block 的具体结构如下:
第一个 1x1 卷积层:
第二个 3x3 卷积层:
第三个 1x1 卷积层:
残差连接:
这种结构设计使得 Bottleneck Block 在减少计算量的同时,保留了网络的表达能力和训练稳定性。
Bottleneck Block 的设计通过在中间引入较少通道的卷积操作,实现了计算效率和性能之间的平衡。以下是 Bottleneck Block 的主要特点:
下图是yoloV8中Bottleneck Block结构,并不是典型的结构。
卷积层 1(Conv 1):首先输入通过一个卷积层,通常卷积核大小为 ( 1 × 1 ) (1 \times 1) (1×1),用于减少特征图的通道数。
卷积层 2(Conv 2):紧接着输入通过一个卷积层,通常卷积核大小为 ( 3 × 3 ) (3 \times 3) (3×3),用于提取特征并增加感受野。
跳跃连接(Skip Connection):在卷积层之间加入跳跃连接,将输入直接连接到输出。这种连接方式可以缓解梯度消失问题,帮助网络更好地学习。
拼接(Concatenate):最后,将跳跃连接后的输出与卷积层的输出进行拼接,形成最终输出。
输入(Input):输入特征图的尺寸,例如 ( 64 × 64 × 256 ) (64 \times 64 \times 256) (64×64×256)。
Conv 1:第一个卷积层的参数,通常包括卷积核大小、步长和填充方式等。例如,卷积核大小为 ( 1 × 1 ) (1 \times 1) (1×1),输出通道数为 64。
Conv 2:第二个卷积层的参数,通常包括卷积核大小、步长和填充方式等。例如,卷积核大小为 ( 3 × 3 ) (3 \times 3) (3×3),输出通道数为 128。
跳跃连接(Skip Connection):表示是否使用跳跃连接。
输出(Output):输出特征图的尺寸。
YOLOv8 的瓶颈块通过减少参数、增加网络深度和缓解梯度消失问题,显著提高了模型的性能和训练效果。该结构在保持计算效率的同时,增强了特征提取的能力,使得 YOLOv8 在目标检测任务中表现出色。
下图显示了YOLOv8的C2f模块结构:
SPPF(Spatial Pyramid Pooling - Fast)块是为了高效地捕捉多尺度信息而设计的,它利用简化版的空间金字塔池化。这个块允许网络处理不同尺度的特征,这在目标检测任务中特别有用,因为目标在图像中可能以不同的大小出现。
初始卷积块:
MaxPool2d层:
池化层用于下采样输入体积的空间维度,减少网络的计算复杂度并提取主要特征。最大池化是一种特定的池化操作,对于输入张量的每个区域,仅保留最大值,其他值则被丢弃。
在MaxPool2d的情况下,池化在输入张量的高度和宽度维度上进行。该层通过指定池化核的大小和步幅来定义。核大小决定每个池化区域的空间范围,步幅则决定连续池化区域之间的步长。
拼接:
最终卷积块: 拼接后的特征图再经过一个卷积层,卷积核大小为1x1,输出通道数与初始输入特征图相同。这个卷积层的作用是融合不同尺度的特征,生成最终的输出特征图。
以下是SPPF块的概念伪代码表示:
import torch import torch.nn as nn class SPPFBlock(nn.Module): def __init__(self, in_channels, out_channels, pool_size=5): super(SPPFBlock, self).__init__() self.initial_conv = nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, padding=0), nn.BatchNorm2d(out_channels), nn.SiLU() ) self.pool1 = nn.MaxPool2d(kernel_size=pool_size, stride=1, padding=pool_size // 2) self.pool2 = nn.MaxPool2d(kernel_size=pool_size, stride=1, padding=pool_size // 2) self.pool3 = nn.MaxPool2d(kernel_size=pool_size, stride=1, padding=pool_size // 2) self.final_conv = nn.Sequential( nn.Conv2d(out_channels * 4, out_channels, kernel_size=1, stride=1, padding=0), nn.BatchNorm2d(out_channels), nn.SiLU() ) def forward(self, x): x_initial = self.initial_conv(x) x1 = self.pool1(x_initial) x2 = self.pool2(x1) x3 = self.pool3(x2) x_concat = torch.cat((x_initial, x1, x2, x3), dim=1) x_final = self.final_conv(x_concat) return x_final # 使用示例 sppf_block = SPPFBlock(in_channels=64, out_channels=128) output = sppf_block(input_tensor)
SPPFBlock 类:
initial_conv
、pool1
、pool2
、pool3
和final_conv
。initial_conv
是一个顺序块,包括卷积、批归一化和SiLU激活。pool1
、pool2
和pool3
是三个MaxPool2d层,它们通过不同的卷积核大小和步幅对特征图进行池化。final_conv
是一个卷积块,用于处理拼接后的特征图。forward 方法:
x
通过 initial_conv
处理。pool1
、pool2
和 pool3
层。final_conv
处理,生成最终的输出。检测块负责检测物体。与之前版本的YOLO不同,YOLOv8是一个无锚点模型,这意味着它直接预测物体的中心,而不是从已知的锚点框的偏移量进行预测。无锚点检测减少了框预测的数量,加快了推理后筛选候选检测结果的复杂后处理步骤。检测块包含两个轨道。第一轨道用于边界框预测,第二轨道用于类别预测。这两个轨道都包含两个卷积块,随后是一个单独的Conv2d层,分别给出边界框损失和类别损失。
由最上面的YOLOv8网络结构图我们可以看出在其中的Backbone部分,由5个卷积模块和4个C2f模块和一个SPPF模块组成,
对应到yolo的yaml文件中的:
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2 第0层,-1代表将上层的输入作为本层的输入。第0层的输入是640*640*3的图像。Conv代表卷积层,相应的参数:64代表输出通道数,3代表卷积核大小k,2代表stride步长。
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4 第1层,本层和上一层是一样的操作(128代表输出通道数,3代表卷积核大小k,2代表stride步长)
- [-1, 3, C2f, [128, True]] # 第2层,本层是C2f模块,3代表本层重复3次。128代表输出通道数,True表示Bottleneck有shortcut。
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8 第3层,进行卷积操作(256代表输出通道数,3代表卷积核大小k,2代表stride步长),输出特征图尺寸为80*80*256(卷积的参数都没变,所以都是长宽变成原来的1/2,和之前一样),特征图的长宽已经变成输入图像的1/8。
- [-1, 6, C2f, [256, True]] # 第4层,本层是C2f模块,可以参考第2层的讲解。6代表本层重复6次。256代表输出通道数,True表示Bottleneck有shortcut。经过这层之后,特征图尺寸依旧是80*80*256。
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16 第5层,进行卷积操作(512代表输出通道数,3代表卷积核大小k,2代表stride步长),输出特征图尺寸为40*40*512(卷积的参数都没变,所以都是长宽变成原来的1/2,和之前一样),特征图的长宽已经变成输入图像的1/16。
- [-1, 6, C2f, [512, True]] # 第6层,本层是C2f模块,可以参考第2层的讲解。6代表本层重复6次。512代表输出通道数,True表示Bottleneck有shortcut。经过这层之后,特征图尺寸依旧是40*40*512。
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32 第7层,进行卷积操作(1024代表输出通道数,3代表卷积核大小k,2代表stride步长),输出特征图尺寸为20*20*1024(卷积的参数都没变,所以都是长宽变成原来的1/2,和之前一样),特征图的长宽已经变成输入图像的1/32。
- [-1, 3, C2f, [1024, True]] #第8层,本层是C2f模块,可以参考第2层的讲解。3代表本层重复3次。1024代表输出通道数,True表示Bottleneck有shortcut。经过这层之后,特征图尺寸依旧是20*20*1024。
- [-1, 1, SPPF, [1024, 5]] # 9 第9层,本层是快速空间金字塔池化层(SPPF)。1024代表输出通道数,5代表池化核大小k。结合模块结构图和代码可以看出,最后concat得到的特征图尺寸是20*20*(512*4),经过一次Conv得到20*20*1024。
在Block 0中,处理从大小为 ( 640 × 640 × 3 ) (640 \times 640 \times 3) (640×640×3)的输入图像开始,输入图像被送入一个卷积块,该卷积块的参数如下:卷积核大小为3,步长为2,填充为1。当使用步长为2时,空间分辨率会减少。以下是具体的计算过程:
输入图像:输入图像的尺寸为 ( 640 × 640 × 3 ) (640 \times 640 \times 3) (640×640×3),其中640表示高度和宽度,3表示颜色通道(RGB)。
卷积块参数:
步长和填充的影响:
输出计算:
代入公式计算:
W
o
u
t
=
(
640
−
3
+
2
×
1
)
2
+
1
=
640
−
3
+
2
2
+
1
=
639
2
+
1
=
320
W_{out} = \frac{(640 - 3 + 2 \times 1)}{2} + 1 = \frac{640 - 3 + 2}{2} + 1 = \frac{639}{2} + 1 = 320
Wout=2(640−3+2×1)+1=2640−3+2+1=2639+1=320
H
o
u
t
=
(
640
−
3
+
2
×
1
)
2
+
1
=
640
−
3
+
2
2
+
1
=
639
2
+
1
=
320
H_{out} = \frac{(640 - 3 + 2 \times 1)}{2} + 1 = \frac{640 - 3 + 2}{2} + 1 = \frac{639}{2} + 1 = 320
Hout=2(640−3+2×1)+1=2640−3+2+1=2639+1=320
因此,输出特征图的尺寸为 ( 320 × 320 ) (320 \times 320) (320×320)。
输出特征图:
经过一个卷积核大小为3、步长为2、填充为1的卷积块后,输入尺寸为 ( 640 × 640 × 3 ) (640 \times 640 \times 3) (640×640×3)的图像被减少到尺寸为 ( 320 × 320 ) (320 \times 320 ) (320×320)的特征图。由于步长为2,空间分辨率减半。
YOLOv8中的C2f模块由多个瓶颈块组成,具有两个关键参数:
shortcut
:一个布尔值,表示瓶颈块是否使用快捷连接。
shortcut = true
,则C2f模块内的瓶颈块使用快捷连接(残差连接)。输入 -----> 1x1卷积 -----> 3x3卷积 -----> 1x1卷积 -----> 输出shortcut = false
,则C2f模块内的瓶颈块不使用快捷连接。输入 -----> 1x1卷积 -----> 3x3卷积 -----> 1x1卷积 -----> 输出n
:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。