yolov4,yolov5(学习记录)

输入端创新

1、Mosaic数据增强

yolov4中使用的Mosaic是参考2019年底提出的CutMix数据增强的方式,但CutMix只使用了两张图片进行拼接,而Mosaic数据增强则采用了4张图片,随机缩放、随机剪裁、随机排布的方式进行拼接。

preview

这里首先要了解为什么要进行Mosaic数据增强呢?

在平时项目训练时,小目标的AP一般比中目标和大目标低很多。而Coco数据集中也包含大量的小目标,但比较麻烦的是小目标的分布并不均匀。(小目标的AP指的是识别的准确率吗??也就是小目标识别不准,为了解决这个问题吗) 

小目标的定义:

可以看到小目标的定义是目标框的长宽0×0~32×32之间的物体。

但在整体的数据集中,小、中、大目标的占比并不均衡。
如上表所示,Coco数据集中小目标占比达到41.4%,数量比中目标和大目标都要多。

但在所有的训练集图片中,只有52.3%的图片有小目标,而中目标和大目标的分布相对来说更加均匀一些。

针对这种状况,Yolov4的作者采用了Mosaic数据增强的方式。

主要有几个优点:

  1. 丰富数据集:随机使用4张图片,随机缩放,再随机分布进行拼接,大大丰富了检测数据集,特别是随机缩放增加了很多小目标,让网络的鲁棒性更好。
  2. 减少GPU:可能会有人说,随机缩放,普通的数据增强也可以做,但作者考虑到很多人可能只有一个GPU,因此Mosaic增强训练时,可以直接计算4张图片的数据,使得Mini-batch大小并不需要很大,一个GPU就可以达到比较好的效果。

此外,发现另一研究者的训练方式也值得借鉴,采用的数据增强和Mosaic比较类似,也是使用4张图片不是随机分布),但训练计算loss时,采用“缺啥补啥”的思路:

如果上一个iteration中,小物体产生的loss不足(比如小于某一个阈值),则下一个iteration就用拼接图;否则就用正常图片训练,也很有意思。

参考链接:https://www.zhihu.com/question/3901

2、BackBone创新

(1)CSPDarknet53

CSPDarknet53是在yolov3主干网络Darknet53基础上,借鉴2019年CSPNet的经验,产生的Backbone结构,其中包含了5个CSP模块

preview

这里因为CSP模块比较长,不放到本处,大家也可以点击Yolov4的netron网络结构图,对比查看,一目了然。 

每个CSP模块前面的卷积核的大小都是3*3,stride=2,因此可以起到下采样的作用。

因为Backbone有5个CSP模块,输入图像是608*608,所以特征图变化的规律是:608->304->152->76->38->19

经过5次CSP模块后得到19*19大小的特征图。

而且作者只在Backbone中采用了Mish激活函数,网络后面仍然采用Leaky_relu激活函数。

我们再看看下作者为啥要参考2019年的CSPNet,采用CSP模块?

CSPNet论文地址:https://arxiv.org/pdf/1911.11929.pdf

CSPNet全称是Cross Stage Paritial Network,主要从网络结构设计的角度解决推理中计算量很大的问题。

CSPNet的作者认为推理计算过高的问题是由于网络优化中的梯度信息重复导致的。

因此采用CSP模块先将基础层的特征映射划分为两部分,然后通过跨阶段层次结构将它们合并,在减少了计算量的同时可以保证准确率。

因此Yolov4在主干网络Backbone采用CSPDarknet53网络结构,主要有三个方面的优点:

优点一:增强CNN的学习能力,使得在轻量化的同时保持准确性。

优点二:降低计算瓶颈

优点三:降低内存成本

(2)Mish激活函数

Mish激活函数是2019年下半年提出的激活函数

论文地址:https://arxiv.org/abs/1908.08681

Leaky_relu激活函数的图形对比如下:

Yolov4作者实验测试时,使用CSPDarknet53网络在ImageNet数据集上做图像分类任务,发现使用了Mish激活函数的TOP-1TOP-5的精度比没有使用时都略高一些。(什么是TOP-1和TOP-5精度

因此在设计Yolov4目标检测任务时,主干网络Backbone还是使用Mish激活函数。

(3)Dropblock

Yolov4中使用的Dropblock,其实和常见网络中的Dropout功能类似,也是缓解过拟合的一种正则化方式。(Dropout是什么在好多地方见过了,有时间看看)

Dropblock在2018年提出,论文地址:https://arxiv.org/pdf/1810.12890.pdf

传统的Dropout很简单,一句话就可以说的清:随机删除减少神经元的数量,使网络变得更简单。

剩下的部分跳过,可以参考知乎江大白  大佬的博客:深入浅出Yolo系列之Yolov3&Yolov4&Yolov5&Yolox核心基础知识完整讲解 - 知乎

下面直接进入YOLOv5部分

二、YOLOv5 

深入浅出Yolo系列之Yolov5核心基础知识完整讲解 - 知乎

1、自适应锚框计算

2、自适应图片缩放

在常用的目标检测算法中,不同的图片长宽都不相同,因此常用的方式是将原始图片统一缩放到一个标准尺寸,再送入检测网络中。

比如Yolo算法中常用416*416,608*608等尺寸,比如对下面800*600的图像进行缩放。

Yolov5代码中对此进行了改进,也是Yolov5推理速度能够很快的一个不错的trick。

作者认为,在项目实际使用时,很多图片的长宽比不同,因此缩放填充后,两端的黑边大小都不同,而如果填充的比较多,则存在信息冗余,影响推理速度。

因此在Yolov5的代码中datasets.py的letterbox函数中进行了修改,对原始图像自适应的添加最少的黑边

图像高度上两端的黑边变少了,在推理时,计算量也会减少,即目标检测速度会得到提升。

这种方式在之前github上Yolov3中也进行了讨论:https://github.com/ultralytics/yolov3/issues/232

在讨论中,通过这种简单的改进,推理速度得到了37%的提升,可以说效果很明显。

但是有的同学可能会有大大的问号??如何进行计算的呢?大白按照Yolov5中的思路详细的讲解一下,在datasets.py的letterbox函数中也有详细的代码。

第一步:计算缩放比例

原始缩放尺寸是416*416,都除以原始图像的尺寸后,可以得到0.52,和0.69两个缩放系数,选择小的缩放系数。

第二步:计算缩放后的尺寸 

原始图片的长宽都乘以最小的缩放系数0.52,宽变成了416,而高变成了312。

第三步:计算黑边填充数值

 下面省略了,这个技术其实对我不太重要,了解一下

3、Backbone

3.1 Focus结构

Focus结构,在Yolov3&Yolov4中并没有这个结构,其中比较关键是切片操作。

比如右图的切片示意图,4*4*3的图像切片后变成2*2*12的特征图。

以yolov5s的结构为例,原始608*608*3的图像输入Focus结构,采用切片操作,先变成304*304*12的特征图,再经过一次32个卷积核的卷积操作,最终变成304*304*32的特征图

需要注意的是:yolov4s的Focus结构最后使用了32个卷积核,而其他三种结构,使用的数量有所增加,先注意下,后面会讲解到四中结构的不同点。

3.2  CSP结构

yolov4网络结构中,借鉴了CSPNet的设计思路,在主干网络中设计了CSP结构。

yolov5与Yolov4的不同点在于,yolov4中只有主干网络使用了CSP结构,而yolov5中设计了两种CSP结构,以yolov5s网络为例,CSP1_X结构应用于Backbone主干网络,另一种CSP2_X结构则应用于Neck中。 

3.3  Neck

yolov4的Neck结构中,采用的都是普通的卷积操作。而yolov5的Neck结构中,采用借鉴CSPnet设计的CSP2结构,加强网络特征融合的能力

3.4  yolov5四种网络结构的不同点

yolov5代码中的四种网络,和之前的yolov3,yolov4的cfg文件不同,都是以yaml的形式来呈现。

而且四个文件的内容基本上都是一样的,只有最上方的depth_multiple和width_multiple两个参数不同 

3.4.1  四种结构的参数

(1)yolov5s.yaml

(2)Yolov5m.yaml

(3)Yolov5l.yaml

(4)Yolov5x.yaml

四种结构就是通过上面的两个参数,来控制网络的深度和宽度。其中depth_multiple控制网络的深度,width_multiple控制网络的深度。

3.4.2  yolo5网络结构 

四种结构的yaml文件中,下方的网络架构代码都是一样的。

为了便于讲解,将其中的Backbone部分提出来,讲解如何控制网络的宽度和深度,yaml文件中的Head部分也是同样的原理

在对网络结构进行解析时,Yolo.py中下方的这一行代码将四种结构的depth_multiple,width_multiple提取出,赋值给gd,gw。后面主要对gd,gw这两个参数进行详解。

下面再细致剖析下,看是如何控制每种结构,深度和宽度的。

3.4.3  yolov5四种网络的深度

(1)不同的网络深度

在上图中,画了两种CSP结构,CSP1和CPS2,其中CSP1结构主要应用于Backbone中,CSP2结构主要应用于Neck中。

需要注意的是,四种网络结构中每个CPS结构的深度都是不同的。

a.以yolov5s为例,第一个CSP1中,使用了1个残差组件,一次是CSP1_1。而在yolov5m中,则增加了网络的深度,咋第一个CSP1中,使用了2个残差组件,因此是CSP1_2        。

而yolov5l中,同样的位置,则使用了3个残差组件,yolov5x中,使用了4个残差组件。

其余的第二个CSP1和第三个CSP1也是同样的原理。

b.在第二种CSP2结构中也是同样的方式,以第一个CSP2结构为例,yolov5s组件中使用了2*X=2*1=2个卷积,因为X=1所以使用了1组卷积,因此是CSP2_1。

而yolov5m中使用了2组,yolov5l中使用了3组,yolov5x中使用了4组

yolov5中,网络的不断加深,也在不断增加网络特征提取和特征融合的能力。

(2)控制深度的代码

控制四种网络结构的核心代码是yolo.py中下面的代码,存在两个变量,n和gd。

我们再将n和gd代入计算,看每种网络的变化结果。

其实上面这个代码的具体功能没看明白) 

