YOLO系列详解

YOLO1(You only look once)

YOLO,即You Only Look Once的缩写,是一个基于卷积神经网络的物体检测算法。

最近的方法,如R-CNN使用区域提出方法首先在图像中生成潜在的边界框,然后在这些提出的框上运行分类器。在分类之后,后处理用于细化边界框,消除重复的检测,并根据场景中的其它目标重新定位边界框。这些复杂的流程很慢,很难优化,因为每个单独的组件都必须单独进行训练。

我们将目标检测重新看作单一的回归问题,直接从图像像素到边界框坐标和类概率。使用我们的系统,您只需要在图像上看一次(YOLO),以预测出现的目标和位置。

基本思想

单阶段检测

YOLO将输入图像分成 S ∗ S S*S SS个格子,若某个物体 Ground truth 的中心位置的坐标落入到某个格子,那么这个格子就负责检测出这个物体。如下图所示,图中物体狗的中心点(红色原点)落入第5行、第2列的格子内,所以这个格子负责预测图像中的物体狗。
在这里插入图片描述

​ 每个格子预测B个bounding box及其置信度(confidence score),以及C个类别概率。Bounding box信息包含5个数据值,分别是x,y,w,h,和confidence。其中(x,y,w,h)为物体的中心位置相对格子位置的偏移及宽度和高度,均被归一化。confidence置信度反映是否包含物体以及包含物体情况下位置的准确性,定义为 P r ( O b j e c t ) × I O U p r e d t r u t h , 其 中 P r ( O b j e c t ) ∈ 0 , 1 . P_r(Object)×IOU_{pred}^{truth},其中P_r(Object)∈{0,1}. Pr(Object)×IOUpredtruth,Pr(Object)0,1.

网络结构

YOLO的整体结构:

这里写图片描述

YOLO网络借鉴了GoogLeNet分类网络结构。不同的是,YOLO未使用inception module,而是使用1x1卷积层(此处1x1卷积层的存在是为了跨通道信息整合)+3x3卷积层简单替代。 由24个卷积层与2个全连接层构成,网络入口为448x448(v2为416x416),图片进入网络先经过resize,YOLO网络最终的全连接层的输出结果为一个张量,其维度为:
S ∗ S ∗ ( B ∗ 5 + C ) S∗S∗(B∗5+C) SS(B5+C)
下面来看一下输出是怎么定义的 :

将图片分为S×S个单元格(原文中S=7),之后的输出是以单元格为单位进行的:
1.如果一个object的中心落在某个单元格上,那么这个单元格负责预测这个物体。
2.每个单元格需要预测B个bbox值(bbox值包括坐标和宽高,原文中B=2),同时为每个bbox值预测一个置信度(confidence scores)。也就是每个单元格需要预测B×(4+1)个值。
3.每个单元格需要预测C(物体种类个数,原文C=20,这个与使用的数据库有关)个条件概率值.

因此输出向量为7*7*(20+2*5)=1470维。

因为这里是当作回归问题来解决的,所以所有的输出包括坐标和宽高最好都定义在0到1之间。

img

来看一下每个单元格预测的B个 ( x , y , w , h , c o n f i d e n c e ) (x,y,w,h,confidence) (x,y,w,h,confidence)的向量和C的条件概率中,每个参数的含义(假设图片宽为{wi}高为{hi},将图片分为S×S):
1.(x,y)是bbox的中心相对于单元格的offset
对于下图中蓝色框的那个单元格(坐标为(Xcol=1,Yrow=4)),假设它预测的输出是红色框的bbox,设bbox的中心坐标为(Xc,Yc),那么最终预测出来的(x,y)是经过归一化处理的,表示的是中心相对于单元格的offset,计算公式如下:
x = x c w i S − x c o l , y = y c h i S − y c o l x=\frac{x_c}{w_i}S-x_{col},y=\frac{y_c}{h_i}S-y_{col} x=wixcSxcol,y=hiycSycol

2.(w,h)是bbox相对于整个图片的比例
预测的bbox的宽高为wb,hb,(w,h)表示的是bbox的是相对于整张图片的占比,计算公式如下:
w = w b w i , h = h b h i w=\frac{w_b}{w_i},h=\frac{h_b}{h_i} w=wiwb,h=hihb
3.confidence

这个置信度是由两部分组成,一是格子内是否有目标,二是bbox的准确度。定义置信度为
P r ( O b j e x t ) ∗ I o U p r e d t r u t h P_r(Objext)*IoU_{pred}^{truth} Pr(Objext)IoUpredtruth
其中若bounding box包含物体,则 P r ( o b j e c t ) = 1 P_r(object)=1 Pr(object)=1,否则 P r ( o b j e c t ) = 0 P_r(object)=0 Pr(object)=0。IOU(intersection over union)为预测bounding box与物体真实区域的交集面积(以像素为单位,用真实区域的像素面积归一化到[0,1]区间)。

4.C类的条件概率
条件概率定义为 P r ( C l a s s i ∣ O b j e c t ) Pr(Classi|Object) Pr(ClassiObject),表示该单元格存在物体且属于第i类的概率。

