深度学习之目标检测(六)YOLOv1理论介绍
本章学习 YOLO v1 相关理论知识,学习视频源于 Bilibili,部分参考叙述源自 知乎 。
1. YOLO v1
YOLO v1 原始论文为发表于 2016 CVPR 的 You Only Look Once: Unified, Real-Time Object Detection。在 PASCAL VOC2007 的测试集上达到了 63.4 mAP,在 $448 \times 448$ 的输入图像上的二推理能达到 45 FPS。注意 SSD 是达到了 74.3 mAP 和 59 FPS (300 的输入尺寸),相比于 YOLO v1 而言明显更具有优势。然而想要知道 YOLO 是如何一步一步变强的,就需要从 YOLO v1 开始说起。YOLO v1 网络结构如下所示:
(没有标s意味着默认步距为1)
网络结构借鉴了 GoogLeNet ,24个卷积层,2个全连接层,用1×1 reduction layers 紧跟 3×3 convolutional layers 取代Goolenet的 inception modules 。注意到原始论文中没有交代清楚最后那点展平,全连接,再全连接,再reshape。
关于 YOLO v1 的优势,原文中作者提到:
-
YOLO 很快,因为用回归的方法,并且不用复杂的框架。
- YOLO 会基于整张图片信息进行预测,而其他滑窗式的检测框架,只能基于局部图片信息进行推理。
- YOLO 学到的图片特征更为通用。作者尝试了用自然图片数据集进行训练,用艺术画作品进行预测,YOLO 的检测效果更佳。
1.1 论文思想
首先,YOLO v1 讲一副图像分成 $S \times S$ 个网格 (grid cell),如果某个 object 的中心落在这个网格中,则这个网格就负责预测这个 object。例如在左下 角的图中,将图片分成了 $7 \times 7$ 的网格、如何知道中心在哪里呢?我们从 ground-truth 的标注信息中可以算出来。
第二步呢,每个网格要预测 B 个 bounding box,每个 bounding box 除了要预测位置之外,还要附带预测一个 confidence 值。每个网格还要预测 C 个 类别分数。注意,这个 confidence 值在之前讲解的 Faster R-CNN 和 SSD 中是没有的。这是在 YOLO 系列中独有的一个参数。预测的坐标参数中 (x,y) 就是预测目标边界框中心坐标相对 grid cell 而言的位置(即在 0~1 之间),而预测目标的宽和高则是相对于整个图像尺寸而言的(即在 0~1 之间)。confidence 根据原论文的解释可视为预测的 bounding box 与对应真实目标的 bounding box 的 IoU 和网格中是否有目标 (0和1) 的乘积。即如果网格中有目标,Pr(object) = 1,confidence 就等于 IoU;如果网格中没有目标,则 Pr(object) = 0,confidence 也为 0。
例如使用 PASCAL VOC 数据集,每个网格需要预测的参数是两个 bounding box 及其 confidence 值,以及 20 个类别的分数,共计 30 个值。整体需要预测 $7 \times 7 \times 30$ 个值。其实也就是 $7 \times 7$ 且深度 (通道数) 为 30 的一个矩阵。
注意:在 YOLO v1 中是没有 Anchor 这个概念的。所以网络预测的值直接就是坐标信息。在测试的时候,预测的类别分数乘上 confidence 值就可视为最终的目标类别预测概率。
为什么每个 cell 要预测多个 bounding box? 假设每个格点预测两个矩形框。那么在训练时,见到一个真实物体,我们是希望两个框都去逼近这个物体的真实矩形框,还是只用一个去逼近?或许通常来想,让两个人一起去做同一件事,比一个人做一件事成功率要高,所以可能会让两个框都去逼近这个真实物体。但实际上作者没有这样做,在损失函数计算中,只对和真实物体最接近的框计算损失,其余框不进行修正。这样操作之后作者发现,一个格点的两个框在尺寸、长宽比、或者某些类别上逐渐有所分工,总体的召回率有所提升。最后测试的时候通过使用非极大值抑制来生成预测框。
1.2 损失函数
YOLO v1 的损失分为三部分,第一部分是对于目标 bounding box 的损失,第二部分是 confidence 损失,第三部分是分类损失。原论文中主要都是使用误差平方和来进行计算。
为什么宽和高都要进行开根号处理呢?以下图为例,假设绿色为真实目标边界框,蓝色为预测的目标边界框。假设小物体和大物体预测的偏移是一样的,则对于小目标而言预测结果比较差,而对于大目标而言预测结果还算比较好。所以要提升小目标的损失。如果不取根号,损失函数往往更倾向于调整尺寸比较大的预测框。例如,20个像素点的偏差,对于 $800 \times 600$ 的预测框几乎没有影响,此时的 IoU 数值还是很大,但是对于 $80 \times 60$ 的预测框影响就很大。开根号是为了尽可能的消除大尺寸框与小尺寸框之间的差异。
此外,confidence 损失需要计算正负样本,而 bounding box 以及 class 损失都只计算正样本的。正样本的 confidence 真实值应该为预测框与真实物体框的 IoU 数值;负样本的 confidence 真实值应该为 0。(我觉得这里和 RPN 的感觉很像,或者说将背景的学习融入了 confidence 中去)
最后再来看 $\lambda_{coord}$ 与 $\lambda_{noobj}$,目标检测问题是一个典型的类别数目不均衡的问题。其中 49 个格点,含有物体的格点往往只有几个,其余全是不含有物体的格点。此时如果不采取点措施,正样本被负样本所淹没,那么目标检测的 mAP 不会太高,因为模型更倾向于不含有物体的格点。$\lambda_{coord}$ 与 $\lambda_{noobj}$ 的作用就是让含有物体的格点,在损失函数中的权重更大,让模型更加“重视”含有物体的格点所造成的损失。在论文中 $\lambda_{coord}$ 与 $\lambda_{noobj}$ 取值分别为 5 与 0.5。
1.3 YOLO v1 存在的问题
第一个问题是,对于群体性的小目标检测效果很差,例如一群鸟飞过去。因为 YOLO v1 对于每个 cell 只预测两个 bounding box,而且这两个 bounding box 都是属于同一个类别的。因为对于一个 cell 只预测一组类别参数,所以应该是同一个类别的目标。所以当一些小目标集中在一起时,YOLO v1 的检测性能就很差。
第二个问题是,当目标出现的新的尺寸或者配置的时候,YOLO v1 的检测性能也很差。
最后一个问题是,作者发现主要的问题都源自于定位不准确。这也是源于作者直接预测目标的坐标信息,而不是像 Faster R-CNN 和 SSD 一样预测相对 Anchor 的回归参数。所以从 YOLO v2 开始就会基于 Anchors 进行回归预测。