YOLO v2学习笔记
上一次介绍了YOLO 目标检测的第一个版本,今天继续又看了它的第二个版本,这篇论文是:YOLO9000:Better, Faster, Stronger。这篇论文主要分为两部分,第一部分介绍了YOLO v1的改进,包括如何如何使得YOLO检测算法效果更好、速度更快。第二部分是扩展YOLO算法的检测目标类别,由于标注目标检测数据集的成本比标注分类图像数据的成本高,所以目前目标检测的样本数目相对而言并不多,而且包含的目标种类也不多。作者是利用一种wordtree的方法,在COCO目标检测数据集和ImageNet图像分类数据集上联合训练,得到可以检测9000种目标的YOLO9000网络。
由于后面YOLO9000中关于wordtree的操作过程我单看论文其实也没有看的很明白,后面还需要再结合代码看看,所以先记录前面改进YOLO v1的部分。
提高YOLO检测精度
从YOLO v1的实验效果可以看出,它相比Faster RCNN而言,有着较大的定位location误差和较低的召回率recall。为了提高神经网络的精度,可以加深网络层数或者添加一些更加复杂的结构,但是这样会带来更大的时间损耗,这对于real time detection这一任务并不适用,所以作者引入了一些独特的操作环节:
-
Batch Normalization:这一层的含义我具体参考了另外一个博客:http://blog.****.net/hjimce/article/details/50866313
我们在给神经网络输入数据的时候,都要先对数据进行归一化,这么做的原因
- 一方面是输入数据不同维度的数据的尺度不一样,比如某一个维度的取值范围是1—10,而另一个维度的取值范围是1—100。不同评价指标(即特征向量中的不同特征就是所述的不同评价指标)往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可比性。原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价。
- 另一个方面,原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。
对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度和效果。
所以在每个卷积层之前都先通过一个BN层,消除数据之间由于尺度带来的干扰信息。从而使得网络训练速度和效果更好。
-
High Resolution Classifier
一般的网络都会在ImageNET上进行预训练提取图像特征,用AlexNet网络结构进行预训练的时候,输入的图像都是较小分辨率的图像,等到真正检测任务的训练的时候,输入图像变为高分辨率,这导致网络不仅要学习目标的检测,还要学习适应分辨率的改变。YOLOv2中将预训练分成两步:先在ImageNet上用224*224的输入从头开始训练网络,大概160个epoch,然后再将输入调整到448*448,再训练10个epoch。最后再在检测的数据集上fine-tuning,也就是检测的时候用448*448的图像作为输入就可以顺利过渡了。 -
Anchor Boxes思想
YOLO v2不再直接预测bounding boxes的坐标和宽度长度信息,而是借鉴Faster RCNN中region proposal network(RPN)的做法,引入预先hand picked的Anchor Boxes,然后需要预测的是期望的bounding boxes 的信息相对于hand picked 的Anchor Boxes的偏移量。YOLO v2不再在最后得到的特征图上每个网格直接预测两个bounding boxes,而是在最后得到的13*13的特征图,每个特征图有个五个Anchor Boxes,增加box数量是为了提高目标的定位准确率。
同时,删掉全连接层和最后一个pooling层,使得最后的卷积层可以有更高分辨率的特征;而且输入图片大小从448*448缩减到416*416,目的是为了最后得到的特征图中网格的个数n*n,n为奇数,保证图片的中心是一个网格而不是四个网格,这是因为一般情况下,图片中较大的物体处于图片的中心,用一个网格去预测它比用四个相近的网格去预测它效果更好。 -
Dimension Clusters
如果我们能够预先找到较为准确的hand picked anchor boxes,那么后面的预测将较为容易一点,作者在YOLO v2中的做法是利用训练样本中的bounding boxes进行k-means聚类,得到五个聚类中心,作为先验的anchor boxes。同时需要注意的是,作者不是直接用训练数据中的bounding boxes的x、y、w、h作为四维数据利用欧式距离进行聚类的度量,因为这样的度量方式收bounding boxes 的大小影响较大。作者利用的是IOU信息:
通过分别计算每个boxes与当前五个聚类中心的IOU,IOU越大的说明这两个boxes距离越近,从而距离度量d(box,centriod)应该越小。 -
Direct location prediction
YOLO v2没有直接回归bounding boxes的坐标和高和宽,因为那样训练的初始阶段预测的非常不准,使得训练收敛过程十分不稳定。所以如同上面所说,作者预测特征图中每个网格产生的bounding boxes的偏移(该图片引用出处见最下方参考链接): -
Fine-Grained Features
这里添加了一个直通层(passthrough layer),即就是源码中的reorg layer,将前面一层的2626的特征图和本层1313的特征图进行连接,与ResNet网络的shortcut类似,以前面更高分辨率的特征图为输入,然后将其连接到后面的低分辨率特征图上。
在1313的特征图上做预测,虽然对于大目标已经足够了,但对小目标不一定足够好,这里合并前面大一点的特征图可以有效的检测小目标。
具体操作:对于2626512的特征图,经passthrough层处理之后就变成了13132048的新特征图(特征图大小变为1/4,而通道数变为以前的4倍),然后与后面的13131024特征图连接在一起形成1313*3072的特征图,最后在该特征图上卷积做预测。 -
Multi-Scale Training
作者每隔10 batches就随机改变输入图片的尺寸大小,达到多尺度训练的目的,我觉得这样能增强网络对于不同分辨率图片的检测能力。 -
Darknet-19
YOLOv2,作者采用了新的分类模型作为基础网络,那就是Darknet-19。
网络包含19个卷积层和5个max pooling层,而在YOLOv1中采用的GooleNet,包含24个卷积层和2个全连接层,因此Darknet-19整体上卷积操作比YOLOv1中用的GoogleNet要少,这是计算量减少的关键。最后用average pooling层代替全连接层进行预测,即1000个特征图分别取均值得到11000的分类概率。
先用上面的网络结构进行分类预训练,然后在检测任务训练阶段,作者移除最后的一层卷积层,而用三层33的卷积层(1024个filters)取代,最后再连接上一个11卷积操作,卷积核filters的个数等于最后每个网格对应的向量长度,如论文中一个网格包括五个anchor boxes,一个boxes包含4个坐标和1个置信度,还有预测20类目标,所以filters数量为5(5+20),这跟YOLO v1略有不同。
同时增加一个passthrough 直通layer,将最后一个33512卷积层与倒数第二个卷积层连接,从而获取细粒度特征。
YOLO v2的网络结构图如图:(参考链接如最下)
LOSS function
关于loss function论文里没有介绍,需要后面再看看代码,先参考摘抄另一个博主的文章:
和YOLOv1一样,对于训练图片中的ground truth,若其中心点落在某个cell内,那么该cell内的5个先验框所对应的边界框负责预测它,具体是哪个边界框预测它,需要在训练中确定,即由那个与ground truth的IOU最大的边界框预测它,而剩余的4个边界框不与该ground truth匹配。YOLOv2同样需要假定每个cell至多含有一个grounth truth,而在实际上基本不会出现多于1个的情况。(这句话不是很理解,为什么一个cell至多只有一个目标,不是应该是5个?)与ground truth匹配的先验框计算坐标误差、置信度误差(此时target为1)以及分类误差,而其它的边界框只计算置信度误差(此时target为0)。
具体的loss function计算公式如下:
(1)W,H分别指的是特征图(1313)的宽与高;
(2)A指的是先验框数目(这里是5);
(3)各个λ值是各个loss的权重系数,参考YOLOv1的loss;
(4)第一项loss是计算background的置信度误差,但是哪些预测框来预测背景呢,需要先计算各个预测框和所有ground truth的IOU值,并且取最大值Max_IOU,如果该值小于一定的阈值(YOLOv2使用的是0.6),那么这个预测框就标记为background,需要计算noobj的置信度误差;带有上标o的b应该是指网络预测值的置信度,对于background的预测框当然希望置信度越小越好。
(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.wtruth.h),这样对于尺度较小的boxes其权重系数会更大一些,起到和YOLOv1计算平方根相似的效果。
(7)第四项是预测为有目标的框计算其置信度与期望值IOU的误差
(8)第五项是计算检测到有目标的框的分类误差
参考链接
一个博主博客:https://blog.****.net/lwplwf/article/details/82895409