您的位置:首页 > 其它

YOLO v1,YOLO v2,YOLO9000算法总结与源码解析

2017-05-23 09:37 274 查看
1.YOLO v1简介

YOLO出自2016 CVPR 《You Only Look Once:Unified, Real-Time Object Detection》。YOLO将目标区域定位于目标类别预测整合于单个神经网络模型中,实现了在准确率较高的情况下快速目标检测与识别,YOLO达到了45帧每秒,Fast YOLO达到了155帧每秒,适用于实时的目标检测。



YOLO利用单个卷积神经网络,将目标检测问题转换为直接从图像中提取bounding boxes和类别概率的回归问题。整个检测过程分为3个阶段:

(1)将图像缩放到448*448

(2)通过神经网格进行检测和分类

(3)NMS抑制,输出最终结果

具体地,YOLO首先将图像分为S*S的格子(grid cell)。如果一个目标的中心落入格子,则该格子就负责检测该目标(如下图)。每个格子(grid cell)预测B个边界盒(bounding box)和C类判别属性(最终输出S*S*(B*5+C)维向量)。每一个边界盒包含5个值:x,y,w,h(分别为边界盒中心点横、纵坐标,宽,高)和边界盒包含目标的置信值confidence。置信值为格子包含目标的概率与IOU的乘积。每个格子预测包含某一类目标的条件概率值。每个bounding box通过对应格子的类别概率和box置信度相乘得到该类别的置信分数。这个分数衡量了该类别出现在box中的概率以及该box与目标的吻合程度。





在VOC上训练中,S=7,B=2,C=20,最终输出7*7*(2*5+20)维度的信息。





YOLO v1缺陷:

1.YOLO对相互靠的很近的物体(挨在一起且中点都落在同一个格子上的情况),还有很小的群体 检测效果不好,这是因为一个网格中只预测了两个框,并且只属于一类。

2.测试图像中,当同一类物体出现的不常见的长宽比和其他情况时泛化能力偏弱。

3.由于损失函数的问题,定位误差是影响检测效果的主要原因,尤其是大小

物体的处理上,还有待加强。

2.YOLO v2简介

YOLO相对于目前最好的目标检测系统存在的问题是精确度不够。相对于Fast R-CNN,YOLO在目标定位方面错误率较高。YOLO v2是YOLO的升级版,作者采用了一系列的方法优化了YOLO的模型结构,产生了YOLO v2,在快速检测的同时准确率达到了state of the art,并且增强了定位精确度。

2.1为了达到更精确(Better)的目的,YOLO v2主要做了如下改进:

1 Batch normalization

神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的

分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度。

解决办法之一是对数据做一个归一化预处理。YOLOv2网络通过在每一个

卷积层后添加batch normalization,极大的改善了收敛速度同时减少了对其它regularization方法的依赖(舍弃了dropout优化后依然没有过拟合),使得mAP获得了2%的提升。

2 High Resolution Classifier

YOLOv2首先修改预训练分类网络的分辨率为448*448,在ImageNet数据

集上训练10轮(10 epochs)。这个过程让网络有足够的时间调整filter去适应高分辨率的输入。然后fine tune为检测网络,mAP获得了4%的提升。

3 Convolutional With Anchor Boxes

YOLO(v1)使用全连接层数据进行bounding box预测(将全连接层转换为S*S*(B*5+20)维的特征),这会丢失较多的空间信息,导致定位不准。

YOLOv2借鉴了Faster R-CNN中的anchor思想: 简单理解为卷积特征图上进行滑窗采样,每个中心预测9种不同大小和比例的建议框。由于都是卷积不需要reshape,很好的保留了空间信息,最终特征图的每个特征点和原图的每个cell一一对应。而且用预测相对偏移(offset)取代直接预测坐标简化了问题,方便网络学习。总的来说就是移除全连接层(以获得更多空间信息)使用 anchor boxes去预测 bounding boxes。并且,YOLOv2将预测类别的机制从空间位置(cell)中解耦,由anchor box同时预测类别和坐标(YOLO是由每个cell来负责预测类别,每个cell对应的2个bounding负责预测坐标)。



