描述

这篇文章为Yolo系列开个篇,介绍YOLO-v1的算法。

Abstract

YOLO,将目标检测转化为了一种回归问题,直接回归出对象的边界框和相关概率。将完整图像输入网络,直接可以得到预测的边界框和类别概率,因此可以端到端进行优化。YOLO的运行速度很快,基本模型可以每秒45帧,Fast YOLO版本可以每秒处理155帧。但是YOLO也误差也会更大,背景上的一些正样本有可能误检。

1. Introduction

人类瞥一眼图像,就可以知道图像有什么物体,它们在哪,它们是什么关系。类似R-CNN的方法,会利用region proposal(区域候选)的方法在图像中生成潜在的边界框,然后在这些框上运行分类器,分类后再后处理来细化边界框,消除重复框,并根据场景中的其他对象对检测框进行重新评分。这种方法是很慢的,且难以优化。

作者利用YOLO,可以将目标检测任务重新定义为单一的回归问题,输入图像,直接得到检测框和概率。YOLO的效果就像下图一样。

YOLO的优点:

1.运行快,模型简单

2.YOLO的输入是整张图像,而强如RCNN可能错误得将背景patch当做对象

3.YOLO通用性好,网络学习的是对象的通用特征,在自然照片上的网络训练结果也可以在美术图像上去用

2. Unified Detection统一检测

YOLO网络使用整个图像的特征来预测每个边界框,输入一幅图像,预测图像中的出现的所有类别,预测所有对象的边界框。(说是这么说,但是YoloV1有明显的缺点)

模型结果的tensor尺寸是(S×S×(B×5+C)),图像划分为S×S个格子,每个格子都预测B个检测框出来,每个框有5个值(这个检测框的概率p,中心点x,中心点y,宽度w,高度h),每个格子还包含一个维度为C,代表这个格子有什么对象的类别特征。作者在PASCAL VOC数据集上评价提出的Yolo,选取S=7,B=2,而PASCAL VOC有20个类别,所以YoloV1预测的是一个(7×7×30)的张量

