深度学习之 YOLO v1,v2,v3详解

(写在前面:若是你想 run 起来,立马想看看效果,那就直接跳转到最后一张,动手实践,看告终果再来往前看吧,开始吧······)python

1、YOLOv1 简介

这里再也不赘述,以前的个人一个 GitChat 详尽的讲述了整个代码段的含义,以及如何一步步的去实现它linux

2、YOLOv2 简介

V1 版本的缺陷和不足,就是 V2 版本出现的源泉与动力,而 V1 版本究竟在哪些地方是它的短板之处呢:算法

V1 缺陷之处:shell

  1. 输入尺寸固定:因为输出层为全链接层,所以在检测时,YOLO 训练模型只支持与训练图像相同的输入分辨率。其它分辨率须要缩放成此固定分辨率;
  2. 占比较小的目标检测效果很差:虽然每一个格子能够预测 B 个 bounding box,可是最终只选择只选择 IOU 最高的 bounding box 做为物体检测输出,即每一个格子最多只预测出一个物体。当物体占画面比例较小,如图像中包含畜群或鸟群时,每一个格子包含多个物体,但却只能检测出其中一个。

2.1 anchor box 的思想引入网络

为提升物体定位精准性和召回率,YOLO 做者提出了 《YOLO9000: Better, Faster, Stronger》 (Joseph Redmon, Ali Farhadi, CVPR 2017, Best Paper Honorable Mention),也就是 YOLOv2 的论文全名,相比 v1 提升了训练图像的分辨率;引入了 faster rcnn 中 anchor box 的思想,对网络结构的设计进行了改进,使得模型更易学习。框架

什么是(候选区域框)anchor box?dom

假设特征能够看作一个尺度 6448 像素的 256 通道图像,对于该图像的每个位置,考虑 9 个可能的候选窗口:三种面积三种比例。这些候选窗口称为 anchors。下图示出 6448 图像 anchor 中心,在每一个面积尺寸下,取三种不一样的长宽比例(1:1,1:2,2:1),这样一来,咱们获得了一共 9 种面积尺寸各异的 anchor。示意图以下:函数

anchor box

以一个点 9 种尺寸来取 proposal,重复区域多。并且 feature map 相邻两个点对应原图的 9 个 proposal 也是不少重复区域。只是整个 faster RCNN 中的第一步,只是对候选区域进行提取 (RPN, region proposal networks, 候选区域生成网络)。这个过程只是但愿可以获得覆盖目标的候选区域,因此有不一样尺寸不一样比例的 proposal(这样才有最大可能能够在一个候选框中包括完整的目标)。而在这以后,确实会有不少重复区域,而这实际上是候选区域生成以后的下一个问题。针对这个问题,通常会采用非极大值抑制算法进行去重 (NMS, non maximum suppression)。工具

至于这个 anchor 究竟是怎么用的,这个是理解整个问题的关键。学习

下面是整个 faster RCNN 结构的示意图:

faster rcnn

输入图像不管是什么大小的样本,都要转化为 224*224(可根据状况本身设定)大小的图片,送进网络进行训练。( 为何要固定输入网络图片尺寸呢?后面解释。)

对于每一个 3x3 的窗口,做者就计算这个滑动窗口的中心点所对应的原始图片的中心点。而后做者假定,这个 3x3 窗口,是从原始图片上经过 SPP 池化 获得的,而这个池化的区域的面积以及比例,就是一个个的 anchor。换句话说,对于每一个 3x3 窗口,做者假定它来自 9 种不一样原始区域的池化,可是这些池化在原始图片中的中心点,都彻底同样。这个中心点,就是刚才提到的,3x3 窗口中心点所对应的原始图片中的中心点。如此一来,在每一个窗口位置,咱们均可以根据 9 个不一样长宽比例、不一样面积的 anchor,逆向推导出它所对应的原始图片中的一个区域,这个区域的尺寸以及坐标,都是已知的。而这个区域,就是咱们想要的 proposal。因此咱们经过滑动窗口和 anchor,成功获得了 51x39x9 个原始图片的 proposal。接下来,每一个 proposal 咱们只输出 6 个参数:每一个 proposal 和 ground truth 进行比较获得的前景几率和背景几率 (2 个参数)(对应图上的 clsscore);因为每一个 proposal 和 ground truth 位置及尺寸上的差别,从 proposal 经过平移放缩获得 ground truth 须要的 4 个平移放缩参数(对应图上的 bboxpred)。

为何以前的 CNN 要固定输入网络图片尺寸呢?

