对象识别这件事(一张图片仅包含一个对象,且基本占据图片的整个范围),最近几年基于CNN卷积神经网络的各种方法已经能达到不错的效果了。所以主要需要解决的问题是,对象在哪里。
最简单的想法,就是遍历图片中所有可能的位置,地毯式搜索不同大小,不同宽高比,不同位置的每个区域,逐一检测其中是否存在某个对象,挑选其中概率最大的结果作为输出。显然这种方法效率太低。RCNN开创性的提出了候选区(Region Proposals)的方法,先从图片中搜索出一些可能存在对象的候选区(Selective Search),大概2000个左右,然后对每个候选区进行对象识别。大幅提升了对象识别和定位的效率。
不过RCNN的速度依然很慢,其处理一张图片大概需要49秒。因此又有了后续的Fast RCNN 和 Faster RCNN,针对 RCNN的神经网络结构和候选区的算法不断改进,Faster RCNN已经可以达到一张图片约0.2秒的处理速度。
但总体来说,RCNN系列依然是两阶段处理模式two-stage:先提出候选区经过ALEXNET打一个标签,再用SVM识别候选区中的对象。
YOLO意思是You Only Look Once,创造性的将候选区和对象识别这两个阶段合二为一,看一眼图片就能知道有哪些对象以及它们的位置,直接一步到位。
RCNN虽然会找到一些候选区,但毕竟只是候选,等真正识别出其中的对象以后,还要对候选区进行微调,使之更接近真实的bounding box。这个过程就是边框回归:将候选区bounding box调整到更接近真实的bounding box。既然反正最后都是要调整的,干嘛还要先费劲去寻找候选区呢,大致有个区域范围就行了,YOLO就是这么干的。
因为只是一些常规的神经网络结构,所以,理解YOLO的设计的时候,重要的是理解输入和输出的映射关系。
2.输入和输出的映射关系
训练好的YOLO网络,输入一张图片,将输出一个 7* 7* 30 的张量(tensor)来表示图片中所有网格包含的对象(概率)以及该对象可能的2个位置(bounding box)和可信程度(置信度)。 为了从中提取出最有可能的那些对象和位置,YOLO采用NMS(Non-maximal suppression,非极大值抑制)算法。
3 .输入
参考图5,输入就是原始图像,唯一的要求是缩放到448 * 448的大小。主要是因为YOLO的网络中,卷积层最后接了两个全连接层,全连接层是要求固定大小的向量作为输入,所以倒推回去也就要求原始图像有固定的尺寸。那么YOLO设计的尺寸就是448 * 448。
4.输出
输出是一个 7* 7* 30 的张量。
1、YOLO 为什么能检测目标?
YOLO 是 One-Stage (单阶段) 检测算法,它只需要看图片一次,就可以预测图片中所有的物体边框。我个人有一个形象的比喻,那就是撒渔网。一个渔网撒下去,所有的鱼儿都要捕获。
YOLO 把一张图片划分成了 SxS 个格子。这里的 S 不固定,可以根据实际情况由开发者自主决定。
论文中,S 取值为 7,所以整张图片被分割成 7*7=49 个格子(Cell)。
这些 Cell 每个 Cell 都会预测 B 个 bbox。在论文中 B 取值为 2。
所以,一张图片经 YOLO 跑一遍,就会产生 98 个 bbox。如下图
这么多 bbox,怎么选择呢?以上面的图片为例:
图片中有狗、自行车、汽车 3 个目标,但是预测到的 bbox 有 98 个之多,最终肯定只能从 98 个 bbox 中选择 3 个。那么,怎么操作呢?
首先,有选择的响应 cell。
总共有 49 个 cell,但是并不是每一个 cell 的预测都有意义,我们需要找出有意义的 cell。那么哪些 cell 算是有意义呢?引入 Confidence 可信度的概念。每个 Cell 预测 B 个 bbox(论文中取值2),还有每个 bbox 对应的 Confidence。
Confidence 公式定义如下:
其中 Pr(Obj)取值只有 0 和 1 两种可能性,代表一个 cell 中是否存在物体,下面对这个概念详细解释一下。
假设:我们要检测的目标只有狗、汽车、自行车 3 种,那么其他的物体都被当成背景。
在上面的图片中,00,01,02 这些 cell 不包含任何的目标,所以它们的 Pr(Obj) 为0,所以 Confidence 也为 0。10 和 20 两个 cell 因为包含了自行车的一部分,所以它们的 Pr(Obj),它们的 Confidence 实质上就是 bbox 和 groundtruth 的 IOU。
另外怎么判断某个 cell 中有没有包含 Object 呢?这其实是通过 label 中的 groundtruth 在线算出来的。
因此,一张图片经过 YOLO 跑一遍后,除了预测出 98 个 bbox,还会给出 49 个 cell 的 confidence(98个)。
所以,那些 confidence 不为 0 的 cell 都算作有意义。
再往下走。每个 Cell 还会预测 C 个类别的概率。这是条件概率。
如果一个 Cell 存在 Object,预测这个 Object 的 class 才有意义。
在测试阶段,这个条件概率还要与 Cell 的 Confidence 相乘。
它的公式表达了两个思想:
原论文中说到,YOLO的模型结构受 GoogLeNet 启发。但是,有少许不同。YOLO 采用了 1x1 和 3x3 的序列组合替代 Inception 模块。总共 24 个卷积层加上 2 个全连接层。输出层正是前面提到过的 7x7x30 的 tensor,用来预测最终的结果。然后,需要注意的是 YOLO 将定位和目标分类统一成了一个回归问题。
30维向量
具体来看每个网格对应的30维向量中包含了哪些信息。
① 20个对象分类的概率
因为YOLO支持识别20种不同的对象(人、鸟、猫、汽车、椅子等),所以这里有20个值表示该网格位置存在任一种对象的概率。可以记为
之所以写成条件概率,意思是如果该网格存在一个对象Object,那么它是Ci的概率是
② 2个bounding box的位置
每个bounding box需要4个数值来表示其位置,(Center_x,Center_y,width,height),即(bounding box的中心点的x坐标,y坐标,bounding box的宽度,高度),2个bounding box共需要8个数值来表示其位置。
③ 2个bounding box的置信度
bounding box的置信度 = 该bounding box内存在对象的概率 * 该bounding box与该对象实际bounding box的IOU
用公式来表示就是
YOLO 的训练并不复杂,其中最重要的内容就是 Loss 的设定。
1.预训练
取 YOLO 模型前面的 20 个卷积加上 1 个全连接层在 ImageNet 上训练,也就是为了目标识别,目的是为了获取目标的特征表达能力。
2. 目标检测训练
在具体的图像识别中,一个 Object 可能覆盖很多个 Cell。我们还需要从中选择一个 Cell,作为代表,这个 Cell 就负责(responsible)此 Object 的预测。
比如上面的图,狗的 groundtruth 覆盖了总共 15 个 Cell,那么哪个 cell 负责这条狗呢?
答案就是上图标示出来的 cell。为什么是它呢?
原则只有 1 个:Object 的中心落在哪个 cell,就决定了那个 cell 的核心地位。
目标检测训练在预训练的基础上增加了 4 个卷积层和 2 个全连接层。另外,为了归一化的效果,对于之前预测的 bbox,YOLO 也做了特别的处理。一般,我们讲 bbox 中的 4 个参数 (x,y,width,height) 指的是下图所示:
YOLO 做了调整。X,Y 在预测的 bbox 中代表框的中心点位置,并且是相对于 Cell 中心点的偏移比例,取值是 0 到 1 之间。可能难以理解,图例说明。
上图中某个 cell 预测了一个 bbox。
黄色的原点代表 cell 的中心。
红色的圆圈代表 bbox 的中心。
那么 x,y 的取值就是两个中心的偏移量和 cell 本身宽高的比值。
另外 bbox 包含的 w,h 也是一个归一化的结果。是 bbox 的宽高和整张图片的宽高的比值。所以,w,h 同样取值为 0 到 1。
讲完 bbox 的 4 个参数,再回到训练上来。YOLO 的激活层除了最后一层外都是采用 ReLu。
YOLO 用误差平方和(SSE) 进行优化,论文作者说因为这样比较简单。
但是 YOLO 的 Loss 由 4 个子 Loss 构成,也是这部分比较难以理解的一部分。
公式很长,慢慢分析其实也还行。
首先 Loss 要计算:
前面讲到一张图片产生 49 个 cell,有些 cell 没有什么意义,因为它们不包含任何的 Object。
所以,计算 Loss 时就只考虑有 Object 存在的 cell。
下标 i 代表 cell 的序号,下标 j 代表这个 cell 的第 j 个 bbox。
这行 Loss 就是所有的存在目标的 cell 中所预测的 bbox 中心点的 SSE。
前面的 λcoord是权重,为什么要加这个权重呢?
SSE 导致了 bbox 的定位和分类问题权重一样,并且那些没有包含物体的 cell ,它们的 confidence 是 0,这会导致训练过程中,梯度变化不平衡,整个模型变得不稳定。
为了解决这个问题,所以引入了两个λ 分别代表有 object 和没有 object 的权重。
这两个权重是惩罚项,代表不同的内容对于整个优化过程的贡献度。
另外注意到计算 bbox 宽高的 Loss 时。
为啥是平方根的差呢?
因为 bbox 对于尺寸敏感度很高。第2行宽度和高度先取了平方根,因为如果直接取差值的话,大的对象对差值的敏感度较低,小的对象对差值的敏感度较高,所以取平方根可以降低这种敏感度的差异,使得较大的对象和较小的对象在尺寸误差上有相似的权重。
所以,用平方根就是为了缩短这种差距。
为此,我们可以对 Loss 总结如下:
YOLO算法的优点: 1、YOLO的速度非常快。在Titan X GPU上的速度是45 fps(frames per second),加速版的YOLO差不多是150fps。2、YOLO是基于图像的全局信息进行预测的。这一点和基于sliding window以及region proposal等检测算法不一样。3、与Fast R-CNN相比,YOLO在误检测(将背景检测为物体)方面的错误率能降低一半多。4、准确率高,有实验证明。
YOLO算法的缺点: 因为一个 cell 只能预测一个类别,所以如果比较小的物体成群出现,会导致许多的 object 的中心点其实在一个 cell 中,那么就会出现漏检。