YOLO五部曲之YOLO v2: Better Stronger
在上篇文章YOLO五部曲二之YOLO v1:Unified, Real-Time Object Detection中我们学习了YOLO v1的内容,在文章结尾我们点出来YOLO v1存在的一些问题,主要为以下两点:
- 定位不够准确
- 和Fast R-CNN等region proposal方法相比召回率更低
针对上面的问题,YOLO的作者做了下面的改进:
1. BatchNormalization
每个卷积层后面添加BN
实验结果:mAP提升了2%
2 High Resolution Classifier
YOLOV1预训练的时候使用的输入,检测的时候采用的是的输入,这会导致分类切换到检测的时候,模型需要适应图像分辨率的改变。
YOLOV2中将预训练分成两步:首先用的输入来训练大概160个,然后再把输入调整到再训练10个,然后再与训练好的模型上进行fine-tuning,检测的时候用就可以顺利过渡了。
实验结果:mAP提升了4%
Convolutions with Anchor Boxes
- YOLO v2移除了最后的全连接层,使用Anchor预测bouding box
- 移除了一个Pooling 层,增大了输出分辨率
- 使用416x416的图像训练网路,经过Pooling会得到一个13x13的网格输出
- 不使用anchor box的网络得到了69.5%mAP和81%Recall,
- 使用anchor box的网络获得了69.2%mAP和88%Recall,mAP少量下降,Recall大量提升,遂用之
Dimension Clusters
上面提到了使用Anchor,但是有两个问题 ,一是使用Anchor的尺寸,二是Anchor如何表示更容易学习,在Faster R-CNN和SSD中,先验框的维度(长和宽)都是手动设定的,带有一定的主观性。如果选取的先验框维度比较合适,那么模型更容易学习,从而做出更好的预测。因此,YOLOv2采用k-means聚类方法对训练集中的边界框做了聚类分析。比较了复杂度和精确度后,选用了K值为5,也就是选取了5中Anchor.
418分辨率下的五个Anchor大小
Direct Location Prediction
YOLO v1对Location没有做出约束,导致模型在训练的早期会不稳定,因为预测的bounding box 可能与原本的grid位置偏差很多
YOLO v2使用logistic激活函数σ对location进行了范围约束。
上面提到,每个格子有5个Anchor,每个Anchor预测五个值:,其中是当前网格相对于左上角的坐标,Anchor的先验宽高为,那么对Anchor进行微调后的bounding box,计算公式如下图:
实验结果: mAP提升了5%
Fine Grained Features
YOLO v2采用了的输入,这个尺度对于大的物体差不多够用,但是小物体可能还有问题,于是作者把前一层较高分辨率的特征图也加入了进来,前一层为2626512,当前为,作者将映射成然后与链接,得到的特征图,最后在此特征图进行卷积预测.
作者在后期的实现中借鉴了ResNet网络,不是直接对高分辨特征图处理,而是增加了一个中间卷积层,先采用64个 卷积核进行卷积,然后再进行passthrough处理,这样 的特征图得到 的特征图。这算是实现上的一个小细节。使用Fine-Grained Features之后YOLOv2的性能有1%的提升。
实验结果:精度提升了1%
Multi-Scale Training
YOLO v2去掉了全链接层,理论上可以接受任意尺寸的输入,YOLO v2进行了5此最大池化,下采样32倍,所以YOLO v2使用了下面的策略进行多尺度训练:
每10个bach,随机使用新的分辨率图像进行训练,分辨率为等差32的数列{320,352,..,608}。
New BackBone (Faster)
使用Darknet-19,其对图像做一次前向传播需要55.8亿次浮点计算,比YOLO v1使用的VGG卷积网络更快,精度更高
Darknet-19对精度和速度做好很好的tradeoff
Training for classification
作者使用Darknet-19在标准1000类的ImageNet上训练了160次,用的随机梯度下降法,starting learning rate 为0.1,polynomial rate decay 为4,weight decay为0.0005 ,momentum 为0.9。训练的时候仍然使用了很多常见的数据扩充方法(data augmentation),包括random crops, rotations, and hue, saturation, and exposure shifts。 (这些训练参数是基于darknet框架,和caffe不尽相同)
初始的224 * 224训练后,作者把分辨率上调到了,然后又训练了10次,学习率调整到了0.001。高分辨率下训练的分类网络在top-1准确率76.5%,top-5准确率93.3%。
Training for detection
分类网络训练完后,就该训练检测网络了,除最后一个卷积层、global avgpooling层以及softmax层,并且新增了三个 卷积层,同时增加了一passthrough层,最后使用 卷积层输出预测结果。对于VOC数据集,预测5种boxes大小,每个box包含5个坐标值和20个类别,所以总共是个输出维度。同时也添加了转移层(passthrough layer ),从最后那个的卷积层连到倒数第二层,使模型有了细粒度特征。
作者的检测模型以0.001的初始学习率训练了160次,在60次和90次的时候,学习率减为原来的十分之一。其他的方面,weight decay为0.0005,momentum为0.9,依然使用了类似于Faster-RCNN和SSD的数据扩充(data augmentation)策略。
其他
YOLOv2的网络结构以及训练参数我们都知道了,但是貌似少了点东西。仔细一想,原来作者并没有给出YOLOv2的训练过程的两个最重要方面,即先验框匹配(样本选择)以及训练的损失函数,难怪Ng说YOLO论文很难懂,没有这两方面的说明我们确实不知道YOLOv2到底是怎么训练起来的。不过默认按照YOLOv1的处理方式也是可以处理,我看了YOLO在TensorFlow上的实现,发现它就是如此处理的:和YOLOv1一样,对于训练图片中的ground truth,若其中心点落在某个cell内,那么该cell内的5个先验框所对应的边界框负责预测它,具体是哪个边界框预测它,需要在训练中确定,即由那个与ground truth的IOU最大的边界框预测它,而剩余的4个边界框不与该ground truth匹配。YOLOv2同样需要假定每个cell至多含有一个grounth truth,而在实际上基本不会出现多于1个的情况。与ground truth匹配的先验框计算坐标误差、置信度误差(此时target为1)以及分类误差,而其它的边界框只计算置信度误差(此时target为0)。YOLOv2和YOLOv1的损失函数一样,为均方差函数。
但是我看了YOLOv2的源码(训练样本处理与loss计算都包含在文件region_layer.c中,YOLO源码没有任何注释,反正我看了是直摇头),并且参考国外的blog以及allanzelener/YAD2K(Ng深度学习教程所参考的那个Keras实现)上的实现,发现YOLOv2的处理比原来的v1版本更加复杂。先给出loss计算公式
我们来一点点解释,首先 分别指的是特征图的宽与高,而 指的是先验框数目(这里是5),各个值是各个loss部分的权重系数。第一项loss是计算background的置信度误差,但是哪些预测框来预测背景呢,需要先计算各个预测框和所有ground truth的IOU值,并且取最大值Max_IOU,如果该值小于一定的阈值(YOLOv2使用的是0.6),那么这个预测框就标记为background,需要计算noobj的置信度误差。第二项是计算先验框与预测宽的坐标误差,但是只在前12800个iterations间计算,我觉得这项应该是在训练前期使预测框快速学习到先验框的形状。第三大项计算与某个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置信度时,target=1,但与YOLOv1一样而增加了一个控制参数rescore,当其为1时,target取预测框与ground truth的真实IOU值(cfg文件中默认采用这种方式)。对于那些没有与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)(这里w和h都归一化到(0,1)),这样对于尺度较小的boxes其权重系数会更大一些,可以放大误差,起到和YOLOv1计算平方根相似的效果
参考
- 小小将:目标检测|YOLOv2原理与实现
- 和蔼的zhxing:YOLO系列算法详解1:YOLOV2
- Sik-Ho Tsang:Review: YOLOv2 & YOLO9000 — You Only Look Once (Object Detection)