4 Dimension Clusters(维度聚类)

在使用anchor时,Faster-RCNN中anchor boxes的个数和宽高维度往往是手动精选的先验框(hand-picked priors),如果能够一开始就选择了更好的、更有代表性的先验boxes维度,那么网络就应该更容易学到准确的预测位置。YOLOv2中利用K-means聚类方法,通过对数据集中的ground truth box做聚类,找到ground truth box的统计规律。以聚类个数k为anchor boxes个数,以k个聚类中心box的宽高维度为anchor box的维度。

5 Direct location prediction

使用anchor boxes的另一个问题是模型不稳定,尤其是在早期迭代的时候。大部分的不稳定现象出现在预测box的(x,y)坐标时。YOLOv2中预测相对于grid cell的坐标位置,同时把ground truth限制在0到1之间,解决了模型随机初始化之后将需要很长一段时间才能稳定预测敏感的物体偏移的问题。



使用Dimension Clusters和Direct location prediction这两项anchor boxes改进方法,mAP获得了5%的提升。

6 Fine-Grained Features(细粒度特征)

YOLOv2使用了一种不同的方法,简单添加一个 passthrough layer,把浅层特征图(分辨率为26*26)连接到深层特征图。

passthroughlaye把高低分辨率的特征图做连结,叠加相邻特征到不同通道(而非空间位置),类似于Resnet中的identity mappings。这个方法把26*26*512的特征图叠加成13*13*2048的特征图,与原生的深层特征图相连接。

YOLOv2的检测器使用的就是经过扩展后的的特征图,它可以使用细粒度特征,使得模型的性能获得了1%的提升。

7 Multi-ScaleTraining

原始YOLO网络使用固定的448*448的图片作为输入,加入anchor boxes后输入变成416*416,由于网络只用到了卷积层和池化层,就可以进行动态调整(检测任意大小图片)。为了让YOLOv2对不同尺寸图片的具有鲁棒性,在训练的时候也考虑了这一点。

不同于固定网络输入图片尺寸的方法,每经过10批训练(10 batches)就会随机选择新的图片尺寸。网络使用的降采样参数为32,于是使用32的倍数{320,352,…,608},最小的尺寸为320*320,最大的尺寸为608*608。 调整网络到相应维度然后继续进行训练。

这种机制使得网络可以更好地预测不同尺寸的图片,同一个网络可以进行不同分辨率的检测任务,在小尺寸图片上YOLOv2运行更快,在速度和精度上达到了平衡。

在低分辨率图片检测中,YOLOv2是检测速度快(计算消耗低),精度较高的检测器。输入为228*228的时候,帧率达到90FPS,mAP几乎和Faster R-CNN的水准相同。使得其更加适用于低性能GPU、高帧率视频和多路视频

场景。

在高分辨率图片检测中,YOLOv2达到了先进水平(state-of-the-art)。

2.2为了达到更快速(Faster)的目的,YOLO v2主要做了如下改进:

1. Darknet-19

为了精度与速度并重,YOLOv2使用了一个新的分类网络作为特征提取部分,参考了前人的工作经验。类似于VGG,网络使用了较多的3*3卷积核,在每一次池化操作后把通道数翻倍。借鉴了network in network的思想,网络使用了全局平均池化(global average pooling)做预测,把1*1的卷积核置于3*3的卷积核之间,用来压缩特征。使用batch normalization稳定模型训练,加速收敛,正则化模型。最终得出的基础模型就是Darknet-19,包含19个卷积层、5个最大值池化层(max pooling layers )。

2. Training for classifier

作者使用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框架)初始的224*224训练后把分辨率上调到了448*448,使用同样的参数又训练了10次,学习率调整到了10的-3次方。高分辨率下训练的分类网络top-1准确率76.5%,top-5准确率93.3%。

3. Training for detection

为了把分类网络改成检测网络,去掉原网络最后一个卷积层,增加了三个 3 *3 (1024 filters)的卷积层,并且在每一个卷积层后面跟一个1*1的卷积层,输出维度是检测所需数量。

