《YOLO9000:Better,Faster,Stronger》
论文:https://arxiv.org/abs/1612.08242
主要包括三个部分:Better,Faster,Stronger,其中前面两部分基本上讲的是YOLO v2,最后一部分讲的是YOLO9000。
Better
这部分细节很多,要详细了解的话还是需要结合源码来看。
本篇论文是YOLO作者为了改进原有的YOLO算法所写的。
YOLO有两个缺点:
(1)定位不准确
(2)和基于region proposal的方法相比召回率较低。
因此YOLOv2主要是要在这两方面做提升。另外YOLOv2并不是通过加深或加宽网络达到效果提升,反而是简化了网络。
下面就是使用的一些手段。
1、Batch Normalization
BN(Batch Normalization)层简单讲就是对网络的每一层的输入都做了归一化,这样网络就不需要每层都去学数据的分布,收敛会快点。作者在YOLOv2种为每个卷积层都添加了BN层,由于BN可以规范模型,所以加入BN后就把dropout去掉了,实验证明添加了BN层可以提高2%的mAP。
2、High Resolution Classifier
现在基本跑个分类或目标检测模型都不会从随机初始化所有参数开始,所以一般都是用预训练的网络来fine-tuning自己的网络,而且预训练的网络基本上都是在ImageNet数据集上跑的,一方面数据量大,另一方面训练时间久,而且也比较容易得到。
YOLOv1在预训练的时候用的是224*224
的输入,一般预训练的分类模型都是在ImageNet数据集上进行的,然后在检测的时候采用448*448
的输入。这会导致从分类模型切换到检测模型的时候,模型还要适应图像分辨率的改变。
YOLOv2中将预训练分成两步:先用224*224
的输入从头开始训练网络,大概160个epoch
,然后再将输入调整到448*448
,再训练10个epoch
。**注意这两步都是在ImageNet数据集上操作。**最后再在检测的数据集上fine-tuning,也就是检测的时候用448*448
的图像作为输入就可以顺利过渡了。
3、Convolutional With Anchor Boxes
YOLOv1是利用全连接层直接预测bounding box的坐标。
YOLOv2则借鉴了Faster R-CNN的思想,引入anchor。
YOLOv2做了以下改变:
(1)删掉全连接层和最后一个pooling层,使得最后的卷积层可以有更高分辨率的特征;
(2)缩减网络,用416*416
大小的输入代替原来448*448
。这样做是希望希望得到的特征图都有奇数大小的宽和高,奇数大小的宽和高会使得每个特征图在划分cell的时候就只有一个中心cell。因为大的目标一般会占据图像的中心,所以希望用一个中心cell去预测,而不是4个中心cell。网络最终将416*416
的输入下采样32倍
变为13*13
大小的feature map输出,查看.cfg
文件可以看到有8个pooling
层。
YOLOv1中将输入图像分成7*7
的网格,每个网格预测2个bounding box,一共只有7*7*2=98个box
。
YOLOv2中引入anchor boxes,输出feature map大小为13*13
,每个cell有5个anchor box
预测得到9个bounding box
,一共有13*13*9=1521个box
。增加box数量是为了提高目标的定位准确率。
4、Dimension Clusters
Faster R-CNN中anchor box的大小和比例是按经验设定的,然后网络会在训练过程中调整anchor box的尺寸。
如果一开始就能选择到合适尺寸的anchor box,那肯定可以帮助网络更好地预测。所以作者采用k-means的方式对训练集的bounding boxes做聚类,试图找到合适的anchor box。
作者发现采用标准的k-means(即用欧式距离来衡量差异),在box的尺寸比较大的时候其误差也更大,而我们希望的是误差和box的尺寸没有太大关系。所以通过IOU定义了距离函数,使得误差和box的大小无关:
设置先验框的主要目的是为了使得预测框与ground truth的IOU更好,所以聚类分析师使用box与聚类中的box之间的IOU值作为距离指标。
在VOC和COCO数据集上的聚类分析结果,随着聚类中心数目的增加,平均IOU值(各个边界框与聚类中心的IOU的平均值)是增加的,但是综合考虑模型复杂度和召回率,作者最终选取5个聚类中心作为先验框。
对于两个数据集,5个先验框的width和height如下:
COCO: (0.57273, 0.677385), (1.87446, 2.06253), (3.33843, 5.47434), (7.88282, 3.52778), (9.77052, 9.16828)
VOC: (1.3221, 1.73145), (3.19275, 4.00944), (5.05587, 8.09892), (9.47112, 4.84053), (11.2364, 10.0071)
- 1
- 2
这里先验框的大小具体指什么作者在论文中并没有说明,从代码实现上看,应该是相对于13*13的特征图的大小。
实验对比:
(1)采用聚类分析得到的先验框比手动设置的先验框平均IOU值更高,因此模型更容易训练学习。
(2)仅选取5种box就能达到Faster RCNN的9种box的效果。
5、Direct Location prediction
这部分细节很多
作者在引入anchor box的时候遇到的第二个问题:模型不稳定,尤其是在训练刚开始的时候。作者认为这种不稳定主要来自预测box的中心坐标(x,y)
值。
在基于region proposal的目标检测算法中,是通过预测tx
和ty
来得到(x,y)
值,也就是预测的是offsets。
论文这里公式是错的,应该是“+”
号。依据是下文中的例子,以及Faster R-CNN中的公式。
这个公式是无约束的,预测的边界框很容易向任何方向偏移。
当tx=1
时,box将向右偏移一个anchor box的宽度;
当tx=-1
时,box将向左偏移一个anchor box的宽度;
因此,每个位置预测的边界框可以落在图片任何位置,这导致模型的不稳定性,在训练时需要很长时间来预测出正确的offsets。
YOLOv2中没有采用这种预测方式,而是沿用了YOLOv1的方法,就是预测边界框中心点相对于对应cell左上角位置的相对偏移值。
网络在最后一个卷积层输出13*13
的feature map,有13*13
个cell,每个cell有5个anchor box来预测5个bounding box,每个bounding box预测得到5个值。
分别为:tx、ty、tw、th和to(类似YOLOv1的confidence)
为了将bounding box的中心点约束在当前cell中,使用sigmoid函数将tx、ty
归一化处理,将值约束在0~1
,这使得模型训练更稳定。
6、Fine-Grained Features
细粒度特征
这里添加了一个直通层(passthrough layer),即就是源码中的reorg layer,将前面一层的26*26
的特征图和本层13*13
的特征图进行连接,与ResNet网络的shortcut类似,以前面更高分辨率的特征图为输入,然后将其连接到后面的低分辨率特征图上。
在13*13
的特征图上做预测,虽然对于大目标已经足够了,但对小目标不一定足够好,这里合并前面大一点的特征图可以有效的检测小目标。
具体操作:对于26*26*512
的特征图,经passthrough层处理之后就变成了13*13*2048
的新特征图(特征图大小变为1/4,而通道数变为以前的4倍),然后与后面的13*13*1024
特征图连接在一起形成13*13*3072
的特征图,最后在该特征图上卷积做预测。
7、Multi-Scale Training
YOLOv2中只有卷积层和池化层,因此不需要固定的输入图片的大小。
为了让模型更有鲁棒性,作者引入了多尺度训练。就是在训练过程中,每迭代一定的次数,改变模型的输入图片大小。
注意:这一步是在检测数据集上fine-tuning时候采用的,不要跟前面在Imagenet数据集上的两步预训练分类模型混淆。
具体操作:在训练时,每10个batch?确定不是10个epoch?网络就会随机选择另一种size的输入。
网络输入是416*416
,经过5次max pooling之后会输出13*13
的feature map,也就是下采样32倍,因此作者采用32的倍数作为输入的size,具体采用320、352、384、416、448、480、512、544、576、608
共10种size。
输入图片大小为320*320
时,特征图大小为10*10
,输入图片大小为608*608
时,特征图大小为19*19
。
每次改变输入图片大小还需要对最后检测层进行处理,然后开始训练。
这种网络训练方式使得相同网络可以对不同分辨率的图像做检测。
在输入size较大时,训练速度较慢,在输入size较小时,训练速度较快,而multi-scale training又可以提高准确率,因此算是准确率和速度都取得一个不错的平衡。
Faster
YOLOv1,作者采用的训练网络是基于GooleNet,GooleNet在计算复杂度上要优于VGG16,但是在ImageNet上的top-5准确率要稍低于VGG16。
YOLOv2,作者采用了新的分类模型作为基础网络,那就是Darknet-19。
1、Darknet-19
网络包含19个卷积层和5个max pooling层,而在YOLOv1中采用的GooleNet,包含24个卷积层和2个全连接层,因此Darknet-19整体上卷积卷积操作比YOLOv1中用的GoogleNet要少,这是计算量减少的关键。最后用average pooling层代替全连接层进行预测。
2、Training for Classification
这部分前面有提到,就是训练处理的小trick。
这里的Training for Classification都是在ImageNet上进行预训练。
YOLOv2的训练主要包括三个阶段:
第一阶段:在ImageNet分类数据集上从头开始预训练Darknet-19,训练160个epoch
。输入图像的大小是224*224
,初始学习率为0.1
。另外在训练的时候采用了标准的数据增加方式比如随机裁剪,旋转以及色度,亮度的调整等。
第二阶段:将网络的输入调整为448*448
,继续在ImageNet数据集上fine-tuning分类模型,训练10个epoch
。参数的除了epoch和learning rate改变外,其他都没变,这里learning rate改为0.001
。
3、Training for Detection
第三阶段:修改Darknet-19分类模型为检测模型,并在检测数据集上继续fine-tuning网络。
网络修改包括:移除最后一个卷积层、global avgpooling层以及softmax层,新增了三个332014卷积层,同时增加了一个passthrough层,最后使用1*1卷积层输出预测结果。输出通道数计算如下。
对于VOC数据,每个cell预测num=5
个bounding box,每个bounding box有5个坐标值和20个类别值,所以每个cell有125个filter。即:filter_num = num * (classes + 5) = 5 * (20 + 5) = 125
注意:
(1)这里filter_num的计算和YOLOv1不同,在YOLOv1中filter_num = classes + num * (coords + confidence) = 20 + 2 * (4 + 1) = 30
,在YOLOv1中,类别概率是由cell来预测的,一个cell对应的两个box的类别概率是一样的,但是在YOLOv2中,类别概率是属于box的,每个box对应一个类别概率,而不是由cell决定,因此这边每个box对应25个预测值(5个坐标加20个类别值)。
(2)YOLOv2和YOLOv3的计算方式是一致的。
YOLOv2训练的三个阶段如下图所示:
YOLOv2的结构示意图如下:
论文里没有说明先验框匹配和loss是怎么做的,所以有很多细节就需要去挖掘一下!
查资料有人参考YOLO在TensorFlow上的实现darkflow(见yolov2/train.py)给出了解释(见文后Reference,写的非常好,这里为了连贯我直接贴出来):
(1)和YOLOv1一样,对于训练图片中的ground truth,若其中心点落在某个cell内,那么该cell内的5个先验框所对应的边界框负责预测它,具体是哪个边界框预测它,需要在训练中确定,即由那个与ground truth的IOU最大的边界框预测它,而剩余的4个边界框不与该ground truth匹配。YOLOv2同样需要假定每个cell至多含有一个grounth truth,而在实际上基本不会出现多于1个的情况。与ground truth匹配的先验框计算坐标误差、置信度误差(此时target为1)以及分类误差,而其它的边界框只计算置信度误差(此时target为0)。
(2)YOLOv2和YOLOv1的损失函数一样,为均方差函数。但是看了YOLOv2的源码(训练样本处理与loss计算都包含在文件region_layer.c
中),并且参考国外的blog以及allanzelener/YAD2K(Ng深度学习教程所参考的那个Keras实现)上的实现,发现YOLOv2的处理比原来的v1版本更加复杂。
loss计算公式:
对应源码,参考YOLOv2–region层源码分析:https://blog.csdn.net/lwplwf/article/details/82894930:
(1)W,H
分别指的是特征图(13*13)
的宽与高;
(2)A指的是先验框数目(这里是5);
(3)各个λ
值是各个loss的权重系数,参考YOLOv1的loss;
(4)第一项loss是计算background的置信度误差,但是哪些预测框来预测背景呢,需要先计算各个预测框和所有ground truth的IOU值,并且取最大值Max_IOU,如果该值小于一定的阈值(YOLOv2使用的是0.6),那么这个预测框就标记为background,需要计算noobj的置信度误差;
(5)第二项是计算先验框与预测宽的坐标误差,但是只在前12800个iterations间计算,我觉得这项应该是在训练前期使预测框快速学习到先验框的形状;
(6)第三大项计算与某个ground truth匹配的预测框各部分loss值,包括坐标误差、置信度误差以及分类误差。
先说一下匹配原则,对于某个ground truth,首先要确定其中心点要落在哪个cell上,然后计算这个cell的5个先验框与ground truth的IOU值(YOLOv2中bias_match=1
),计算IOU值时不考虑坐标,只考虑形状,所以先将先验框与ground truth的中心点都偏移到同一位置(原点),然后计算出对应的IOU值,IOU值最大的那个先验框与ground truth匹配,对应的预测框用来预测这个ground truth。
在计算obj置信度时,在YOLOv1中target=1
,而YOLOv2增加了一个控制参数rescore,当其为1时,target取预测框与ground truth的真实IOU值。对于那些没有与ground truth匹配的先验框(与预测框对应),除去那些Max_IOU低于阈值的,其它的就全部忽略,不计算任何误差。这点在YOLOv3论文中也有相关说明:YOLO中一个ground truth只会与一个先验框匹配(IOU值最好的),对于那些IOU值超过一定阈值的先验框,其预测结果就忽略了。这和SSD与RPN网络的处理方式有很大不同,因为它们可以将一个ground truth分配给多个先验框。
尽管YOLOv2和YOLOv1计算loss处理上有不同,但都是采用均方差来计算loss。
另外需要注意的一点是,在计算boxes的和误差时,YOLOv1中采用的是平方根以降低boxes的大小对误差的影响,而YOLOv2是直接计算,但是根据ground truth的大小对权重系数进行修正:l.coord_scale * (2 - truth.w*truth.h)
,这样对于尺度较小的boxes其权重系数会更大一些,起到和YOLOv1计算平方根相似的效果。
Stronger
带标注的检测数据集量比较少,而带标注的分类数据集量比较大,因此YOLO9000主要通过结合分类和检测数据集使得训练得到的检测模型可以检测约9000类物体。
一方面要构造数据集(采用WordTree解决),另一方面要解决模型训练问题(采用Joint classification and detection)。
Reference
1.https://blog.csdn.net/l7H9JA4/article/details/79955903
2.https://blog.csdn.net/u014380165/article/details/77961414