CNN 大致包含 3 部分:卷积、池化、全链接

  1. 卷积层。卷积操做对图片输入的大小会有要求吗?好比一个 5 * 5 的卷积核,我输入的图片是 30 * 81 的大小,能够获得 (26,77) 大小的图片,并不会影响卷积操做。我输入 600 * 500,它仍是照样能够进行卷积,也就是卷积对图片输入大小没有要求,只要你喜欢,任意大小的图片进入,均可以进行卷积。
  2. 池化层。池化对图片大小会有要求吗?好比我池化大小为(2,2)我输入一张 30 * 40 的,那么通过池化后能够获得 15 * 20 的图片。输入一张 53 * 22 大小的图片,通过池化后,我能够获得 26 * 11 大小的图片。所以池化这一步也没对图片大小有要求。只要你喜欢,输入任意大小的图片,均可以进行池化。
  3. 全链接层。既然池化和卷积都对输入图片大小没有要求,那么就只有全链接层对图片结果又要求了。由于全链接层咱们的链接劝值矩阵的大小 W,通过训练后,就是固定的大小了,好比咱们从卷积到全连层,输入和输出的大小,分别是 50、30 个神经元,那么咱们的权值矩阵(50,30)大小的矩阵了。所以空间金字塔池化,要解决的就是从卷积层到全链接层之间的一个过分。

这里插入卷积、池化层的输入输出计算方法:

enter image description here 例子计算详情 例子

怎么改变这个现状呢,也就是不管输入图片是什么大小,不须要都转化为统一大小的图片,再送入网络的预处理过程。这就出现了大神何凯明的 CNN 应用之 SPP。空间金字塔池化的卷积神经网络物体检测,很详细,能看懂其中缘由和机理,不赘述。

2.2 YOLOv2 多处改进

2.2.1 输出层使用卷积层替代 YOLOv1 的全链接层

附 darknet-19 的结构表:

darknet-19

包含 19 conv + 5 maxpooling。用 1x1 卷积层替代 YOLOv1 的全链接层。

1x1 卷积层(此处 1x1 卷积层的存在是为了跨通道信息整合)如上图的红色矩形框部分。

引入一点:YOLO,YOLOv二、YOLO9000,Darknet-19,Darknet-53,YOLOv3 分别是什么关系?

  1. YOLOv2 是 YOLO 的升级版,但并非经过对原始加深或加宽网络达到效果提高,反而是简化了网络。
  2. YOLO9000 是 CVPR2017 的最佳论文提名。首先讲一下这篇文章一共介绍了 YOLOv2 和 YOLO9000 两个模型,两者略有不一样。前者主要是 YOLO 的升级版,后者的主要检测网络也是 YOLOv2,同时对数据集作了融合,使得模型能够检测 9000 多类物体。而提出 YOLO9000 的缘由主要是目前检测的数据集数据量较小,所以利用数量较大的分类数据集来帮助训练检测模型。
  3. YOLOv2 使用了一个新的分类网络做为特征提取部分,参考了前人的先进经验,好比相似于 VGG,做者使用了较多的 3 * 3 卷积核,在每一次池化操做后把通道数翻倍。借鉴了 network in network 的思想,网络使用了全局平均池化(global average pooling),把 1 * 1 的卷积核置于 3 * 3 的卷积核之间,用来压缩特征。也用了 batch normalization(前面介绍过)稳定模型训练。最终得出的基础模型就是 Darknet-19,如上图,其包含 19 个卷积层、5 个最大值池化层(maxpooling layers )

2.2.2 卷积层所有使用 Batch Normalization

v1 中也大量用了 Batch Normalization,同时在定位层后边用了 dropout,v2 中取消了 dropout,在卷积层所有使用 Batch Normalization。

2.2.3 K-Means 算法

咱们知道在 Faster R-CNN 中 anchor box 的大小和比例是按经验设定的,而后网络会在训练过程当中调整 anchor box 的尺寸。可是若是一开始就能选择到合适尺寸的 anchor box,那确定能够帮助网络越好地预测 detection。因此做者采用 k-means 的方式对训练集的 bounding boxes 作聚类,试图找到合适的 anchor box。

另外做者发现若是采用标准的 k-means(即用欧式距离来衡量差别),在 box 的尺寸比较大的时候其偏差也更大,而咱们但愿的是偏差和 box 的尺寸没有太大关系。因此经过 IOU 定义了以下的距离函数,使得偏差和 box 的大小无关:

Faster R-CNN 采用的是手选先验框方法,YOLOv2 对其作了改进,采用 k-means 在训练集 bbox 上进行聚类产生合适的先验框. 因为使用欧氏距离会使较大的 bbox 比小的 bbox 产生更大的偏差,而 IOU 与 bbox 尺寸无关, 所以使用 IOU 参与距离计算, 使得经过这些 anchor boxes 得到好的 IOU 分值。距离公式:

