小言_互联网的博客

死磕YOLO系列,YOLOv1 的大脑、躯干和手脚

531人阅读  评论(0)

系列文章:
死磕YOLO系列,YOLOv2的自我修养
YOLO 是我非常喜欢的目标检测算法,堪称工业级的目标检测,能够达到实时的要求,它帮我解决了许多实际问题。


这就是 YOLO 的目标检测效果。它定位了图像中物体的位置,当然,也能预测物体的类别。

之前我有写博文介绍过它,但是每次重新读它的论文,我都有新的收获,为此我准备写一个系列的文章来详尽分析它。这是第一篇,从它的起始 YOLOv1 讲起。

YOLOv1 的论文地址:https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Redmon_You_Only_Look_CVPR_2016_paper.pdf

建议没有看过原论文的都应该好好看看。

YOLO 预测时,很简单。

1.缩放输入的图片
2.将图片送入到卷积神经网络中进行预测
3.通过预测的结果进行置信度的阈值处理,得到最终的结果。

本文围绕:

  1. YOLO 为什么能检测目标?
  2. YOLO 长什么样子?
  3. YOLO 如何训练?

三大问题来详细展开,为此我类比为 YOLO 的大脑、躯干和手脚。

1. 大脑,为什么能检测目标?

YOLO 是 One-Stage (单阶段) 检测算法,它只需要看图片一次,就可以预测图片中所有的物体边框。

我个人有一个形象的比喻,那就是撒渔网。

一个渔网撒下去,所有的鱼儿都要捕获。

而实际上,YOLO 真的有类似渔网的操作。

YOLO 把一张图片划分成了 SxS 个格子。

这里的 S 不固定,可以根据实际情况由开发者自主决定。


论文中,S 取值为 7,所以整张图片被分割成 7*7=49 个格子(Cell)。

这些格子像不像渔网的网眼呢?

那么,这些 Cell 是干什么用的呢?为什么要设置这么多的 Cell ?

这些 Cell 每个 Cell 都会预测 B 个 bbox。在论文中 B 取值为 2。

所以,一张图片经 YOLO 跑一遍,就会产生 98 个 bbox。


有同学可能会思考:

这么多 bbox,比目标的个数还要多,怎么选择呢?

以上面的图片为例:


图片中有狗、自行车、汽车 3 个目标,但是预测到的 bbox 有 98 个之多,最终肯定只能从 98 个 bbox 中选择 3 个。

那么,怎么操作呢?

分 2 步走。

第一步,有选择的响应 cell。

总共有 49 个 cell,但是并不是每一个 cell 的预测都有意义,我们需要找出有意义的 cell。

那么哪些 cell 算是有意义呢?

先来看看一个叫做 Confidence 可信度的概念。

每个 Cell 预测 B 个 bbox,还有每个 bbox 对应的 Confidence。

Confidence 公式定义如下:
C o n f i d e n c e = P r ( O b j ) ∗ I O U p r e d t r u t h Confidence = Pr(Obj)*IOU_{pred}^{truth} Confidence=Pr(Obj)IOUpredtruth

其中 P r ( O b j ) Pr(Obj) Pr(Obj) 取值只有 0 和 1 两种可能性,代表一个 cell 中是否存在物体。

下面对这个概念详细解释一下。

假设:我们要检测的目标只有狗、汽车、自行车 3 种,那么其他的物体都被当成背景。


在上面的图片中,00,01,02 这些 cell 不包含任何的目标,所以它们的 P r ( O b j ) Pr(Obj) Pr(Obj) 为0,所以 Confidence 也为 0.

10 和 20 两个 cell 因为包含了自行车的一部分,所以它们的 P r ( O b j ) Pr(Obj) Pr(Obj) 为 1,它们的 Confidence 实质上就是 bbox 和 groundtruth 的 IOU。

另外怎么判断某个 cell 中有没有包含 Object 呢?

这其实是通过 label 中的 groundtruth 在线算出来的。

因此,一张图片经过 YOLO 跑一遍后,除了预测出 98 个 bbox,还会给出 49 个 cell 的 confidence.

所以,那些 confidence 不为 0 的 cell 都算作有意义。

不过,还可以更进一步。

一个 Object 可能覆盖很多个 Cell。

我们还需要从中选择一个 Cell,作为代表,这个 Cell 就负责(responsible)此 Object 的预测。


我们看上图。

狗的 groundtruth 覆盖了总共 15 个 Cell,那么哪个 cell 否则这条狗呢?


答案就是我上图标示出来的 cell。

为什么是它呢?

原则只有 1 个:Object 的中心落在哪个 cell,就决定了那个 cell 的核心地位。

很好理解嘛,一个国家最高的机构落地的城市,就是首都。

再往下走。

每个 Cell 还会预测 C 个类别的概率。

这是条件概率。

P r ( C l a s s i ∣ O b j e c t ) Pr(Class_{i}|Object) Pr(ClassiObject)

如果一个 Cell 存在 Object,预测这个 Object 的 class 才有意义。

在测试阶段,这个条件概率还要与 Cell 的 Confidence 相乘。

它的公式表达了两个思想:

  1. 类别的概率
  2. 预测的框距离 groudtruth 有多接近

需要注意的是,每个 Cell 输出的是一组概率,代表了 C 个类别的概率,在论文中 YOLO 的 C 取值为 20.

所以,YOLO 最终就是通过下图的方式来预测的。

它的本质是因为 YOLO 模型的最后一层是一个 7x7x30 的 tensor。

7x7 对应图像分割成 49 个 cell。

30 包含了 2 个 bbox 的数据,及 20 个 class 的概率。


