最近用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 V4的代码是基于C++的,如下:https://github.com/AlexeyAB/darknet
基于Keras+Tensorflow的代码,如下:https://github.com/Ma-Dan/keras-yolo4
这里我先给出YOLO V4的总结构图,如下:
主要有以下三部分组成
接下面将逐个分析!
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目标检测架构的基础上,采用了近些年CNN领域中最优秀的优化策略,从数据处理、主干网络、网络训练、激活函数、损失函数等各个方面都有着不同程度的优化,虽没有理论上的创新,但是会受到许许多多的工程师的欢迎,各种优化算法的尝试。文章如同于目标检测的trick综述,效果达到了实现FPS与Precision平衡的目标检测 new baseline。
①论文主要有以下三点贡献:[1]
②作者把训练的方法分成了两类:
1.Bag of freebies:只改变训练策略或者只增加训练成本,比如数据增强。
2.Bag of specials:插件模块和后处理方法,它们仅仅增加一点推理成本,但是可以极大地提升目标检测的精度。
YOLOv4总体上可以划分为两部分,一部分是讲Bag of freebies和Bag of Specials; 另外一部分讲的是YOLOv4的创新点。
1.Mosaic数据增强方法
这个方法在解析U版YOLOv3的时候就讲过了,将4张不同的图片镶嵌到一张图中,其优点是:
1. 混合四张具有不同语义信息的图片,可以让检测器检测超出常规语境的目标,增强模型的鲁棒性。
2. 由于BN是从四张图片计算得到的,所以可以减少对大的mini-batch的依赖。
评价:这个方法在U版YOLOv3中很早就出现了,在自己数据集上也用过,但是感觉效果并不是很稳定。笔者数据集只有一个类,所以可能不需要这种特殊的数据增强方法,欢迎各位读者通过自己的实验来验证这个数据增强方法的有效性。
YOLOv4的模型结构笔者读了一下yolov4.cfg文件,然后根据结构画出了大体结构:
其中,没有详细展开backbone部分,其实backbone之前在解读CSPNet的时候就讲过了,YOLOv4使用的是CSPDarknet53作为Backbone。
这篇文章的贡献如下:
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 损失
参考资料:(部分内容直接参考复制粘贴,在此声明)
https://zhuanlan.zhihu.com/p/150127712?from_voters_page=true
https://zhuanlan.zhihu.com/p/137393450
https://www.cnblogs.com/pprp/p/12771430.html
https://www.pianshen.com/article/33231186672/