0x00 Abstract

  • YOLO9000:先进的、实时的、能够检测超过9000种不同对象的目标检测系统
  • 对YOLOv1进行了创新性地改进,得到了YOLOv2
  • YOLOv2在PASCAL VOC和COCO数据集上都取得了非常高的成绩
  • YOLOv2采用了新颖的、多尺度训练方法,用一个YOLOv2能够识别不同尺度的输入、网络根据输入在速度和精度间自动平衡(输入大尺度:慢、精度高,小尺度:快、精度低)——输入可以不同尺寸
  • “快”的举例:在VOC2007数据集上,YOLOv2达到67FPS、76.8mAP
  • “准”的举例:YOLOv2在40FPS下,取得78.6mAP,明显优于Faster RCNN(使用ResNet作为backbone)和SSD。不仅速度快,精度还高
  • 提出了一个结合目标检测和图像分类的方法。用这个方法同时在ImageNet和COCO上训练了YOLO9000
  • YOLO9000能够预测仅仅标注了分类而没有标注具体位置的图像中对象的位置(ImageNet上只有分类标签)
  • 在ImageNet上对YOLO9000做验证,获得了19.7mAP,ImageNet目标检测数据集包括200个类别,其中只有44个来自COCO。对156个不在COCO中的类进行预测,获得了16.0mAP
    • 用到了3个数据集:
      • COCO detection dataset:训练,有80个类别
      • ImageNet classification dataset:训练,有22k个类别(只有类别,没有定位标签)——弱监督
      • ImageNet detection validation set:验证,有200个类别,其中44个来自COCO
      • YOLO能预测超过200个类别,超过9000个不同的目标
  • 具有实时性

0x01 Introduction

  • 通用目标检测应该满足:快、准、更多目标
    • 通用:相对专用,能检测更多种物体
    • 专用:专门检测某类或某几类的框架,如检测人脸、行人的等
  • CNN让目标检测更快、更准。然而,大多数系统检测的数量还是少
  • 相比图像分类、标注等任务,目标检测受限于数据集有限。大多数公共的目标检测数据集包含几千到数十万张图像,及其数十到数百个标签,而图像分类数据集通常包括几百万张图像,其中包含数万到数十万个类别。
  • 但是标注目标检测的图像的成本远大于分类和标注。因此,在未来很长一段时间内,还无法看到像图像分类那么大规模的目标检测数据集
  • 提出了一种新的方法来利用现有的大量分类数据,并利用它来增强目前的目标检测系统。这一方法使用目标分类的分层视图(World Tree),将不同的数据集结合起来
  • 提出了一种联合的训练方法,可以同时在检测和分类数据集上训练(ImgaeNet+COCO)。利用目标检测数据集中标注好的检测图像来学习精确定位目标,利用分类数据集来增加其词汇量(类别数量)和鲁棒性
  • 使用这一方法训练得到YOLO9000,一个可以检测超过9000个不同物体类别的实时目标检测器
  • 首先在YOLOv1基础上构建了YOLOv2,然后用上面那种数据集结合和联合训练方法,在超过9000个类别的ImageNet和COCO数据集上训练,得到YOLO9000

0x02 Better

YOLOv1的不足:

  • 相比较Fast RCNN,YOLO的错误主要是定位错误
  • 相比基于候选框的方法,YOLO有着更低的召回率(漏检高)

复习一下召回率和精确率:

YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
  • 精确率:找到的里面有多少是正确的。例如找到4个对象,其中3个是飞机,精确率75%
  • 召回率:找到的正确对象占所有对象的多少,例如找到3个飞机,所有里面有5个飞机,召回率60%
  • 因此,YOLOv2在保持分类精度的基础上,侧重提高召回率和定位准确性
  • YOLOv2试图构建一个更精确的网络,同时保持高速。我们没有扩容网络,相反简化了网络,并使特征更容易被学习到
  • 提出了一些改进:
YOLOv2网络学习笔记-萤火

1. Batch Normalization

  • BN层,批量归一化
  • 可以显著提升收敛性,同时消除其他形式的正则化的需求(例如Dropout)
  • 在YOLO所有卷积层加入BN层,可以获得2%的mAP提升
  • 可以帮助模型正则化
  • 使用BN层,可以在保 证不拟合的情况下,移除dropout层
  • 为什么?在神经网络层数比较多的时候,在训练网络时,每一层的参数都会发生变化,也就是参数进行更新,并且前面层参数的变化可能会导致我们这一层输入的分布和没进行参数更新前的参数分布有一个比较大的差距,这样就会导致神经网络要去适应这个新的分布,导致训练过程变慢。BN层的加入就可以加快训练速度
  • 是什么?在训练过程中,选取上一层所有神经元的输出,计算它的均值和方差,接着对这小批量的所有数据做归一化处理,经过这个处理后会使得每个小批次的数据的均值和方差保持在一定的范围
  • 怎么做?
  1. 选择上一层所有神经元的输出作为BN层的输入
    $$B={x_1,x_2,…,x_m}$$
  2. 求出这批数据的均值和方差
    $$\mu_B=\frac{1}{m}\sum_{i=1}^mx_i$$
    $$\sigma^2=\frac{1}{m}\sum_{i=1}^{m}{(x_i-\mu_B)^2}$$
  3. 做归一化,Z-score Normalization,让处理后的数据均值为0,方差为1 。标准差加一个值是为了防止分母为0
    $$\hat{x_i}=\frac{x_i-\mu_B}{\sqrt{\sigma_B^2+\varepsilon}}$$
    这样例如后面的激活函数用的是sigmoid,那么就会落在中间部分,但这样基本是线性的,不利于网络训练,会得到效果较差的模型,因此还要下面一步,引入变换重构,使用可学习参数γ和β
YOLOv2网络学习笔记-萤火
这样就可以让均值和方差分布发生变化,处于激活函数的非线形部分

4. 注意点:

  • γ和β是模型在反向传播过程中学习到的值,初始化一般为1和0
  • 均值和方差是计算得到的
  • BN一般不与dropout一起使用,BN输出均值为0,dropout输出均值减半(假如概率是0.5)
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火

2. High Resolution Classifier

  • 所有顶尖的检测器抖使用的分类器都在ImageNet上进行预训练
  • 自从AlexNet开始,大多数分类器都在小于256×256的输入图像上运行
  • 原始的YOLO先在224×224的输入下训练分类器,然后在448×448分辨率下推理,这意味着,网络在切换到检测学习时还必须调整到新的输入分辨率(YOLOv1的训练和推理的输入图像尺寸时不一样的)
  • 对于YOLOv2,在检测之前,会先把预训练完的模型 先在ImageNet上以448×448的完整分辨率进行10个epoch
  • 这让网络有时间调整其卷积核,以便在更高分辨率下更好地工作
  • 然后我们再对检测网络的结果微调
  • 这个高分辨率的分类网络增加了4%的mAP
  • 这里引入迁移学习(Transfer learning)的概念:把已训练好的模型(预训练模型)参数迁移到新的模型帮助新模型训练。

迁移学习有三种方式 Transfer Learning:冻结预训练模型的全部卷积层,只训练自己定制的全连接层。 Extract Feature Vector:先计算出预训练模型的卷积层对所有训练和测试数据的特征向量,然后抛开预训练模型,只训练自己定制的简配版全连接网络。 Fine-tuning(微调):冻结预训练模型的部分卷积层(通常是靠近输入的多数卷积层,因为这些层保留了大量底层信息)甚至不冻结任何网络层,训练剩下的卷积层(通常是靠近输出的部分卷积层)和全连接层。

  • Fine-tuning原理:利用已知网络结构和已知网络的参数,修改output层为我们自己的层,微调最后一层前的若干层的训练参数,这样就有效利用了深度神经网络强大的泛化能力,又免去了设计复杂的模型以及耗时良久的训练。
  • YOLOv1在采用 224×224 分类模型预训练后将分辨率增加到 448×448 ,并使用这个高分辨率在检测数据集上finetune。但是直接切换分辨率,检测模型可能难以快速适应高分辨率。所以YOLOv2增加了在ImageNet数据集上使用448×448输入来finetune分类网络这一中间过程(10 epochs).YOLOv2将预训练分成两步:先用224×224的输入从头开始训练网络,大概160个epoch(表示将所有训练数据循环跑160次),然后再将输入调整到448×448,再训练10个epoch,这可以使得模型在检测数据集上finetune之前已经适应高分辨率输入。使用高分辨率分类器后,YOLOv2的mAP提升了约4%。

3. Convolutional with Anchor Boxes

  • YOLOv1中,把图像分成7×7个格子,每个格子预测2个框,一般叫这2个框predictor
  • YOLOv2中,分成里13×13个格子(这样就可以预测更多的对象了),同时每个格子都有5个预测框,这5个叫做Anchor
  • YOLOv1中,2个predictor是野蛮生长的,而YOLOv2中,5个Anchor是有预定义大小的,也就是会预先设置一个长宽比例
YOLOv2网络学习笔记-萤火
  • YOLOv1直接使用全连接层来预测bbox的坐标
  • 区别于YOLO这种直接预测,Faster RCNN使用手动选取的先验框来预测bbox坐标(例如预测汽车宽高比2:1,预测行人1:2)
    • YOLOv2不是用手动的方式,而是用聚类的方式
  • Faster RCNN中的RPN(区域生成网络)只使用卷积层来预测anchor的偏移量、置信度
  • 由于预测层使用的是卷积,RPN预测了feature map(特征图)中每个位置的偏移量
  • 预测偏移量而不是坐标可以简化问题,使网络更容易学习
  • YOLOv2移除了全连接层,并使用anchor来预测bbox
  • 首先,去除了一个池化层,以使得网络卷积层的输出具有更高的分辨率
  • 收缩了网络,使其在416×416的输入图像上运行,而不是448×448
    • 这么做的原因是想让feature map中有奇数个位置,以便只有一个中心
      • 416/32=13(奇),448/32=14(偶)
    • 目标,尤其是大型的目标,其中中心点往往位于图像的中心位置。此外,希望用中心位置的一个单元格来预测这类目标,而不是让中心附近的四个单元格都来预测它
YOLOv2网络学习笔记-萤火
  • YOLOv2的卷积层对图像进行了32倍下采样,因此,针对416×416的输入,可以得到一个13×13的feature map
    • 输出tensor维度:(batch-size,13,13,125)
      • 125的原因:5个anchor,每个anchor都有4个定位信息+1个confidence+20个分类:5x(5+20)=125
  • 引入anchor机制,就可以把分类和定位分开
  • 和YOLOv1一样,目标预测仍然预测候选框与真实框的IOU,而类别预测则是在有目标的前提下,该类别的条件概率,例如:P(狗|包含对象)
  • 使用anchor,会让准确率略有下降
  • 在YOLOv1中,每张图片只预测了98个框。但是,使用了anchor后,可以预测13x13x5=845个框
  • 在没有使用anchor地情况下,mAP为69.5,召回率为81%,加入anchor之后,mAP为69.2(略有下降),但是召回率提升到了88%(提升较大,这也是为什么使用anchor机制的原因)
  • 虽然mAP下降了,但是召回率的提升意味着我们的模型有更大的改善空间

4. Dimension Clusters

  • 尺度聚类
  • 在YOLO中使用anchor会有2个问题:
    • 第1个问题:anchor box的尺度是手动设定的网络虽然能够自动学习如何构造好的anchor box,但是如果我们能够为网络构建更好的先验框(预选框)则能够让预测变得更加容易(先验框:特定比例、大小,如3:1用于汽车检测,1:2用于行人检测)
      • 在训练集上通过k-means自动地找到好的先验框,而不是手动设定
        • 如果使用基于欧氏距离的k-means,尺度大的box会产生更大的误差(但是其实小的box应该偏差更大),我们想要的是与box尺度无关的,能够获得好的IOU分数的先验框,因此,在距离尺度上,使用的是:

$$d(box,centroid)=1-IOU(box,centroid)$$

用1减去代表IOU越大,距离越近 。centroid是聚类中心,box是其他待聚类的框。这里所用的特征就是框的宽、高,与框的中心点无关,即每一轮按宽高均值去划分。因为最终是想要得到k个anchor box,所以就和中心没关系

YOLOv2网络学习笔记-萤火
  • 作者计算了不同k值控制下k-means算法,并画出了相似质心的IOU情况
    • 左图:横坐标-聚类簇数,纵轴-平均IOU
    • 在综合考虑模型复杂度和召回率后,选择了k=5
    • 聚类质心(综合考量形状等)与手动选取的anchor box又显著区别
    • 高瘦的多,矮胖的少
    • 右侧:VOC和COCO相对形状,COCO尺度变化更大

举例:k-means(k=2):

YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火

选择5个anchor就达到了竞品(Faster RCNN)9个anchor的效果(对方60.9,我们61),如果我们也用9个,平均IOU是67.2

5. Direct location prediction

  • 直接位置预测
  • 在YOLO中使用anchor,遇到的第二个问题:模型不稳定,尤其是迭代的早期
  • 大多数不稳定性来自于位置预测
  • 在位置预测中,其关系如公式所示(原论文的公式是错误的,这里改正):

$$x=(t_x*w_a)+x_a$$
$$y=(t_y*h_a)+y_a$$

  • xa、ya:anchor的中心位置
  • wa、ha:anchor的宽高
  • tx、ty:偏移量
  • x、y:预测框的中心位置
  • 例如当tx=1,box将右移,tx=1,box将左移
  • 这个公式收到的限制较少,预测框无论在那个anchor box开始,都会在任何位置结束(例如出界)。在随机初始化的情况下,模型需要花费较大的时间才能稳定地预测出合理的偏移量
  • 我们没有采用上述的预测偏移量的方式,采用了YOLO的方式:预测相对于grid cell的坐标。这将ground truth限制在[0, 1]内
  • 使用sigmoid函数将预测值限制在[0, 1]内
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火

\(\sigma(x)\)使得结果处于[0, 1]
\(e^x\)保证结果为正数,因为宽高不能为负数

  • 最终的feature map中,在每个grid cell中预测5个bbox,每个bbox预测5个值(位置+置信度)
  • 由于限制了位置预测,参数更加容易学习,让网络更稳定。
  • 使用anchor 聚类和直接位置预测预测,提高了5%mAP

6. Fine-Grained Feature(含Passthrough)

  • 细粒度特征
  • Faster RCNN和SSD都在不同的特征图上运行他们的网络,以获取对多分辨率的支持
  • 我们采用了一种不同的方式,加入了一个passthrough层(直通层)从26×26分辨率传过来的(把26×26拆成4个13×13)
  • 与ResNet类似,直通层(passthrough)不采用空间平面组合的方式,而是采用堆叠的方式将通道组合在一起
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
YOLOv2网络学习笔记-萤火
  • 它将26x26x512的特征图变为13x13x2048的特征图,以便可以与辨识特征连接起来。(思想:细粒度+高层抽象特征融合)
  • 检测器在扩展后的特征图上运行,这使得它可以访问细粒度的特征
  • 这种方式,使性能提升了1%

7. Multi-Scale Training

  • 尺度训练
  • YOLOv1的输入分辨率是448×448。v2加入anchor后,变为了416×416
  • 模型通过卷积核池化实现了降采样的效果
  • 为了让模型能适应不同的输入,有更好的鲁棒性,做了一些尝试:
    • 不再使用固定尺度的输入,而是不断地改拜年输入尺度
      • 每10个batch,随机地调整一次输入的尺度
      • 由于降采样的尺度为32,输入尺度集合为{320, 352,…,608},最小尺度为320×320,最大为608×608
      • 不断地调整,不断地训练
  • 速度、精度的平衡

0x03 Faster

  • 大多数模型都以来VGG-16作为基础的特征提取模型
    • 功能强大、分类准确(ImgaeNet top-5: 90%),但是过于复杂
  • YOLOv1使用了基于GooLeNet结构的自定义网络
    • 速度快,但是精度略低(ImgaeNet top-5: 88%)

1. Darknet-19

YOLOv2网络学习笔记-萤火
  • backbone
  • 与VGG类似,主要是用了3×3卷积,每次下采样后,卷积核数量翻倍
  • 参考NiN网络,使用了全局平均池化(GAP)进行预测,在卷积层之间使用了1×1卷积进行降维
  • 使用了BN层稳定训练、加速收敛、正则化网络
  • 包含19个卷积层、5个最大值池化层
  • top-1:72.9%,top-5:91.2%

2. Global Average Pooling

  • GAP,全局平均池化
  • 与增加全连接层不同,针对feature map计算均值,然后将计算均值得到的向量值直接输入给后续的softmax层
  • 相比较于全连接层,GAP层的一个优点在于:它保留了卷积结构,强化了feature map和类间的对应关系
  • 因此,feature map能够非常容易地理解为类的置信度
  • 另外一个优点在于GAP不需要参数,因此可以有效避免过拟合
  • 除此之外,GAP综合类空间位置信息,因此它具有更好的空间鲁棒性

3. 1×1卷积

  • 可以用于降维/升维
  • 减少运算量
  • 输入channel多少,卷积核的channel就有多少
  • 输出channel多少,用到的卷积核的个数就有多少
YOLOv2网络学习笔记-萤火

4. Training for classification

  • 在标准ImageNet 1000分类数据集上训练
  • SGD,学习率从0.1开始,运行160个epochs
  • 一开始在224×224分辨率上训练,接下来微调网络让输入为448×448

5. Training for detection

  • 把最后的卷积层移除,取而代之,使用了3个10024个核的3×3卷积,以及1个核数量由输出个数指定的1×1卷积(其实就是125个)
  • 针对VOC,每个box预测125个值,因此需要125个卷积核(125=(5+20)*5)
  • 还加了一个passthrough层
YOLOv2网络学习笔记-萤火
  • 下面这个是源码的,有64个1×1卷积:
YOLOv2网络学习笔记-萤火

0x04 Stronger

  • 提出了一种联合训练机制,同时在分类集和目标检测集上进行训练
    • 使用带有标签的数据(VOC、COCO)学习bbox坐标、置信度
    • 用只有类型标注的图像集(ImageNet)扩展能够检测到的类别信息
  • 在训练阶段,我们将检测和分类的数据集混合在一起
  • 看到的是带标签的图像(来自VOC、COCO),反向传播YOLOv2的损失函数(位置、置信度信息)
  • 看到的是分类图像(来自ImageNet),仅仅通过网络的特定部分来反向传播分类信息

这样做遇到的问题:

  • 目标检测的标签粒度比较粗,如”狗“、”船”,分类数据集中的标签粒度更细,如有超过100种狗。这就需要采用一个一致性的方式来合并这些标签
YOLOv2网络学习笔记-萤火
  • 大多数的分类方式,都是采用softmax层完成分类计算,而softmax方式假设类间是互斥关系。因此导致了组合数据集问题,例如,我们不能简单地将COCO和ImageNet进行组合,因为二者中“Norfolk terrier”和“Dog”并不是互斥的
YOLOv2网络学习笔记-萤火
  • 采用多标签模式来组合数据集,这种方式并不需要假设数据集的彼此互斥

1. Hierarchical classification分层分类

  • ImageNet标签来源于WordNet,它是一个彼此交叉的网状结构(一个节点可能有多个父节点)
YOLOv2网络学习笔记-萤火
  • 我们没有用图结构,而是简化为了树结构,叫做WordTree
YOLOv2网络学习笔记-萤火
  • 根节点:physical object
  • 在ImageNet中,先找到WordNet中只有一条道根节点的那些,加入到我们的WordTree中
  • 如果一个节点有多条路径都可以到根节点,选那条较短的路径加入到WordTree

为了使用WordTree完成分类,我们在每个节点上预测条件概率

YOLOv2网络学习笔记-萤火

如果想要计算一个特定节点的绝对概率,那就沿着树的路径到根节点,不断地乘以沿途每个节点的条件概率。

YOLOv2网络学习笔记-萤火

完成分类时,通常假设图像中包含一个物体,因此:

$$Pr(physical object)=1$$

YOLOv2网络学习笔记-萤火
  • 为了验证我们的方法,我们在使用1000个类别的ImageNet所构建的WordTree上训练Darknet-19模型。为了构建WordTree1k,我们加入了所有的中间节点,将标签从1000扩大到1369个
  • 在训练过程中,我们传播父类标签。例如,如果一张图片被标记为“诺福克梗犬”,它也会被标记为“狗”和“哺乳动物”
  • 为了计算条件概率,我们的模型预测了一个由1369个值组成的向量,我们计算了所有作为同一概念的系统集的softmax(如果具有相同的父节点,那么它们是互斥的)
  • 准确率下降了一点点
  • 这种方式在新的或者未知的对象预测时,性能下降不明显。例如如果网络看到一张狗的图片,虽然不能确定这是一种什么类型的狗,但是仍然会以高置信度将其预测为“狗“,当然,在具体的子类中,它的置信度会降低

2. Dataset combination with WordTree

YOLOv2网络学习笔记-萤火

只需简单地将数据集中的类别映射到树上即可

3. Joint classification and detection

  • 使用了COCO目标检测集和ImageNet完整版前9000个类来构建联合数据集。为了评估,又加入了一些尚未包括的类别
  • 该数据集构造的WordTree有9418个类
  • 相比COCO而言,ImageNet是一个更大的数据集。因此,我们通过COCO的过采样来平衡两个数据集。实践中,ImageNet仅仅是COCO的4被
  • 使用YOLOv2训练,但是只保留3个Anchor,以控制输出大小。因此输出是(13, 13, 3, 5+9418)
  • 我们的网络看到是一个检测图像时,与普通网络一样将损失进行反向传播
  • 对于分类损失,我们只在标签的相应级别或者父类别上反向传播损失。例如,如果标签是”狗“,则我们不给树上子集的预测分配任何损失,例如”德国牧羊犬“和”金毛猎犬“就不会得到损失,因为我们不知道他到底是哪种狗,索性就不传递了
  • 当网络看到一个分类图像时,我们只传播分类损失。要实现这个目标,我们只需要找到IOU最高的那个bbox,并计算其在预测树上的损失,当然,预测框与真实框至少要有0.3的IOU

0x05 损失函数

YOLOv2网络学习笔记-萤火