以上,就是 YOLOv1 目标检测的核心思想,它能检测就是基于上面的思路。

2.躯干,长什么样子?

我指的躯干其实就是 YOLO 的神经网络结构。

这部分比较简单,我将快速略过。

原论文中说到,YOLO v1 的模型结构受 GoogLeNet 启发。

但是,有少许不同。

YOLO 采用了 1x1 和 3x3 的序列组合替代 Inception 模块。

总共 24 个卷积层加上 2 个全连接层。

输出层正是前面提到过的 7x7x30 的 tensor,用来预测最终的结果。

然后,需要注意的是 YOLO 将定位和目标分类统一成了一个回归问题。

3. 手脚,如何训练

YOLO 的训练并不复杂,其中最重要的内容就是 Loss 的设定。

1. 预训练

取 YOLO 模型前面的 20 个卷积加上 1 个全连接层在 ImageNet 上训练,也就是为了目标识别,目的是为了获取目标的特征表达能力。

2. 目标检测训练

在 pretrain 的基础上增加了 4 个卷积层和 2 个全连接层。

因为目标检测任务的训练一般对图像分辨率精细度要求比较高,所以,在这以阶段,输入图像的尺寸从之前 ImageNet 需要的尺寸 224x224,变成了 448x448。

另外,为了归一化的效果,对于之前预测的 bbox,YOLO 也做了特别的处理。

一般,我们讲 bbox 中的 4 个参数 (x,y,width,height) 指的是下图所示:


YOLO 做了调整。

X,Y 在预测的 bbox 中代表框的中心点位置,并且是相对于 Cell 中心点的偏移比例,取值是 0 到 1 之间。

可能难以理解,图例说明。


上图中某个 cell 预测了一个 bbox。

黄色的原点代表 cell 的中心。
红色的圆圈代表 bbox 的中心。

那么 x,y 的取值就是两个中心的偏移量和 cell 本身宽高的比值。

x = (bbox.x-cell.x)/cell.width
y = (bbox.y - cell.y)/cell.height

另外 bbox 包含的 w,h 也是一个归一化的结果。是 bbox 的宽高和整张图片的宽高的比值。

所以,w,h 同样取值为 0 到 1。

w = bbox.width / image.width
h = bbox.height / image.height

好,讲完 bbox 的 4 个参数,再回到训练上来。

YOLO 的激活层除了最后一层外都是采用 ReLu。

YOLO 用误差平方和(SSE) 进行优化,作者说因为这样比较简单。

但是 YOLO 的 Loss 由 4 个子 Loss 构成,也是最难以理解的一部分。


公式很长,慢慢分析其实也还行。

首先 Loss 要计算:

  • 中心点的 Loss
  • 宽高的 Loss
  • 置信度的 Loss
  • 目标类别的 Loss

前面讲到一张图片产生 49 个 cell,有些 cell 没有什么意义,因为它们不包含任何的 Object。

所以,计算 Loss 时就只考虑有 Object 存在的 cell。

这也是下面的符号代表的意义。

1 i j o b j 1_{ij}^{obj} 1ijobj

下标 i 代表 cell 的序号,下标 j 代表这个 cell 的第 j 个 bbox。

这行 Loss 就是所有的存在目标的 cell 中所预测的 bbox 中心点的 SSE。

前面的 λ c o o r d \lambda_{coord} λcoord 是权重,为什么要加这个权重呢?

这个需要细致说一下。

SSE 导致了 bbox 的定位和分类问题权重一样,并且那些没有包含物体的 cell ,它们的 confidence 是 0,这会导致训练过程中,梯度变化不平衡,整个模型变得不稳定。

为了解决这个问题,所以引入了两个 λ \lambda λ 分别代表有 object 和没有 object 的权重。

这两个权重是惩罚项,代表不同的内容对于整个优化过程的贡献度。

另外有人注意到计算 bbox 宽高的 Loss 时。

为啥是平方根的差呢?

因为 bbox 对于尺寸敏感度很高。


假设上图两组 bbox 预测与真值比对结果中,w 这一维度的结果都是 0.2.

但是左右两组对于这个数值敏感度是不一样的,我们可以看到,右边那组小尺寸的更加敏感。

所以,用平方根就是为了缩短这种差距。

为此,我们可以对 Loss 总结如下:

  • 计算有物体的 Cell 的 bbox 中心点、宽高、物体类别的 Loss
  • 计算所有 Cell 的 Confidence 的 Loss,但是无 Object 的 Cell 它的 Loss 权重很低
  • 相对于物体类别,bbox 定位的权重要更高。

Loss 讲完后,YOLO 就差不多讲完了,接下来快速陈述一下它的训练过程。

训练过程

在 PASCAL VOC 2007 和 2012 训练和验证,总共 135 epochs。

batch size 是 64.
momentum 是 0.9
decay 是 0.0
  1. 第一个 epoch ,学习率缓慢从 0.001 到 0.02.
  2. 以 0.02 训练 75 个 epochs。
  3. 以 0.001 训练 30 个 epochs。
  4. 以 0.0001 训练最后 30 个 epochs。

为了防止过拟合,采用了 dropout 技术,比率为 0.5.

另外还做了数据增强。

YOLO 的局限性

因为一个 cell 只能预测一个类别,所以如果比较小的物体成群出现,会导致许多的 object 的中心点其实在一个 cell 中,那么就会出现漏检。

下一步

学完 YOLOv1 只是第一步。

下一步建议你将 YOLOv2 和 YOLOv3 也学习。

另外,你可以根据你的理解用 Tensorflow 或 Pytorch 复现或者仿照一个 YOLO 网络。


转载:https://blog.csdn.net/briblue/article/details/103149407
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场