k-means

以下图 Figure2,左边是聚类的簇个数核 IOU 的关系,两条曲线分别表明两个不一样的数据集。在分析了聚类的结果并平衡了模型复杂度与 recall 值,做者选择了 K=5,这也就是 Figure2 中右边的示意图是选出来的 5 个 box 的大小,这里紫色和黑色也是分别表示两个不一样的数据集,能够看出其基本形状是相似的。并且发现聚类的结果和手动设置的 anchor box 大小差异显著。聚类的结果中可能是高瘦的 box,而矮胖的 box 数量较少。

enter image description here

K-Means 算法概述:k-means 是非监督学习中的聚类算法; 基本 K-Means 算法的思想很简单,事先肯定常数 K,常数 K 意味着最终的聚类类别数,首先随机选定初始点为质心,并经过计算每个样本与质心之间的类似度 (这里为欧式距离),将样本点归到最类似的类中,接着,从新计算每一个类的质心 (即为类中心),重复这样的过程,知道质心再也不改变,最终就肯定了每一个样本所属的类别以及每一个类的质心。因为每次都要计算全部的样本与每个质心之间的类似度,故在大规模的数据集上,K-Means 算法的收敛速度比较慢。

enter image description here

使用聚类进行选择的优点是达到相同的 IOU 结果时所需的 anchor box 数量更少, 使得模型的表示能力更强, 任务更容易学习。

2.2.4 Multi-Scale Training

和 YOLOv1 训练时网络输入的图像尺寸固定不变不一样,YOLOv2(在 cfg 文件中 random=1 时)每隔几回迭代后就会微调网络的输入尺寸。训练时每迭代 10 次,就会随机选择新的输入图像尺寸。由于 YOLOv2 的网络使用的 downsamples 倍率为 32,因此使用 32 的倍数调整输入图像尺寸 {320,352,…,608}。训练使用的最小的图像尺寸为 320 x 320,最大的图像尺寸为 608 x 608。 这使得网络能够适应多种不一样尺度的输入。更多详细的资料可查看这里目标检测之 YOLOv3,YOLOv3 才是全文的的重点。

这里给出官方的 YOLOv2 与其它模型在 VOC 2007 数据集上的效果对比

对比

三:YOLO v3 简介

本文的重点,先一张图看看 V3 版本的强大

对比

横轴是每张图像的预测推理时间,单位 ms。纵轴是在 COCO 数据集上预测的 mAP@0.5 的精度。不管是在耗费时间,仍是预测精度上面,v3 版本都完赛过去的一些模型。

darknet-53 模型

v3 注:YOLO Detection 层: 坐标及类别结果输出层;Region 82,Region 94,Region 106。

YOLOv3 的改进之处:多尺度预算

  • 坐标预测:bbox 预测还是 yolov2 的使用维度聚类(dimension clusters )做为 anchor boxes 来预测边界框. 在训练期间,咱们使用平方偏差损失的总和。

  • 对象分数:YOLOv3 使用逻辑回归预测每一个边界框(bounding box)的对象分数。 若是先前的边界框比以前的任何其余边界框重叠 ground truth 对象,则该值应该为 1。若是之前的边界框不是最好的,可是确实将 ground truth 对象重叠了必定的阈值以上,咱们会忽略这个预测,按照 [15] 进行。咱们使用阈值 0.5。与 [15] 不一样,咱们的系统只为每一个 ground truth 对象分配一个边界框。若是先前的边界框未分配给 grounding box 对象,则不会对坐标或类别预测形成损失。

  • 类别预测:每一个框使用多标签分类来预测边界框可能包含的类。在训练过程当中,使用二元交叉熵损失来进行类别预测。

补充:Darknet 框架 Darknet 由 C 语言和 CUDA 实现, 对 GPU 显存利用效率较高 (CPU 速度差一些, 经过与 SSD 的 Caffe 程序对比发现存在 CPU 较慢,GPU 较快的状况). Darknet 对第三方库的依赖较少, 且仅使用了少许 GNU linux 平台 C 接口, 所以很容易移植到其它平台, 如 Windows 或嵌入式设备.

四:动手实践篇

来开始本文的重中之重吧——

第一步:首先根据官网提示,一步步的走一遍,直到可以训练 VOC 数据集,就能够停下来歇歇了。官网点这里穿越若是一块儿正常,恭喜你,就能够开始以后的步骤了。固然有兴趣想了解 YOLOv3 中设计上的更多细节,能够去看下诙谐幽默的论文,点这里,看 YOLOv3: An Incremental Improvement后面也会就论文中和修改中的一些联系,作个解释。

