YOLO V3 详解

  • 概述
  • 网络介绍
  • Yolov3和V2、V1的比较
  • Yolov3网络结构
  • 目标位置预测以及损失函数选择
  • 总结


概述

目前在做工业上的目标检测项目,用了很久的Yolov3算法模型,刚开始是基于Keras平台的,后来使用基于Darknet平台的训练。项目要结束了,终于有时间好好的整理下笔记。先推出算法网络的原理,后续写基于darknet的C++的部署和利用Opencv的dnn模块调用模型的C++部署。

网络介绍

Yolov3和V2、V1的比较

Yolov3算法相比YOLOV2和YOLOV1算法保留的功能有:

  1. “分而治之”,从yolov1开始,yolo算法就是通过划分单元格来做检测,只是划分的数量不一样。Yolov1分成7x7网格,yolov3分成13x13网格。
  2. 采用"leaky ReLU"作为激活函数。
  3. 端到端进行训练。一个损失函数(loss function)搞定训练,只需关注输入端和输出端。
  4. 从yolov2开始,yolo就用BN算法(batch normalization)作为正则化、加速收敛和避免过拟合,把BN层和leaky relu层接到每一层卷积层之后。
  5. 多尺度训练。在速度和准确率之间权衡。想速度快点,可以牺牲准确率;想准确率高点儿,可以牺牲一点速度。
  6. Yolo系列的每一代的提升很大一部分决定于神经网络(backbone)的提升,从v2的darknet-19到v3的darknet-53。Yolov3还提供替换神经网络backbone的tiny darknet网络。tiny darknet网络是darknet-53的轻量级网络。

Yolov3网络结构

Yolov3的网络结构如下所示:

yolov是3dcnn吗 yolov3用什么实现_yolov是3dcnn吗


如上所示,Yolov3的网络结构可以分为三个部分。分别为输入、基础网络Darknet-53和Yolov3的三个分支(y1,y2,y3)。其中Darknet-53网络中的DBL模块是卷积、BN算法、线性激活函数Leaky relu的总称,也是yolov3算法的最基本单元。

BN算法:Batch Normalization是2015年一篇论文中提出的数据归一化方法,往往用在深度神经网络中激活层之前。其作用可以加快模型训练时的收敛速度,使得模型训练过程更加稳定,避免梯度爆炸或者梯度消失。并且起到一定的正则化作用,几乎代替了Dropout。

核心公式为:

yolov是3dcnn吗 yolov3用什么实现_激活函数_02

  1. 输入为数值集合(yolov是3dcnn吗 yolov3用什么实现_神经网络_03),可训练参数 [yolov是3dcnn吗 yolov3用什么实现_算法_04,yolov是3dcnn吗 yolov3用什么实现_算法_05] ;
  2. BN的具体操作为:先计算的yolov是3dcnn吗 yolov3用什么实现_神经网络_03均值和方差,之后将yolov是3dcnn吗 yolov3用什么实现_神经网络_03集合的均值、方差变换为0和1(对应上式中yolov是3dcnn吗 yolov3用什么实现_算法_08),最后将yolov是3dcnn吗 yolov3用什么实现_算法_08乘以yolov是3dcnn吗 yolov3用什么实现_算法_04再加上yolov是3dcnn吗 yolov3用什么实现_算法_05输出。[yolov是3dcnn吗 yolov3用什么实现_算法_04,yolov是3dcnn吗 yolov3用什么实现_算法_05]是可训练参数,参与整个网络的BP。

归一化的目的:将数据规整到统一区间,减少数据的发散程度,降低网络的学习难度。BN的精髓在于归一之后,使用作为还原参数,在一定程度上保留原数据的分布。

线性激活函数Leaky ReLU:是线性激活函数ReLu的改进版,它在负轴保留了非常小的常数leak,使得输入信息小于0时,信息没有完全丢掉,进行了相应的保留。即ReLU在取值小于零部分没有梯度,Leaky relu在取值小于0部分给一个很小的梯度。函数坐标图如下:

yolov是3dcnn吗 yolov3用什么实现_神经网络_14

公式如下:yolov是3dcnn吗 yolov3用什么实现_深度学习_15
其中leak是小数,例如leak=0.1。
将激活函数代入公式中:

  1. 将Leak ReLu看作神经网络中的一层,设第yolov是3dcnn吗 yolov3用什么实现_激活函数_16层输出的是yolov是3dcnn吗 yolov3用什么实现_神经网络_17,然后输入Leak ReLu激活函数输出的是yolov是3dcnn吗 yolov3用什么实现_神经网络_18
  2. 设损失函数yolov是3dcnn吗 yolov3用什么实现_激活函数_19关于第l层输出的yolov是3dcnn吗 yolov3用什么实现_神经网络_17偏导是

resn:n代表数字,有res1,res2, … ,res8等等,表示这个res_block里含有多少个res_unit。这是yolov3的大组件,yolov3开始借鉴了ResNet的残差结构,使用这种结构可以让网络结构更深(从v2的darknet-19上升到v3的darknet-53,前者没有残差结构)。对于res_block,可以在上图的右下角直观看到,其基本组件也是DBL。

concat:张量拼接。将darknet中间层和后面的某一层的上采样进行拼接。拼接的操作和残差层add的操作是不一样的,拼接会扩充张量的维度,而add只是直接相加不会导致张量维度的改变。

整个yolov3网络包含252层,组成如下:

yolov是3dcnn吗 yolov3用什么实现_yolov是3dcnn吗_21


从上图可以看出,对于代码层面的layers数量一共有252层,包括add层23层(主要用于res_block的构成,每个res_unit需要一个add层,一共有1+2+8+8+4=23层)。除此之外,BN层和LeakyReLU层数量完全一样(72层),在网络结构中的表现为:每一层BN后面都会接一层LeakyReLU。卷积层一共有75层,其中有72层后面都会接BN+LeakyReLU的组合构成基本组件DBL。看结构图,可以发现上采样和concat都有2次,和表格分析中对应上。每个res_block都会用上一个零填充,一共有5个res_block。

整个yolov3结构里面,是没有池化层和全连接层的。前向传播过程中,张量的尺寸变换是通过改变卷积核的步长来实现的,比如步长stride=(2, 2),这就等于将图像边长缩小了一半(即面积缩小到原来的1/4)。在yolov2中,要经历5次缩小,会将特征图缩小到原输入尺寸的 ,即1/32。输入为416x416,则输出为13x13(416/32=13)。Yolov3也和yolov2一样,神经网络backbone都会将输出特征图缩小到输入的1/32。所以,通常都要求输入图片是32的倍数。

下图所示为yolov2和yolov3的结构对比图。

yolov是3dcnn吗 yolov3用什么实现_yolov是3dcnn吗_22


yolov2中对于前向过程中张量尺寸变换,都是通过最大池化来进行,一共有5次。而yolov3是通过卷积核增大步长来进行,也是5次。(darknet-53最后面有一个全局平均池化,在yolov3里面没有这一层,所以张量维度变化只考虑前面那5次)。

yolov3输出了3个不同尺度的特征图feature map,这个借鉴了FPN(feature pyramid networks)网络,采用多尺度来对不同size的目标进行检测,越精细的grid cell就可以检测出越精细的物体。y1,y2和y3的深度都是255,边长的规律是13:26:52。对于COCO类别而言,有80个种类,所以每个box应该对每个种类都输出一个概率。yolov3设定的是每个网格单元预测3个box,所以每个box需要有(x, y, w, h, confidence)五个基本参数,然后还要有80个类别的概率。所以3*(5 + 80) = 255。Yolov3用上采样的方法来实现这种多尺度的特征图feature map,结合yolov3的网络结构图中concat连接的两个张量是具有一样尺度的(两处拼接分别是26x26尺度拼接和52x52尺度拼接,通过上采样来保证concat拼接的张量尺度相同)。

目标位置预测以及损失函数选择

位置预测结构图:

yolov是3dcnn吗 yolov3用什么实现_激活函数_23


