一些参考博客:CSDN人工智能头条,洲洲_starry,shishi_m037192554,fariver,图像所浩南哥,AI之路
YOLO系列的官方网站:https://pjreddie.com/darknet/yolo/
虽然网上关于YOLO的介绍非常多,思想阐述的非常透彻,但总是觉得有种理解不透彻的感觉。因此另开一贴,记录下我的感悟。
YOLOv1
首先,YOLO的思想很简单:在它之前的方法都是将检测问题转化为分类问题进行的,即“生成候选框->识别”的two-stage方式。虽然准确率不错,但实时性差了太多。YOLO对此的解决方法也很粗暴:把检测问题变成回归问题,物体的边框坐标和分类置信度通通用一个网络给你搞定。网络的结构如下图,非常清晰。
YOLO将全图分成了S×S块(上图取的7×7),每一块检测B个物体(上图取2个)和这些物体的C分类置信度值(上图取20类),每个物体的参数包含边框的角点位置和宽高(4),置信度值(1),因此对于20分类问题其输出就是7×7×(2×(4+1)+20)=7×7×30,也即最右侧的输出。
也即,每个格子中,有B个边框预测器(用来输出边框位置和大小),而这B个边框预测器共享类别预测器。自然的,需要一个B选1的方式。
网络有了以后,另一个重点就是训练细节。YOLO使用的损失函数是sum-squared error,相关的讲解和图片都引自CSDN人工智能头条:
直接使用sum-squared error存在以下几个问题:
第一,8维的 localization error 和20维的 classification error 同等重要显然是不合理的;
第二,如果一个网格中没有 object(一幅图中这种网格很多),那么就会将这些网格中的 box 的 confidence push 到 0,相比于较少的有 object 的网格,这种做法是 overpowering 的,这会导致网络不稳定甚至发散。
解决办法:
更重视8维的坐标预测,给这些损失前面赋予更大的 loss weight, 记为在 pascal VOC 训练中取 5。
对没有 object 的 box 的 confidence loss,赋予小的 loss weight,记为在 pascal VOC 训练中取 0.5。
有 object 的 box 的 confidence loss 和类别的 loss 的 loss weight 正常取 1。
对不同大小的 box 预测中,相比于大 box 预测偏一点,小 box 预测偏一点肯定更不能被忍受的。而 sum-square error loss 中对同样的偏移 loss 是一样。
为了缓和这个问题,作者用了一个比较取巧的办法,就是将 box 的 width 和 height 取平方根代替原本的 height 和 width。这个参考下面的图很容易理解,小box 的横轴值较小,发生偏移时,反应到y轴上相比大 box 要大。(也是个近似逼近方式)
一个网格预测多个 box,希望的是每个 box predictor 专门负责预测某个 object。具体做法就是看当前预测的 box 与 ground truth box 中哪个 IoU 大,就负责哪个。这种做法称作 box predictor 的 specialization。
最后整个的损失函数如下所示:
为什么把图放在引用外面?因为我发现这图的原图画错了……还因此误导了我好久。原文中写的是:表示物体是否出现在网格
中。上面的图已经修正了这一错误。
其实这个损失函数,我们看一眼就能很清楚它的工作机理了。而最令人困惑的是:和
到底是如何取值的?这里参考了下洲洲_starry的图和代码,引用如下:
假设一个物体的轮廓是这样的,那么,的输出,是这样的:
[[0. 1. 1. 1. 0.]
[0. 1. 1. 1. 0.]
[0. 1. 1. 1. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
也即,只要边框部分包含的格子,都纳入了类别损失函数的计算。
而的输出,是这样的
[[(0,0). (0,0). (0,0). (0,0). (0,0).]
[(0,0). (0,0). (1,0). (0,0). (0,0).]
[(0,0). (0,0). (0,0). (0,0). (0,0).]
[(0,0). (0,0). (0,0). (0,0). (0,0).]
[(0,0). (0,0). (0,0). (0,0). (0,0).]]
也就是说,只有标注物体的中心所在的那个格子的其中一个边框预测器的输出是1。那具体是哪个呢?原文的描述是“这个格子中IoU最大的预测器”,也即边框回归结果与真实结果最接近的那个。
了解了这些以后,再回头去看损失函数,就能更加明确训练过程:
- 只有需要“负责”的边框预测器的预测结果会通过损失函数优化。由于这样的预测器很少,因此权值很高(原文是5)
- 需要和不需要负责的边框预测器的置信度值都会以一定权值通过损失函数优化(原文分别是1和0.5)。
- 有物体在其中的块的分类结果要通过损失函数优化。(原文权值是1)
其他一些细节,例如使用leak ReLU等,这里就不再赘述了。
最后在预测阶段,参考shishi_m037192554的博客,最终会首先设置置信度阈值对98个框进行初步筛选,然后留下的框有两种筛选方法:全部NMS筛选再分类,以及先分类再根据类别进行NMS筛选。这里原文好像使用的是前面的那种,不过后面那种的结果应当更好。
为了进一步分析Yolo算法,文章还做了误差分析,将预测结果按照分类与定位准确性分成以下5类:
- Correct:类别正确,IOU>0.5;(准确度)
- Localization:类别正确,0.1 < IOU<0.5(定位不准);
- Similar:类别相似,IOU>0.1;
- Other:类别错误,IOU>0.1;
-
Background:对任何目标其IOU<0.1。(误把背景当物体)
Yolo与Fast R-CNN的误差对比分析如下图所示:
可以看出,YOLO相比于Faster RCNN,定位的准确率较低,但也更不容易把背景识别成物体。
最后,YOLO自身的主要缺点是:
- 因为物体检测基于分块这一强约束,导致处在相近中心点的不同物体无法检出。
- 两个边框以及只有负责部分优化的做法,导致非常依赖训练数据集的物体和边框分布。
YOLOv2(YOLO9000)
论文链接:https://arxiv.org/abs/1612.08242
首先,对于YOLOv2的改进,原文中有一张图很写的很明白,这里给一张fariver博客中的中文版图:
图像所浩南哥的博客里关于YOLOv2的改正写的十分详细,推荐各位阅读。
1.使用批标准化。相关的原理见我写的BN介绍。
2.YOLOv1是用224×224的图像进行预训练,然后用448×448做fine-tune,这导致输入图像尺度不匹配问题。因此这里换成了直接用448×448做预训练,效果提升显著。也说明了尺度匹配的重要性。
3.将网格数量由7×7提高到13×13(输入图像为416×416),主要是提升了小物体检测能力。
4.使用Faster-RCN中的anchor机制,具体来说,YOLOv1中直接回归出了边框的坐标,这种只有正值的方法在很多实验中都不如通过偏移量表示的方法(更接近0平均分布,不至于偏移太远)。anchor box的具体原理如下图,即预设了几个边框,每个边框具有不同的长宽比(1:1,1:2,2:1等),而最终输出的值是在这个确定的(x,y,width,height)基础上的偏移值。如此其实就通过预设使网络具备了多尺度,多比例形状的检测能力。
这里YOLOv2比YOLOv1还有一个变动,就是特征数据结构方面,每一个边框有自己的分类结果了。如下图所示。
5.使用新网络结构Darknet-19。其与其他经典网络架构的效果比较如下图所示。
6.加入Anchor box的先验。作者通过K-means实验发现当Anchor数量设置为5,取一些特定比例形状时,这样预设最接近ImageNet和COCO数据的边框。因此用上,结构实现了效果提升。
7.作者实验发现,直接回归出offset值的方法会导致训练过程的不稳定,因此最终使用数学对结果进行了限制。这里我直接引用图像所浩南哥的博客:
直接对Bounding Boxes求回归会导致模型不稳定,其中心点可能会出现在图像任何位置,有可能导致回归过程震荡,甚至无法收敛,尤其是在最开始的几次迭代的时候。大多数不稳定因素产生自预测Bounding Box的中心坐标(x,y)位置的时候。
YOLOv2的网络在特征图(13*13)的每一个单元格中预测出5个Bounding Boxes(对应5个Anchor Boxes),每个Bounding Box预测出5个值(tx,ty,tw,th,t0),其中前4个是坐标偏移值,t0是置信度结果(类似YOLOv1中的边界框置信度Confidence)。YOLOv2借鉴了如下的预测方式,即当Anchor Box的中心坐标和宽高分别是(xa,ya)和(wa,wh)时,Bounding Box坐标的预测偏移值(tx,ty,tw,th)与其坐标宽高(x,y,w,h)的关系如下:
基于这种思想,YOLOv2在预测Bounding Box的位置参数时采用了如下强约束方法:
图中,黑色虚线框是Anchor Box,蓝色矩形框就是预测的Bounding Box结果,预测出的Bounding Box的坐标和宽高为(bx,by)和(bw,bh),计算方式如图2-8中所示,其中:对每个Bounding Box预测出5个值(tx,ty,tw,th,t0),Cell与图像左上角的横纵坐标距离为(cx,cy),σ定义为sigmoid激活函数(将函数值约束到[0,1]),该Cell对应的Anchor Box对应的宽高为(pw,ph)。简而言之,(bx,by)就是(cx,cy)这个Cell附近的Anchor Box针对预测值(tx,ty)得到的Bounding Box的坐标预测结果,同时可以发现这种方式对于较远距离的Bounding Box预测值(tx,ty)能够得到很大的限制。
8.细粒度特征融合
YOLOv2通过添加一个转移层(Passthrough Layer:Route + Reorg),把高分辨率的浅层特征连接到低分辨率的深层特征(把特征堆积在不同Channel中)而后进行融合和检测。具体操作是先获取前层的26*26的特征图,将其同最后输出的13*13的特征图进行连接,而后输入检测器进行检测(检测器的FC层起到了全局特征融合的作用),以此来提高对小目标的检测能力。
9.在训练时使用多尺度输入,从而使网络在输入尺度不同时也能产生较好的效果。
之后,YOLOv2还介绍了如何融合分类和检测网络(ImageNet和COCO),作者提出了一种将分类数据集和检测数据集联合训练的方法,在训练的过程,我们将这两类数据集混合,当输入的检测数据集时,反向传播全部的误差损失(YOLOv2的loss),当遇到分类数据集时,只反向传播分类误差损失。具体请参照原文。
YOLOv3
论文地址:https://pjreddie.com/media/files/papers/YOLOv3.pdf
AI之路和CSDN人工智能头条写的都不错,这里就主要摘抄其中的重要思想。
1.分类方面将原来用于单标签多分类的softmax层换成用于多标签多分类的逻辑回归层。事实证明准确度不会下降。
2.使用了多尺度预测,类似FPN,在3个不同尺度的每个格子各输出3个结果。因此最终的检测框数量比v2要多(5 vs 3×3)。
3.提出了Darknet-53架构,完全使用卷积实现下采样等操作。