第二步:上面作完,只是说明你能够检测和训练了官方的图片数据集,下面开始本身的数据集。

注意点: 若是你的电脑设备是有 GPU 加速图像运算的,那样在第一步中,默认的仍是 CPU 下的训练,想要使用 GPU 就要改 Makefile 文件这里了

GPU 这是我这一个博客中看到的,将红色框圈中的部分改成 1,修改了以后,在 darknet 文件目录下 make clean 清除以前的 make 文件,从新 make,发现速度明显提升,使用上了 GPU 训练。(其实在以前第一次我从新 make 时候报 opencv 错误,后来尽管发错 opencv 没有安装好,make 也经过了,对这个没有影响,就没有太关注这里了,有经验的求告知)。相同的命令,再来训练一次 VOC 数据试试看,速度是否是提升杠杠的。

第三步:数据集的采集,制做标签,这块还参考手把手实践 YOLO 深度残差神经网络拐点检测,一句话也就是 labelImg 标记软件工具了,具体不详述了。其中有一点就是 ImageSets/Main/ 文件夹下的 train.txt,test.txt,val.txt,这里的文件须要改成本身待训练的图片全部名字编号,在生成待训练的 train.txt 大有用处。

第四步:对待训练初始配置参数进行修改

**改动一 **

首先肯定你须要作几个类别的物体检测,也就是 classes=1,仍是 classes=5 或者 7,或者 20。我这里待检测的类别为一类,因此 classes=1, 以下图的 cfg 文件夹下的.data 文件:

  • class 为训练的类别数
  • train 为训练集 train.txt
  • valid 为验证集 val.txt(未标识添加,后期可加入)
  • names 为 my_target.names,里面为本身训练的目标名称
  • backup 为 weights 的存储位置

将 VOC 格式的 xml 文件转换成 YOLO 格式的 txt 文件。

  • train.txt 为 python voclabel.py 自动生成的,为本身的待训练样本文件位置。其中在 voclabel.py 文件我对其进行了修改,sets=[] 也进行了删减,只留下本身须要的那一部分;lasses=[" "], 里面为本身的检测类别;生成的 train.txt 也只是本身须要的部分,以下图(若有不妥或者错误,求批评指正,本身想着改的,并未看到相关材料指导)

enter image description here

  • <文件名>.names 文件 原始的部分为 coco.data。若是你不想惹麻烦,直接将此处改名为 coco.data 便可。如若你想将此处的.data 文件更改成本身的特有命名,如 my_yolov3.data。这就须要在 examples 里面的 darknet.c 文件的 440 行处进行修改成本身的命名,而后 cd 到 darknet 文件夹下 make clean 删除以前的 make 文件,而后从新 make 便可。

没改以前直接使用,会出现这个错误提示(训练和检测报错都有):

提示

改动就是在这里修改:

coco.names

make 命令百科

在软件开发中,make 是一个工具程序(Utility software),经由读取叫作“makefile”的文件,自动化建构软件。它是一种转化文件形式的工具,转换的目标称为“target”;与此同时,它也检查文件的依赖关系,若是须要的话,它会调用一些外部软件来完成任务。它的依赖关系检查系统很是简单,主要根据依赖文件的修改时间进行判断。大多数状况下,它被用来编译源代码,生成结果代码,而后把结果代码链接起来生成可执行文件或者库文件。它使用叫作“makefile”的文件来肯定一个 target 文件的依赖关系,而后把生成这个 target 的相关命令传给 shell 去执行。

许多现代软件的开发中 (如 Microsoft Visual Studio),集成开发环境已经取代 make,可是在 Unix 环境中,仍然有许多任务程师采用 make 来协助软件开发。

  • /backup/ 文件夹下用于存放训练好的.weights 参数文件,源代码里面是迭代次数小于 1000 时,每 100 次保存一次,大于 1000 时,没 10000 次保存一次。本身能够根据需求进行更改,而后从新编译便可。代码位置在 examples 里面的 detector.c line 138,和上面的同样,cd 到 darknet 文件夹下 make clean 删除以前的 make 文件,而后从新 make 便可。这样.data 文件就这么些内容。

10000

**改动二 **

cfg 文件夹下的.cfg 文件,有不少,用到的只是 yolov3-voc.cfg(如今还不知作别的.cfg 文件该怎么用,求指点,因而我把别的文件全删除了,只留下 coco.data 和 yolov3-voc.cfg)一切正常,还没发现出错。删了 -- 更名,就这样了(改了名以后报错?就须要改动一处的指示了,回看改动一)

