系列文章:
死磕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.通过预测的结果进行置信度的阈值处理,得到最终的结果。
本文围绕:
- YOLO 为什么能检测目标?
- YOLO 长什么样子?
- 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(Classi∣Object)
如果一个 Cell 存在 Object,预测这个 Object 的 class 才有意义。
在测试阶段,这个条件概率还要与 Cell 的 Confidence 相乘。
它的公式表达了两个思想:
- 类别的概率
- 预测的框距离 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
- 第一个 epoch ,学习率缓慢从 0.001 到 0.02.
- 以 0.02 训练 75 个 epochs。
- 以 0.001 训练 30 个 epochs。
- 以 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