(3)验证控制深度的有效性

我们选择最小的yolov5.yaml和中间的yolov5l.yaml两个网络结构,将gd(depth_multiple)系数带入,看是否正确

a.yolov5s.yaml

其中depth_multiple=0.33,即gd=0.33,而n则由上面红色框中的信息获得

以上面网络框图中的第一个CSP1为例,即上面的第一个红色框。n等于第二个数值3.

而gd=0.33,带入(2)中的计算代码,结果n=1。因此第一个CSP1结构内只有1个残差组件,即CSP1_1.

第二个CSP1结构中,n等于第二个数值9,而gd=0.33,带入(2)计算,结果n=3,因此第二个CSP1结构中有3个残差组件,即CSP1_3.

第三个CSP1结构也是同理

b.yolov5l.yaml

其中depth_multiple=1,即gd=1

和上面的计算方式相同,第一个CSP1结构中,n=3,带入代码中,结果n=3,因此为CSP1_3

下面第二个CPS1和第三个CSP1结构都是同样的原理。

3.4.4  yolov5四种网络的宽度 

(1)不同网路的宽度:

如上图表格中所示,四种yolov5结构在不同阶段的卷积核的数量都是不一样的,因此也直接影响卷积后特征图的第三维度,即厚度,这里表示为网络的宽度。

a.以yolov5s结构为例,第一个Focus结构中,最后卷积操作时,卷积核的数量是32个,因此经过Focus结构,特征图的大小变成304*304*32

而yolov5m的Focus结构中的卷积操作使用了48个卷积核,因此Focus结构后的特征图变成304*304*48。yolov5l,yolov5x也是同样的原理。

