YOLOv1详解:从那只狗开始...

前言

在学习YOLO之前,请务必要有一定图像分类的深度学习基础,从LeNet到ResNet,基本就可以了,如果你还没学可以去学一下哦(本博客中也有滴)

背景

论文:[1506.02640] You Only Look Once: Unified, Real-Time Object Detection

YOLO全称 You Only Look Once(你只看一眼),是Joseph Redmon大神在2016年提出的目标检测方法,开创了“一眼看全图”的新时代。

主要在于,快且准,他是单阶段,检测到目标位置的同时分类。区分于先检测出物体,再进行分类的R-CNN,Fast-RCNN。

网络结构

大致看看

先大致看看结构图

….好像和前面学的LeNet, AlexNet没啥区别呢,都是(卷积, 池化, … , 全连接层),就是最后有一块不认识的东西,似乎换成Softmax就可以用来图像分类了??

没错,前面的本质上就和之前学习的图像分类的处理差不多,最后的结果就可以用来做检测,所以本文最重要的就是来拆解这个块块。

另外,yolo的输出是前面四个确定框框在哪、多大,后面两个分别是置信度和概率。

细看

一些小细节:

  • 最后一层(输出层) 也就是的那个全连接层使用了线性激活函数以外,其余层均为Leaky ReLU激活函数
  • 训练中使用了Dropout与数据增强的方法来防止过拟合。参数太多了
  • 对于最后一个卷积层,它输出一个形状为(7, 7, 1024)的张量。然后张量展开,使用2个全连接层作为一种线性回归的形式,它输出1470个参数,然后reshape为(7, 7, 30)。

参数

利用公式就可以推算出结果。

结果

怎么来的

结果最后映射到原图的49个区域(grid cell),每个区域是的向量。

对于每个grid cell:

  1. 如果某个物体的中心落在该网格中,那么这个网格就负责预测这个物体
  2. 预测B个边界框(bounding box)(在yolov1中选择2个边界框作为预测结果)。因为可能会多个物体中心落在一个格子中
  3. B个边界框中,每个边界框包含5个元素,分别为,中心坐标:x, y;检测框的宽和高:w, h;对应检测框的置信度c
  4. 每个网格,还要预测C个类别的分数,也就是概率p
  5. 所以这里是

结果解析

将结果中的展现在上图中

先看左图

基准:大红色框代表grid cell,蓝色点表示该grid cell的左上角坐标,为(0, 0);

结果:

  • 深红色和绿色框代表该grid cell包含的两个bounding box,深红点和绿色点表示这两个bounding box的中心坐标(bounding box的中心坐标一定在该grid cell内部)。
  • x, y坐标值为归一化后的坐标值,在0-1之间,以当前grid cell的左上坐标(0, 0)为参考。因此,绿色边界框的坐标为(0.5, 0.5)。深红色边界框的坐标为(0.35, 0.85)。

再看右图

  • w, h:是指该bounding box的宽和高,也归一化到了0-1之间,表示相较于原始图像的宽和高(即448个像素)。
  • 图中的bounding box预测的框宽为w=0.43,高为h=0.40。

一个小概念,

全称交并比(Intersection Over Union),通过这个名称我们大概可以猜到IOU的计算方法。计算的是“预测的边框”和“真实的边框”的交集和并集的比值。,当时,代表两个框没有交集;当时,代表两个框重合。

在目标检测任务中,用于匹配预测的边界框(bounding box)和真实的边界框。通过计算两者之间的,可以判断预测是否正确地检测到了目标。同时在非极大值抑制(NMS)计算中作为其中的重要指标。

一个小概念,置信度,也就是中的