如上图所示,yolov是3dcnn吗 yolov3用什么实现_神经网络_24yolov是3dcnn吗 yolov3用什么实现_神经网络_25为检测框的中心点,yolov是3dcnn吗 yolov3用什么实现_yolov是3dcnn吗_26yolov是3dcnn吗 yolov3用什么实现_yolov是3dcnn吗_27为上图左上角网格坐标(1,1)的偏移量。yolov是3dcnn吗 yolov3用什么实现_yolov是3dcnn吗_28yolov是3dcnn吗 yolov3用什么实现_算法_29为对应(y1,y2,y3)尺寸归一化后的偏移量。yolov是3dcnn吗 yolov3用什么实现_算法_30yolov是3dcnn吗 yolov3用什么实现_深度学习_31为单元网格的距离,这里都为1。yolov是3dcnn吗 yolov3用什么实现_深度学习_32yolov是3dcnn吗 yolov3用什么实现_激活函数_33为anchor的宽、高与特征图(feature map)的宽、高的比值。yolov3算法利用k-mean算法对数据中的标记框进行聚类,生成9个anchor,每个输出(y1,y2,y3)各有三个anchor。yolov是3dcnn吗 yolov3用什么实现_深度学习_34yolov是3dcnn吗 yolov3用什么实现_神经网络_35为检测框的宽和高。

Yolov3损失函数:

yolov是3dcnn吗 yolov3用什么实现_算法_36


在YOLOV3中,Loss分成三个部分

1、目标框位置(左上角和长宽)带来的误差,也即是box带来的loss。而在box带来的loss中又分为带来的BCE Loss以及带来的MSE Loss。

2、目标置信度带来的误差,也就是目标obj带来的loss(BCE Loss)。

3、类别带来的误差,也就是种类class带来的loss(类别数个BCE Loss)。

其中BCE Loss为二值交叉熵损失函数,MSE Loss为均方误差损失函数。2-yolov是3dcnn吗 yolov3用什么实现_激活函数_37为制衡值。因为当存在小目标的时候,小目标与anchor的IOU会相对变小,所以yolov是3dcnn吗 yolov3用什么实现_激活函数_37越小,2-yolov是3dcnn吗 yolov3用什么实现_激活函数_37越大,相当于制衡值。

在keras版本的yolov3训练时,有利用k-mean算法生成9个anchor,现在对k-mean做个简单介绍。

K-mean算法:聚类是基于数据中的模式将整个数据划分为组(也称为簇)的过程。K-Means算法是一种无监督分类算法,假设有无标签数据集:

yolov是3dcnn吗 yolov3用什么实现_激活函数_40

该算法的任务是将数据集聚类成yolov是3dcnn吗 yolov3用什么实现_神经网络_41个簇yolov是3dcnn吗 yolov3用什么实现_yolov是3dcnn吗_42最小损失函数为yolov是3dcnn吗 yolov3用什么实现_神经网络_43

其中yolov是3dcnn吗 yolov3用什么实现_深度学习_44为簇yolov是3dcnn吗 yolov3用什么实现_激活函数_45的中心点:yolov是3dcnn吗 yolov3用什么实现_激活函数_46

要找到以上问题的最优解需要遍历所有可能的簇划分,K-Means算法使用贪心策略求得一个近似解,具体步骤如下:

  1. 在样本中随机选取k个样本点充当各个簇的中心点yolov是3dcnn吗 yolov3用什么实现_激活函数_47
  2. 计算所有样本点与各个簇中心之间的距离yolov是3dcnn吗 yolov3用什么实现_神经网络_48,然后把样本点划入最近的簇中,yolov是3dcnn吗 yolov3用什么实现_神经网络_49
  3. 根据簇中已有的样本点,重新计算簇中心yolov是3dcnn吗 yolov3用什么实现_深度学习_50
  4. 重复2、3
  5. 当样本点不更换簇中心,或者到达设定的迭代上限等停止迭代。

总结

在工程上使用yolov3有很多的技巧,包括部署时候,如何提高速度和准确率等。