赞
踩
与yolov3对比,yolov5主要进行了下面4方面的改进:(其实很多在yolov4中已经存在了,这里再仔细研究一下)。以5.0版本来介绍,6.0版本将Focus去掉了。结构图见3.1
下面分别详细解说:
Yolov4/5中使用的Mosaic是参考2019年底提出的CutMix数据增强的方式,但CutMix只使用了两张图片进行拼接,而Mosaic数据增强则采用了4张图片,随机缩放、随机裁剪、随机排布的方式进行拼接。
这里首先要了解为什么要进行Mosaic数据增强呢?
在平时项目训练时,小目标的AP一般比终目标和大目标低很多。而Coco数据集中也包含大量的小目标,但比较麻烦的是小目标的分布并不均匀。首先看下小、中、大目标的定义:
2019年发布的论文《Augmentation for small object detection》对此进行了区分:
可以看到小目标的定义是目标框的长宽0*0~32*32之间的物体
但在整体的数据集中,小、中、大目标的占比并不均衡。如上表所示,Coco数据集中小目标占比达41.4%,数量比中目标和大目标都要多。但在所有的训练集图片中,只有52.3%的图片有小目标,而终目标和大目标的分布相对来说更加均匀一些。针对这种情况,YOLOV4/5的作者采用了Moscaic数据增强的方式。主要有几个优点:
次外,发现另一研究者的训练方式也值得借鉴,采用的数据增强和Mosaic比较类似,也是使用4张图片(不是随机分布),但训练计算loss时,采用”缺啥补啥“的思路:如果上一个iteration中,小物体产生的loss不足(比如小于某一阈值),则下一个iteration就用拼接图;否则就用正常图片训练。
Focus模块在v5中是图片进入backbone前,对图片进行切片操作,具体操作是在一张图片中每隔一个像素拿到一个值,类似于邻近下采样,这样就拿到了四张图片,四张图片互补,长的差不多,但是没有信息丢失,这样一来,将W、H信息就集中到了通道空间,输入通道扩充了4倍,即拼接起来的图片相对于原先的RGB三通道模式变成了12个通道,最后将得到的新图片再经过卷积操作,最终得到了没有信息丢失情况下的二倍下采样特征图。
其实就是yolov2里面的ReOrg+Conv操作,也就是亚像素卷积的反向操作版本,简单来说就是把数据切分成4份,每份数据都是相当于2倍下采样得到的,然后再channel维度进行拼接,最后进行卷积操作。可以最大程度的减少信息损失而进行下采样操作。
以yolov5s为例,原始的640 × 640 × 3的图像输入Focus结构,采用切片操作,先变成320 × 320 × 12的特征图,再经过一次卷积操作,最终变成320 × 320 × 32的特征图。切片操作如下:
先引用yolov5官方解答:
Focus() 是用来降低FLOPS的,跟mAP无关,但接下来你可能看到使用Focus() 之后对比普通卷积层FLOPS反而增加了,那作者为什么说可以降低呢?作者又回答了:一个Focus层可以代替3个yolov3/4的层。层数减少了,FLOPS肯定是降低啦。
在讨论Focus的作用之前,先了解两个概念:
总所周知,图片在经过Focus模块后,最直观的是起到了下采样的作用,但是和常用的卷积下采样有些不一样,可以对Focus的计算量和普通卷积的下采样计算量进行做个对比:在yolov5s的网络结构中,可以看到,Focus模块的卷积核是3 × 3,输出通道是32:
那么做个对比:
普通下采样:即将一张640 × 640 × 3的图片输入3 × 3的卷积中,步长为2,输出通道32,下采样后得到320 × 320 × 32的特征图,那么普通卷积下采样理论的计算量为:
FLOPs(conv) = 3 × 3 × 3 × 32 × 320 × 320 = 88473600(不考虑bias情况下)
params参数量(conv) = 3 × 3 × 3 × 32 +32 +32 = 928 (后面两个32分别为bias和BN层参数)
Focus:将640 × 640 × 3的图像输入Focus结构,采用切片操作,先变成320 × 320 × 12的特征图,再经过3 × 3的卷积操作,输出通道32,最终变成320 × 320 × 32的特征图,那么Focus理论的计算量为:
FLOPs(Focus) = 3 × 3 × 12 × 32 × 320 × 320 = 353894400(不考虑bias情况下)
params参数量(Focus)= 3 × 3 × 12 × 32 +32 +32 =3520 (为了呼应上图输出的参数量,将后面两个32分别为bias和BN层的参数考虑进去,通常这两个占比比较小可以忽略)
可以明显的看到,Focus的计算量和参数量要比普通卷积要多一些,但是~实际上是代替了三层,经过改进之后参数量还是变少了,也达到了提速的效果
Yolov4和v5都使用CSPDarknet作为Backbone,从输入图像中提取丰富的信息特征。CSPNet全称是Cross Stage Partial Networks,也就是跨阶段局部网络。CSPNet解决了其他大型卷积神经网络框架Backbone中网络优化的梯度信息重复问题,将梯度的变化从头到尾地集成到特征图中,因此减少了模型的参数量和FLOPS数值,既保证了推理速度和准确率,又减小了模型尺寸。CSPNet实际上是基于Densnet的思想,复制基础层的特征映射图,通过dense block 发送副本到下一个阶段,从而将基础层的特征映射图分离出来。这样可以有效缓解梯度消失问题(通过非常深的网络很难去反推丢失信号) ,支持特征传播,鼓励网络重用特征,从而减少网络参数数量。
CSPDarknet53是在yolov3主干网络Darknet53的基础上,借鉴2019年的CSPNet的经验,产生的Backbone结构,其中包含了5个CSP模块。
每个CSP模块前面的卷积核大小都是3*3,stride=2,因此可以起到下采样的作用。因为Backbone有5个CSP模块,输入图象是608*608,所以特征图变化的规律是:608-->304-->152-->76-->38-->19。经过5次CSP模块后得到19*19大小的特征图。而且作者只在Backbone中采用了Mish激活函数,网络后面仍然采用了Leaky_relu激活函数。为啥要采用CSP模块?CSPNet全称是Cross Stage Paritial Network,主要从网络结构设计的角度解决推理中从计算量很大的问题。CSPNet的作者认为推理计算过高的问题是由于网络优化中的梯度信息重复导致的。因此采用CSP模块先将基础层的特征映射划分为两部分,然后通过跨阶段层次结构将它们合并,在减少了计算量的同时可以保证准确率。因此Yolov4在主干网络Backbone采用CSPDarknet53网络结构,主要有三个方面的优点:
这篇文章的CSP思想介绍的很详细。
Mish激活函数(https://zhuanlan.zhihu.com/p/263555912)
激活函数是为了提高网络的学习能力,提升梯度的传递效率。CNN常用的激活函数也在不断地发展,早期网络常用的有ReLU, LeakyReLU, softplus等,后来又有了Swish,Mish等。Mish激活函数的计算复杂度比ReLU要高不少,如果你的计算资源不是很够,可以考虑使用LeakyReLU代替Mish。在介绍之前,需要先了解softplus和tanh函数。
softplus激活函数的公式如下:ζ(x)=log(1+ex)ζ(x)=log(1+ex)
上图是其输出曲线,softplus和ReLU的曲线具有相似性,但是其比ReLU更为平滑。目前的普遍看法是,平滑的激活函数允许更好的信息深入神经网络,从而得到更好的准确性和泛化。
tanh的公式如下:tanh(x)=ex−e−xex+e−xtanh(x)=ex−e−xex+e−x
Mish激活函数的公式为:Mish(x)=x×tanh(ζ(x))Mish(x)=x×tanh(ζ(x))
上图为Mish的曲线。首先其和ReLU一样,都是无正向边界的,可以避免梯度饱和;其次Mish函数是处处光滑的,并且在绝对值较小的负值区域允许一些负值。
CSP结构
CSP结构,其初衷是减少计算量并且增强梯度的表现。主要思想是:在输入block之前,将输入分为两个部分,其中一部分通过block进行计算,另一部分直接通过一个shortcut进行concatenate。作者基于Dense block(对DenseNet网络不熟悉的同学可以查看这里)讲述了CSP的结构,如下图:
上图中,上者为原始的Dense Block,下者为Partial Dense Block。假设将输入按照part_ratio=0.5的比例分成两部分,并且假设一个Dense Block的输入为w *h* c,growth rate为 d,Dense block的layer数量为m,则:对于原始的DenseBlock,其CIO为(Convolutional input/Output)为cm + [(mm+m)d]/2;而对于使用了CSP结构的结构来说,其CIO下降为[cm + (mm+m)d]/2。
作者阐述了CSP结构的优点:
讨论(https://zhuanlan.zhihu.com/p/263555912):
按照CSP论文中的思路,我开始认为的CSP结构应该是这样的——特征输入之后,通过一个比例将其分为两个部分(CSPNet中是二等份),然后再分别输入block结构,以及后面的Partial transition处理。这样符合CSPNet论文中的理论思路。
但是实际上,我参考了一些源码以及darknet配置文件中的网络参数,得到的结构是这样的:
和我所理解不同的是,实际的结构在输入后没有按照通道划分成两个部分,而是直接用两路的1x1卷积将输入特征进行变换。 可以理解的是,将全部的输入特征利用两路1x1进行transition,比直接划分通道能够进一步提高特征的重用性,并且在输入到resiudal block之前也确实通道减半,减少了计算量。虽然不知道这是否吻合CSP最初始的思想,但是其效果肯定是比我设想的那种情况更好的。性能是王道。
先将yolov5-5.0结构图贴上:(https://blog.csdn.net/Q1u1NG/article/details/107511465)
3.1.1 CONV模块
作者在CONV模块(CBL模块)中封装了三个功能:包括卷积(Conv2d)、BN以及Activate函数(在新版yolov5中,作者采用了SiLU函数作为激活函数),同时autopad(k, p)实现了padding的效果。
总的说来Conv实现了将输入特征经过卷积层,激活函数,归一化层,得到输出层。
3.1.2 Bottleneck模块(Resunit)
3.1.3 C3模块,v5.0用C3模块代替了CSP。
C3模块
BottleNeckCSP模块
3.1.4 SPP模块(v6.0里新增了SPPF层)
作用:SPP是由微软研究院的何凯明大神提出,主要为了解决两个问题:
但在yolo中不是为解决这两个问题的,yolo版本的SPP实际上只是借鉴了空间金字塔的思想,通过SPP模块实现了局部特征和全部特征,这也是为什么SPP模块中的最大池化核大小要尽可能地接近或者等于需要池化的特征图的大小,特征图经过局部特征与全矩特征相融合后,丰富了特征图的表达能力,有利于待检测图像中目标大小差异较大的情况,尤其是对于yolo这种复杂的多目标检测,对检测的精度上有了很大的提升。
SPPF():先贴上官方介绍:
可以用来代替SPP,结果是一样的,但是可以降低FLOPS,运行的更快。
FPN就是这样,自顶向下的模式,将高层特征传下来。而底层特征却无法影响高层特征,并且FPN中的这种方法中,顶部信息流往下传,是逐层地传,计算量比较大。PAN解决了这一问题。先看下YOLOV3中未加PAN的结构图:
可以看到经过几次下采样,三个紫色箭头指向的地方,输出分别是76*76, 38*38,19*19.以及最后prediction中用于预测的三个特征图①19*19*255、②38*38*255、③76*76*255。[注:255表示80类别(1+4+80)×3=255] ,我们将Neck部分用立体图画出来(右),更直观的看下两部分之间是如何通过FPN结构融合的。
PANet引入了自底向上的路径,使得底层信息更容易传递到高层顶部。左边图(a),V3中讲过,特征融合,featureMap越小,感受野越大;可能要走例如100层,才能遍历玩ResNet。现在加入要将底层特征传递到特征图顶部,如图a红线,如果是采用上述FPN算法,可能要走很多层,增加了很多计算量。而PANet采用的是:在进行自顶向下的特征融合后(实际上,PANet无论是bottom-top,还是top-bottom进行特征信息传递,都是在“从原始网络中提取低、中、高层特征图之后”,进行的),然后再进行自下向顶(这里遍历的最终的特征图P2-5,而不是原始100多层特征图)的特征融合,如图(b)绿色线条,这样特征传递需要“穿越”的特征图数量大大减少,几层就到了。
而Yolov4中Neck这部分除了使用FPN外,还在此基础上使用了PAN结构:
前面CSPDarknet53中讲到,每个CSP模块前面的卷积核都是3*3大小,步长为2,相当于下采样操作。因此可以看到三个紫色箭头处的特征图是76*76、38*38、19*19。以及最后Prediction中用于预测的三个特征图:①76*76*255,②38*38*255,③19*19*255。我们也看下Neck部分的立体图像,看下两部分是如何通过FPN+PAN结构进行融合的。
我们都知道,深层的feature map携带有更强的语义特征,较弱的定位信息。而浅层的feature map携带有较强的位置信息,和较弱的语义特征。FPN就是把深层的抑郁特征传到前蹭,从而增强多个尺度上的语义表达。而PAN则相反把前蹭的定位信息传导到深层,增强多个尺度上的定位能力。
PANet 结构是在FPN的基础上引入了 Bottom-up path augmentation 结构。FPN主要是通过融合高低层特征提升目标检测的效果,尤其可以提高小尺寸目标的检测效果。Bottom-up path augmentation结构可以充分利用网络浅特征进行分割,网络浅层特征信息对于目标检测非常重要,因为目标检测是像素级别的分类浅层特征多是边缘形状等特征。PANet 在 FPN 的基础上加了一个自底向上方向的增强,使得顶层 feature map 也可以享受到底层带来的丰富的位置信息,从而提升了大物体的检测效果。
这样结合操作,FPN层自顶向下传达强语义特征,而特征金字塔则自底向上传达强定位特征,两两联手,从不同的主干层对不同的检测层进行参数聚合,这样的操作确实很皮。FPN+PAN借鉴的是18年CVPR的PANet,当时主要应用于图像分割领域,但Alexey将其拆分应用到Yolov4中,进一步提高特征提取的能力。
YOLOv5损失函数包括:
总的损失函数:classification loss + localization loss + confidence loss (组成部分从yolov1~yolov5都是这三类,但具体损失的计算方法有变)
YOLOv5 采用了BECLogits 损失函数计算objectness score的损失,class probability score采用了交叉熵损失函数(BCEcls loss),bounding box采用了GIOU(DIOU, CIOU) Loss。GIoU Loss 用来计算bounding box的 Loss, GIOU 是在CVPR2019中,论文https://arxiv.org/pdf/1902.09630.pdf中提出。GIOU直接把IoU设为回归的 Loss。
GIoU=IoU−|C\(AUB)||C|GIoU=IoU−|C\(AUB)||C|
上面公式的意思是将两个任意框A,B,我们找到一个最小的封闭形状C,让C可以把A,B包含在内,接着计算C种没有覆盖A和B的面积占C总面积的比值,然后用A与B的IoU减去这个比值。与IoU类似,GIoU也可以作为一个距离,loss可以用
LGIoU=1−GIoULGIoU=1−GIoU
最后引入B站上大神的yolov5训练技巧:
刚开始训练时,模型的权重是随机初始化的,此时若选择一个较大的学习率,可能带来模型的不稳定(振荡)。选择Warmup预热学习率的方式可以使得开始训练的几个epoches或者一些steps内学习率较小,在预热的小学习率下,模型可以慢慢趋于稳定,等模型相对稳定后再选择预先设置的学习率进行训练,使得模型收敛速度变得更快,模型效果更佳。
余弦退火调整学习率CosineAnnealingLR:https://arxiv.org/pdf/1608.03983.pdf
Anchor给出了目标宽高的初始值,需要回归的是目标真实宽高与初始宽高的偏移量,而不适用anchor的做法需要回归宽高的绝对量。Autoanchor only runs when the best possible recall(BPR, 最大可能召回率) is under threshold. yolov5的threshold是98%。
自动计算锚框是采用聚类方法,You can disable autoanchor with python train.py -- noautoanchor. AutoAnchor will attach anchors automatically to your model.pt file (i.e. last.pt or best.pt)
Hyperparameter evolution is a method of Hyperparameter Optimization using a Genetic Algorithm(GA) for optimization. 好吧,还是看官网吧(https://github.com/ultralytics/yolov5/wiki/Tips-for-Best-Training-Results)
You use --resume by itself with no arguments, or by pointing to a last.pt to resume from:
python train.py --resume # resume from most recent last.pt python train.py --resume runs/exp0/weights/last.pt # resume from specific weights
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。