yolov5-v6.0详细解读
- 一、yolov5版本介绍
- 二、网络结构
- 2.1 Backbone特征提取部分
- 2.1.1 ConvBNSiLU模块
- 2.1.2 C3模块
- 2.1.2.1 BottleNeck模块
- 2.1.3 SPPF模块
- 2.2 Neck特征融合部分
- 2.2.1 FPN
- 2.2.2 PANet
- 2.3Head模块
- 三、目标框回归
- 3.1 yolo标注格式
- 3.2 yolov4目标回归框
- 3.3 yolov5目标回归框
- 四、正负样本匹配
- 五、 损失函数
- 5.1 总损失
- 5.2 边界框损失
- 5.3 分类损失
- 5.4 置信度损失
- 六、训练技巧
- 6.1 Mosaic数据增强
- 6.2 自适应锚框
- 6.3自适应图片缩放
- 6.4 训练预热 Warmup
- 6.5 余弦退火调整学习率
- 6.6 超参数进化
【yolo专题】目标检测评估指标
【yolo专题】yolov1:背景介绍与算法精讲
【yolo专题】yolo9000:Better, Faster, Stronger的目标检测网络
【yolo专题】YOLOv3:算法与论文详细解读
【yolo专题】YOLOV4改进方法详细介绍—看这一篇就够了!
一、yolov5版本介绍
YOLOv5目前有YOLOv5n、YOLOv5s、YOLOv5m、YoLOv5l、YOLOv5x五个版本。这五个版本在网络结构上是没有区别的,唯一的区别就是网络的宽度和深度不一样,在这5个版本的配置文件里面是通过设置不同的depth_multiple和width_multiple来控制网络的大小。其中depth_multiple控制网络的深度(BottleneckCSP数),width_multiple控制网络的宽度(卷积核数量)。通过设置这两个不同参数,不同复杂度模型数量如下表:
当depth_multiple和width_multiple都为1的时候,此时的网络结构是没有增加和减少的。我们常用的是版本YOLOv5s,此时网络模型的深度(BottleneckCSP数量)是YOLOv5L的1/3,宽度(conv)是YOLOv5L的一半。
二、网络结构
yolov5的网络结构如下:
图片链接:https://github.com/ultralytics/yolov5/issues/6885
2.1 Backbone特征提取部分
YOLOv5-v6.0版本的Backbone主要由ConBNSiLU模块、C3和SPPF模块三部分组成。
Backbone特征提取部分采用的是CSPNet网络结构,CSP(Cross Stage Partial Network)跨阶段局部网络,它的网络结构图如下,使用csp网络有以下优点。
- 减少计算量和参数数量:CSPNet通过将网络分成两个阶段,并在两个阶段之间引入CSP模块,可以减少整体的计算量和参数数量。CSP模块通过将输入特征图一分为二,并将其中一部分直接通过跳跃连接连接到后续的层级,有效地减少了后续层级的计算量,从而提高了网络的效率。
- 提升信息流动性:CSPNet中的CSP模块还能够增强特征图中信息的流动性。通过将特征图分成两部分,并在不同部分之间引入交叉连接,CSP模块可以更好地促进特征之间的信息传递和交换,从而增强了特征图的表达能力。
- 增强特征重用性:CSPNet通过引入CSP模块,将输入特征图分成两部分并进行交叉连接,使得网络可以更充分地利用输入特征图中的信息。这种交叉连接的设计增强了特征的重用性,有助于提高网络的泛化能力和分类性能。
- 降低过拟合风险:由于CSPNet通过减少参数数量和引入跳跃连接来降低计算量,这也有助于减轻过拟合的风险。相比于传统的深度神经网络结构,CSPNet具有更好的泛化能力,能够更好地适应不同的数据集和任务。
- 保持高性能:尽管CSPNet减少了计算量和参数数量,但它仍然能够保持较高的分类性能。通过有效地利用输入特征图中的信息,并增强特征图之间的交互,CSPNet可以在保持高效率的同时实现与传统网络相媲美甚至更好的分类性能。
2.1.1 ConvBNSiLU模块
ConvBNSiLU模块在yolo的配置文件中是以Conv的形式出现的,为了方便理解,后面都将 ConvBNSiLU理解为CBS模块,它主要由以下三个部分组成:
YOLOv5在ConvBNSiLU模块中封装了三个功能:普通的卷积(Conv2d)、Batch Normalization和激活函数SiLU(sigmoid linear unit),这里会发现激活函数和yolov5旧版本不太一样,旧版本使用的是Leaky ReLU。
SiLU激活函数图像如下,相对于ReLU激活函数,它在x轴的负半轴有段向下的曲线:
- 正数区域内,SiLU 函数的输出与 ReLU 函数的输出相同。
- 在负数区域内,SiLU 函数的输出与 sigmoid 函数的输出相同。
- SiLU 函数在整个定义域内都是可微的,这使得在反向传播过程中的梯度计算更加稳定。
- SiLU函数不是单调递增的,而是在x≈−1.28时达到全局最小值−0.28,这可以起到一个隐式正则化的作用,抑制过大的权重。
2.1.2 C3模块
这里解释一下为什么叫C3模块,因为是由三个CBS模块,也就是三个卷积层,再加上若干个BottleNeck模块构成,输入进来的特征,分为两个部分,一部分特征是只经过CBS模块处理,一部分经过CBS+BottleNeck处理,最后通过concat将两部分特征进行拼接,再经过一个CBS层将特征维度进行恢复。
YOLOv5-v6.0版本中使用了C3模块,替代了早期的BottleneckCSP模块。这两者结构作用基本相同,均为CSP架构,只是在修正单元的选择上有所不同,C3模块包含了3个标准卷积层以及多个Bottleneck模块,与BottleneckCSP模块所不同的是,经过Bottleneck模块输出后的Conv模块被去掉了。
2.1.2.1 BottleNeck模块
在C3模块中存在若干个BottleNeck模块,该模块其实存在两种形式,也就是BottleNeck1和BottleNeck2,BottleNeck1是以resnet残差结构连接的,该残差结构是由两条路构成,其中一路先进行1×1卷积将特征图的通道数减小一半,从而减少计算量,再通过3×3卷积提取特征,并且将通道数加倍,其输入与输出的通道数是不发生改变的,而另外一路通过shortcut进行残差连接,与第一路的输出特征图相加,从而实现特征融合;BottleNeck2只是经过一次1x1卷积的CBS和一次3x3卷积的CBS。
2.1.3 SPPF模块
YOLOv5-v6.0版本使用了SPPF(Spatial Pyramid Pooling Fast)模块来代替SPP(Spatial Pyramid Pooling)模块。
其中SPP是Spatial Pyramid Pooling的简称,即空间金字塔池化,YOLOv5借鉴了SPPNet的思想。这里先来看一下SPP结构,该结构是何凯明15年在Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition论文中提出来的,在RCNN中第一阶段检测出来的候选框大小不一样,为了让这些候选框可以变成固定大小送进FC层,SPP就可以达到这一目的。
旧版本的yolov5中的SPP:feature map首先经过一个卷积降维,然后分别进行kernel size为5, 9, 13的max polling层,最后将它们与降维之后的特征concat起来,然后再经过一个卷积将channel恢复成原来大小。
SPPF模块采用多个小尺寸池化核级联代替SPP模块中单个大尺寸池化核,从而在保留原有功能,即融合不同感受野的特征图,丰富特征图的表达能力的情况下,进一步提高了运行速度。该模块输入的特征图首先经过卷积层进行降维,再经过三个kernel size=5的卷积核进行最大池化,将每次池化后的特征与卷积之后的特征进行concat,最后再经过一次卷积,将特征图的尺度进行恢复。
2.2 Neck特征融合部分
2.2.1 FPN
论文链接:https://arxiv.org/abs/1612.03144
即Feature Pyramid Network(特征金字塔)。原来多数的目标检测算法只是采用顶层特征做预测,但我们知道浅层的特征所携带的语义信息较少,而位置信息更强;深层的特征所携带的语义信息较丰富,而位置信息更弱。FPN的思想就是把深层的语义信息传递到浅层,从而增强多个尺度上的语义表达。
通俗地说,FPN可以比喻成一座金字塔,每一层代表不同尺度的特征图。底部的特征图尺寸较大,但信息较为粗糙,适合检测大的物体;而顶部的特征图尺寸较小,但信息更加精细,适合检测小的物体。FPN通过自上而下的反卷积(upsampling)和自下而上的跳跃连接(skip connection)的方式,将这些不同尺度的特征图融合在一起,形成一个特征金字塔,使得网络能够同时关注不同尺度的特征。
FPN的大致结构如上图所示,左边是一个自底向上(Bottom-up)的传播路径,也就是特征提取部分,右边是一个自顶向下(Top-down)的传播路径,中间是通过横向连接(lateral connection)进行特征融合。
自底向上(Bottom-up)的过程就是网络的前向传播过程,从结构图可以看出,取经过第2个C3和第3个C3以及最后一个SPPF模块的Feature map来构成金字塔,当输入图片大小是640x640x3的时候,该特征金字塔的Feature map分别是80x80x256、40x40x512、20x20x1024组成。
自顶向下(Top-down)的过程是从小尺寸的feature map开始逐个进行1/2降维和2倍上采样,(这里的顶表示深层次的网络信息,也就是Backbone特征提取网络最后一层20x20x1024的信息),然后与特征金字塔上一层的Feature map进行concat拼接,这里的降维操作使用的是1x1的卷积降低特征图通道数;最顶层的特征图为20x20x1024大小,通过降维和上采样之后变成40x40x512特征图与特征金字塔第二层的Feature map40x40x512进行拼接,得到40x40x1024的特征图。
在拼接融合之后还会对每个拼接结果进行C3模块卷积,目的是消除上采样的混叠效应(aliasing effect)。然后继续降维上采样与第一层的Feature map进行拼接。
2.2.2 PANet
论文链接:https://arxiv.org/abs/1803.01534
FPN通过自顶向下(Top-down)的结构,将深层的语义信息传递到浅层,但是浅层的位置信息却无法影响到深层特征。同时,FPN中顶部信息流需要通过骨干网络(Backbone)逐层地往下传递,由于层数相对较多,如果使用原路返回的方法,计算量比较大。此时想到另外一种方法,如果能够将已经经过特征金字塔融合的特征,再进行自底向上传递的话就可以解决计算量大的问题,而PANet有效地解决了上述这些问题。
(a)FPN骨干。(b)PANet自下而上的路径增强。©自适应特征池。(d)箱形分支。(e)全连接融合。
如上图(b)所示,PANet在FPN的基础上又引入了一个自底向上(Bottom-up)的路径。经过自顶向下(Top-down)的特征融合后,再进行自底向上(Bottom-up)的特征融合,这样底层的位置信息也能够传递到深层,从而增强多个尺度上的定位能力。同时,与FPN相比(如红色线条所示),PANet中的底层特征传递所需要穿越的feature map数量大大减少(如绿色线条所示),使得底层的位置信息更容易传递到顶部。
经过FPN之后的特征图,再进行下采样与特征金字塔中已经融合的特征再进行拼接融合。其中自底向上(Bottom-up)的过程是沿着N2 → N3 → N4 → N5路径,逐个stage通过3×3卷积进行2倍下采样,然后与FPN中相应大小的feature map进行相加融合(在YOLOv5中采用的是拼接融合)。也就是P2进行下采样之后生成的N2与P3进行拼接成为N3,N3在再与P4进行拼接。
2.3Head模块
在YOLOv5中,Head模块通过1x1卷积将Neck模块得到的不同尺度的特征图的通道数量扩展,扩展后的通道数为(类别数量+5)乘以每个检测层上的anchor数量。其中,5表示预测框的中心点的横坐标、纵坐标、宽度、高度和置信度。这里的置信度代表了预测框中存在目标的可信度,其取值范围在0到1之间,值越大表示该预测框中可能存在目标的可能性越高。
在YOLOv5的Head模块中,包含了3个检测层,分别对应Neck模块中得到的3种不同尺寸的特征图。针对这3种特征图,YOLOv5在每个网格上预设了3个不同宽高比的anchor,用来预测和回归目标。因此,Head模块中扩展后的通道维度可以理解为在特征图的通道维度上保存了所有基于anchor先验框的位置信息和分类信息。
三、目标框回归
3.1 yolo标注格式
在PASCAL VOC中物体在图像中的位置是以左上角坐标和右下角坐标进行确定的,yolo物体标记的物体位置则是用相对位置进行标记,物体的具体位置是由中心点坐标以及宽、高决定的。那么如何将PASCAL VOC坐标转换为yolo格式的坐标呢,假设该物体的坐标由(187,21)、(403,627)决定,此时我们需要计算该目标的中心点坐标(x,y),再除以图片的宽高,就可以得到yolo格式的中心点坐标,同理,物体相对于该图片的大小也使用该方法计算。
3.2 yolov4目标回归框
先分析一下yolov4的目标框回归公式:
首先Anchor给出了目标宽高的初始值,需要回归的是目标真实宽高与初始宽高的偏移量
- 预测边界框中心点相对于对应cell左上角位置的相对偏移值
- 为了将边界框中心点约束在当前cell中,使用sigmoid函数处理偏移值,使预测偏移值在(0,1)范围内
3.3 yolov5目标回归框
yolov5的tx、ty,tw,th都经过了sigmoid函数处理,因为原始的yolo/darknet框方程式存在严重缺陷。宽度和高度完全不受限制,因为它们只是out = exp(in),这很危险,因为它可能导致失控的梯度、不稳定、NaN损失并最终完全失去训练。
对于yolov5,确保通过sigmoid所有模型输出来修补此错误,同时还要确保中心点保持不变1 = fcn(0),当tx、ty,tw,th偏移量都为0,此时预测值都为1,此时得到的就是锚框大小。 当前的方程式将锚点的倍数从最小0限制为最大4,并且锚点-目标匹配也已更新为基于宽度-高度倍数,标称上限阈值超参数为4.0,超过这个值就认为bbox和anchor匹配度不高,而认为是背景。为什么公式中要取平方运算,通过下面这幅实验图可以看出输入和输出的关系。
四、正负样本匹配
YOLOv5的每个检测层上的每个网格都预设了多个anchor先验框,但并不是每个网格中都存在目标,也并不是每个anchor都适合用来回归当前目标,因此需要对这些anchor先验框进行筛选,将其划分为正样本和负样本。本文的正负样本指的是预测框而不是Ground Truth(人工标注的真实框)。
与YOLOv3/4不同的是,YOLOv5采用的是基于宽高比例的匹配策略,它的大致流程如下:
- 对于每一个Ground Truth(人工标注的真实框),分别计算它与9种不同anchor的宽与宽的比值(w1/w2, w2/w1)和高与高的比值(h1/h2, h2/h1)。
- 找到Ground Truth与anchor的宽比(w1/w2, w2/w1)和高比(h1/h2, h2/h1)中的最大值,作为该Ground Truth和anchor的比值。
- 若Ground Truth和anchor的比值小于设定的比值阈值(超参数中默认为anchor_t = 4.0),那么这个anchor就负责预测这个Ground Truth,即这个anchor所回归得到的预测框就被称为正样本,剩余所有的预测框都是负样本。
通过上述方法,YOLOv5不仅筛选了正负样本,同时对于部分Ground Truth在单个尺度上匹配了多个anchor来进行预测,总体上增加了一定的正样本数量。除此以外,YOLOv5还通过以下几种方法增加正样本的个数,从而加快收敛速度。
- 跨网格扩充: 假设某个Ground Truth的中心点落在某个检测层上的某个网格中,除了中心点所在的网格之外,其左、上、右、下4个邻域的网格中,靠近Ground Truth中心点的两个网格中的anchor也会参与预测和回归,即一个目标会由3个网格的anchor进行预测。
- 如果点(xg,yg)在格子的左上角,则取左边、上方的两个格子;
- 如果点(xg,yg)在格子的右上角,则取右边、上方的两个格子;
- 如果点(xg,yg)在格子的左下角,则取左边、下方的两个格子;
- 如果点(xg,yg)在格子的右下角,则取右边、上下方的两个格子
- 跨分支扩充:YOLOv5的检测头包含了3个不同尺度的检测层,每个检测层上预设了3种不同长宽比的anchor,假设一个Ground Truth可以和不同尺度的检测层上的anchor匹配,则这3个检测层上所有符合条件的anchor都可以用来预测该Ground Truth,即一个目标可以由多个检测层的多个anchor进行预测。
五、 损失函数
5.1 总损失
YOLOv5损失函数包括:
- classification loss, 分类损失
- localization loss, 定位损失(预测边界框与GT之间的误差)
- confidence loss, 置信度损失(框的目标性;objectness of the box)
把640x640的输入图像划分成NxN(通常为80x80、40x40、20x20)的网格,然后对网格的每个格子都预测三个指标:矩形框、置信度、分类概率。
其中:
- 矩形框表征目标的大小以及精确位置。
- 置信度表征所预测矩形框(简称预测框)的可信程度,取值范围0~1,值越大说明该矩形框中越可能存在目标。
- 分类概率表征目标的类别
总的损失函数:Aclassification loss + Blocalization loss + C*confidence loss(A,B,C表示每个损失所占的权重大小)
由于yolov5生成的是三个尺寸的特征图,所以需要对每一个尺寸的特征图都求损失,最后的总损失是每个特征图的分类损失+边界框损失+置信度损失。
上式中α1、α2、α3为各网格损失函数值的权重系数。考虑到图像中往往小型目标比较多,中型目标次之,大型目标最少,因此通常把8080网格的权重α1设置最大,4040网格的权重α2次之,20*20网格的权重α3最小,使得训练时网络更加专注于数量多的目标。
5.2 边界框损失
YOLOV5使用 CIOU Loss作为bounding box回归的损失。关于CIOU以及GIOU和DIOU的损失计算方法可以参考这篇文章:YOLOV4改进方法详细介绍—看这一篇就够了
5.3 分类损失
类别预测:大多数分类器假设输出标签是互斥的。 如果输出是互斥的目标类别,则确实如此。 因此,YOLO应用softmax函数将得分转换为总和为1的概率。 而YOLOv3/v4/v5使用多标签分类。 例如,输出标签可以是“行人”和“儿童”,它们不是非排他性的。 (现在输出的总和可以大于1)。YOLOv3/v4/v5用多个独立的逻辑(logistic)分类器替换softmax函数,以计算输入属于特定标签的可能性。在计算分类损失进行训练时,YOLOv3/v4/v5对每个标签使用二元交叉熵损失。 这也避免使用softmax函数而降低了计算复杂度。
神经网络对80*80网格的每个格子都预测三个预测框,每个预测框的预测信息都包含了N个分类概率。其中N为总类别数,比如COCO数据集有80个类别,那么N取80。所以对于COCO数据集,每个预测框有80个0~1的分类概率,那么神经网络总共预测3x80x80x80个分类概率,组成预测概率矩阵。
YOLOv5默认使用二元交叉熵函数来计算分类损失。二元交叉熵函数的定义为:
5.4 置信度损失
对于一张图像分割成的80*80的网格,神经网络对其中每个格子都预测三个位于该格子附近的矩形框(简称预测框),每个预测框的预测信息包括中心坐标、宽、高、置信度、分类概率,因此神经网络总共输出3x80x80个0~1的预测置信度,与3x80x80个预测框一 一对应。每个预测框的置信度表征这个预测框的靠谱程度,值越大表示该预测框越可信靠谱,也即越接近目标的真实最小包围框。
比如下图中,红点A、B、C、D表示检测目标,那么每个红点所在格子的三个预测置信度应该比较大甚至接近1,而其它格子的预测置信度应该较小甚至接近0。
这样一来,标签值的大小与预测框、目标框的重合度有关,两框重合度越高则标签值越大。如果CIOU的取值范围是-1.5-1,而置信度标签的取值范围是0~1,所以需要对CIOU做一个截断处理:当CIOU小于0时直接取0值作为标签。
与计算分类损失一样,YOLOv5默认使用二元交叉熵函数来计算置信度损失。
六、训练技巧
6.1 Mosaic数据增强
Mosaic数据增强是指将4张图片随即缩放、随机裁剪、随机排布的方式进行拼接成新的图片,该方式仅在训练过程中使用。下图就是一个Mosaic数据增强的过程。
- 丰富数据集:随机使用4张图片,随机缩放,再随机分布进行拼接,大大丰富了检测数据集,特别是随机缩放增加了很多小目标,让网络的鲁棒性更好。
- 减少GPU:可能会有人说,随机缩放,普通的数据增强也可以做,但作者考虑到很多人可能只有一个GPU,因此Mosaic增强训练时,可以直接计算4张图片的数据,使得Mini-batch大小并不需要很大,一个GPU就可以达到比较好的效果。
6.2 自适应锚框
传统的yolo会先设置初始的锚框,这些初始锚框是根据COCO等数据集进行聚类得到的:
anchors:- [10,13, 16,30, 33,23] # P3/8- [30,61, 62,45, 59,119] # P4/16- [116,90, 156,198, 373,326] # P5/32
之前我们学的 YOLOv3、YOLOv4,对于不同的数据集,都会计算先验框 anchor。然后在训练时,网络会在 anchor的基础上进行预测,输出预测框,再和标签框进行对比,最后就进行梯度的反向传播。
在 YOLOv3、YOLOv4 中,训练不同的数据集时,是使用单独的脚本进行初始锚框的计算,在 YOLOv5 中,则是将此功能嵌入到整个训练代码里中。所以在每次训练开始之前,它都会根据不同的数据集来自适应计算 anchor。
6.3自适应图片缩放
在常用的目标检测算法中,不同的图片长宽都不相同,因此常用的方式是将原始图片统一缩放到一个标准尺寸,再送入检测网络中,如下图所示。但是,在项目实际使用时,很多图片的长宽比不同,因此缩放填充后,两端的黑边大小都不同,而如果填充的比较多,则存在信息冗余,影响推理速度。因此YOLOv5作者在augmentations.letterbox()中对图像自适应添加最少的灰边(代码中添加的是灰边,本文以黑边代替)。
训练时没有采用缩减黑边的方式,还是采用传统填充的方式,即缩放到640*640大小。只是在测试,使用模型推理时,才采用缩减黑边的方式,提高目标检测,推理的速度。
6.4 训练预热 Warmup
由于刚开始训练时,模型的权重(weights)是随机初始化的,此时若选择一个较大的学习率,可能带来模型的不稳定(振荡),选择Warmup预热学习率的方 式,可以使得开始训练的几个epoch或者一些step内学习率较小,在预热的小学习率下,模型可以慢慢趋于稳定,等模型相对稳定后在选择预先设置的学习率进行训练,使得模型收敛速度变得更快,模型效果更佳。
6.5 余弦退火调整学习率
参考论文:https://arxiv.org/pdf/1608.03983.pdf
在每一次运行中,我们用余弦退火对每个批次的学习率进行衰减,如下所示:
通过训练学习率曲线和精确度曲线可以看出,使用余弦退火的曲线更加平滑。
6.6 超参数进化
超参数进化是一种利用遗传算法进行超参数优化的方法用于优化的算法(GA)。目前模型提供的默认参数是通过在COCO数据集上使用超参数进化得来的(由于超参数进化会耗费大量的资源和时间,如果默认参数训练出来的结果能满足你的使用,使用默认参数也是不错的选择)