置信度作用定义有两重:

  1. 代表当前box是否有对象,这个概率值为1或者0,注意,这里是对象,不是某个类别的对象,也就是说它用来说明当前box内只是个背景(backgroud)还是有某个物体(对象)
  2. 表示当前的box有对象时,它自己预测的box与物体真实的box之间的交并比,注意:这里所说的物体真实的box实际是不存在的,这只是模型表达自己框出了物体的自信程度。 因此此时置信度的公式为:
  • 训练时,我们是有真实的框的,所以逻辑很顺畅。
  • 预测时,没有真实的框,不需要计算公式,直接读取网络输出的中的这个值。这个是神经元计算出来的,已经经过成百上千训练的不断迭代,各种参数能保证他的准确性。
    • 当它前面的卷积层传来“这里像是一片蓝天”的信号时,它的权重参数会让它输出一个接近 0 的值。
    • 当它前面的卷积层传来“这里有狗头纹理”的信号时,它的权重参数会让它输出一个接近 1 的值。

当然越形象就越偏离正确过程,这里是帮助理解的例子。

最后是里面的概率

每个grid cell都会有20个概率,这个概率是通过进行映射得到的,维度为,最后会取最大值作为该grid cell的概率结果,如下图

到这里,如果你突然对置信度和概率有点混淆,那就正好,这里来分辨一下:

一句话:置信度对应框,概率对应类别;;;后面筛选目标会用到一个类别置信度,就在预测时筛选的第二步。

前面我们说过,YOLO,即You Only Look Once,只看一眼就可以检测到目标位置的同时分类,好像还真是。

损失函数

分成一块一块来看

首先我之前没见过这个 𝟙,那就先来看这个吧。是一个指示函数。 这里 𝟙 的意思是:第 i 个网格的第 j 个预测框是否负责预测该物体? 注意是以框为单位不是以grid cell为单位 值为 1 的条件(同时满足):

  1. 真实框的中心点落在这个网格  中。
  2. 这个预测框  是该网格两个框中与真实框 更大的那个。
  3. 也就是不止限制grid cell,还只取一个框。其余情况均为0。

𝟙 的意思是,和 𝟙 包含的情况取反,当第i个网格的第j个预测框补负责预测该物体时,为1,否则为0。

我们先称 𝟙时的框为正样本,𝟙时的框为负样本。注意是以框为单位不是以grid cell为单位

然后看出现很多次的,这个我第一直觉是双重循环遍历??还真有点这个意思,就是“外层循环“遍历grid cell,“内层循环“遍历该grid cell的bounding box

之后看那个,意思是,我们要遍历所有可能的类别(比如 VOC 数据集有 20 类),把每一类的预测概率误差(平方差)都加起来。

我们还发现有两个参数:

在一张图片中,绝大多数网格都是背景(负样本)。如果不加控制,这些负样本的 Loss 会淹没掉少数正样本的 Loss,导致网络学不到东西。 解决方案:YOLOv1 给负样本的置信度 Loss 乘了一个很小的权重 同时:为了让框更准,给坐标 Loss 乘了一个大的权重。因为只有正样本可以有坐标 Loss 嘛。

现在分别来看三个损失,普通的就说了,通过上面的符号解析也能很轻松看出来:

坐标损失:有一个开根的操作,为什么呢,其实是模拟一个真实情况,看下图

对于小目标和大目标,当偏移相同距离(即)时,小目标误差应该大一些,如果不开根直接做差,那是一个一次函数,小目标误差和大目标误差一样,明显是不对的。所以这里进行一个开根,看上图中,发现误差这就对了。

置信度损失:当 𝟙时,也就是认为该框内没有物体,就将该真实值设为0;当 𝟙时,就用来计算就好了。 当然你可能会问:为什么当 𝟙时不把真实值设为1呢,我也不知道,不过后来可能发现设置为1更好,所以在Yolov2v3的时候,是将真实值设为1,而不是使用了。不过v3后面好像又改了,这个了解就好。

类别损失:这个没啥好说的

怎么筛选出目标

大概计算一下,发现应该是个框框呀,为什么常见到的yolo预测出来的结果图都是精准的一个或几个框框??

Thinking…..

分为训练时和预测时:

训练时:

我们手中有真实的框,所以就分为了两类grid cell,一种是真实框的中心落到grid cell的(正样本),另一种是没落到grid cell的(负样本)