在测试的时候每个单元格预测最终输出的概率定义为,如下两图所示(两幅图不一样,代表一个框会输出B列概率值)
P r ( C l a s s i ∣ O b j e c t ) ∗ P r ( O b j e c t ) ∗ I o U p r e d t r u t h = P r ( C l a s s i ) ∗ I o U p r e d t r u t h P_r(Class_i|Object)*P_r(Object)*IoU_{pred}^{truth}=P_r(Class_i)*IoU_{pred}^{truth} Pr(ClassiObject)Pr(Object)IoUpredtruth=Pr(Classi)IoUpredtruth
img

img

最后将(S×S)×B×20 列的结果送入NMS,最后即可得到最终的输出框结果

损失函数

​ YOLO全部使用了均方和误差作为loss函数.由三部分组成:坐标误差、IOU误差和分类误差。损失函数的设计目标就是让坐标$(x,y,w,h),confidence,classification $这个三个方面达到很好的平衡。

l o s s = ∑ i = 0 s 2 c o o r d E r r + i o u E r r + c l s E r r loss=\sum_{i=0}^{s^2}coordErr+iouErr+clsErr loss=i=0s2coordErr+iouErr+clsErr

简单的全部采用了sum-squared error loss来做这件事会有以下不足: 简单相加时还要考虑每种loss的贡献率,YOLO对上式loss的计算进行了如下修正。

[1] 位置相关误差(坐标)与分类误差对网络loss的贡献值是不同的,这里更重视8维的坐标预测,给这些损失前面赋予更大的loss weight,因此YOLO在计算loss时,使用[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-38Qcbi2N-1611727122293)(http://www.zhihu.com/equation?tex=%5Clambda+_%7Bcoord%7D+%3D5)]修正[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9KvfYcZu-1611727122298)(http://www.zhihu.com/equation?tex=coordError)]。

[2] 在计算IOU误差时,包含物体的格子与不包含物体的格子,二者的IOU误差对网络loss的贡献值是不同的。(注此处的‘包含’是指存在一个物体,它的中心坐标落入到格子内)。

  • 若有物体落入边界框中,则计算预测边界框含有物体的置信度Ci和真实物体与边界框IoUCi_hat的损失,我们希望两差值越小损失越低。
  • 若没有任何物体中心落入边界框中,则Cihat为0,此时我们希望预测含有物体的置信度Ci越小越好。然而,大部分边界框都没有物体,积少成多,造成loss的第3部分与第4部分的不平衡,为解决这个问题,在loss的三部分使用[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LDok3Lmx-1611727122303)(http://www.zhihu.com/equation?tex=%5Clambda+%7Bnoobj%7D+%3D0.5)]修正[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-33m7ZPKV-1611727122306)(http://www.zhihu.com/equation?tex=iouError)]。

[3]对于相等的误差值,大物体误差对检测的影响应小于小物体误差对检测的影响。这是因为,相同的位置偏差占大物体的比例远小于同等偏差占小物体的比例。YOLO将物体大小的信息项(w和h)进行求平方根来改进这个问题。(注:这个方法并不能完全解决这个问题)。

[4]对于每个格子而言,作者设计只能包含同种物体。若格子中包含物体,我们希望希望预测正确的类别的概率越接近于1越好,而错误类别的概率越接近于0越好。loss第4部分中,若pi©_hat中c为正确类别,则值为1,若非正确类别,则值为0。

在这里插入图片描述

其中,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W1YvEB2A-1611727122309)(http://www.zhihu.com/equation?tex=x%2Cy%2Cw%2CC%2Cp)]为网络预测值,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ts0zgslT-1611727122311)(http://www.zhihu.com/equation?tex=x%2Cy%2Cw%2CC%2Cp)]帽 为标注值。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hMNyOGzU-1611727122313)(http://www.zhihu.com/equation?tex=%5CPi+%7Bi%7D%5E%7Bobj%7D+)]表示物体落入格子i中,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ec481CyW-1611727122316)(http://www.zhihu.com/equation?tex=%5CPi+%7Bij%7D%5E%7Bobj%7D+)]和[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XkRGB3ts-1611727122318)(http://www.zhihu.com/equation?tex=%5CPi+_%7Bij%7D%5E%7Bnoobj%7D+)]分别表示物体落入与未落入格子i的第j个bounding box内。

Ⅱ i j o b j Ⅱ_{ij}^{obj} ijobj表示物体落入格子i的第j个bbox内.如果某个单元格中没有目标,则不对分类误差进行反向传播;B个bbox中与GT具有最高IoU的一个进行坐标误差的反向传播,其余不进行。

这里详细介绍一下[3]:

  • 对不同大小的bbox预测中,相比于大bbox预测偏一点,小box预测偏相同的尺寸对IOU的影响更大。而sum-square error loss中对同样的偏移loss是一样。

为了缓和这个问题,作者用了一个巧妙的办法,就是将box的width和height取平方根代替原本的height和width。 如下图:small bbox的横轴值较小,发生偏移时,反应到y轴上的loss(下图绿色)比big box(下图红色)要大。

这里写图片描述

例如,一个同样将一个100x100的目标与一个10x10的目标都预测大了10个像素,预测框为110 x 110与20 x 20。显然第一种情况我们还可以接受,但第二种情况相当于把边界框预测大了一倍,但如果不使用根号函数,那么损失相同,都为200。但把宽高都增加根号时:
( 20 − 10 ) 2 = 3.43 , ( 110 − 100 ) 2 = 0.48 (\sqrt{20}-\sqrt{10})^2=3.43, (\sqrt{110}-\sqrt{100})^2=0.48 (20 10 )2=3.43,(110 100 )2=0.48
显然,对小框预测偏差10个像素带来了更高的损失。通过增加根号,使得预测相同偏差与更小的框产生更大的损失。但根据YOLOv2的实验证明,还有更好的方法解决这个问题。

训练过程

1)预训练。使用 ImageNet数据训练YOLO网络的前20个卷积层+1个average池化层+1个全连接层。训练图像分辨率resize到224x224。

2)预训练完事后,也就得到前20个卷积层权重,在此基础上添加4个卷积层和2个FC层。得到最终模型。检测通常需要有细密纹理的视觉信息,所以为提高图像精度,在训练检测模型时,将输入图像分辨率从224 × 224 resize到448x448。