对于VOC数据集,预测5种boxes,每个box包含5个坐标值和20个类别,所以总共是5*(5+20)= 125个输出维度。

也添加了passthrough layer,从最后3*3*512的卷积层连到倒数第二层,使模型有了细粒度特征。

学习策略是:先以10的-3次方的初始学习率训练了160次,在第60次和

第90次的时候学习率减为原来的十分之一。weight decay为0.0005,momentum为0.9,以及类似于Faster-RCNN和SSD的数据扩充(data augmentation)策略:random crops, color shifting, etc。使用相同的策略在 COCO 和VOC上训练。

3.YOLO9000简介

YOLO9000是在YOLOv2的基础上得到的,相比于YOLO v2,YOLO9000

具有更强大(Stronger)的检测功能,可以检测出更多的类别。作者提出了一种在分类数据集和检测数据集上联合训练的机制。使用检测数据集的图片去学习检测相关的信息,例如bounding box 坐标预测,是否包含物体以及属于各个物体的概率。使用仅有类别标签的分类数据集图片去扩展可以检测的种类。

训练过程中把监测数据和分类数据混合在一起。当网络遇到一张属于检测数据集的图片就基于YOLOv2的全部损失函数(包含分类部分和检测部分)做反向传播。当网络遇到一张属于分类数据集的图片就仅基于分类部分的损失函数做反向传播。 作者最后采用一种不要求互不包含的多标签模型(multi-label model)来整合数据集。这种方法忽略了数据集的结构(例如 COCO数据集的所有类别之间是互不包含的)。

1. Hierarchical classification(层次式分类)

WordNet是一个有向图结构(而非树结构),因为语言是复杂的(例如“dog”既是“canine”又是“domestic animal”),为了简化问题,作者从ImageNet的概念中构建了一个层次树结构(hierarchical tree)来代替图结构方案。最终结果是一颗 WordTree (视觉名词组成的层次结构模型)

2.Dataset combination with WordTree

使用WordTree把多个数据集整合在一起。

3.joint classification and detection(联合训练分类和检测)

使用WordTree整合了数据集之后就可以在数据集(分类-检测数据)上训练联合模型。我们想要训练一个检测类别很大的检测器所以使用COCO检测数据集和全部ImageNet的前9000类创造一个联合数据集。为了评估我们使用的方法,也从ImageNet detection challenge 中向整合数据集添加一些还没有存在于整合数据集的类别。相应的WordTree有9418个类别。由于ImageNet是一个非常大的数据集,所以通过oversampling COCO数据集来保持平衡,使ImageNet:COCO = 4:1。

使用上面的数据集训练YOLO9000。采用基本YOLOv2的结构,anchor box数量由5调整为3用以限制输出大小。

当网络遇到一张检测图片就正常反向传播。其中对于分类损失只在当前及其路径以上对应的节点类别上进行反向传播。当网络遇到一张分类图片仅反向传播分类损失。在该类别对应的所有bounding box中找到一个置信度最高的(作为预测坐标),同样只反向传播该类及其路径以上对应节点的类别损失。反向传播objectness损失基于如下假设:预测box与ground truth box的重叠度至少0.31IOU。

采用这种联合训练,YOLO9000从COCO检测数据集中学习如何在图片中寻找物体,从ImageNet数据集中学习更广泛的物体分类。

作者在ImageNet detection task上评估YOLO9000。ImageNet detection task和COCO有44个物体类别是相同的。这意味着YOLO9000只从大多数测试数据集中看到过分类数据而非检测数据。最终整体精度为19.7mAP,在从未见过的156个物体检测数据类别上精度为16.0mAP。这个结果高于DPM,但是YOLO9000是在不同数据集上进行半监督训练。而且YOLO9000可以同时实时检测9000多种其它物体类别。

