当前位置 博文首页 > 微信号:Custom-Software:YOLOV4网络结构总结

    微信号:Custom-Software:YOLOV4网络结构总结

    作者:[db:作者] 时间:2021-06-24 15:17

    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对比,主要做了以下改变:

    1. 相较于YOLO V3的DarkNet53,YOLO V4用了CSPDarkNet53
    2. 相较于YOLO V3的FPN,YOLO V4用了SPP+PAN
    3. CutMix数据增强和马赛克(Mosaic)数据增强
    4. DropBlock正则化等等

    原作者YOLO V4的代码是基于C++的,如下:https://github.com/AlexeyAB/darknet

    基于Keras+Tensorflow的代码,如下:https://github.com/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]

    1. 开发了一个高效而强大的模型,使得任何人都可以使用一张1080Ti或者2080Ti GPU去训练一个超级快速和精确的目标检测器。
    2. 验证了一系列state-of-the-art的目标检测器训练方法的影响。
    3. 修改了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。

    这篇文章的贡献如下:

    1. 我们设计了一个高效并且强大的目标检测模型。它使每个人都可以使用1080 Ti或2080 TiGPU来训练一个超级快速和精确的目标探测器。
    2. 我们验证了在检测器训练过程中,最先进的“Bag of freebies(免费包)”和“Bag of specials(特价包)” 的目标检测方法的影响。
    3. 我们修改了当前最先进的一些方法(包括CBN、PAN、SAM etc.),使其更有效,更适合于单GPU训练。
    4. 总之,在速度差不多的情况下,精度最好;在精度差不多的情况下,速度最好。

    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/

    下一篇:没有了