训练时B个bbox的ground truth设置成相同的.
在这里插入图片描述

YOLO1缺点

  1. 占比较小的目标检测效果不好.虽然每个格子可以预测B个bounding box,但是最终只选择只选择IOU最高的bounding box作为物体检测输出,即每个格子最多只预测出一个物体。当物体占画面比例较小,如图像中包含畜群或鸟群时,每个格子包含多个物体,但却只能检测出其中一个。

(2) 图片进入网络前会先进行resize为448 x 448,降低检测速度(it takes about 10ms in 25ms),如果直接训练对应尺寸会有加速空间。

(3)输入尺寸固定:由于输出层为全连接层,因此在检测时,YOLO训练模型只支持与训练图像相同的输入分辨率。其它分辨率需要缩放成改分辨率.

(3) 基础网络计算量较大,yolov2使用darknet-19进行加速。

YOLO2

这里写图片描述

Batch Normalization

  • V1中也大量用了BN,同时在定位层dropout
  • V2中取消了dropout,均使用BN

深入理解BN

机器学习领域有个很重要的假设:IID独立同分布假设,就是假设训练数据和测试数据满足相同分布的,就是通过训练数据获得的模型能够在测试集获得好的效果的一个基本保障。

BatchNorm就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布的。

接下来一步一步的理解什么是BN。

为什么深度神经网络随着网络深度加深,训练起来越困难,收敛越来越慢?

解决方法,比如ReLU激活函数,再比如Residual Network,BN本质上也是解释并从某个不同的角度来解决这个问题的。

一、"Internal Covariate Shift"问题

首先理解什么是“Internal Covariate Shift”?

covariate shift的概念:如果ML系统实例集合<X,Y>中的输入值X的分布老是变,这不符合IID假设,网络模型很难稳定的学规律

Internal指的是深层网络的隐层,是发生在网络内部的事情,而不是covariate shift问题只发生在输入层。

对于深度学习这种包含很多隐层的网络结构,在训练过程中,因为各层参数不停在变化,所以每个隐层都会面临covariate shift的问题,也就是在训练过程中,隐层的输入分布老是变来变去,这就是所谓的“Internal Covariate Shift”.

为解决这一问题,提出了BatchNorm的基本思想:能不能让每个隐藏层节点的激活输入分布固定下来。

启发来源:之前研究表明如果在图像处理中对输入图像进行白化(whiten)操作(就是对输入数据分布变换到0均值,单位方差的正态分布),那么神经网络会较快收敛。

图像是深度神经网络的输入层,做白化能加快收敛,那么其实对于深度网络来说,其中某个隐层的神经元是下一层的输入,意思是其实深度神经网络的每一个隐层都是输入层,不过是相对于下一层来说而已,BN可以理解为对深层神经网络每个隐层神经元的激活值做简化版本的白化操作。

二、BN的本质思想

BN的基本思想其实相当直观:因为深层神经网络在做非线性变换前的激活输入值(Y=WX+B,X是输入)随着网络深度加深或者在训练过程中,其分布逐渐发生偏移或者变动,之所以训练收敛慢,一般是整体分布逐渐往非线性函数的取值区间的上下限两端靠近,所以这导致反向传播时底层神经网络的梯度消失,这是训练深层神经网络收敛越来越慢的本质原因,而BN就是通过一定的规范化手段,把每层神经网络任意神经元这个输入值得分布强行拉回到均值为0方差为1的标准正太分布,这样使得激活输入值落在非线性函数对输入比较敏感的区域,意思是这样让梯度变大,避免梯度消失问题产生,而且梯度变大意味着学习收敛速度快,能大大加快训练速度。

有人会提出一个疑问:如果都通过BN,那么不就跟把非线性函数替换成线性函数相同了?

所以BN为了保证非线性的获取,对变换后的满足均值为0方差为1的x又进行了scale加上shift操作(y=scale*x+shift),每个神经元增加了两个参数scale和shift参数,这两个参数是通过训练学习的,意思是通过scale和shift把这个值从标准正态分布左移或者右移一点并长胖一点或者变瘦一点,每个实例挪动的程度不一样,这样等价于非线性函数的值从正中间周围的线性区往非线性区动了动。核心思想应该是想找到一个线性和非线性的较好平衡点,既能享受非线性的较强表达能力的好处,又避免太靠非先行区两头使得网络收敛速度太慢。

三、训练阶段如何做BN

对于Mini-Batch SGD来说,一次训练过程里包含m个训练实例,其具体BN操作就是对于隐层内每个神经元的激活值来说,进行如下变换:

x ^ ( k ) = x k − E [ x k ] V a r [ x k ] ​ \hat{x}^{(k)}=\frac{x^k-E[x^k]}{\sqrt{Var[x^k]}}​ x^(k)=Var[xk] xkE[xk]

经过这个变换后某个神经元的激活x形成了均值为0,方差为1的正太分布,目的是把值往后续要进行的非线性变换的线性去拉动,增大导数值,增强反向传播信息流动性,加快训练收敛速度。但是这样会导致网络表达能力下降,为了防止这一点,每个神经元增加两个调节参数(scale和shift),这两个参数是通过训练来学习到的,用来对变换后的激活反变换,使得网络表达能力增强,即对变换后的激活进行如下的scale和shift操作,这其实是变换的反操作:

y k = γ k ∗ x ^ k + β k y^k=\gamma^k*\hat{x}^k+\beta^k yk=γkx^k+βk

BN其具体操作流程,如下:

img

四、BN的好处

  • 收敛过程大大加快,提升训练速度
  • 增加分类效果,一种解释是类似于Dropout的一种防止过拟合的正则化表达方式,所以不用Dropout也能达到相当的效果
  • 调参过程简单,对于初始化要求没那么高,而且可以使用大的学习率等。

High Resolution Classifier(高分辨率分类器)

预训练分类模型采用了更高分辨率的图片

  • v1中使用224x224预训练,448x448用于检测网络
  • v2以448x448的分辨率微调最初的分类网络

所有优秀的检测方法基本都会使用ImageNet预训练的分类器来提取特征。但这些网络输入尺寸往往比较小,对于检测任务,其目标就会变得很小。

YOLO1先在ImageNet(224x224)分类数据集上预训练模型的主体部分(大部分目标检测算法),然后再训练网络的时候将网络的输入从224x224增加为448x448,这样模型需要去适应新的分辨率。

YOLO2修改预训练网络输入为448x448,在ImageNet上训练10轮(其实也是fine-tunning),让网络适应高分辨率的输入。

img

Convolutional with Anchor Boxes

使用了anchor boxes去预测bounding boxes,去掉了最后的全连接层,网络仅采用了卷积层和池化层

  • 预测bbox的偏移,使用卷积代替FC
  • 输入尺度:416
  • max pooling下采样

YOLO1使用全连接层数据进行bounding box预测(要把1470*1的全连接层reshape为7*7*30的最终特征),这会丢失较多的空间信息,造成定位不准。

YOLO2借鉴了Faster R-CNN的思想,在卷积层输出的特征图上做滑窗采样,每个中心预测9种不同大小和比例的建议框(没有reshape因此保留了空间信息)

具体做法:

1)去掉最后的池化层,确保输出的卷积特征有更高的分辨率

2)网络输入尺寸调整为416*416(前面的448*448是预训练的尺寸),这样后面产生的卷积尺寸都为奇数,有一个center cell.(这样做是因为我们要在我们的特征映射中有奇数个位置,所以只有一个中心单元。目标,特别是大目标,往往占据图像的中心,所以在中心有一个单独的位置来预测这些目标,而不是四个都在附近的位置是很好的)

3)使用factor为32的卷积层降采样,最终得到 13*13的特征图(416/32=13)

4)YOLO1中每个cell仅预测一个类别,YOLO2由anchor box同时预测类别和坐标
在这里插入图片描述

Dimension Clusters(维度聚类)

(关于anchor boxes的第一个问题:如何确定尺寸)

  • 利用Kmeans聚类,选择anchor boxes的尺寸

     在Faster R-CNN和SSD中,先验框的维度(长和宽)都是手动设定的,带有一定的主观性。YOLO2采用k-means聚类方法对训练集中的groud truth做了聚类分析。传统的K-means聚类方法使用的是欧氏距离函数,也就意味着较大的boxes会比较小的boxes产生更多的error,聚类结果可能会偏离。为此,作者采用的评判标准是IOU得分(也就是boxes之间的交集除以并集),这样的话,error就和box的尺度无关了,最终的距离函数为:
    

d ( b o x , c e n t r o i d ) = 1 − I o U ( b o x , c e n t r o i d ) d(box,centroid)=1-IoU(box,centroid) d(box,centroid)=1IoU(box,centroid)

Direct location prediction(直接坐标预测)

关于anchor boxes的第二个问题:如何确定位置

  • 引入Sigmoid函数预测offset,解决了anchor boxes的预测位置问题

作者借鉴了区域建议网络(RPN)使用的anchor boxes去预测bounding boxes相对于图片分辨率的offset,通过(x,y,w,h)四个维度去确定anchor boxes的位置.

在Faster-RCNN中:

img

公式中,符号的含义解释一下:x 是坐标预测值,xa 是anchor坐标(预设固定值),x 是坐标真实值(标注信息),其他变量 y,w,h 以此类推,t 变量是偏移量。然后把前两个公式变形,就可以得到正确的公式:

x = ( t x ∗ w a ) + x a ​ x=(t_x∗w_a)+x_a​ x=(txwa)+xa

y = ( t y ∗ w a ) + y a y=(t_y∗w_a)+y_a y=(tywa)+ya

这个公式的理解为:当预测 tx=1,就会把box向右边移动一定距离(具体为anchor box的宽度),预测 tx=−1,就会把box向左边移动相同的距离。

但是这样在早期迭代中x,y会非常不稳定,这个公式没有任何限制,无论在什么位置进行预测,任何anchor boxes可以在图像中任意一点。

