1.前言
最近用YOLO V4做车辆检测,配合某一目标追踪算法实现车辆追踪+轨迹提取等功能,正好就此结合论文和代码来对YOLO V4做个解析。先放上个效果图(半成品),如下:
YOLO V4的论文链接在这里,名为《YOLOv4: Optimal Speed and Accuracy of Object Detection》,相信大家也是经常看到这几个词眼:大神接棒、YOLO V4来了、Tricks 万花筒等等。
阅读YOLO V4的原文,我觉得它更像一篇目标检测模型Tricks文献综述。
从本质上,YOLO V4就是筛选了一些从YOLO V3发布至今,被用在各式各样检测器上,能够提高检测精度的tricks,并以YOLO V3为基础进行改进的目标检测模型。YOLO V4在保证速度的同时,大幅提高模型的检测精度(当然,这是相较于YOLO V3的)。
上图可以看出来,虽然检测精度不如EfficientDet这种变态,但是速度上是遥遥领先的,说明YOLO V4并没有忘记初心(速度和精度的trade off,我YOLO才是佼佼者)!
与YOLO V3对比,主要做了以下改变:
- 相较于YOLO V3的DarkNet53,YOLO V4用了CSPDarkNet53
- 相较于YOLO V3的FPN,YOLO V4用了SPP+PAN
- CutMix数据增强和马赛克(Mosaic)数据增强
- DropBlock正则化等等
原作者YOLO V4的代码是基于C++的,如下:https:///AlexeyAB/darknet
基于Keras+Tensorflow的代码,如下:https:///Ma-Dan/keras-yolo4
2. YOLO V4的网络结构
这里我先给出YOLO V4的总结构图,如下:
主要有以下三部分组成
- BackBone:CSPDarknet53
- Neck:SPP+PAN
- HEAD:YOLO HEAD
接下面将逐个分析!
2.1 BackBone:CSPDarknet53
目前做检测器MAP指标的提升,都会考虑选择一个图像特征提取能力较强的backbone,且不能太大,那样影响检测的速度。YOLO V4中,则是选择了具有CSP(Cross-stage partial connections)的darknet53,而是没有选择在imagenet上跑分更高的CSPResNext50
结合了在目标检测领域的精度来说,CSPDarknet53是要强于 CSPResNext50,这也告诉了我们,在图像分类上任务表现好的模型,不一定很适用于目标检测(这不是绝对的!)。
那么这个带有CSP结构的Darknet53,到底长什么样呢?如果对CSP结构感兴趣的,欢迎点击原文链接。
这里我们直接从代码上看看这个CSPDarknet53什么样子,定义如下“
def darknet_body(x):
'''Darknent body having 52 Convolution2D layers'''
x = DarknetConv2D_BN_Mish(32, (3,3))(x)
x = resblock_body(x, 64, 1, False)
x = resblock_body(x, 128, 2)
x = resblock_body(x, 256, 8)
x = resblock_body(x, 512, 8)
x = resblock_body(x, 1024, 4)
return x
如果把堆叠的残差单元(resblock_body)看成整体的话,那么这个结构和Darknet53以及ResNet等的确差别不大,特别是resblock_body的num_blocks为【1,2,8,8,4】和darknet53一模一样。
那么我们解析一下resblock_body的定义,如下:
def resblock_body(x, num_filters, num_blocks, all_narrow=True):
'''A series of resblocks starting with a downsampling Convolution2D'''
# Darknet uses left and top padding instead of 'same' mode
preconv1 = ZeroPadding2D(((1,0),(1,0)))(x)
preconv1 = DarknetConv2D_BN_Mish(num_filters, (3,3), strides=(2,2))(preconv1)
shortconv = DarknetConv2D_BN_Mish(num_filters//2 if all_narrow else num_filters, (1,1))(preconv1)
mainconv = DarknetConv2D_BN_Mish(num_filters//2 if all_narrow else num_filters, (1,1))(preconv1)
for i in range(num_blocks):
y = compose(
DarknetConv2D_BN_Mish(num_filters//2, (1,1)),
DarknetConv2D_BN_Mish(num_filters//2 if all_narrow else num_filters, (3,3)))(mainconv)
mainconv = Add()([mainconv,y])
postconv = DarknetConv2D_BN_Mish(num_filters//2 if all_narrow else num_filters, (1,1))(mainconv)
route = Concatenate()([postconv, shortconv])
return DarknetConv2D_BN_Mish(num_filters, (1,1))(route)
残差单元的结构绘制出来,如下:
对照代码和上面的图片,可以比较清晰地看出来这个CSP残差单元和DarkNet/ResNet的残差单元的区别了。当然了,图上的DarknetConv2D_BN_Mish模块定义如下
(1) DarknetConv2D_BN_Mish
def DarknetConv2D_BN_Mish(*args, **kwargs):
"""Darknet Convolution2D followed by BatchNormalization and LeakyReLU."""
no_bias_kwargs = {'use_bias': False}
no_bias_kwargs.update(kwargs)
return compose(
DarknetConv2D(*args, **no_bias_kwargs),
BatchNormalization(),
Mish())
(2) DarknetConv2D
def DarknetConv2D(*args, **kwargs):
"""Wrapper to set Darknet parameters for Convolution2D."""
darknet_conv_kwargs = {}
darknet_conv_kwargs['kernel_initializer'] = keras.initializers.RandomNormal(mean=0.0, stddev=0.01)
darknet_conv_kwargs['padding'] = 'valid' if kwargs.get('strides')==(2,2) else 'same'
darknet_conv_kwargs.update(kwargs)
return Conv2D(*args, **darknet_conv_kwargs)
2.2 Neck:SPP+PAN & Head:YOLO HEAD
目标检测模型的Neck部分主要用来融合不同尺寸特征图的特征信息。常见的有MaskRCNN中使用的FPN等,这里我们用EfficientDet论文中的一张图来进行说明。
一、YOLO-v4主要做了什么?
通俗的讲,就是说这个YOLO-v4算法是在原有YOLO目标检测架构的基础上,采用了近些年CNN领域中最优秀的优化策略,从数据处理、主干网络、网络训练、激活函数、损失函数等各个方面都有着不同程度的优化,虽没有理论上的创新,但是会受到许许多多的工程师的欢迎,各种优化算法的尝试。文章如同于目标检测的trick综述,效果达到了实现FPS与Precision平衡的目标检测 new baseline。
①论文主要有以下三点贡献:[1]
- 开发了一个高效而强大的模型,使得任何人都可以使用一张1080Ti或者2080Ti GPU去训练一个超级快速和精确的目标检测器。
- 验证了一系列state-of-the-art的目标检测器训练方法的影响。
- 修改了state-of-the-art方法,使得他们在使用单个GPU进行训练时更加有效和适配,包括CBN,PAN,SAM等。
②作者把训练的方法分成了两类:
1.Bag of freebies:只改变训练策略或者只增加训练成本,比如数据增强。
2.Bag of specials:插件模块和后处理方法,它们仅仅增加一点推理成本,但是可以极大地提升目标检测的精度。
1. 思维导图
YOLOv4总体上可以划分为两部分,一部分是讲Bag of freebies和Bag of Specials; 另外一部分讲的是YOLOv4的创新点。
2. 创新点
1.Mosaic数据增强方法
这个方法在解析U版YOLOv3的时候就讲过了,将4张不同的图片镶嵌到一张图中,其优点是:
1. 混合四张具有不同语义信息的图片,可以让检测器检测超出常规语境的目标,增强模型的鲁棒性。
2. 由于BN是从四张图片计算得到的,所以可以减少对大的mini-batch的依赖。
评价:这个方法在U版YOLOv3中很早就出现了,在自己数据集上也用过,但是感觉效果并不是很稳定。笔者数据集只有一个类,所以可能不需要这种特殊的数据增强方法,欢迎各位读者通过自己的实验来验证这个数据增强方法的有效性。
3. 结构
YOLOv4的模型结构笔者读了一下yolov4.cfg文件,然后根据结构画出了大体结构:
其中,没有详细展开backbone部分,其实backbone之前在解读CSPNet的时候就讲过了,YOLOv4使用的是CSPDarknet53作为Backbone。
这篇文章的贡献如下:
- 我们设计了一个高效并且强大的目标检测模型。它使每个人都可以使用1080 Ti或2080 TiGPU来训练一个超级快速和精确的目标探测器。
- 我们验证了在检测器训练过程中,最先进的“Bag of freebies(免费包)”和“Bag of specials(特价包)” 的目标检测方法的影响。
- 我们修改了当前最先进的一些方法(包括CBN、PAN、SAM etc.),使其更有效,更适合于单GPU训练。
- 总之,在速度差不多的情况下,精度最好;在精度差不多的情况下,速度最好。
YOLOv4 使用了以下特征组合:
1. 加权残差连接(Weighted-Residual-Connections,WRC)
2. 跨阶段部分连(Cross-Stage-Partial-connection,CSP)
3. 跨小批量标准化(Cross mini-Batch Normalization,CmBN)
4. 自对抗训练(Self-adversarial-training,SAT)
5. Mish 激活(Mish-activation)
6. Mosaic 数据增强
7. DropBlock 正则化
8. CIoU 损失