YOLOv2理解学习
YoloV2 理解学习
接替YOLO,YOLO的作者Joseph Redmon又改进了YOLO,做出了YOLO9000,也就是平常我们所说的YOLOv2;它的论文是YOLO9000: Better, Faster, Stronger 。发表在CVPR2017。
YOLOv2简介
YOLOv2的原始论文叫做YOLO9000,YOLO9000的来历是,在2017年前,与其它任务相比,目标检测的数据集是非常少的,作者想到一种方法,将ImageNet中的分类数据集与目标检测的MSCOCO数据集一块儿训练,因为ImageNet中的数据集种类非常多,有几千种,将这两种数据集结合在一起训练则会有9000多种类别。因此YOLO9000就出现了,但是一块儿训练的效果有限。
YOLOv2特点
由题目可以看出,YOLOv2有三大优点:分别是 Better,Faster,Stronger,我们分别对其进行介绍,因为Stronger不是目标检测方面的提升,因此暂时不讨论这个方面。
Better
YOLO与R-CNN相比,有更多的定位错误(Localization Errors),且目标都检测出的能力较低(Recall值偏低)。YOLOv2就在这两方面对YOLO进行升级。在当时,计算机视觉训练一个更大更深的网络会出现更好的效果,但是与之对应的是,越大越深的网络会制约训练和检测时间。所以YOLOv2在升级的时候,除了提升目标检测的准确率之外,还保持了YOLO原本就快速的特点。主要使用了以下几种方法或技巧:

1、Batch Normalization
加上BatchNormalization层,可以使得参数更加的趋向规整。在每一层上加一个BatchNormalization,就可以不使用Dropout层了,通过加上一个BatchNormalization 层之后,YOLO提升了2%左右的mAP。
2、High Resolution Classifier
所有的目标检测方法都是在ImageNet数据集上训练的分类器,从AlexNet开始大多数分类器采用小于$256\times256$的输入,YOLO也是一开始训练 $224\times224$的数据并后面提升到一个$448$的检测。这也就意味着网络需要同时进行学习并且还要调整检测输入的大小。对于YOLOv2来说,首先在ImageNet上进行10个epochs的全 $448\times448$的分辨率的图像进行微调。这也就是给模型一点时间去调整高分辨率的图像输入并让这个网络工作的更好。这个高分辨率检测的方法提升了约4个百分点的提升。
3、Convolutional With Anchor Boxes.
YOLO是直接预测检测框的坐标位置,而Fast R-CNN是预测检测框的offset偏移量,这大大简化了预测问题和使得模型更加容易训练。从YOLO中移除了全连接层使用Anchor Box来进行Bounding Box的预测。首先移除一个Pooling 层使得卷积层输出更高的分辨率的图像。将$448\times448$的图像压缩到 $416\times416$ ,因为这样可以使获得一个奇数行和奇数列,则会在图像的中间有一个grid cell,这样的话在中间的物体则会被一个完整的grid cell预测到,而不是4个grid cell 一起分这一个目标。在YOLO的卷积层(Convolutional )中使用32倍下采样,则对于一张$416\times416$将得到一个 $13\times13$的特征图(Feature map)。
换成Anchor Boxes之后也换了预测方式,为每个框都预测objectness(有目标的概率) 和 conditional probability (当这个框有目标且是这个类别的概率).
换成Anchor Boxes之后,在准确率上稍微下降了一下,但是提高了recall值。也就是说虽然不太准确了,但是检测出来的目标变多了,其实也没有下降太多,仅仅下降了 0.3 个百分点的mAP。但Recall 则从 $81%$提升到了 $88%$,有7个百分点的提升。
4、Dimension Clusters.
在YOLO中,Bounding Box是手动选择的两个。但是在YOLOv2中,使用了k-means 聚类方法自动地找到Anchor boxes,如果使用欧式距离,则大框的误差要远远大于小框的误差。因此我们使用IOU相关的来消除框大小的影响。

由上图中可以看到,选择k=5是一个比较好的选择,在效果上和计算效率上都是一个比较折中的方案。
从下图中我们可以看到,人工选择9个框的水平和使用IOU 的k-means 聚类算法得到5个框的效果是差不多的,当使用聚类算法选择9个框的时候,效率已经远大于人工选择9个框了。

5、Direct location prediction.
使用了Anchor boxes之后,模型训练非常不稳定,尤其是在前几个epochs。不稳的情况来源于预测这些个框的位置$(x, y)$。在RPN中预测的 $t_x$和$t_y$和中心点的坐标$(x,y)$的计算公式如下:
举个例子:当$t_x=1$时,预测框会有一个向右偏移一个预测框的宽度,$t_x=-1$时,预测框则会向左偏移一个预测框的宽度。对于这个 $t_x$ 等偏移没有添加约束的话,这个预测框将会出现在图像上的任意一个角落,因此这个在训练阶段这个效果会非常的不稳健。对于一个非常初始化的训练参数来说的话,需要花费很长时间来进行稳定。
于是就预测中心坐标的时候使用相对于grid cell 的坐标来进行预测。把ground truth 放在 0~1 之间。用一个逻辑回归的激活函数来限制网络预测的值在grid cell 这个范围中。
这个网络会为每个 grid cell 预测5个bounding box。会为每个框预测出5个坐标偏移信息,分别为 $t_x, t_y, t_w, t_h, and \ t_o$。如果grid cell的偏移量 $(c_x, c_y)$ 在左上角,并且这个bounding box的宽高分别为 $p_w, p_h$,则这个预测的数值对应的变为
这种方式会把预测框的中心点完全限制在了grid cell 中。如下图