RPN是一个区域预测一次,但是YOLO中是169个gird cell一起预测,处于A gird cell 的x,y可能会跑到B gird cell中,到处乱跑,导致不稳定(因为回归的offset可以使box偏移到图片的任何地方 ),模型随机初始化之后将需要很长一段时间才能稳定预测敏感的物体偏移。

因此作者就没有采用预测直接的offset的方法,而使用了预测边界框中心点相对于对应cell左上角位置的相对偏移值,为了将边界框中心点约束在当前cell中,使用sigmoid函数处理偏移值,这样预测的偏移值在(0,1)范围内(每个cell的尺度看做1),轻松解决了这个offset的问题,关于w,h的也改进了YOLOv1中平方差的差的平方的方法,用了RPN中的log函数。

现在,神经网络在特征图(13 *13 )的每个cell上预测5个bounding boxes(聚类得出的值),同时每一个bounding box预测5个坐值,分别为 t x , t y , t w , t h , t o t_x,t_y,t_w,t_h,t_o tx,ty,tw,th,to,其中前四个是坐标,to是置信度。(最终得到的边框坐标值是 b x , b y , b w , b h b_x,b_y,b_w,b_h bx,by,bw,bh,而网络学习目标是 t x , t y , t w , t h t_x,t_y,t_w,t_h tx,ty,tw,th)

img

这几个公式参考上面Faster-RCNN和YOLOv1的公式以及下图就比较容易理解。

其中 ( c x , x y ) (c_x, x_y) (cx,xy) 为cell的左上角坐标,在计算时每个cell的尺度为1,所以当前cell的左上角坐标为 (1,1) 。 t x , t y t_x,t_y tx,ty 经sigmod函数处理过,取值限定在了0~1,边界框的中心位置会约束在当前cell内部,防止偏移过多,实际意义就是使anchor只负责周围的box,有利于提升效率和网络收敛。而 p w p_w pw p h ​ p_h​ ph 是先验框的宽度与长度,前面说过它们的值也是相对于特征图大小的,使用 e的幂函数是因为前面做了 ln 计算。

定位预测值被归一化后,参数就更容易得到学习,模型就更稳定。作者使用Dimension Clusters和Direct location prediction这两项anchor boxes改进方法,mAP获得了5%的提升。

Fine-Grained Features(细粒度特征)

添加pass through layer,把浅层特征图(26*26)连接到深层特征图,去捕捉更细粒度的特征

  • Resnet中的identity mapping

  • 把26*26*512的特征图叠加成13*13*2048的特征图,与深层特征图相连接,增加细粒度特征

  • 性能获得了1%的提升

    YOLOv2的输入图片大小为 416*416 ,经过5次max pooling之后得到 13*13 大小的特征图,并以此特征图采用卷积做预测。 13*13 大小的特征图对检测大物体是足够了,但是对于小物体还需要更精细的特征图(Fine-Grained Features)。因此SSD使用了多尺度的特征图来分别检测不同大小的物体,前面更精细的特征图可以用来预测小物体。YOLOv2提出了一种passthrough层来利用更精细的特征图。

这里写图片描述

这个转移层也就是把高低两种分辨率的特征图做了一次连结,连接方式是叠加特征到不同的通道而不是空间位置,类似于Resnet中的identity mappings。

YOLOv2所利用的Fine-Grained Features是 26*26 大小的特征图(最后一个maxpooling层的输入),对于Darknet-19模型来说就是大小为 26*26*512 的特征图。passthrough层与ResNet网络的shortcut类似,以前面更高分辨率的特征图为输入,然后将其连接到后面的低分辨率特征图上。前面的特征图维度是后面的特征图的2倍,passthrough层抽取前面层的每个 2*2 的局部区域,然后将其转化为channel维度,对于 26*26*512 的特征图,经passthrough层处理之后就变成了 13*13*2048 的新特征图(特征图大小降低4倍,而channles增加4倍),这样就可以与后面的 13*13*1024 特征图连接在一起形成 13*13*3072 大小的特征图,然后在此特征图基础上卷积做预测。在YOLO的C源码中,passthrough层称为reorg layer。在TensorFlow中,可以使用tf.extract_image_patches或者tf.space_to_depth来实现passthrough层:

ut = tf.extract_image_patches(in, [1, stride, stride, 1], [1, stride, stride, 1], [1,1,1,1], padding="VALID"
// or use tf.space_to_depth

out = tf.space_to_depth(in, 2)

img

另外,作者在后期的实现中借鉴了ResNet网络,不是直接对高分辨特征图处理,而是增加了一个中间卷积层,先采用64个 1*1 卷积核进行卷积,然后再进行passthrough处理,这样 26*26*512 的特征图得到 13*13*256 的特征图。这算是实现上的一个小细节。

Multi-Scale Training

由于YOLO2网络只包含卷积层和池化层,因此可以接受任意尺寸的图像输入。

YOLO2每经过10批训练,就会随机选择新的图片尺寸继续训练。

  • 输入尺寸{320,352,…,608}
  • 尺度的变化

由于YOLOv2模型中只有卷积层和池化层,所以YOLOv2的输入可以不限于416x416大小的图片。为了增强模型的鲁棒性,YOLOv2采用了多尺度输入训练策略,具体来说就是在训练过程中每间隔一定的iterations之后改变模型的输入图片大小。由于YOLOv2的下采样总步长为32,输入图片大小选择一系列为32倍数的值:{320,352,384,…,608},输入图片最小为320x320,此时对应的特征图大小为10x10(不是奇数了,确实有点尴尬),而输入图片最大为 608x608,对应的特征图大小为19x19。在训练过程,每隔10个iterations随机选择一种输入图片大小,然后只需要修改对最后检测层的处理就可以重新训练。采用Multi-Scale Training策略,YOLOv2可以适应不同大小的图片,并且预测出很好的结果。

网络结构

Darknet-19

  • 主要使用3*3卷积

  • pooling之后channel增加

  • global average pooling

  • 1*1卷积压缩特征表示

  • batch normalization

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aniW1zlM-1611727122325)(C:\F\notebook\YOLO\1551083374(1)].png)