对于正样本,有两个框,选出一个大的框当作正样本,另一个依旧按照负样本来算,计算,并进行反向传播

对于负样本,不计算坐标误差类别误差,因为框里面没东西呀。对于置信度误差就是正常用公式计算就好,其,所以,之后进行反向传播。也就是负样本并不是不处理,而是告诉他反馈,并让他修整,之后用来预测的时候,基本就会在第一步置信度筛选的时候被筛选掉。

预测时:

这是由于98个框经过了筛选和后处理,大致为三步:

一、根据置信度来进行筛选

每个预测框(Bounding Box)都包含一个置信度分数 (Confidence Score)。这个分数由网络预测,代表两层含义。

  1. 框里有物体的概率 。(有=1, 无=0)
  2. 框的位置准不准 (预测框与真实框的 )。

我们可以设定一个阈值,比如0.1。框的置信度分数低于这个阈值,直接扔掉

二、根据类别分数筛选

Yolov1中,每个网格(grid cell)预测了一组类别概率 。最终每个框针对特定类别的得分是这样计算的:也就是:框的置信度 × 类别概率,这个就是类别置信度

所以,如果一个框虽然置信度很高(觉得有东西),但是算出来的“是狗的概率”、“是猫的概率”都很低,那么它也会被过滤掉。

三、非极大值抑制 (Non-Maximum Suppression, NMS)

经过前两步,虽然过滤掉了很多背景框,但对于同一个物体(比如那只狗),往往会有多个框保留下来。

  • 有的框只框住了狗头。
  • 有的框偏左了一点。
  • 有的框是最佳的。

我们既然要检测目标,这时候就需要 NMS 来去除重复的框,只保留最好的那一个。

NMS 的逻辑是这样的:

  1. 排序: 把所有剩下的框,按照类别置信度从高到低排列。
  2. 选高分: 取出类别置信度最高的那个框(假设是框 A),把它作为最终保留的“赢家”。
  3. 筛低分: 拿框 A 去和后面所有的框比较。如果后面的某个框 B 和框 A 的重叠度(IoU)很高(比如超过 0.5),我们就认为框 B 和框 A 预测的是同一个物体,既然框 A 分数更高,那框 B 就是多余的,直接删掉框 B。
  4. 循环: 对剩下的没被删除的框堆,重复上述过程,直到所有框堆都被处理完。

训练过程

分两个阶段:分类和检测

第一阶段:在ImageNet分类数据集上预训练分类模型。首先将yolov1的模型转化为分类模型;利用前20卷积作为模型的特征提取网络。随后利用全局平均池化层进行池化操作,随后利用全连接层进行1000分类。此时模型的输入为224x224,对该网络进行了大约一周的训练,并在ImageNet2012验证集上实现了单个作物前5名的准确率达到88%,与传统的图像识别方法相当。

第二阶段:将网络的输入调整为448x448。并将模型调整为检测模型,那么此时检测模型的参数如右图所示,及去除全局平均池化加入4个卷积层和两个全连接层,最后将模型的输出调整为7×7×30这样的向量大小。在分类模型参数上继续finetune网络(135轮)

优势和局限

优势:

YOLO非常快,因为将物体检测定义为回归问题, 所以检测也不需要复杂的组件。 YOLO基于全图进行检测,所以不像滑动窗口和预 选区技术,YOLO中隐含着隐式编码的上下文信息。

局限:

群体小目标:因为一个网格只能预测 2 个框且只能属于 1 个类别,所以如果两个物体靠得很近(比如一群鸟),YOLOv1 效果很差。 泛化能力:对长宽比不常见的物体检测效果一般。 定位误差:由于直接回归坐标,相比于 R-CNN 系列的 Anchor 机制,定位不够精准。

代码

我目前暂未实现,贴一个别人的 PyTorch 实现:abeardear/pytorch-YOLO-v1: an experiment for yolo-v1, including training and testing.

Reference