论文地址:You Only Look Once: Unified, Real-Time Object Detection
前记: 在YOLO之前,绝大部分目标检测算法都是采用分类的思想进行的,比较具有代表性的如DPM算法,通常都是在图像上采用滑窗的方法,然后对每一个小窗口进行分类,最后就完成整张图像的目标检测,将检测问题转化为分类问题是这一类方法的主要思想,但是这一类方法存在一个巨大的弊端,由于你无法确定目标的大小,因此,在做使用滑窗算法的时候必须选用不同大小比例的窗口进行滑动,以确保不会存在漏检,这就导致会有很多并不包含目标的子区域,这些大量子区域通过分类器进行预测无疑需要很大的计算量,R-CNN为了避免这一问题采用了selective search的方法来尽可能找到包含目标的子区域,尽管效率有所提升,但是整个过程还是非常耗时的。
YOLO则转变思想,将检测问题当作一个回归问题来解决,只需要单一的一个网络便能预测出目标的类别以及位置,属于one-stage类算法,前面文章SSD也属于这一类算法,正因为如此,YOLO可以实现end-to-end的预测,达到实时的检测目标, 一个简单的检测流程如下图:
YOLO的优势:
- YOLO检测速度非常快,在TITAN X GPU上能达到45帧每秒,实现了实时的检测,fast yolo能达到150帧每秒,相对于其它实时检测算法而言,yolo的精度是其它算法平均水平的两倍
- YOLO在预测的时候看到的是图像的全局信息,不同于sliding window 和region proposal方法只能看到局部信息,相对于Fast R-CNN Yolo 有着更低的背景误检率(将背景检测为目标)
- YOLO学习了目标的generalizable representations, 即泛化能力更强
统一检测:
- YOLO将输入图像分为S X S个单元网格, 如果目标的中心落入到某一个单元网格中,那么该网格就负责预测该目标
- 每一个单元网格预测B个bounding box, 每一个bounding box 预测一个置信度和四个坐标值(x, y, w, h),置信度表明该box 包含目标的可能性,置信度的计算 方法定义为:, 如果该box不包含目标时为0, 则confidence为0, 如果包含目标为1, 则confidence为该box与ground truth的IOU值(注意置信度不能简单理解为该box是否包含目标的概率,而是该box与grounding truth的位置准确度), (x,y)坐标表示bounding box相对于单元网格的中心值, 即相对于单元网格的偏移量, 取值范围在(0, 1)。宽度和高度是相对于整张图像预测的, 即bounding box 的宽度和高度除以图像的宽度和高度
- 每一个单元网格预测C个条件类别概率, 当然,前提时该网格包含目标, 注意YOLOV1不是以bounding box为单位预测类别概率, 最终bounding box 预测类别概率等于网格类别概率乘以该网格中bouding box的confidence
- 文章中S=7, B=2, VOC类别C=20, 所以最终输出为的矩阵
网络设计:
Yolo采用卷积网络来提取特征,然后使用全连接层来得到预测值。网络结构参考GooLeNet模型,包含24个卷积层和2个全连接层,如下图所示。对于卷积层,主要使用1x1卷积来做channle reduction,然后紧跟3x3卷积。对于卷积层和全连接层,采用Leaky ReLU**函数: max(x, 0.1x) ,最后一层采用线性**函数。
对于最后输出全连接层的理解:
可以看到网络的最后输出为 $7x 7x 30 $大小的张量。这个张量所代表的具体含义为:7 x 7为单元格 的数量, 对于每一个单元格,前20个元素是类别概率值,然后2个元素是边界框置信度,两者相乘可以得到类别置信度,最后8个元素是边界框的 (x, y,w,h) ,之所以把置信度 c 和 (x, y,w,h) 都分开排列,而不是按照 (x, y,w,h,c) 这样排列,其实纯粹是为了计算方便,因为实际上这30个元素都是对应一个单元格,其排列是可以任意的。
训练:
网络结构
先是使用前20个卷积层加上一个平均池化层和一个全连接层在Image Net1000上进行预训练,然后这20个卷积层加上随机初始化的4个卷积层和两个全连接层进行目标检测训练, 并且将输入图像的分辨率从224 x 224提高到448 x 448
损失函数
以上 = 5, = 0.5, 是为了增加包含目标的bounding box 产生的坐标预测误差, 减少不包含目标的bounding box 产生的置信度误差,因为大不部分box是不包含目标的。表示目标是否出现在网格单元中,表示网格单元中的第个bounding box负责预测该目标。
损失函数采用平方和误差的形式,主要分为两块儿:一是定位误差,前四行,第一二行为坐标误差,第二行之所以对w, h取根号,是因为大box产生的小偏差与小box产生的小偏差影响是不相同的,因此,就取根号加以权衡, 第三四行为bounding box 的置信度误差。这里特别说一下置信度的target值, 如果是不存在目标,此时由于,那么 。如果存在目标, ,此时需要确定 ,当然你希望最好的话,可以将IOU取1,这样 ,但是在YOLO实现中,使用了一个控制参数rescore(默认为1),当其为1时,IOU不是设置为1,而就是计算truth和pred之间的真实IOU。不过很多复现YOLO的项目还是取 ,这个差异应该不会太影响结果吧。二是分类误差,第五行为每一个包含目标单元产生的分类误差
测试:
输入一张图像,跑到网络的末端得到的三维矩阵,这里虽然没有计算IOU,但是由训练好的权重已经直接计算出了bounding box的confidence。然后再跟预测的类别概率相乘就得到每个bounding box属于哪一类的概率。注意在预测的过程中要使用到NMS算法进行最终预测结果的筛选
算法性能对比:
可以看到YOLO在准确率不错的情况下达到了实时检测的效果
缺点:
- YOLO每个grid cell只负责预测一类目标,而且只能是两个bounding box中与ground truth 的IOU值最大的那个负责预测它,因此对于小物体以及密集的物体检测效果不好
- YOLO 有较大的定位误差
参考:
https://zhuanlan.zhihu.com/p/32525231
https://blog.csdn.net/u014380165/article/details/72616238