YOLOv2使用了一个新的分类网络作为特征提取部分,参考了前人的先进经验,比如类似于VGG,作者使用了较多的3 * 3卷积核,在每一次池化操作后把通道数翻倍。借鉴了network in network的思想,网络使用了全局平均池化(global average pooling),把1 * 1的卷积核置于3 * 3的卷积核之间,用来压缩特征。也用了batch normalization(前面介绍过)稳定模型训练。

最终得出的基础模型就是Darknet-19,如上图,其包含19个卷积层、5个最大值池化层(maxpooling layers ),下图展示网络具体结构。Darknet-19运算次数为55.8亿次,imagenet图片分类top-1准确率72.9%,top-5准确率91.2%。

YOLO3

改进之处:

  • 更好的分类器
  • 多尺度预测(类FPN)
  • 更好的主干网络(类ResNet)

分类器-类别预测:

将原来的单标签分类改进为多标签分类

更好的分类器:binary cross-entropy loss

  • Softmax不适用于多标签分类
  • Softmax可被独立的多个logistic分类器替代,且准确率不会下降

YOLO3不使用Softmax对每个框进行分类,主要考虑因素有两个:

1.Softmax使得每个框分配一个类别(score最大的一个),而对于Open Images这种数据集,目标可能有重叠的类别标签,因此Softmax不适用于多标签分类。

2.Softmax可被独立的多个logistic分类器替代,且准确率不会下降。分类损失采用binary cross-entropy loss.

​ 因此网络结构上就将原来用于单标签多分类的softmax层换成用于多标签多分类的逻辑回归层。首先说明一下为什么要做这样的修改,原来分类网络中的softmax层都是假设一张图像或一个object只属于一个类别,但是在一些复杂场景下,一个object可能属于多个类,比如你的类别中有woman和person这两个类,那么如果一张图像中有一个woman,那么你检测的结果中类别标签就要同时有woman和person两个类,这就是多标签分类,需要用逻辑回归层来对每个类别做二分类。逻辑回归层主要用到sigmoid函数,该函数可以将输入约束在0到1的范围内,因此当一张图像经过特征提取后的某一类输出经过sigmoid函数约束后如果大于0.5,就表示属于该类。

网络结构(Darknet-53)

一方面基本采用全卷积(YOLO v2中采用pooling层做feature map的sample,这里都换成卷积层来做了),另一方面引入了residual结构(YOLO v2中还是类似VGG那样直筒型的网络结构,层数太多训起来会有梯度问题,所以Darknet-19也就19层,因此得益于ResNet的residual结构,训深层网络难度大大减小,因此这里可以将网络做到53层,精度提升比较明显)。Darknet-53只是特征提取层,源码中只使用了pooling层前面的卷积层来提取特征,因此multi-scale的特征融合和预测支路并没有在该网络结构中体现,

Darknet-53网络:
在这里插入图片描述

残差操作流程,如图:
在这里插入图片描述

使用FPN网络(Feature Pyramid Networks)

多个scale融合的方式做预测

  • 聚类来得到bbox的先验,选择9个簇以及3个尺度
  • 将这9个簇均匀的分布在这3个尺度上

每种尺度预测3个box, anchor的设计方式仍然使用聚类,得到9个聚类中心,将其按照大小均分给3种尺度.

  • 尺度1: 在基础网络之后添加一些卷积层再输出box信息.
  • 尺度2: 从尺度1中的倒数第二层的卷积层上采样(x2)再与最后一个26x26大小的特征图相加,再次通过多个卷积后输出box信息.相比尺度1变大两倍.
  • 尺度3: 与尺度2类似,使用了52x52大小的特征图.
    在这里插入图片描述

使用FPN 多层级预测架构以提升小物体预测能力,特征层从单层13x13 变成了多层13x13、26x26 和52x52,单层预测5 种bounding box 变成每层3 种bounding box (共9 种) .

原来的YOLO v2有一个层叫:passthrough layer,假设最后提取的feature map的size是13*13,那么这个层的作用就是将前面一层的26*26的feature map和本层的13*13的feature map进行连接,有点像ResNet。当时这么操作也是为了加强YOLO算法对小目标检测的精确度。这个思想在YOLO v3中得到了进一步加强,在YOLO v3中采用类似FPN的upsample和融合做法(最后融合了3个scale,其他两个scale的大小分别是26*26和52*52),在多个scale的feature map上做检测,对于小目标的检测效果提升还是比较明显的。

