深度剖析YOLO系列的原理

                      深度剖析YOLO系列的原理

                      本文系做者原创,转载请注明出处:http://www.javashuo.com/article/p-btcodynk-dr.htmlhtml

目录

1. YOLO的做用

2. YOLO(v1,v2,v3)的技术演化

 


 

 

 

1. YOLO的做用

yolo是当前目标检测最顶级的算法之一,v1版本是2016年提出来的,v2是2017年提出来的,v3是2018年提出的。算法

官网地址:https://pjreddie.com/darknet/yolo/网络

说它最牛掰,有两点:架构

一是由于它采用深层卷积神经网络,吸取了当前不少经典卷积神经网络架构的优秀思想,在位置检测和对象的识别方面,性能

性能达到最优(准确率很是高的状况下还能达到实时检测)。this

二是由于做者还将代码开源了。真心为做者这种大公无私的心胸点赞。spa

美中不足的是:做者虽然将代码开源,可是在论文介绍架构原理的时候比较模糊,特别是对一些重要改进,基本上是一笔带过。3d

如今在网络上有不少关于YOLO原理的讲解,我的感受讲得不是很清楚,总感受有点知其然而不知其因此然。好比:orm

yolo是在什么背景下出现的?htm

v1是在哪一个经典网络架构上发展起来的?解决了什么问题?又存在什么问题?

v2针对v1的缺点作了哪些改进?改进后效果怎么样?又存在什么问题?

v3针对v2的缺点作了哪些改进?

这些问题不搞清楚,我以为对yolo就谈不上真正的理解。废话很少说,下面就来介绍yolo的技术演进。

 

2. YOLO(v1,v2,v3)的技术演化

问题1:yolo v1是在什么背景下出现的?

yolo v1是在 R-CNN 基础上发展起来的。

R-CNN(region proposals + cnn),采用卷积神经网络进行目标检测的开山之做。

 

 

主要思想:对输入图片采用selective search 搜索查询算法,提取出大约 2000 我的眼感兴趣的候选边框,而后每一个边框都经过一个独立的

卷积神经网络进行预测输出,后面再加上一个SVM(支持向量机)预测分类。

优势:位置检测与对象分类准确率很是高。

缺点:运算量大,检测速度很是慢,在 GPU 加持下一帧检测时间要 13s 左右,这在工程应用上是不可接受的。

形成速度慢的缘由主要有 2 个:

> 用搜索查询算法提取 2000 个候选边框

> 每一个候选边框都采用一个独立的CNN通道,这意味着卷积核的参数和全链接的参数都是不同的,总的参数个数是很是恐怖的。

针对这个缺点,yolo v1作了哪些改进呢。

 

 

上面的图片是官网论文给出的结构图,可是我的感受画得不太好,它容易让人误认为对输入图片进行网格化处理,每一个网格化的小窗口是 7*7。

真实状况是,由最终输出是 7*7*30 大小表明的物理含义是:你能够把输入图片当作是通过了网格化(grid cell 7*7),每一个网格化后的小窗口经过 CNN 预测出 1*30。

这里可能有点很差理解。总之一句话,在真正网络架构流程中,没有对输入图片进行任何网格化处理。

 

v1 改进点:

> Backbone: googLeNet22 (采用googLeNet22层卷积结构)

> 输入图片只处理一次(yolo名称的由来),经过多个卷积层提取不一样的特征,每次卷积的时候共享卷积核参数。

输入图片只处理一次:表示输入图片只在第一次卷积的时候做为输入进行卷积运算,第一次卷积后的输出做为第二次卷积的输入,经过多个卷积层递进的方式来提取不一样的特征。

而且这些特征经过的CNN通道都是相同的,从而能够共享卷积核参数。

> 每一个 3*3 卷积核前面引入了 1*1 卷积核,做用有两个,一是提取更丰富的特征,二是减小卷积核的参数个数。

你们可能对减小卷积核参数个数的做用比较难以理解,这里举个例子。