cfg

最重要的改动,是在 my_yolov3.cfg(已图片处的名字为例)下的参数,欲知详情,娓娓道来······

  • my_yolov3.cfg 下参数改动:Training or Testing pattern?

pattern

如图:

  • batch:每次迭代要进行训练的图片数量
  • subdivisions:batch 中的图片再产生子集,源码中的图片数量 int imgs = net.batch * net.subdivisions * ngpus (一次传入 batch 张图像,细分红 subdivisions 组行迭代训练,此时的 subdivisions=8,就会发现 train 时候,两次迭代输出之间,共输出了 8 次 Region 82,Region 94,Region 106。这里的 batch 是 16,即 8 组 2 个图像。你也能够设定 batch=64,此时的训练迭代就有 8 组 8 个图像了。)
  1. Training pattern:注释掉 Testing 下的 batch 和 subdivisions 两个初始参数,让 Training 下的 batch 和 subdivisions 两个初始参数参与运算;
  2. Testing pattern:反之,注释掉 Training 下的 batch 和 subdivisions 两个初始参数,让 Testing 下的 batch 和 subdivisions 两个初始参数参与运算。(上图就是在 test 下的参数模式,切记)

YOLOv3 预测 3 个不一样尺度的 box

咱们的系统使用相似的概念以金字塔网络(SPP)从这些量表中提取特征。最后一层网络预测一个 3D 张量编码的边界框,对象和类的预测(classes)。COCO 试验中,咱们预测每一个尺度上的 3 个盒子,因此这个张量是 NN3(4+1+80)的 4 个边界框偏移量,1 个目标预测,和 80 个类的预测。若是 classes=1,也就是上面的 my_yolov3.data,文件里面定义的,此时的最后一层 filters=3*(4+1+1)=18。

论文对最后一层网络的解释以下

论文

第五步:Now we can train my target_yolo!

参考这个官方提示来作对应的修改,改成本身的命名形式,若是仍是不行,恐怕就是你的 make 步骤没有作。make clean-- --make

三色

  • 红色框:cfg 文件夹下的.data 文件
  • 绿色框:cfg 文件夹下的.cfg 文件
  • 黄色框:darknet-53 的预训练参数做为整个 train 的初始参数

train 具体的输出详解 enter image description here

Region Avg IOU: ----0.326577 is the average of the IOU of every image in the current subdivision. A 32,66% overlap in this case, this model still requires further training. Class: -----0.742537 still figuring this out Obj: -----0.033966 still figuring this out No Obj:----- 0.000793 still figuring this out The Avg Recall:------ 0.12500 is defined in code as recall/count, and thus a metric for how many positives YOLOv2 detected out of the total amount of positives in this subdivision. In this case only one of the eight positives was correctly detected. count: -----8 is the amount of positives (objects to be detected) present in the current subdivision of images (subdivision with size 8 in our case). Looking at the other lines in the log, you'll see there are also subdivision that only have 6 or 7 positives, indicating there are images in that subdivision that do not contain an object to be detected.

若是不幸,输出的是这个样子

样子

那就是你在 2.1.1 节时候,把 Training or Testing 注释错了,更改下,再试试。

若是成功了,那就出去溜溜等着吧,记得回来看看 loss 参数,迭代输出像这样

enter image description here

9798----- indicates the current training iteration/batch. 0.370096 -----is the total loss. 0.451929 ------avg is the average loss error, which should be as low as possible. As a rule of thumb, once this reaches below 0.060730 avg, you can stop training. 0.001000----- rate represents the current learning rate, as defined in the .cfg file. 3.300000 -----seconds represents the total time spent to process this batch. The 627072 -----images at the end of the line is nothing more than 9778 * 64, the total amount of images used during training so far.

序列测试,这里将 cfg/myyolov3.data 进行修改,加入 valid 的测试序列地址,从新 python voclabel.py

valid

valid 测试

./darknet detector valid cfg/myyolov3.data cfg/myyolov3.cfg backup/yolo-voc_final.weights

/在终端只返回用时,在./results/comp4dettest_[类名].txt 里保存测试结果/

打开查看内容

valid

依次表示的是:文件名;每一个框中存在该分类物体的几率;框框坐标 xmin;框框坐标 ymin;框框坐标 xmax;框框坐标 ymax,代码区以下截图,位置 examples/detector.c code

固然也有别的测试方式,并返回评价指标,如图,可本身尝试

 enter image description here

相关文章
相关标签/搜索