作者也分析了YOLO9000在ImageNet上的性能,发现可以学习新的动物表现很好,但是学习衣服和设备这类物体则不行。因为从COCO数据集上动物类别那里学习到的物体预测泛化性很好。但是COCO数据集并没有任何衣服类别的标签数据(只有”人”类别),所以YOLO9000很难对“太阳镜”,“游泳裤”这些类别建模。

4.YOLO源码解析

4.1 train 解析

从main()方法(darknet.c中)开始,首先读取参数;

第一个参数是yolo,故跳转到run_yolo函数(yolo.c中);

第二个参数是train,所以跳转到了train_yolo函数(yolo.c中)。

第三个参数是cfg/yolo.train.cfg, 网络架构文件

第四个参数是预训练权重参数weightfile,预训练参数文件



4.1.1相关函数解析

网络参数解析函数:parse_network_cfg

1.首先创建一个list,取名sections,记录一共有多少个section(一个section存储了CNN一层所需参数);

2.然后创建一个node,该node的void类型的指针指向一个新创建的section;该section的char类型指针指向.cfg文件中的某一(line),然后将该section的list指针指向一个新创建的node,该node的void指针指向一个kvp结构体,kvp结构体中的key就是.cfg文件中的关键字(如:batch,subdivisions等),val就是对应的值;如此循环就形成了上述的参数网络图。



注:用矩形表示list,椭圆表示section,圆形表示node,六边形表示kvp,为了表达方便,我就把section和kvp放到了node里面

加载权重函数:load_weights(&net,weightfile)

1.调用load_weights_upto(net, filename, net->n)函数;

2.分别加载每一层的权重;

网络训练函数:train_network(network net, data d)

1.加载训练数据至网络中

2.调用train_network_datum(net, x, y)训练网络

3.调用forward_network(net, state); backward_network(net, state);

4.计算损失



4.2 test 解析

从main()方法(darknet.c中)开始,首先读取参数;

第一个参数是yolo,故跳转到run_yolo函数(yolo.c中);

第二个参数是test,所以跳转到了test_yolo函数(yolo.c中)。

第三个参数是cfg/yolo.cfg

第四个参数是预训练权重参数weightfile

第五个参数是filename,为待测试的图片文件



4.3 YOLO 代码框架总结

关于YOLO代码的框架,大概总结下darknet的优缺点。

优点:

1.代码依赖项少,只有cuda,甚至连opencv都可以不需要,如果在cpu平台,cuda都可以扔了(当然darknet的cup代码并没有做什么优化,跑起来就很慢)。可以较容易得将代码移植到其他平台;

缺点:

1.在darknet中,所有层的lr都一样,这对微调造成了很大的困难,因为微调需要把前面几层的lr都设置的很小很小,然后主要训练最后一层的权重

2.总的来说就是darknet的接口确实很差,如果想把网络改成inception或者resnet的构架,需要改大量的代码,这对于验证模型可行性来说,非常浪费时间。

补充:

YOLO v1训练流程:

1.输入图片,接受输入维度为([None, 448, 448, 3]);

2.随机初始化网络权重(若是基于已有的网络模型,则在已有的模型上进行微调);

3.根据各层初始化的权重,得到输出bounding box的初始位置(x,y,w,h),置信度(confidence),类别概率C,对于一张输入图片,输出为S*S*(5*B+C)维的向量,其中B=2,C=20,输出维度为输出维度为([None,1470]);

4.根据输出向量计算损失值(detection 层才有cost);根据损失值指导权重更新;

5.当达到最大迭代次数时结束训练;

YOLO v1测试流程:

1.输入测试图片;

2.根据网络模型计算输出向量,即为图片的cell预测的bounding box位置、置信度信息及类别概率信息;

3.每个网格预测的类别概率信息和每个bounding box预测的confidence信息相乘,得到每个bounding box属于某一类的置信得分(class-specific confidence score);对每一个网格预测的每一个bbox执行同样的操作:7*7*2=98 bbox(每个bbox既有对应的class信息又有坐标信息);



4.得到每个bbox的class-specific confidence score以后,设置阈值,滤掉得分低的boxes,对保留的boxes进行NMS处理,就得到最终的检测结果;

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: