最近几天看目标检测的一篇论文 YOLO,这篇论文是发表于CVPR2016,作者是Joseph Redmon, Santosh Divvala, Ross Girshick, Ali Farhadi。虽然这篇论文发表于2016年,但却不失是one stage中的一篇经典论文,V1也是YOLO系列的开山之作。
论文名称:You only look once unified real-time object detection
论文链接:https://arxiv.org/pdf/1506.02640.pdf
代码下载:https://github.com/pjreddie/darknet
为了 更好让大家理解YOLO V1,我接下来先介绍下 分类,对象定位,对象检测它们之间的联系和区别。
图像分类:顾名思义,是一个输入图像,输出对该图像内容分类的描述的问题。
对象定位: 一般是指一张图有一个类别,有单个物体需要去定位,且物体较大,位于图片的中间。
目标检测:是指图片中有多个对象, 有可能是不同种类,并且将图片中的多个对象位置输出
下面从分类——>对象定位——>YOLO讲。之所以这样讲,是为了方便大家理解YOLO V1的思想
由于分类比较简单,我就不详细解释,下面通过一幅图介绍下,
如图所示,输入一张图片,经过卷积操作和全连接操后,得到 一个N*1维的列向量,其中N表示类别数。在这里我先假设N=4
分别是 car, dog,people,background。图片的理论输出是(1,0,0,0)T。
若我们想知道car的位置,我们该如何? 这就涉及到了目标定位,如下图所示。
我们可以让神经网络多输出几个单元 0
关于目标定位的损失函数可以定义平方误差和为:
这里解释下,图片中没有目标时,即我们不关注 x,y,w,h,c1...
以上就是对分类,和目标定位的解释,可能存在偏差,望大家理解。接下来我正式介绍YOLO V1
传统的目标检测算法是将检测工作视作分类器(RCNN,Fast RCNN,Faster RCNN等),而本文的作者在YOLO算法中把目标检测问题看作一个回归问题,也就是说用一个卷积神经网络结构就可以从输入图像直接预测Bbox和类别的概率。
YOLO算法的优点:1、YOLO的速度非常快。在Titan X GPU上的速度是45 fps(frames per second),加速版的YOLO差不多是155fps。2、YOLO是基于图像的全局信息进行预测的。这一点和基于sliding window以及region proposal等检测算法不一样。与Faster R-CNN相比,YOLO在误检测(将背景检测为物体)方面的错误率能降低一半多。3、YOLO学习目标的泛化能力强。4、准确率高,与其他的实时目标检测系统相比,map是其两倍以上。
缺点:
1、精度落后于最先进的检测系统 (faster RCNN)
2、位置精确性差,对于小目标物体以及物体比较密集的也检测不好,比如一群小鸟。
3、YOLO虽然可以降低将背景检测为物体的概率,但同时导致召回率较低
YOLO过程很简单:如下图所示。结构上的主要特点就是unify detection ,即统一单个卷积网络同时预测这些盒子的多个边界框和类概率。YOLO在全图像上训练并直接优化检测性能。这就保证了模型的运行速度快,可以直接学习图像的全局信息,真正的end-to-end训练。You Only Look Once正是来源于此。
算法首先把输入图像划分为S*S的格子,然后对每个格子都预测B个Bounding boxes,每个Bounding box都包含5个预测值:x,y,w,h和confidence。其中0
在这里我说说自己对作者将图像划分为S*S的理解:在这里作者借鉴了目标定位的思想(这也就是我为什么开头介绍目标定位的原因),相当于图像中每个grid cell进行了分类定位,只不过将S*S进行一次操作,这就呼应了后面的S*S*(B*5+C)。我们可以这样想想,如果我们令S=1,而刚好图像中恰好只有一个目标,这不正是目标定位吗。不过这里也显露出YOLO V1中的一个缺点,就是一个grid cell 只能检测一类,而不能从一个grid cell中识别两类,不管一个grid cell的边界框数量B是多少,但却有可能从一个grid cell中框出一类中的两个目标(比如两个人在一个grid cell)。
还有我看来需要关于YOLO的博客评论,有许多读者对x,y,w,h 是怎么产生的?关于这个,我认为想x,y,w,h是网络中通过权重产生的,也就是一张图片经过卷积之后,自然 feature map中有一组对应数据,而最终通过整个网络,自然有对应的x,y,w,h 。至于confident就是通过Pr(Object)*IOU得到。B组的数值无法确定是否相同,因为B组的数值与权重相关,权重不同,对应的数值也就不同。
另外作者还对每个grid cell都预测C个类别的概率。作者在本篇论文中令S=7,B=2,C=20(因为PasCa VOC有20个类别),所以最后就有7*7*30个tensor。如下图所示
关于confidence的计算公式:
关于这个公式的解释:因为每个bbox都有一个对应的confidence ,如果grid cell里面没有object ,则confidence=0,若有目标存在,则confidence等于预测的Bbox和ground truth的IOU的值,公式如上。所以如何判断一个grid cell中是否包含object呢?答案是:如果一个object的ground truth的中心点坐标在一个grid cell中,那么这个grid cell就是包含这个object,也就是说这个object的预测就由该grid cell负责。
每个grid cell都预测C个类别概率,表示一个grid cell在包含object的条件下属于某个类别的概率,公式如下:
注意,这个条件类别概率针对的是grid cell,不管grid cell的边界框的数量B是多少。在这里也就说明了为什么一个grid cell只能检测一类 (就假设,一个grid cell有两个class,但在这里却只能说明这个grid cell是哪一类,而不是属于这两类)
作者受到GoogleNet图像分类模型的启发。设计的网络有24个卷积层,后面是2个全连接层。作者只使用1×1降维层,后面是3×3卷积层,这与Lin等人[22]类似,而不是GoogLeNet使用的Inception模块。完整的网络如图3所示
另外两个小细节:1、作者先在ImageNet数据集上预训练网络,而且网络只采用fig3的前面20个卷积层,输入是224*224大小的图像。然后在检测的时候再加上随机初始化的4个卷积层和2个全连接层,同时输入改为更高分辨率的448*448。2、Relu层改为pRelu,公式如下:
损失函数:损失函数是这篇论文的精华所在,里面有几个细节,我会下面一一介绍。
作者采用sum-squared error的方式把localization error(bounding box的坐标误差)和classificaton error整合在一起。细节1 :如果二者的权值一致,容易导致模型不稳定,训练发散。因为很多grid cell是不包含任何对象的,这样的话很多bbox的confidence score为0(就比如论文图2 ,只有三个grid cell 有对象,其他46个均没有对象,如果权重相同,则会导致偏差出现)。所以采用设置不同权重方式来解决,一方面提高localization error的权重,另一方面降低没有object的box的confidence loss权值,loss权重分别是5和0.5。而对于包含object的box的confidence loss权值还是原来的1。 公式如下
这里详细讲一下loss function。在loss function中,前面两行表示localization error(即坐标误差),第一行是box中心坐标(x,y)的预测,第二行为宽和高的预测。细节2 :用宽和高的开根号代替原来的宽和高,这样做主要是因为相同的宽和高误差对于小的目标精度影响比大的目标要大。举个例子,原来w=10,h=20,预测出来w=8,h=22,跟原来w=3,h=5,预测出来w1,h=7相比,其实前者的误差要比后者小,但是如果不加开根号,那么损失都是一样:4+4=8,但是加上根号后,变成0.15和0.7。第三、四行表示bounding box的confidence损失,就像前面所说的,分成grid cell包含与不包含object两种情况。细节3:这里注意下因为每个grid cell包含两个bounding box,所以只有当ground truth 和该网格中的某个bounding box的IOU值最大的时候,才计算这项。第五行表示预测类别的误差,细节4:注意前面的系数只有在grid cell包含object的时候才为1。具体细节参考最后的参考资料3
还是以论文2为例: 在计算该图的损失时:坐标误差计算只计算了3次,含object的Bbox的confidence预测也只计算了3次,不含object的Bbox的confiden测则95次,类别损失计算也只计算了3次。
所以具体实现的时候是什么样的过程呢?
训练的时候:输入N个图像,每个图像包含M个objec,每个object包含4个坐标(x,y,w,h)和1个label。然后通过网络得到7*7*30大小的三维矩阵。每个1*30的向量前5个元素表示第一个bounding box的4个坐标和1个confidence,第6到10元素表示第二个bounding box的4个坐标和1个confidence。最后20个表示这个grid cell所属类别。注意这30个都是预测的结果。然后就可以计算损失函数的第一、二 、五行。至于第三四行,confidence可以根据ground truth和预测的bounding box计算出的IOU和是否有object的0,1值相乘得到。真实的confidence是0或1值,即有object则为1,没有object则为0。 这样就能计算出loss function的值了。
测试的时候:输入一张图像,跑到网络的末端得到7*7*30的三维矩阵,这里虽然没有计算IOU,但是由训练好的权重已经直接计算出了bounding box的confidence。然后再跟预测的类别概率相乘就得到每个bounding box属于哪一类的概率。过程如下
针对测试时 Bbox产生的confidence理论解释过程如下公式
它为我们提供了每个框特定类别的置信度分数。这些分数编码了该类出现在框中的概率以及预测框拟合目标的程度。也就是说这个公式让我们知道confidence与IOU的值成线性相关,同时也作为框中的类别的概率,计算过程如下:
即得到每个bounding box属于哪一类的confidence score。也就是说最后会得到20*(7*7*2)=20*98的score矩阵,括号里面是bounding box的数量,20代表类别。接下来的操作都是20个类别轮流进行:在某个类别中(即矩阵的某一行),1.将得分少于阈值(0.2)的设置为0,2.再按得分从高到低排序。3. 用NMS算法去掉重复率较大的bounding box(NMS:针对某一类别,选择得分最大的bounding box,然后计算它和其它bounding box的IOU值,如果IOU大于0.5,说明重复率较大,该得分设为0,如果不大于0.5,则不改;这样一轮后,再选择剩下的score里面最大的那个bounding box,然后计算该bounding box和其它bounding box的IOU,重复以上过程直到最后)。经过对矩阵的每一行操作之后 ,最后是从矩阵的每一列中(即每个bounding box),选取score中最大的非零值,那么这个bounding box就是这个socre对应的类别,如果没有大于0的score,说明这个bounding box里面没有物体,跳过即可。具体细节参考最后的参考资料3
关于NMS,参考资料5
参考资料:
1. https://blog.csdn.net/u014380165/article/details/72616238
2. https://blog.csdn.net/guleileo/article/details/80581858
3. https://www.bilibili.com/video/av23354360/?p=3
4. https://zhuanlan.zhihu.com/p/24916786
5. 吴恩达在网易云课程中卷积神经网络的视频
6. https://blog.csdn.net/shuzfan/article/details/52711706