好比输入图片大小是 56*56*256 最终转化的目标大小是 28*28*512。

直接卷积:56*56*256 & 3*3*256*512 -> 56*56*512 & pooling -> 28*28*512 

卷积核参数:3*3*256*512 = 1179648

引入 1*1 卷积:56*56*256 & 1*1*256*128 -> 56*56*128 & 3*3*128*512 -> 56*56*512 & pooling -> 28*28*512

卷积核参数:1*1*256*128 + 3*3*128*512 = 622592

通过改进后,图片检测速度很是快,基本上能够达到实时。可是缺点是位置检测准确度低,而且不能检测出小对象物体。

针对 v1 的缺点,v2作了哪些改进呢?

v2 改进点:

 

 

 

 

> Backbone:darknet19 (采用darknet 19层卷积结构)

> 输入图片批归一化处理(BN),做用是下降不是重要特征的重要性。

这句话可能听得有点晕,举个例子,

你的样本里有两个特征列,一个特征列的数值在[1,10]范围内,另外一个特征列的数值在[1000,10000]范围内,

可是真实状况是,你的这两个特征列重要性多是同样的,只不过你拿到的数据就是这样的,咱们知道,

卷积神经网络训练,实质就是一系列数值运算的过程,若是你将这两个特征列直接经过卷积神经网络进行训练,

那最终生成的模型准确率确定是不高的,因此须要进行归一化处理,将数值归一化到[0,1]范围内,

从而是损失能量在收敛的时候更加平稳。

> 采用passthrough算法,解决池化信息丢失的问题,增长细粒度特征的检测(小对象)。

 

 

passthrough 算法主要是为了解决 pooling(池化)的缺点,不论是最大值池化,仍是平均值池化,都有一个很明显的问题,

就是会形成信息丢失,passthrough 主要思想是在池化以前,将输入信息进行拆分,一拆为四,通过拆分后的大小就和池化后的输出大小相同,

而后叠加,叠加后的结果主要就是维度变化,这样就能解决池化会形成信息丢失的问题。

> 去掉全链接(FC),将输入图片拉伸(resize)到不一样尺寸而后经过卷积神经网络,这样就获得了多尺寸的输出,从而能提高对不一样大小对象的预测准确度。

全链接其实就是矩阵乘法运算,矩阵乘法有一个前提,矩阵 A 的列必须与矩阵 B 的行个数相同,不然是不能进行矩阵乘法运算的。

全链接的参数大小是固定的,那么你的输入大小天然就固定了,这样就没法实现多尺寸的输出,因此这里去掉了全链接层。

通过改进后,精度提高明显,特别是对小对象的检测,缺点是对小对象检测准确度不高。

针对 v2 的缺点,v3 又作了哪些改进呢?

v3 改进点:

 

 

上面是 v3 的结构图,是我跟踪代码,查找资料,绘制这张图真心不容易,正确性绝对有保证,你们若是以为这张图对你理解 yolo 有帮助,麻烦点个赞。

输入大小这里是416*416,输出13*13,26*26,52*52,这里通常要求输入图片大小是 32 的倍数,由于整个卷积神经网络会将图片缩小32倍,16倍,8倍,

这里取最大公倍数32。 123 = 3*(边框坐标 4 + 置信度 1 + 类对象 36)。

> Backbone: darknet53 (采用darknet 53层卷积结构,实际是52层卷积,去掉了全链接层)

能够看出v3的卷积层数是v2的2.8倍,有个潜在的共识:增长模型准确率的一个直接作法是增长网络的深度和厚度,

(深度是指卷积层数,厚度指卷积核的维度或者是种类数),这里做用天然就是提高精度了。

> 用卷积取代池化

以前咱们提到过池化的问题,会形成信息丢失,这里用卷积来实现池化的功能(使图片大小缩小2倍),同时不会形成信息的明显丢失。

> 采用残差网络(resnet)防止梯度消失

