死磕YOLO系列,YOLOv2的自我修养

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

演员需要自我修养,程序员也需要。

YOLO 在当时是非常不错的算法,速度极快,但明显的缺陷就是精度问题特别是小尺寸目标检测问题上。

YOLO 的作者有强调的一个事情是 YOLOv2 仍然是实时的,并且在速度和精度方面做了一定的平衡。

YOLOv2 是 YOLO 的进阶版,它没有彻底否定 YOLO,而是在 YOLOv1 的基础上,融合了很多其它论文优秀的思想做了大幅的提升。

YOLO 作者概括了从 3 个方面入手:

  1. 更好
  2. 更快
  3. 更强

1. 如何更好?

YOLO 作者对比了 Fast R-CNN 发现 YOLO 有一些短板,那就是比较低的召回率和比较高的定位误差。

所以,让 YOLO 变得更好指的是保持准确率的情况下:

  • 提升召回率
  • 降低定位误差

为此,尝试了一些手段。

1. 引入 Batch Normalization

Batch Norm 是一种很有效的正则化手段,所有的卷积层后面引入正则化之后,YOLO 表现如何呢?

  • mAP 提升了 2%
  • 可以去掉了 Dropout 仍然不出现过拟合

不熟悉 Batch Norm 的同学可以尝试阅读我这篇介绍文章

2. 高分辨率图像分类器

所有比较先进的目标检测网络,它的图像分类器都是在 ImageNet 做预训练的。

但从 AlexNet 开始,大多数分类器接受的图片尺寸都比较小,低于 256 * 256。

YOLOv1 训练图像分类时,图片尺寸是 224224,之后训练检测时,图片尺寸是 448 × 448,这代表模型需要同时应对学习检测和分辨率的变化。

YOLOv2 做了相应的改变。

通过对 YOLOv1 的模型进行 finetune,用 448*448 的图片尺寸训练了 10 epoches,主要目的是想让卷积核适应高分辨率。

这个步骤相当于做了减法,减轻了网络的学习任务,让它忽略图片尺寸的变化,专心应对目标检测任务。

这种尝试,让 mAP 涨了近 4 个点。

2. 引入 Anchor Box

YOLOv1 最终是通过全连接网络直接预测目标位置。

另外一个优秀的目标检测模型 Fast R-CNN 是通过 Anchor Box 的形式。

两种方法相比,Anchor Box 更容易学习,因为它是通过手选的,然后通过 RPN(Region Proposal Network) 全卷积层预测每一个位置相对于 Anchor Box 的偏移和置信度。

所以,YOLO 作者把 YOLOv1 进行了改造:

  • 最后的全连接层去掉了
  • 用 Anchor Box 预测 b-box
  • 移除一个 pool 层,使得卷积层输出更高分辨率
  • 缩放网络使其能够接受 416x416 的分辨率,目的是最终生成的 featuremap 只有一个中心 cell,方便定位。
  • 将分类和空间检测解耦,跟随 YOLOv1 的思路,预测每一个 anchor box 的对象 objectness 分数,这个是 anchor box 和 groundtruth 的 IOU 分数,也是一个条件概率,针对的是某个 cell 中有无对象时的概率取值。

在论文中,作者花了很长的篇幅讲解 anchor box 相关。

引入 anchor box 后,YOLO 模型的 accuracy 发生了些许下降。

未引入 anchor box 时,YOLO 预测 98 个 bbox,引入后,总共预测的 bbox 能多达 1000 多个

@无anchor box     @Acc=69.5 mAP  @Recall = 81%

@有anchor box   @Acc = 69.2 mAP   @Recall = 88%

相比于精度的少许损失,召回率提升明显,文章开头说 YOLOv2 的改良有个目标就是提高召回率,而 Anchor BOX 的引入确实起了很明显的效果。

3. 尺寸聚类

在引入 Anchor BOX 到 YOLO 的过程,遇到了 2 个问题。

第一个问题就是 Anchor BOX 的尺寸是手选的。

虽然网络可以渐进学习,但是如果一开始的时候就分配好合理的先验尺寸,那么这无疑会加快学习的速度。

相比于人为指定 anchor box 的尺寸比例,YOLO 作者想到了一个自动化的手段,那就是选择 k-means 聚类手段。

在数据训练集中运行 k-means 算法,可以得到 k 个尺寸比例。

但 K 如何取值呢?

作者不是乱取的,有做很详细的对比实验。

在这里插入图片描述

可以看到,k 从 1 到 15 都有做过测试,最终选择了 k=5,选择 5 的原因是在模型复杂度和召回率之间过一个平衡。

经实验,效果很不错,聚类出来的 anchor box 尺寸如下图所示:

在这里插入图片描述

聚类选择出来的尺寸没有很短和宽的尺寸,偏向于高且瘦的尺寸。

最后,作为聚类算法,距离的度量非常重要。

YOLOv2 没有采用标准的欧式距离作为度量。

欧式距离为什么不好呢?

因为 YOLO 作者发现,大尺寸的 bbox 更容易出现定位错误,所以作者想找一个尺寸独立的距离度量,它想到了 IOU, IOU 本身就是一个比例重合的关系。
d ( b b o x , c e n t r o i d ) = 1 − I O U ( b b o x , c e n t r o i d ) d(bbox,centroid) = 1 - IOU(bbox,centroid) d(bbox,centroid)=1IOU(bbox,centroid)

4. 定位预测

在引入 Anchor BOX 时还遭遇了第 2 个问题:模型的稳定性。

模型的不稳定性来源于坐标(x,y) 的预测。

在 RPN 网络中,坐标(x,y) 是这样的计算公式。
x = t x ∗ W a + x a x = t_{x}*W_{a} + x_{a} x=txWa+xa

y = t y ∗ H a + y a y = t_{y}*H_{a} + y_{a} y=tyHa+ya

YOLO 论文中公式好像错了,加号变成了减号,我在这里更正过来。

W 和 H 是 anchor box a 的宽高。

t 代表预测的框和 anchor box 的偏移比例。

以 x 方向为例。

t = -1,x 相当于 anchor box a 左移动一个自身宽度
t = 1, x 相当于 anchor box a 右移动一个自身宽度

y 也是同样的逻辑,这里不再赘述。

上面的坐标转换很容易懂,但不好训练。因为 x,y 并没有遵守什么约束,所以可能预测的 bbox 会遍布一张图片任何角落。

所以,YOLO 作者还是想借助 YOLOv1 的做法,有别于直接预测定位,YOLOv2 继续使用 bbox 相对于 grid 的偏移。

在这里插入图片描述

σ \sigma σ 是 logistic 函数,此函数限定了 tx 和 ty 的取值范围是 0 ~ 1.

然后,这里有个细节需要认真琢磨一下,那就是每个坐标变量的实际含义。

说实话,因为 YOLO 系列文章写得比较随性,很多细节作者没有题,所以需要自己去推断,我当时学习的时候坐标这个想了好久,好来阅读别人的笔记才意识到问题所在。1

YOLOv2 坐标预测每个 bbox 预测 5 个值:

  • tx

  • ty

  • tw

  • th

  • to

  • bx 和 by 是公式转换出来的,是预测的 bbox 相对于 featuremap 的中心位置偏移,YOLO 作者论文中忽略了它应当和 feature map 的 WH 相比

  • bw 和 bh 也是公式转换出来的,是预测的 bbox 相对于 featuremap 的尺寸比值

  • pw 和 ph 是 anchor box 先验尺寸,想对于 featuremap 的尺寸比例。

假如,featuremap 尺寸是 13x13,输入图片是 416x416

H=13
W=13
cx = 4
cy = 3
sigmoid(tx) = 0.3
sigmoid(ty) = 0.7
exp(tw) = 1.2
exp(th) = 1.4
pw = 3
ph = 4

那么,bbox 实际预测的值是多少呢?

bx = (0.3 + 3)/13*416=105
by = (0.7 + 4)/13*416=150
bw = 3*1.2/13*416=115
bh = 4*1.4/13*416=179

tx 和 ty 是偏移值,经过 sigmoid 函数可以得到 bx、by,相对于 feature map 左上角的偏移(非输入图片),是比例关系

tx 经激活函数输出后的结果是 0~1,代表了预测的bbox 的中心点相对于对应 grid 的左上角的偏移量,也是比例关系。

bw 和 by 也是偏移值,相对于 feature map 的尺寸 H 和 W,也是比例关系

cx 指的是负责预测 bbox 的那个 grid 的左上角相对于 feature map 的左上角的偏移。

YOLOv2 中 featuremap 的尺寸是 13x13,所以每个 grid 其实单位就是 1.

5. 精细化的特征图

YOLOv2 刚开始使用 13x13 的 featuremap 做预测,对于大目标来说足够应付检测了,但是小目标却不行。

像其它的目标检测算法都会利用到空间信息,会利用特征图金字塔去覆盖不同层级的尺寸信息,比如 Faster R-CNN 和 SSD 都生成了多种尺寸featuremap。

但 YOLO 作者另辟蹊径,用了一个 passthrough 手段,简单来说就是从 26x26 的featuremap 中提取信息生成新的 featuremap ,然后和最后 13x13 的 featuremap 拼接起来。

passthrough 有点类似 ResNet 的 shortcut 的思路,都是从较前面的层次获取信息,这样网络就可以应付空间上不同层次的信息。

具体做法如下:

将 26 x 26 x 512 尺寸的 featuremap 进行跨行垮列抽样,然后生成 13 x 13 x 2048 的 featuremap,参数总量没有变,但是尺寸发生了改变,所以 YOLO 源码中称这样的操作为 reorg,相当于一个宽高换深度的重组。

基于这项尝试,YOLOv2 的模型提升了 1% 的效率。

6. 多尺度训练

YOLO 作者不想让 YOLOv2 的模型只局限于 416x416 这单一尺寸的图片,所以训练过程当中,每经过 10 epoches 的训练,输入图像尺寸会发生变化。

因为 YOLOv2 的经过了 5 次下采样,缩小了 32 倍,所以,输入图像的尺寸都能被 32 整除 {320x320,352,…,608}.

多尺度训练使得 YOLOv2 可以在速度和精度上做一个很好的平衡。

低分辨率下,YOLOv2 的速度极快,228x228 的输入图片下,帧率可以到达 90 FPS,但精度和 Fast R-CNN 一致。

高分辨率下,YOLOv2 仍然可以达到实时要求,精度是当时的 state of the art.

在 VOC 2007 数据集 YOLOv2 和其他目标检测模型的对比如下图:

在这里插入图片描述

严密细致的验证

为了 YOLOv2 的整体表现提升,YOLO 作者做的工作很足,做了大量的工作,有些有用,有些无用,下图是作者给出来的验证记录。
在这里插入图片描述

这个说明,YOLO 作者虽然论文写得随性,样貌随性,但思维很严谨,不是一个浮躁的人。

2. 如何更快?

2.1 新的模型 Darknet-19

快是 YOLO 系列模型最大的优势,YOLOv2 如何在这方面精进的呢?

在 YOLOv2 的版本,作者换了一个新的分类器。

大多数目标检测模型是基于 VGG-16 的,它很简单,准确率也很高,但 YOLO 作者认为它太慢了。

处理一张 224x224 的图片,VGG-16 需要 30.69 BFLOPs。

要想快,这个地方肯定可以动刀子,YOLO 作者带来了新的模型 Darknet-19。

Darknet-19 是基于 GoogLeNet 的架构,它比 VGG-16 快,原因在于它的前向推断只要 8.52 BFLOPs。

设计 Darknet-19 参考了很多同行经验。

  1. 基于 GoogLeNet 架构
  2. 借鉴 VGG 大量运用 3x3 filter,并且在每个 pool 层之后,将卷积核的个数翻倍
  3. 借鉴 NIN 运用 global aveage pool,在 3x3 filter 之间插入 1x1 卷积层
  4. 引入 Batch Normal 层

Darknet-19 的结构如下:

在这里插入图片描述

19 个卷积层和 5 个 maxpool 层。

2.2 目标分类任务的训练技巧

要做好目标检测,首先就要做好目标分类。

目标分类是在 ImageNet 上做的,预测 1000 个分类。

  1. 随机梯度下降法做训练
  2. 224x224 尺寸的图片训练 160 epoches
  3. 初始学习率是 0.1,多项式学习率衰减策略,power 为 4
  4. 权重衰减系数为 0.0005,动量为 0.9
  5. 常见的数据增强手段
  6. 224x224 训练完成后,在 448x448 尺寸数据集上再训练 10 epoches ,除了初始学习率为 0.003 外,其它参数保持不变。

在高分率的数据集上,Darknet-19 Top-1 ACC 为 76.5%,Top-5 ACC 为 93.3%.

2.3 目标检测任务的训练细节

Darknet-19 是一个目标分类模型,最后一层输出了 1000 个分类的概率,需要做一些改造才能进行目标检测任务的训练。

    1. 去掉最后 1 个卷积层,然后用 连续 3 个 3x3 的卷积层代替。
    1. 每个 3x3 的卷积层卷积核数量是 1024 个。
    1. 每一个 3x3 的卷积层后面都跟着 n 个 1x1 的卷积核,n 是要检测目标的类别数
    1. 在 VOC 数据集中,类别数目是 20, 网络中每个 grid 预测 5 个 box,每一个 box 需要预测 5 个值(x,y,w,h,conf) 和 20 个类别的概率,所以需要 125 个 filter。
    1. 添加 passthrough 层从最后一个 3x3x512 卷积层到最后一个卷积层,目的是为了获取更精细的 feature。

训练细节:

epoches:160
learning rate: 0.001 在前 60 epoches,60 到 90 epoches 之间学习率除以 10
weight decay: 0.0005 动量是 0.9
数据增强:和 YOLO、SSD 一致
在 COCO 和 VOC 数据集的训练策略是一致的。

3.如何更强?

YOLOv2 的更强指的是作者提出了一种目标检测和目标分类联合训练的方法。2

当遇到目标检测数据集中的图片时,模型反向传播更新整个 YOLOv2 的 loss 函数。

当遇到目标分类数据集中的图片时,反向传播只更新 YOLO 分类的那一部分结构。

另外,将分类进行层次化处理,使得 YOLO 能够识别超过 9000 种类别,这就是 YOLO9000。

由于我的兴趣在于目标检测,所以这一部分不做多讲,有兴趣的同学可以自行阅读相关文档。

总结

YOLOv2 是一个平衡了速度和准确度的模型,它通过一系列 tricks 让自己更快、更好、更强。

如果让我个人评价的话,那一个 tricks 让我眼前一亮,我会投用 k-means 去聚类数据集中的 label 尺寸从而得到 anchor box 尺寸。

这其实是一个很强的先验知识,正因为此 YOLOv2 才会变得比 YOLOv1 更棒,YOLOv2 也没有全部照抄其它模型的 tricks ,而是真正有选择性地运用,这才是真正值得我们学习的地方。

参考


  1. https://zhuanlan.zhihu.com/p/35325884 ↩︎

  2. https://arxiv.org/abs/1612.08242 ↩︎

frank909 CSDN认证博客专家 CV(computer vision)
爱阅读的程序员,专注于技术思考和分享。关注架构设计、Android 开发、AI、数学、自动驾驶领域,个人公号:Frankcall
Linux创始人Linus Torvalds有一句名言:Talk is cheap, Show me the code.(冗谈不够,放码过来!)。 代码阅读是从入门到提高的必由之路。尤其对深度学习,许多框架隐藏了神经网络底层的实现,只能在上层调包使用,对其内部原理很难认识清晰,不利于进一步优化和创新。   YOLOv3是一种基于深度学习的端到端实时目标检测方法,以速度快见长。 YOLOv3的实现Darknet是使用C语言开发的轻型开源深度学习框架,依赖少,可移植性好,可以作为很好的代码阅读案例,让我们深入探究其实现原理。   本课程将解析YOLOv3的实现原理和源码,具体内容包括:      YOLO目标检测原理       神经网络及Darknet的C语言实现,尤其是反向传播的梯度求解和误差计算       代码阅读工具及方法       深度学习计算的利器:BLAS和GEMM       GPU的CUDA编程方法及在Darknet的应用       YOLOv3的程序流程及各层的源码解析   本课程将提供注释后的Darknet的源码程序文件。   除本课程《YOLOv3目标检测:原理与源码解析》外,本人推出了有关YOLOv3目标检测的系列课程,包括:   《YOLOv3目标检测实战:训练自己的数据集》   《YOLOv3目标检测实战:交通标志识别》   《YOLOv3目标检测:原理与源码解析》   《YOLOv3目标检测:网络模型改进方法》   建议先学习课程《YOLOv3目标检测实战:训练自己的数据集》或课程《YOLOv3目标检测实战:交通标志识别》,对YOLOv3的使用方法了解以后再学习本课程。
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值