前面提到过在YOLO v3中每个grid cell预测3个bounding box,看起来比YOLO v2中每个grid cell预测5个bounding box要少,其实不是!因为YOLO v3采用了多个scale的特征融合,所以bounding box的数量要比之前多很多,以输入图像为416*416为例:(13*13+26*26+52*52)*3和13*13*5相比哪个更多应该很清晰了。

关于bounding box的初始尺寸还是采用YOLO v2中的k-means聚类的方式来做,这种先验知识对于bounding box的初始化帮助还是很大的,毕竟过多的bounding box虽然对于效果来说有保障,但是对于算法速度影响还是比较大的。

优势

为什么v3性能上能有这么大的改进?或者说为什么v3在没有提高输入数据分辨率的前提下,对小目标检测变得这么好?

loss不同

作者v3替换了v2的softmax loss 变成logistic loss,而且每个ground truth只匹配一个先验框。

anchor bbox prior不同

v2作者用了5个anchor,一个折衷的选择,所以v3用了3个anchor,提高了IOU。

detection的策略不同

v2只有一个detection,v3一下变成了3个,分别是一个下采样的,feature map为13*13,还有2个上采样的eltwise sum,feature map为26*26,52*52,也就是说v3的416版本已经用到了52的feature map,而v2把多尺度考虑到训练的data采样上,最后也只是用到了13的feature map,这应该是对小目标影响最大的地方。

backbone不同

这和上一点是有关系的,v2的darknet-19变成了v3的darknet-53,为啥呢?就是需要上采样啊,卷积层的数量自然就多了,另外作者还是用了一连串的3*3、1*1卷积,3*3的卷积增加channel,而1*1的卷积在于压缩3*3卷积后的特征表示,这波操作很具有实用性,一增一减,效果棒棒。

模型评估

Yolo模型评估主要采取obect detection ,常见的指标:IoU和mAP

IoU(Intersection over Union)

预测结果与ground truth 的联集分之交集(如下式)。 一般预测任务最常用的指标是.5 IoU, 表示在一次bounding box 预测中,该bounding box 算出的IoU > 0.5 时为预测成功。