b.第二个卷积操作时,yolov5s使用了64个卷积核,因此得到的特征图是152*152*64。而Yolov5m使用96个卷积核,因此得到的特征图是152*152*96.yolov5l,yolov5x也是同理。

c.后面三个卷积下采样操作也是同样的原理,这里不过多讲解。

四种不同结构的卷积核的数量不同,这也直接影响网络中,比如CSP1,CSP2等结构,以及各个普通卷积,卷积操作时的卷积核数量也在同步调整,影响整体网络的计算量。

大家最好可以将结构图和前面第一部分四个网络的特征图链接,对应查看,思路会更加清晰。

当然卷积核的数量越多,特征图的厚度,即宽度越宽,网络提取特征的学习能力也越强

(2)控制宽度的代码

在yolov5的代码中,控制宽度的核心代码是yolo.py文件里面的这一行:

它所调用的子函数make_divisible的功能是:(返回可被除数整除的 x)

Math.ceil(double x/y);功能: 向上取整,即返回大于或等于X/y结果值的整数。 当X/Y结果整除时直接返回结果,否则小数位舍去整数位加1。

(3)验证控制宽度的有效性

我们还是选择最小的yolov5s中间的yolov5l两个网络结构,将width_multiple系数带入,看是否正确。

a. yolov5s.yaml

其中width_multiple=0.5,即gw=0.5

以第一个卷积下采样为例,即Focus结构中下面的卷积操作。

按照上面Backbone的信息,我们知道Focus中,标准的c2=64,而gw=0.5,代入(2)中的计算公式,最后的结果=32。即Yolov5s的Focus结构中,卷积下采样操作的卷积核数量为32个。

再计算后面的第二个卷积下采样操作,标准c2的值=128,gw=0.5,代入(2)中公式,最后的结果=64,也是正确的。

b. yolov5l.yaml

其中width_multiple=1,即gw=1,而标准的c2=64,代入上面(2)的计算公式中,可以得到Yolov5l的Focus结构中,卷积下采样操作的卷积核的数量为64个,而第二个卷积下采样的卷积核数量是128个。

另外的三个卷积下采样操作,以及yolov5m,yolov5x结构也是同样的计算方式,大白这里不过多解释。

4 Yolov5相关论文及代码

4.1 代码

Yolov5的作者并没有发表论文,因此只能从代码角度进行分析。

Yolov5代码:https://github.com/ultralytics/yolov5

大家可以根据网页的说明,下载训练,及测试,流程还是比较简单的。

4.2 相关论文

另外一篇论文,PP-Yolo,在Yolov3的原理上,采用了很多的tricks调参方式,也挺有意思。

感兴趣的话可以参照另一个博主的文章:点击查看

5 小目标分割检测

目标检测发展很快,但对于小目标的检测还是有一定的瓶颈,特别是大分辨率图像小目标检测。比如7920*2160,甚至16000*16000的图像。

图像的分辨率很大,但又有很多小的目标需要检测。但是如果直接输入检测网络,比如yolov3,检出效果并不好。

主要原因是:

(1)小目标尺寸

以网络的输入608*608为例,yolov3、yolov4,yolov5中下采样都使用了5次,因此最后的特征图大小是19*19,38*38,76*76。

三个特征图中,最大的76*76负责检测小目标,而对应到608*608上,每格特征图的感受野是608/76=8*8大小。

再将608*608对应到7680*2160上,以最长边7680为例,7680/608*8=101。

即如果原始图像中目标的宽或高小于101像素,网络很难学习到目标的特征信息。

(PS:这里忽略多尺度训练的因素及增加网络检测分支的情况)

下面更多的内容这次可能用不到了,但还是比较重要并且有意思,有时间一定看一下

深入浅出Yolo系列之Yolov5核心基础知识完整讲解 - 知乎

版权声明:本文为CSDN博主「epic_Lin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/epic_Lin/article/details/121255705

epic_Lin

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