这几天整理了一下目标检测的模型,整理一下以便以后参考。
目前,基于深度学习算法的一系列目标检测算法大致可以分为两大流派:
1.两步走(two-stage)算法:先产生候选区域然后再进行CNN分类(RCNN系列),
2.一步走(one-stage)算法:直接对输入图像应用算法并输出类别和相应的定位(YOLO系列)
RCNN系列
faster—Rcnn中也是整个图片输入,然后得到的是一个端到端的模型,但是Faster-Rcnn中还是采用的RCNN系列的proposal+classifier的思想即先识别出区域再用分类器进行分类,Faster-Rcnn只不过讲提取proposal的步骤方法了卷积层中。详情见上面的链接。
YOLO算法的基本思想是:
YOLO的检测思想不同于R-CNN系列的思想,它将目标检测作为回归任务来解决。它的核心思想就是直接以整张图作为输入,直接在输出层回归bounding box(边界框)的位置信息以及对象所属的类别。
Yolo采用卷积网络来提取特征,然后使用全连接层来得到预测值。网络结构参考GooLeNet模型,包含24个卷积层和2个全连接层,如图所示。对于卷积层,主要使用1x1卷积来做channle reduction,然后紧跟3x3卷积。对于卷积层和全连接层,采用Leaky ReLU激活函数:。但是最后一层却采用线性激活函数
448*448*3 卷积的stride是1,卷积两次,maxpooling 两次448/2/2得到下一层的特征图大小112*112,最后得到的是7*7大小的特征图所以把图片分成7*7大小的网格
因为这里是当作回归问题来解决的,所以所有的输出包括坐标和宽高最好都定义在0到1之间。
来看一下每个单元格预测的B个(x,y,w,h,confidence)的向量和C的条件概率中,每个参数的含义(假设图片宽为{wi}高为{hi},将图片分为S×S):
1.(x,y)是bbox的中心相对于单元格的offset :
对于上图中蓝色框的那个单元格(坐标为,假设它预测的输出是红色框的bbox,设bbox的中心坐标为
,那么最终预测出来的(x,y)是经过归一化处理的,表示的是中心相对于单元格的offset,计算公式如下:
2.(w,h)是bbox相对于整个图片的比例
预测的bbox的宽高为,(w,h)表示的是bbox的是相对于整张图片的占比,计算公式如下:
3.confidence
这个置信度是由两部分组成,一是格子内是否有目标,二是bbox的准确度。定义置信度为
这里,如果格子内有物体,则,此时置信度等于IoU。如果格子内没有物体,则
,此时置信度为0
Yolo算法将目标检测看成回归问题,所以采用的是均方差损失函数。但是对不同的部分采用了不同的权重值。首先区分定位误差和分类误差。对于定位误差,即边界框坐标预测误差,采用较大的权重。
1 预训练分类网络:在 ImageNet 1000-class Competition Dataset上预训练一个分类网络(见网络结构部分),这个网络是前文网络结构中的前20个卷机网络+Average_Pooling Layer+Fully Connected Layer(此时网络输入是224*224)。
2 训练检测网络:文献[6]提到在预训练网络中增加卷积和全链接层可以改善性能。YOLO添加4个卷积层和2个全链接层,随机初始化权重。检测要求细粒度的视觉信息,所以把网络输入也从224*224变成448*448。
(1)一幅图片分成7*7个网格,某个物体的中心落在这个网格中此网格就负责预测这个物体。每个网格预测两个Bounding Box。网格负责类别信息,Bounding Box负责坐标信息(4个坐标信息及一个置信度),有20个类,所以最后一层输出为7*7*(2*(4+1)+20)=7*7*30的维度。
(2)Bounding Box的坐标使用图像的大小进行归一化0-1(见坐标归一化部分)。Confidence使用计算,其中第一项表示是否有物体落在网格里,第二项表示预测的框和实际的框之间的IOU值。
3 损失函数的确定:损失函数的定义(见损失函数部分),损失函数的设计目标就是让坐标,置信度和类别这个三个方面达到很好的平衡.
下面就来分析Yolo的预测过程,这里我们不考虑batch,认为只是预测一张输入图片。根据前面的分析,最终的网络输出是个边界框。
所有的准备数据已经得到了,那么我们先说第一种策略来得到检测框的结果,我认为这是最正常与自然的处理。首先,对于每个预测框根据类别置信度选取置信度最大的那个类别作为其预测标签,经过这层处理我们得到各个预测框的预测类别及对应的置信度值,其大小都是。一般情况下,会设置置信度阈值,就是将置信度小于该阈值的box过滤掉,所以经过这层处理,剩余的是置信度比较高的预测框。最后再对这些预测框使用NMS算法,最后留下来的就是检测结果。一个值得注意的点是NMS是对所有预测框一视同仁,还是区分每个类别,分别使用NMS。Ng在deeplearning.ai中讲应该区分每个类别分别使用NMS,但是看了很多实现,其实还是同等对待所有的框,我觉得可能是不同类别的目标出现在相同位置这种概率很低吧。
yolo v2是在yolo v1版本上的提高,对yolo 进行的改进,提高了yolo中的缺陷。
按照论文顺序来阅读
Better
Faster
Stronger
Batch Normalization (批归一化)
CNN在训练过程中网络每层输入的分布一直在改变, 会使训练过程难度加大,但可以通过normalize每层的输入解决这个问题。新的YOLO网络在每一个卷积层后添加batch normalization,通过这一方法,mAP获得了2%的提升。batch normalization 也有助于规范化模型,可以在舍弃dropout优化后依然不会过拟合
High Resolution Classifier (高分辨率分类器)
目前的目标检测方法中,基本上都会使用ImageNet预训练过的模型(classifier)来提取特征,如果用的是AlexNet网络,那么输入图片会被resize到不足256 * 256,导致分辨率不够高,给检测带来困难。为此,新的YOLO网络把分辨率直接提升到了448 * 448,这也意味之原有的网络模型必须进行某种调整以适应新的分辨率输入。
对于YOLOv2,作者首先对分类网络(自定义的darknet)进行了fine tune,分辨率改成448 * 448,在ImageNet数据集上训练10轮(10 epochs),训练后的网络就可以适应高分辨率的输入了。然后,作者对检测网络部分(也就是后半部分)也进行fine tune。这样通过提升输入的分辨率,mAP获得了4%的提升。
Convolutional With Anchor Boxes
原来的YOLO是利用全连接层直接预测bounding box的坐标(也就是在我们上面提到的7*7大小的卷积层后的全连接层)
,会丢失较多的空间信息,而YOLOv2借鉴了Faster R-CNN的思想,引入anchor。
为了引入anchor boxes来预测bounding boxes,作者在网络中果断去掉了全连接层。剩下的具体怎么操作呢?首先,作者去掉了后面的一个池化层以确保输出的卷积特征图有更高的分辨率。然后,通过缩减网络,让图片输入分辨率为416 * 416,这一步的目的是为了让后面产生的卷积特征图宽高都为奇数,这样就可以产生一个center cell。作者观察到,大物体通常占据了图像的中间位置, 就可以只用中心的一个cell来预测这些物体的位置,否则就要用中间的4个cell来进行预测,这个技巧可稍稍提升效率。最后,YOLOv2使用了卷积层降采样(factor为32),使得输入卷积网络的416 * 416图片最终得到13 * 13的卷积特征图(416/32=13)。
加入了anchor boxes后,可以预料到的结果是召回率上升,准确率下降。我们来计算一下,假设每个cell预测9个建议框,那么总共会预测13 * 13 * 9 = 1521个boxes,而之前的网络仅仅预测7 * 7 * 2 = 98个boxes。具体数据为:没有anchor boxes,模型recall为81%,mAP为69.5%;加入anchor boxes,模型recall为88%,mAP为69.2%。这样看来,准确率只有小幅度的下降,而召回率则提升了7%,说明可以通过进一步的工作来加强准确率,的确有改进空间。
Dimension Clusters (维度聚类)
我们知道在Faster R-CNN中anchor box的大小和比例是按经验设定的,然后网络会在训练过程中调整anchor box的尺寸。但是如果一开始就能选择到合适尺寸的anchor box,那肯定可以帮助网络越好地预测detection。所以作者采用k-means的方式对训练集的bounding boxes做聚类,试图找到合适的anchor box。
另外作者发现如果采用标准的k-means(即用欧式距离来衡量差异),在box的尺寸比较大的时候其误差也更大,而我们希望的是误差和box的尺寸没有太大关系。所以通过IOU定义了如下的距离函数,使得误差和box的大小无关:
Direct Location prediction (直接位置预测)
那么,作者在使用anchor boxes时发现的第二个问题就是:模型不稳定,尤其是在早期迭代的时候。大部分的不稳定现象出现在预测box的(x,y)坐标上了。在区域建议网络中,预测(x,y)以及tx,ty使用的是如下公式():
作者应该是把加号写成了减号。理由如下,anchor的预测公式来自于Faster-RCNN,我们来看看人家是怎么写的:
公式中,符号的含义解释一下:x 是坐标预测值,xa 是anchor坐标(预设固定值),x∗ 是坐标真实值(标注信息),其他变量 y,w,h 以此类推,t 变量是偏移量
这个是faster Rcnn的位置信息回归的损失函数
作者在引入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,这使得模型训练更稳定。
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的特征图,最后在该特征图上卷积做预测。
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。
每次改变输入图片大小还需要对最后检测层进行处理,然后开始训练。
网络包含19个卷积层和5个max pooling层,而在YOLOv1中采用的GooleNet,包含24个卷积层和2个全连接层,因此Darknet-19整体上卷积卷积操作比YOLOv1中用的GoogleNet要少,这是计算量减少的关键。最后用average pooling层代替全连接层进行预测
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。
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
注意:
YOLOv2训练的三个阶段如下图所示:
YOLOv2的结构示意图如下:
改进之处:
YOLO v3采用多个scale融合的方式做预测。
原来的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的特征融合,所以boundign box的数量要比之前多很多,以输入图像为416*416为例:(13*13+26*26+52*52)*3和13*13*5相比哪个更多应该很清晰了。
关于bounding box的初始尺寸还是采用YOLO v2中的k-means聚类的方式来做,这种先验知识对于bounding box的初始化帮助还是很大的,毕竟过多的bounding box虽然对于效果来说有保障,但是对于算法速度影响还是比较大的。作者在COCO数据集上得到的9种聚类结果:(10*13); (16*30); (33*23); (30*61); (62*45); (59*119); (116*90); (156*198); (373*326),这应该是按照输入图像的尺寸是416*416计算得到的。
网络结构(Darknet-53)
一方面基本采用全卷积(YOLO v2中采用pooling层做feature map的sample,这里都换成卷积层来做了),另一方面引入了residual结构(YOLO v2中还是类似VGG那样直筒型的网络结构,层数太多训起来会有梯度问题,所以Darknet-19也就19层,因此得益于ResNet的residual结构,训深层网络难度大大减小,因此这里可以将网络做到53层,精度提升比较明显)。Darknet-53只是特征提取层,源码中只使用了pooling层前面的卷积层来提取特征,因此multi-scale的特征融合和预测支路并没有在该网络结构中体现,
类别预测方面主要是将原来的单标签分类改进为多标签分类
因此网络结构上就将原来用于单标签多分类的softmax层换成用于多标签多分类的逻辑回归层。首先说明一下为什么要做这样的修改,原来分类网络中的softmax层都是假设一张图像或一个object只属于一个类别,但是在一些复杂场景下,一个object可能属于多个类,比如你的类别中有woman和person这两个类,那么如果一张图像中有一个woman,那么你检测的结果中类别标签就要同时有woman和person两个类,这就是多标签分类,需要用逻辑回归层来对每个类别做二分类。逻辑回归层主要用到sigmoid函数,该函数可以将输入约束在0到1的范围内,因此当一张图像经过特征提取后的某一类输出经过sigmoid函数约束后如果大于0.5,就表示属于该类。