每个检测框的置信度,代表了:模型对这个检测框里是否包含一个对象的置信度,以及模型对这个检测框预测是否准确的置信度。所以,作者这样定义每个检测框的置信度P = P_r(Object)*IOU^{truth}_{pred}。如果检测框里没有对象,P_r(Object)就是0,P其实也就是0;如果有障碍物,P=IOU^{truth}_{pred},我们希望这个概率值能够表示检测框和对象真值框的IOU。(解释:如果概率值为0,模型认为这个检测框没有障碍物;概率值比如是0.6,模型认为这个检测框与这个位置潜在的真值障碍物,IOU是0.6;概率值比如是0.99,模型认为IOU是0.99。显然后期我们可以设置阈值,比如0.5,来过滤一些连模型都认为不准确的预测框

每个检测框预测的结果x、y、w、h都是(0,1)之间的

x,y代表中心点的位置,比如格子是16个像素×16个像素的。这个格子左上角(x,y)就是(0,0),右下角(x,y)就是(1,1)。中心位置,比如是这个格子的U方向的4个像素位置,V方向的2个像素位置,(x,y)就是(0.25,0.125)。整个检测框预测出的宽度和高度,除以整个图像的宽度和长度,就是(w,h)。换句话说,预测出的检测框中心位置必须在格子中,宽度和高度都可以超过格子。

每个格子还会预测C个类别条件概率,代表这个格子包含对象时的条件概率。每个格子都预测一组类别概率,而与检测框的个数B无关。一个格子的某个检测框,特定某个类的置信度,要如下计算:(实际上就是,类别的概率还要乘以检测框置信度,从而得到某个检测框的某个类,置信度究竟是多少)

每个格子预测一个类别,如果这个格子同时有猫有狗,显然YoloV1解决不了这个问题。

YoloV1模型图如下

注意图中,class probability map划分后每个格子的颜色是单一的。一个格子,类别最终分类也只能是唯一的>

2.1 Network Design

YoloV1的网络结构如下

2.2 Training

采用Leaky Relu函数

输出模型用的是平方和误差,因为平方和误差很容易优化。但是平方和误差也并不完全符合网络需要最大地提升平均精度的这一目标。分类错误的定位误差被平等地加权处理,这样做不是理想的。此外,在每个图像中,许多网格单元不包含任何对象。将这些网格单元的“置信度”分数向零去收敛(原文用了“push”),也会同时过度影响包含对象的格子的梯度。这可能导致模型不稳定,导致训练在早期发散。为了解决这个问题,我们增加了边界框坐标预测的损失,并减少了不包含对象的框的置信度预测的损失。我们使用两个参数 λ_{coord}λ_{noobj} 来实现这一点。我们设置 λ_{coord}=5λ_{noobj}=0.5。(也就是说,作者在计算Loss Function时用不同的权重,用大权重处理有对象时的格子的预测损失,用小权重处理没对象时格子的预测损失

平方和误差也平等地加权了,大检测框和小检测框中的错误。我们的误差度量应该反映出大检测框的小偏差,应该比小检测框的小偏差小。为了部分解决这个问题,我们直接预测边界框宽度和高度的平方根,而不是直接预测宽度和高度。(作者在计算Loss Function时,宽度和高度都要开平方处理

YOLO 在每个网格单元会预测出多个边界框。在训练时,我们只希望每个对象只分配一个边界框预测器来负责。分配规则是:这个检测框与这个对象ground truth的检测框的IOU,比其他检测框的IOU都要高。这样可以令边界框预测器更“专业化”。每个预测器在预测对象的某些大小、横宽比或类别方面做得更好,提高了整体召回率。(每个格子虽然预测了B个检测框,作者希望在训练过程中,有意的让不同的检测框去学习不同对象。比如作者提出的B=2,也就是2个检测框。比如我们在训练一张包含小狗的图片,网络输出后的检测框1和检测框2,假设检测框1与ground truth标注的狗IOU更高,那么这一次学习网络在计算损失时检测框1来负责这个对象,参与计算损失)

经过学习,在yoloV1也许会发生这样的现象:第1个grid中的检测框1是负责预测狗,同时第4个grid中的检测框2是负责预测狗的。产生这种现象的原因是,并没有事先规定ground truth的编码规则,也就是并没有事先将训练图像的ground truth编码成固定格式,比如检测框1负责狗,检测框2负责猫。而是通过训练时,自己去计算IOU的方式,比较哪个IOU更大,来确定该类别在这个网格由哪个检测框预测的。

YoloV1的损失函数

式子中I_i^{obj} 代表如果第i个网格包含了对象,I_{ij}^{obj} 代表了第i个格子的第j个检测框负责预测这个对象。

式子中的1^{obj}_{i},代表当ground truth图像第i个网格里有对象时,它的值是1,没有对象时它的值是0。式子中的1^{obj}_{ij},代表当第i个网格的第j个检测框负责类别obj这个对象。当ground truth图像第i个网格存在对象obj时,算第j个检测框时它是1,其他检测框它是0。

我们来理解一下这个损失函数

损失函数一共有五项,每一项都有\sum\limits_{i=0}^{s^2},代表了对每个格子的单独损失求和,所以接下来我们只分析一个格子。 假设某一个训练后我们得到了(S×S×(B×5+C))这个张量。我们随便找一个格子,拿到它的(B×5+C)这个张量。我们假设它这个张量,它的某个检测框j是负责检测类别为obj这个障碍物的。如果gound truth中,真的有某个obj类别的对象中心在这个格子内。

第一项,检测框j的loss值是\lambda_{coord}[(x_i-\hat{x_i})^2+(y_i-\hat{y_i})^2]有意义,惩罚检测框j做出的中心点预测,加倍惩罚。其他检测框的loss值都是0;

第二项,检测框j的loss值是\lambda_{coord}[(\sqrt{w_i}-\sqrt{\hat{w_i}})^2+(\sqrt{h_i}-\sqrt{\hat{h_i}})^2]有意义,惩罚检测框j做出的宽高预测,加倍惩罚。其他检测框的loss值都是0;

第三项,检测框j的loss值是(C_i-\hat{C_i})^2有意义,惩罚检测框j做出的置信度p预测,正常惩罚。其他检测框的loss值都是0;

第四项,检测框j的loss值是为0,因为该格子的ground truth存在对象obj。其他检测框的loss值是\lambda_{noobj}(C_i-\hat{C_i})^2,缩小惩罚;

第五项,跟检测框id无关,loss值为\sum\limits_{c\in{classes}}(p_{i}(c)-\hat{p_{i}(c)})^2有意义,惩罚整个格子i做出的类别预测,20个类别概率逐项相减再求平方和,正常惩罚;

损失函数,在试图学习这样的关系,举例子:一幅训练图片,一个格子已经被标注成了狗(包含x,y,w,h)。如果检测框1和这个狗的真实标签IOU更大,那么检测框1需要负责狗的检测。那么网络在这个格子做出的2×5+20的预测值,其中的检测框1做出的x、y、w、h,p都需要算损失,检测框2做出的p需要算损失,20个类别需要算损失,用权重来平衡它们的影响大小。这样训练下来,这个格子的检测框1被数据教导成,它一定要对狗进行准确的位置和宽高预测,而检测框2被教导成,一定不要检测狗出来(概率值在训练时被惩罚了)但仅仅是这个格子,由于网络的初始化情况不同,在另外一个格子也许情况相反,是由检测框2负责预测狗的。

2.4 YoloV1的缺点

YoloV1对边界框预测施加了很强的空间约束,因为每个网格单元只预测两个框,只能属于一个类别。这种空间约束限制了模型可以预测的附近对象的数量。因此,识别不了群体中的小物体,例如鸟群

由于模型是从数据中学习预测边界框,因此它很难预测出新的或宽高比很奇怪的对象。模型使用比较粗糙的特征提取来预测边界框,因为架构包含了多个下采样层。

最后,虽然作者用了能够近似表示检测性能的损失函数来训练,但损失函数在小边界框和大边界框中,对待错误的处理方式相同(都是开根号运算而已)。大框中的一个小错误没多大影响,但小框中的一个小错误对 IOU 的影响要大得多。因此YoloV1的另一个缺点是定位效果差

总结

YoloV1网络的简单描述:搭建网络后,每一次网络输出(S×S×(B×5+C)),确定2个检测框哪个与ground truth的IOU更大,然后再计算这次的损失。网络训练结束后,预测也是输出这样的(S×S×(B×5+C))​,经过非极大值抑制就可以得到最后的检测结果了。

由于YoloV1只是最初的版本,后面的版本会更优,所以这一篇文章着重介绍基本理念,和训练中的损失函数理解。