梯度消失或者梯度爆炸是在深层的卷积神经网络中才有可能出现的,梯度的计算是经过链式求导获得的,随着网络层的增长,链式求导项就会愈来愈长,

由于在每一层卷积后的输出都作了归一化处理,因此梯度只会愈来愈小,有可能为0,而0在后面模块运算中都为0,这样致使的直接后果是:

损失能量在收敛到某一阶段后就中止收敛,最后生成模型的精度天然就不高。而这里采用残差网络就能防止梯度消失,v3结构图里左下角就是残差网络的结构图。

残差网络的思想:每次卷积后的输出当作残差,将卷积前的输入与残差融合,做为整个输出,即便残差为0,整个输出也不会为0。

从残差网络结构图能够看出,每一个3*3卷积核前都引入了1*1卷积,这里沿用了v1的思想。

从v3的结构图能够看出,darknet53网络骨架里大量的引入了残差网络的思想。

> 使用空间金字塔池化网络算法(sppnet spatial pyramid pooling)实现多尺寸的输出

空间金字塔池化网络算法主要思想:不一样尺寸的输入经过sppnet模块后生成一个固定尺寸的输出。

在v3结构图里,有两个地方用到这个思想:

一个是 13*13*512 通过 1*1 卷积,改变特征维度,变成 13*13*256,通过上采样(upsample,这里采用相邻像素插入算法),

改变特征尺寸,变成 26*26*256,而后与 26*26*512 叠加,生成 26*26*768。

另外一个是 26*26*256 与 52*52*256 叠加后生成 52*52*384。

v3的多尺寸输出与v2的多尺寸输出有本质不一样,v2多尺寸输出是对输入图片拉伸到不一样的尺寸,而后经过卷积神经网络获得不一样的输出,

可是这样就存在一个图片失真的问题,由于你是对图片进行的拉伸处理。而v3经过sppnet实现的多尺寸输出,就能有效避免图片失真的问题。

> 13*13*123,26*26*123,52*52*123物理意义

 

 

这里用v1版本论文图片来解释,物理意义:

表示将输入图片网格化,有 13*13,26*26,52*52 大小,每一个网格化的小窗口(grid cell)预测 3 个边框(bounding box),

每一个边框包含 4 个位置坐标,1个置信度,36个对象种类。

123 = 3 *(4 + 1 + 36)

这里就存在一个问题:预测输出如此之多,直接用于损失能量的计算,运算量岂不是很恐怖?

确实是这样,因此这里先通过下面的两个步骤的处理:

(1)每一个小窗口只取置信度最大的边框,由于yolo规定,只能有一个真实的对象中心坐标属于每一个小窗口。

    这样,就得出 13*13*3*41 => 13*13*41,26*26*3*41 => 26*26*41,52*52*3*41 => 52*52*41

    13*13*41,26*26*41,52*52*41 表示一个真实对象有不少预测重叠边框,好比说上面图里属于狗的预测边框很是多,

    可是咱们只须要预测最准确的边框,去掉其余属于狗的重叠边框。

(2)采用NMS(非极大值抑制算法)去除重叠边框。

     这样 13*13*41,26*26*41,52*52*41 => N*41 (N表示不一样对象预测数目,好比说上面图理想状况下,N = 3)。

> 损失能量(采用交叉熵)

     

 

 

损失能量的计算是v1版本提出来的,这里放到了v3来讲,有3个改进点:

(1)将位置检测与对象识别做为一个总体,进行训练预测,这从损失能量的计算能够直接反应出来。

(2)位置的宽度和高度先开根号,与归一化的做用相同,下降不是重要特征的重要性。

(3)增长权重参数  ,当边框预测出含有对象时,增大它的权重值,当边框预测出不含有对象时,减少它的权重值,这样就能使损失能量计算更准确。

 

 

不要让懒惰占据你的大脑,不要让妥协拖垮了你的人生。青春就是一张票,能不能遇上时代的快车,你的步伐就掌握在你的脚下。

相关文章
相关标签/搜索