​ IoU(A,B)=A∩B/A∪B

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FI8CyOjm-1611727122327)(https://1.bp.blogspot.com/-VNwuKuOJsCU/WzEkFxjWDII/AAAAAAABbfw/zkViGokafvMO6caJsZ45uytFcs9ytUgUwCLcBGAs/s1600/detection_iou.png)]

mAP(Mean Average Precision)

计算各个种类的精确度并平均,这里的精确度即是使用IoU 作为判别准则,通常为.5 IoU。

  • TP©: True Positive in class c,预测的proposal 和ground true 吻合(种类正确且重叠部份够高)。
  • FP©: False Positive in class c,预测的proposal 和ground true 不吻合(种类错误或重叠部份不够高)。

因此由以上步骤可知在class c 中的准确率为:

​ TP©/(TP©+FP© )

因此每个class 平均的准确率为:
m A P = 1 c l a s s e s ∑ c ∈ c l a s s e s T P ( c ) T P ( C ) + F P ( c ) mAP=\frac{1}{classes}\sum{c∈classes}\frac{TP(c)}{TP(C)+FP(c)} mAP=classes1cclassesTP(C)+FP(c)TP(c)

使用K-means聚类计算anchor boxes的具体方法

k-means需要有数据,中心点个数是需要人为指定的,位置可以随机初始化,但是还需要度量到聚类中心的距离。这里怎么度量这个距离是很关键的。

距离度量如果使用标准的欧氏距离,大盒子会比小盒子产生更多的错误。例(100-95)^2=25, (5-2.5)^2=6.25。因此这里使用其他的距离度量公式。

聚类的目的是anchor boxes和临近的ground truth有更大的IOU值,这和anchor box的尺寸没有直接关系。自定义的距离度量公式: d(box,centroid)=1-IOU(box,centroid) 到聚类中心的距离越小越好,但IOU值是越大越好,所以使用 1 - IOU,这样就保证距离越小,IOU值越大

①使用的聚类原始数据是只有标注框的检测数据集,YOLO2、3都会生成一个包含标注框位置和类别的txt文件,其中每行都包含(xj,yj,wj,hj),即ground truth boxes相对于原图的坐标,(x_j,y_j)是框的中心点,(w_j,h_j)是框的宽和高,N是所有标注框的个数;

②首先给定k个聚类中心点(W_i,H_i),i\in{1,2,...,k},这里的W_i,H_i是anchor boxes的宽和高尺寸,由于anchor boxes位置不固定,所以没有(x,y)的坐标,只有宽和高;

③计算每个标注框和每个聚类中心点的距离 d=1-IOU(标注框,聚类中心),计算时每个标注框的中心点都与聚类中心重合,这样才能计算IOU值,即d=1-IOU\left [ (x_j,y_j,w_j,h_j),(x_j,y_j,W_i,H_i) \right ],j\in{1,2,...,N},i\in{1,2,...,k}。将标注框分配给“距离”最近的聚类中心;

④所有标注框分配完毕以后,对每个簇重新计算聚类中心点,计算方式为W_i^{'}=\frac{1}{N_i}\sum w_{i},H_i^{'}=\frac{1}{N_i}\sum h_{i}N_i是第i个簇的标注框个数,就是求该簇中所有标注框的宽和高的平均值。 重复第3、4步,直到聚类中心改变量很小。

总结

基本思想V1

  • 将输入图像分成S*S个格子,每个格子负责预测中心在此格子中的物体

  • 每个格子预测B个bounding box及其置信度(confidence score),以及C个类别概率

  • bbox信息(x,y,w,h)为物体的中心位置相对格子位置的偏移及宽度和高度,均被归一化

  • 置信度反映是否包含物体,以及包含物体情况下位置的准确度。定义为Pr(object)*IOU,其中Pr(object)∈{0,1}

改进的V2

YOLO v2主要改进是提高召回率和定位能力

  • Batch Normalization:

    V1中也大量用了Batch Normalization,同时在定位层后边用了dropout,V2中取消了dropout,在卷积层全部使用Batch Normalization.

  • 高分辨率分类器

​ V1中使用224*224训练分类器网络,扩大到448用于检测网络。v2将ImageNet以448*448的分辨率微调最初的分类网络,迭代10epochs.

  • Anchor Boxes:

    v1中直接在卷积层之后使用全连接层预测bbox的坐标。

    v2借鉴Faster R-CNN的思想预测bbox的偏移,移除了全连接层,并且删掉了一个pooling层使特征的分辨率更大。调整了网络的输入(448->416),以使得位置坐标为奇数,这样就只有一个中心点。加上Anchor Boxes能预测超过1000个。

  • 先验框

    YOLO v2对Faster R-CNN的首选先验框方法做了改进,采样k-means在训练集bbox上进行聚类产生合适的先验框。由于使用欧氏距离会使较大的bbox比小的bbox产生更大的误差,而IoU与bbox尺寸无关,因此使用IOU参与距离计算,使得通过这些anchor boxes获得好的IOU分值。

  • 细粒度特征

    借鉴了Faster R-CNN 和 SSD使用的不同尺寸的feature map,以适应不同尺度大小的目标。YOLOv2使用了一种不同的方法,简单添加一个pass through layer,把浅层特征图连接到深层特征图。通过叠加浅层特征图相邻特征到不同通道(而非空间位置),类似于Resnet中的identity mapping。这个方法把26x26x512的特征图叠加成13x13x2048的特征图,与原生的深层特征图相连接,使模型有了细粒度特征。此方法使得模型的性能获得了1%的提升。

  • Multi-Scale Training

    和YOLOv1训练时网络输入的图像尺寸固定不变不同,YOLOv2(在cfg文件中random=1时)每隔几次迭代后就会微调网络的输入尺寸。训练时每迭代10次,就会随机选择新的输入图像尺寸。因为YOLOv2的网络使用的down samples倍率为32,所以使用32的倍数调整输入图像尺寸{320,352,…,608}。训练使用的最小的图像尺寸为320 x 320,最大的图像尺寸为608 x 608。 这使得网络可以适应多种不同尺度的输入。

  • V2对V1的基础网络也做了修改。

改进的V3

  • 多尺度预测 ,类似FPN(feature pyramid networks)
  • 更好的基础分类网络(类ResNet)和分类器

分类器:

  • YOLOv3不使用Softmax对每个框进行分类,而使用多个logistic分类器,因为Softmax不适用于多标签分类,用独立的多个logistic分类器准确率也不会下降。
  • 分类损失采用binary cross-entropy loss.

多尺度预测:

  • 每种尺度预测3个box, anchor的设计方式仍然使用聚类,得到9个聚类中心,将其按照大小均分给3中尺度。

基础网络Darknet-53:

仿ResNet, 与ResNet-101或ResNet-152准确率接近。

  • 9
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
需要学习Windows系统YOLOv4的同学请前往《Windows版YOLOv4目标检测实战:原理与源码解析》,课程链接 https://edu.csdn.net/course/detail/29865【为什么要学习这门课】 Linux创始人Linus Torvalds有一句名言:Talk is cheap. Show me the code. 冗谈不够,放码过来!  代码阅读是从基础到提高的必由之路。尤其对深度学习,许多框架隐藏了神经网络底层的实现,只能在上层调包使用,对其内部原理很难认识清晰,不利于进一步优化和创新。YOLOv4是最近推出的基于深度学习的端到端实时目标检测方法。YOLOv4的实现darknet是使用C语言开发的轻型开源深度学习框架,依赖少,可移植性好,可以作为很好的代码阅读案例,让我们深入探究其实现原理。【课程内容与收获】 本课程将解析YOLOv4的实现原理和源码,具体内容包括:- YOLOv4目标检测原理- 神经网络及darknet的C语言实现,尤其是反向传播的梯度求解和误差计算- 代码阅读工具及方法- 深度学习计算的利器:BLAS和GEMM- GPU的CUDA编程方法及在darknet的应用- YOLOv4的程序流程- YOLOv4各层及关键技术的源码解析本课程将提供注释后的darknet的源码程序文件。【相关课程】 除本课程《YOLOv4目标检测:原理与源码解析》外,本人推出了有关YOLOv4目标检测的系列课程,包括:《YOLOv4目标检测实战:训练自己的数据集》《YOLOv4-tiny目标检测实战:训练自己的数据集》《YOLOv4目标检测实战:人脸口罩佩戴检测》《YOLOv4目标检测实战:中国交通标志识别》建议先学习一门YOLOv4实战课程,对YOLOv4的使用方法了解以后再学习本课程。【YOLOv4网络模型架构图】 下图由白勇老师绘制  

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值