论文学习——YOLOv8网络解析
官方源码:https://github.com/ultralytics/ultralytics
论文地址:说是将会发布论文
官方说明文档:https://docs.ultralytics.com/
YOLOv8网络解析
0 前言
One key feature of YOLOv8 is its extensibility. It is designed as a framework that supports all previous versions of YOLO, making it easy to switch between different versions and compare their performance. This makes YOLOv8 an ideal choice for users who want to take advantage of the latest YOLO technology while still being able to use their existing YOLO models.
In addition to its extensibility, YOLOv8 includes a number of other innovations that make it an appealing choice for a wide range of object detection and image segmentation tasks. These include a new backbone network, a new anchor-free detection head, and a new loss function. YOLOv8 is also highly efficient and can be run on a variety of hardware platforms, from CPUs to GPUs.
从说明文档里面可以看到ultralytics
公司把YOLOv8
定义为一个算法框架(所以github库的名字并不是YOLOv8
而是ultralytics
),这个框架会支持以往所有版本的YOLO
,方便大家进行尝试和性能的对比。此外,YOLOv8
也引入了新的改进,包括新的backbone
、新的anchor-free
检测头和新的损失函数。YOLOv8
支持图像分类、物体检测和实例分割任务,而且能在CPU到GPUs不同的硬件平台上运行。
从官方贴出来的对比图来看,YOLOv8
比YOLOv5
的精度提升了不少,但是推理速度变慢了。
1 网络结构
YOLOv5
结构图:
YOLOv8
结构图:
YOLOv5
与YOLOv8
的对比:
YOLOv5 | YOLOv8 | |
---|---|---|
Backbone | C3模块的CSPDarknet结构 | C2f模块的CSPDarknet结构 |
Neck | SPPF、C3模块的PAN | SPPF、C2f模块的PAN |
Head | Coupled Head、Anchor-based | Decoupled-Head、Anchor-free |
Loss | 分类使用BEC Loss、回归使用CIoU Loss | 分类使用VFL Loss、回归使用DFL Loss+CIoU Loss |
标签分配 | 静态分配策略 | Task-Aligned Assigner分配 |
Backbone
YOLOv4的CSP模块
CSP
结构(来自CSPNet
)是先将基础层的特征分流为两部分,可以称为梯度流主分支和梯度流次分支,然后通过跨阶段层次结构再将它们合并,这样的设计能够实现更丰富的梯度组合,同时减少了计算量,该模块能与许多主流网络相结合,比如ResNet
、DenseNet
等。
CSPDarknet
是YOLOv4
在Darknet53
基础上引入了CSP
结构,梯度流主分支中的Bottleneck
采用的就是多个残差组件。
YOLOv5的C3模块
YOLOv5
的C3
模块与YOLOv4
中的CSP
模块区别不大,梯度流主分支中仍然使用的是残差组件,其中一个区别是YOLOv4
中卷积层后面使用的是Mish
激活函数,YOLOv5
使用的是SiLU
激活函数,C3
模块的详细结构可以查看该博文。
C3
模块的Pytorch
代码:
class C3(nn.Module):
# CSP Bottleneck with 3 convolutions
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c1, c_, 1, 1)
self.cv3 = Conv(2 * c_, c2, 1) # optional act=FReLU(c2)
self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, k=((1, 1), (3, 3)), e=1.0) for _ in range(n)))
def forward(self, x):
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))
YOLOv8的C2f模块
YOLOv8
的C2f
模块借鉴了YOLOv7
中的ELAN
思想,通过并行更多的梯度流分支,目的是为了在保证轻量化的同时获得更加丰富的梯度流信息,额外还增加了一个Split
操作。
C2f
模块的Pytorch
代码:
class C2f(nn.Module):
# CSP Bottleneck with 2 convolutions
def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
self.c = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, 2 * self.c, 1, 1)
self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
def forward(self, x):
y = list(self.cv1(x).split((self.c, self.c), 1))
y.extend(m(y[-1]) for m in self.m)
return self.cv2(torch.cat(y, 1))
Neck
SPPF对比SPP
左边为SPP
,右边为SPPF
(SPP-Fast
)。
两者的对比请参考这篇博文。两者的作用是一样的,但SPPF
的速度更高。
YOLOv5和YOLOv8的PAN比较
YOLOv5
的Neck
部分:
YOLOv8
的Neck
部分:
PAN
是在FPN
的基础上又增加了从下到上的融合。深层的feature map
携带更强的语义特征,较弱的定位信息,而浅层的feature map
携带较强的位置信息和较弱的语义特征。FPN
将深层的语义特征传到浅层,从而增强多个尺度上的的语义表达,而PAN
则相反把浅层的定位信息传导到深层,增强多个尺度上的定位能力。
YOLOv8
将YOLOv5
的PAN
中C3
模块替换为C2f
模块,并且去掉了上采样之前的1×1
卷积,将Backbone
不同阶段输出的特征直接送入了上采样操作。
Head
Head
部分的变化最大,YOLOv5
采用的耦合头(Coupled Head
)和Anchor-based
策略,YOLOv8
选择了解耦头(Decoupled Head
)和Anchor-free
策略,不再有之前的Objectness
分支,只有解耦的分类和回归分支。
YOLOX
的Head
中也使用了解耦头和Anchor-free
策略。在目标检测中,分类与回归任务的冲突是一种常见问题,因此,分类与定位头的解耦已被广泛应用到单阶段、两阶段检测中。YOLOX
的作者分析发现:检测头耦合会影响模型性能,采用解耦头替换YOLO
的检测头可以显著改善模型收敛速度。
Anchor-based
和Anchor-free
的区别就在于训练过程是否设置了先验框,Anchor-based
策略非常依赖于好的先验框设计,对于不同的任务以及形变较大(高宽比变化大)的目标,可能都需要人为地根据经验对先验框超参数进行设计和调节。Anchor-free
相对于就简单很多,但操作简单的同时可能会带来召回率性能欠佳、对重叠目标的检测效果一般等问题(比如YOLOv1
)。
2 训练策略
Loss
YOLOv5
的分类使用的BCE Loss
、回归使用的CIoU Loss
,YOLOv8
的分类使用的VFL Loss
(VarifocalNet: An IoU-aware Dense Object Detector)(但看下图源码里面其实还是使用的BCE Loss
)、回归使用DFL Loss
(Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for Dense Object Detection论文中所提出)+CIoU Loss
。
VFL Loss
VFL Loss
以BCE Loss
为基础,针对正样本和负样本提出了非对称的加权操作。
q
q
q在论文中表示target score,正样本时
q
q
q表示bbox
与gt
的IoU
分数,负样本时
q
q
q等于0。
对于正样本,VFL
损失就是以
q
q
q为权重的BCE
损失,因为
q
q
q值越大就说明该正样本越属于high-quality positive example,应该聚焦于这些高质量正样本的训练以达到更高的AP
。
对于负样本,VFL
损失会降低这些样本对损失的贡献,方法就是通过赋予
p
γ
p^{\gamma}
pγ权重。
最后为了平衡正样本损失和负样本损失,增加了一个可调整的比例参数
α
\alpha
α给负样本损失。
在YOLOv6
论文中对比了不同的分类损失,最终实验数据表明了VFL
有更好的表现。
DFL Loss
该损失的提出主要是为了解决bbox
的表示不够灵活(inflexible representation)问题。传统目标检测,尤其是复杂场景中,目标物体的真实边界框的定义其实是无法精确给出的(包括标注人的主观倾向,或是遮挡、模糊等造成的边界歧义及不确定性)。如下图所示,水中的帆板边界、被遮挡的大象边界,其实都很难去界定一个精确的位置。
传统的回归方法(下方左图)直接使预测值向一个离散的确定值(标签位置
y
y
y)进行逼近。针对上方所述的场景,回归一个分布范围(下方右图)相比于逼近一个离散值更符合事实。DFL
损失就是基于这样的思想,将框的位置建模成一个general distribution
,让网络能够快速地聚焦于标签位置
y
y
y附近范围的位置分布。
标签分配策略
目标检测的一个底层问题是正负样本分配问题,比如网络预测了10000个预测框,为了训练网络,首先需要知道这10000个预测框的标签是什么?这就会涉及到许多的问题,正样本数多少合适?一些模糊样本(比如与gt
有重叠但是重叠面积不大的预测框)如何处理?不同的标签分配策略会对模型性能带有很大的影响。
分配策略大致分为传统的静态分配和动态分配。静态分配指的是使用先验的固定规则如IoU
最大、最接近anchor
中点、根据尺寸比例等方法进行匹配。动态分配指的就是它会根据当前预测的结果选出最优的prior anchor
对gt
进行匹配。
现在的目标检测模型一般都会采用动态分配策略,比如YOLOX
的simOTA
、TOOD
的TaskAlignedAssigner
。YOLOv5
采用的是静态分配策略,YOLOv8
是直接引用了TOOD
的TaskAlignedAssigner
。
TaskAlignedAssigner
的匹配策略简单总结为: 根据分类与回归的分数加权的分数选择正样本。
3 参考
【2】YOLOv8来啦 | 详细解读YOLOv8的改进模块!YOLOv5官方出品YOLOv8,必卷!
【3】YOLOv5网络详解
【4】深入浅出Yolo系列之Yolov3&Yolov4&Yolov5&Yolox核心基础知识完整讲解
【5】空间金字塔池化改进 SPP / SPPF / SimSPPF / ASPP / RFB / SPPCSPC / SPPFCSPC
更多推荐
所有评论(0)