对以上这个公式可以分析一下:$\sigma$,sigmoid 函数,它的值被限制在了0~1之间。加上由于在 feature map 中每一个 grid cell 的长度和宽度都为1,因此这个 $b_x, \ b_y$一定会落在当前 grid cell 中,其中 $(c_x,\ c_y)$是当前 grid cell的左上角的坐标。$(p_w,\ p_h)$是先验框的高度和宽度。
6、Fine-Grained Features.
在YOLO中,图片只能以一种粗粒度的方式来进行检测,因此YOLOv2对于这个方面也做了改进。首先在feature map 上则原来的$7\times7$变为了现在的 $13\times13$个网络 grid cell,对于一个足够大的图像来说,这将具有更细粒度的能够检测并定位一些小的目标。Fast R-CNN 和 SSD 都是在不同尺度上的 feature map运行他们的网络来获得不同的分辨率。而我们采用了一个passthrough层以$26\times26$的分辨率来获取特征。
passthrough 层将高维的特征和低维的特征连接在一起。将 $26\times26\times512$的特征转换为 $13\times13\times2048$,这可以和原来的特征进行连接。这就使得得到一个更细粒度的特征也参与进来。这大概提升了$1%$的效果。
passthrough的操作类似于resNet中的shortcut有点类似。下图是一个示例

拿$4\times4\times3$ 到 $2\times2\times12$来举个例子,如下图,类比到 $26\times26\times512$ 到 $13\times13\times2048$

7、Multi-Scale Training
原来的YOLO 是用 $448\times448$作为输入的。而YOLOv2在加了Anchor boxes之后,采用了$416\times416$的输入。因为YOLOv2只有卷积层和池化层,所以YOLOv2可以有很好的鲁棒性。每10个batches网络就随机的调整成新的输入图像维度,因为模型采用的是32倍下采样,所以用的都是32的倍数${320,352,\dots,608}$,即最小是 $320\times320$,最大是$608\times608$。这个方法强制网络应对不同的输入维度,这也同时意味着YOLOv2可以进行不同尺度的预测。
在下图中可以看出YOLOv2对于各种输入维度的效果都是非常好的。

Faster
在提高YOLO预测的准确率的情况下,也同时想保留YOLO的速度。比如自动驾驶需要极低的延迟。多数目标检测模型是以VGG-16来做骨干网络的,但是VGG-16需要的参数量是巨大的。YOLOv2使用了自定义网络Darknet-19基于GoogLet,参数里大概是原来的1/7,但准确率有所下降。。
DarkNet19
Darknet-19,包括19个卷积层和5个maxpooling层,如下图所示。Darknet-19与VGG16模型设计原则是一致的,主要采用$3\times3$卷积,采用$2\times2$的maxpooling层之后,特征图维度降低2倍,而同时将特征图的channles增加两倍。与NIN(Network in Network)类似,Darknet-19最终采用global avgpooling做预测,并且在$3\times3$卷积之间使用$1\times1$卷积来压缩特征图channles以降低模型计算量和参数。Darknet-19每个卷积层后面同样使用了batch norm层以加快收敛速度,降低模型过拟合。在ImageNet分类数据集上,Darknet-19的top-1准确度为72.9%,top-5准确度为91.2%,但是模型参数相对小一些。使用Darknet-19之后,YOLOv2的mAP值没有显著提升,但是计算量却可以减少约33%。

网络可视化
http://ethereon.github.io/netscope/#/gist/d08a41711e48cf111e330827b1279c31
YOLOv2训练
YOLOv2的训练主要包括三个阶段。第一阶段就是先在ImageNet分类数据集上预训练Darknet-19,此时模型输入为 $224\times224$ ,共训练160个epochs。然后第二阶段将网络的输入调整为 $448\times448$ ,继续在ImageNet数据集上finetune分类模型,训练10个epochs,此时分类模型的top-1准确度为76.5%,而top-5准确度为93.3%。第三个阶段就是修改Darknet-19分类模型为检测模型,并在检测数据集上继续finetune网络。网络修改包括:移除最后一个卷积层、global avgpooling层以及softmax层,并且新增了三个 $3\times3\times1024$卷积层,同时增加了一个passthrough层,最后使用 $1 \times 1$ 卷积层输出预测结果,输出的channels数为: $num _ anchors \times (5+num _ classes) $ ,和训练采用的数据集有关系。由于anchors数为5,对于VOC数据集输出的channels数就是125,而对于COCO数据集则为425。这里以VOC数据集为例,最终的预测矩阵为 $T$ (shape为 $(batch _ size, 13, 13, 125) $ ),可以先将其reshape为 $(batch_size,13,13,5,25) $,其中 $ T[:,:,:,:,0:4] $ 为边界框的位置和大小 $(t_x,t_y,t_w,t_h)$, $ T[:,:,:,:,4] $ 为边界框的置信度,而 $ T[:,:,:,:,5:] $为类别预测值。

YOLOv2的损失函数
原论文中并没有给出损失函数,广大网友提供了一个版本,如下
首先 $W,H$ 分别指的是特征图( $13 \times 13$ )的宽与高,而 A 指的是先验框数目(这里是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的 $w$ 和 $h$ 误差时,YOLOv1中采用的是平方根以降低boxes的大小对误差的影响,而YOLOv2是直接计算,但是根据ground truth的大小对权重系数进行修正:l.coord_scale * (2 - truth.w*truth.h)(这里w和h都归一化到(0,1)),这样对于尺度较小的boxes其权重系数会更大一些,可以放大误差,起到和YOLOv1计算平方根相似的效果
参考资料
YOLO v2 损失函数源码分析 - 一只有恒心的小菜鸟 - 博客园 (cnblogs.com)




