目标检测two-stage经典方法总结


最近将几个经典的两阶段检测算法进行了一个系统性的学习,网上的资料很多,我根据自己在学习过程中的思考写了这篇博文。

计算机视觉的三大任务

  • 分类(是什么):给定一张图片,为每张图片打一个标签,说出图片是什么物体。然而因为一张图片中往往有多个物体,因此我们允许你取出概率最大的5个,只要前五个概率最大的包含了我们人工标定标签,就认定正确(top-k预测)
  • 定位(在哪儿):除了需要预测出图片的类别,你还要定位出这个物体的位置,同时规定你定位的这个物体框与正确位置差不能超过规定的阈值
  • 检测(在哪儿有什么):给定一张图片,你把图片中的所有物体全部给我找出来(包括位置、类别)

OverFeat

《OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks》

在早期方法中,通常使用以下的传统框架进行目标检测任务(这里以人脸检测作为一个例子):

在这里插入图片描述

可以看到传统的框架通常使用下面的步骤进行检测任务:

  1. 首先利用大量图片训练一个目标检测的分类器
  2. 在不同尺度的待检测图像中使用密集滑窗进行滑动,对每一个滑窗的位置使用第1步训练的分类器进行分类来判断是否为待检测目标
  3. 将密集滑窗策略得到的待检测目标的检测框进行NMS合并

在上面的步骤中很明显可以发现传统检测方法是将分类和定位任务分开进行,并利用滑窗策略来对图像中的所有位置进行定位(后面简称为滑窗定位策略),即将分类和滑窗定位策略合并起来最终完成检测任务。

引入问题

上面的传统方法检测框架中直觉上主要的改进可以朝着两个方向进行:

  1. 对于分类器的改进,使用区别于早期方法的更有效的分类器,在AlexNet取得非常好的结果之后,基本上均是使用卷积神经网络来代替传统分类器,因此在这一点上主要关注的就是卷积神经网络主干网络的发展
  2. 对于滑动窗口方法的改进,OverFeat论文中主要指出几点:

The first idea in addressing this is to apply a ConvNet at multiple locations in the image, in a sliding window fashion, and over multiple scales. Even with this, however, many viewing windows may contain a perfectly identifiable portion of the object (say, the head of a dog), but not the entire object, nor even the center of the object. This leads to decent classification but poor localization and detection.

The second idea is to train the system to not only produce a distribution over categories for each window, but also to produce a prediction of the location and size of the bounding box containing the object relative to the window.

The third idea is to accumulate the evidence for each category at each location and size.

OverFeat改进方法

Overfeat方法便是在以上框架的基础上利用深度学习的卷积神经网络进行改进,将分类,定位和检测任务用一个网络完成,主要改进点为:

  • 改进AlexNet分类网络作为主干网络,也即本文提出的OverFeat,它是将该主干网络作为一个特征提取算子,提取出特征为后面的分类和定位任务做准备
  • 利用在OverFeat后面接上全连接层进行训练,来完成分类任务;然后将全连接层替换成FCN网络,保持训练分类任务的OverFeat结构参数不变,训练检测框回归任务(可以看出早期的深度学习方法还是延续了传统方法的思想,即利用类似于SIFT和HOG这些特征提取算子来提取特征,然后再在后面接各种不同任务的分类器进行分类,实际上在卷积神经网络中是可以将所有方法合并成一个end-to-end的任务的),从而实现将分类、定位和检测集成在一个网络中
  • 引入offset pooling(即一种特征图滑窗策略)来替代传统的在输入图片上进行的密集滑窗策略,并且对特征图中每一个像素点(即每一次滑窗的位置)直接进行回归任务,预测出检测框的位置,而不是原始的密集滑窗策略那样由每一次滑动窗口的位置作为检测框的位置,这样就避免了固定尺寸的检测框会切断物体

OverFeat整体流程图如下所示:

在这里插入图片描述

Offset Pooling

Offset pooling可以看做是一种特征图滑窗策略,用于针对同一尺度下的输入图片产生的特征图中不同位置进行分类和检测,用于替代传统方法中在输入图片上进行密集滑窗策略这种耗时的操作。在论文中的解释如下:

在这里插入图片描述

具体操作步骤为:

在这里插入图片描述在这里插入图片描述

其中的layer5即对应OverFeat整体流程图中特征图2

FCN

在这里插入图片描述

分类任务

OverFeat论文中的特征提取模型是在AlexNet的基础上进行改进(注意后面的分析均是基于高精度模型):

  1. 没有使用局部响应归一化层;
  2. 没有采用重叠池化的方法(即每一次池化层的卷积核的stride为卷积核大小的一半,因此卷积核在滑动的过程中没有重叠部分);
  3. 在第一层卷积层,stride作者是选择了2,这个与AlexNet中的4不用,如果stride选择比较大得话,虽然可以减少网络层数,提高速度,但是会降低精度

在此基础上,作者构造出了快速模型和高精度模型两种架构:

  • 快速模型架构

在这里插入图片描述

  • 高精度模型架构
    在这里插入图片描述

模型训练

在分类任务的训练阶段,OverFeat采用AlexNet的图像增强方法:

  • 对于训练数据集中每一张256×256图片及其镜像,随机crop成一张224×224的图片
  • 利用PCA来处理RGB三通道的值

AlexNet的详细处理步骤为:
在这里插入图片描述

再将上述图像增强后的图片输入网络进行训练

模型测试

AlexNet在模型测试阶段的方法为:

  • 对于输入的一张256×256图片,首先进行multi-view crop,即分别从图片的四个角以及中心裁剪出5张224×224的图片,把原始图片水平翻转一下,再用同样的方式进行裁剪,又可以得到5张图片
  • 把这10张224×224图片作为输入,分别进行预测分类,在softmax得到10张crop图片对应的每一类的概率,再对其取平均值,得到最终每一类的概率值(这也是为什么caffe中AlexNet的网络模型中input的第一维也即是batch的大小是10的原因)

由于AlexNet的测试方法对于检测任务来说,存在以下缺点:

  1. multi-view crop在检测中很容易将待检测物体截断,使crop之后的图片中待检测物体不完整
  2. multi-view crop得到的图片中,各个图片块之间存在很大的重叠面积,因此在测试的过程中存在计算冗余
  3. multi-view crop的方式只是在单一尺度上进行

针对以上问题OverFeat采用以下测试方法:

  • 对原图做以下放大处理(由于通常检测问题中对于大尺寸物体的检测效果较好,对于小物体的检测效果不好,所以构造多尺度输入的时候只放大图片)得到6个尺寸的图片,并对所有尺寸的图片做翻转作为输入。

在这里插入图片描述

  • 将以上图片输入模型直接进行测试,并在此处引入offset pooling来实现原始检测框架中的密集滑窗策略,从而对于每一个尺寸的输入图片产生如上表最后一列所示数量的特征向量
  • 对于网络输出的各个尺度对应的特征向量,例如第一个尺度产生的输出3x3xC,则是对于每一个类别对应的3x3个特征向量取平均值,得到该尺度下每一个类别的概率值,以此类推到各个尺度,便可以求出各个尺度中各个类别的概率。最后将各个尺度中相同类别的概率值做平均,便可以得到最终的各个类别的概率,根据评价指标的需要取最大的一个概率对应的类别作为top-1,或者最大的5个概率对应的类别作为top-5.

定位任务

模型训练

保持分类模型中训练好的OverFeat模型参数不变,在模型后面加上定位任务的网络进行训练,从而得到最终的定位网络(文中并没有给出训练回归任务的loss函数)

模型定位步骤

在这里插入图片描述

从上图可以看到,以281x317的输入尺寸为例,OverFeat论文中对于上面OverFeat整体流程图中特征图2首先进行一个5x5的pooling层得到2x3的特征图,然后经过4096x1x1和1000x1x1的全连接层(这里使用FCN实现)之后最终输出每一个尺度产生的每一个特征图中的每一个像素点映射到原图中的检测框的座标值,即图中的(top, left, right, right box edges)。对此,作者通过下面的几组图片分析了多尺度策略,offset pooling策略对模型产生检测框的密集度:

  • 利用不同的尺寸来进行预测,由于尺寸越大,对应的第五层产生的特征图的大小也越大,而特征图中每一个像素点都对应一个检测框,因此原图尺寸越大,越会产生更多的检测框
    在这里插入图片描述
  • 在上面的基础上,运用offset pooling 即滑窗的方法,因此在每一个scale又产生了不同的3x3个不同滑动窗口,因此进一步的增加了检测窗口的数量
    在这里插入图片描述
  • 此处展示的是上面的每一个尺寸的每一滑窗的每一个像素点对应的位置回归网络产生的四个座标点回归值
    在这里插入图片描述
  • 结合上图中各个尺度各个滑窗上产生的检测框
    在这里插入图片描述
    在这里插入图片描述

分类和定位任务

整体上OverFeat利用OverFeat特征提取器来提取特征,将该特征运用于后面的分类和定位任务,即可以看作对于后面产生的特征图中的每一个像素点映射到原始图中的区域,在该区域预测出分类任务中各个类别的概率以及回归任务中检测框的座标值,下面同样以281x317的输入尺寸为例,给出网络同时进行两项任务的示意图:

在这里插入图片描述

参考资料:

https://zhum.in/blog/project/TrafficSignRecognition/OverFeat论文阅读笔记/

R-CNN

《Rich feature hierarchies for accurate object detection and semantic segmentation》

2012年,AlexNet第一次利用卷积神经网络在ILSVRC比赛上获得了超越第二名几乎一半的成绩,引起了极大的反响,在目标检测领域,主要争论的问题是:

To what extent do the CNN classification results on ImageNet generalize to object detection results on the PASCAL VOC Challenge?

ImageNet上的CNN分类结果在何种程度上能够应用到PASCAL VOC挑战的物体检测任务上?

针对这个问题,本文主要关注两个方面:

  1. localizing objects with a deep network(主要关注如何使用AlexNet中的深度网络来完成定位问题)
  2. training a high-capacity model with only a small quantity of annotated detection data(主要关注如何将AlexNet中深度网络的权重迁移到定位问题上)

下面就上面两个问题进行分析R-CNN的脉络

使用深度网络来定位物体

在图像中定位物体通常使用一下两种方法:

  1. 将定位问题看作是回归问题(OverFeat采用的方法),R-CNN论文中利用Szegedy等的工作说明这种方法不是很好
  2. 构造一个滑动窗口检测器(R-CNN中采用的方法)

下面具体说明R-CNN的具体构造:

在这里插入图片描述

如上图所示,R-CNN的测试部分主要分为三个模块:

  1. 产生类别无关的候选框
  2. 卷积神经网络产生定长的特征向量
  3. 指定类别的SVM线性分类器

产生类别无关的候选框

R-CNN采用论文《Selective search for object recognition》中的Selective Search方法来产生2000个后面需要的候选框,这个方法主要有三个优势:

  • 捕捉不同尺度(Capture All Scales)
  • 多样化(Diversification)
  • 快速计算(Fast to Compute)

Selective Search算法主要包含两个内容

  • Hierarchical Grouping Algorithm
  • Diversification Strategies

Hierarchical Grouping Algorithm

  1. 使用论文《Efficient Graph-Based Image Segmentation》中的方法在图像中产生初始区域(参考:https://blog.csdn.net/ttransposition/article/details/38024557)
  2. 计算所有邻近区域之间的相似性
  3. 两个最相似的区域被组合在一起
  4. 计算合并区域和相邻区域的相似度
  5. 重复2、3过程,直到整个图像变为一个地区。

Diversification Strategies

这个部分涉及到多样性的一些策略,使得抽样多样化,主要有下面三个不同方面:

  1. 利用各种不同不变性的色彩空间
  2. 采用不同的相似性度量
  3. 通过改变起始区域,作者对比了一些初始化区域的方法,发现《Efficient Graph-Based Image Segmentation》中的方法效果最好

主要参考:https://zhuanlan.zhihu.com/p/39927488

卷积神经网络产生定长的特征向量

  1. 将第一步中产生的类别无关的候选框risize成227x227大小的图片

在这里插入图片描述

上图中展示了作者在附录A中实验的几种resize方式:

(B)考虑context(图像中context指RoI周边像素)的各向同性变形,检测框向周围像素扩充到227×227,若遇到图像边界则用候选框像素的均值进行填充

©不考虑context的各向同性变形,直接用建议框像素均值填充至227×227

(D)各向异性变形,简单粗暴对图像resize至227×227

变形前先进行边界像素填充padding处理,即向外扩展建议框边界,以上三种方法中第一行为采用padding=0,第二行为采用padding=16

作者采用的方法即为上图中(D)那一列的下面那一行的方式,在候选框周围加上16的padding(即向外扩展候选框边界),再进行各向异性缩放,作者对比了各种方法后,发现这种方法最好,使得mAp提高了3到5个百分点

  1. 将1中resize以后的候选框图片使用AlexNet中五个卷积层和两个全连接层进行前向传播,最终得到一个4096x1维的特征向量

指定类别的SVM线性分类器

通过对每个类别训练出来的SVM对以上每个候选框产生的4096维特征向量进行打分,然后给出一张图像中所有的打分区域,然后使用NMS(每个类别是独立进行的),拒绝掉一些和高分区域的IOU大于阈值的候选框。

训练网络

CNN的训练

由于目标检测的数据集标注数据较少,训练AlexNet这样的大型网络较为困难,于是产生了上面提到的第二个问题:

training a high-capacity model with only a small quantity of annotated detection data

  1. 利用ImageNet数据集进行预训练
  2. 将ImageNet专用的1000-way分类层,换成了一个随机初始化的21-way分类层(其中20是VOC的类别数,1代表背景)而卷积部分都没有改变
  3. 将PASCAL VOC数据集利用Selective Search方法产生候选框,利用所有候选框区域的图片作为训练数据,其中和真实标注的框的IoU>=0.5就认为是正例,否则就是负例
  4. 利用3中的数据进行finetune,SGD开始的learning_rate为0.001(是初始化预训练时的十分之一),这使得调优得以有效进行而不会破坏初始化的成果。每轮SGD迭代,统一使用32个正例窗口(跨所有类别)和96个背景窗口,即每个mini-batch的大小是128。另外倾向于采样正例窗口,因为和背景相比他们很稀少。

SVM分类器的训练

与上面CNN的finetune过程一样,同样采用步骤3中的方法来产生训练SVM的数据集,但是其中IoU低于0.3的被作为负例,GT作为正例,其余的全部丢弃。然后将这些候选框区域利用上面训练好的CNN提取特征,,对应标签数据,来训练SVM。但是由于这里训练数据太大,难以装进内存,所以R-CNN采用hard negative mining方法,hard negative mining方法使得训练能够很快的收敛,并且mAP在一个epoch之后就停止增长。

hard negative mining:难负例挖掘算法,用途就是解决正负例数量不均衡,而负例分散代表性又不够的问题,用分类器对样本进行分类,把其中错误分类的样本(hard negative)放入负样本集合再继续训练分类器。

这里存在一个问题:当数据量过大的时候,并且其中大部分是负例的时候,没有办法将所有的数据全部装入内存进行训练,所以作者采用难负例来作为负例给SVM进行训练,但是作者并没有说是怎样产生这些难负例的。个人认为,这里的难负例应该是训练CNN的时候产生的,因为SVM作为一个接在CNN之后的分类器,实际上充当的是CNN最后softmax分类的作用,由于其接受的是CNN提取到的特征,而由于CNN的训练样本没有非常清晰的分类边界(下一小节"CNN和SVM训练中的问题"中会讲到),所以肯定会产生很多的false positive例子,而将这些例子进一步给SVM训练,便可以有效的增强SVM对于分类边界的判断。所以SVM的训练样本中的负例一方面来自CNN产生的难分负例,另一方面来自将候选框区域和某一单一类别的真实标注框进行对比,IoU阈值小于0.3的负例

CNN和SVM训练中的问题

一、 为什么使用不同的正负例IoU阈值

首先,两者的不同在于

  • 在CNN的训练中,是将候选框区域和真实标注的框的IoU>=0.5就认为是正例,否则就是负例,其中候选框区域是针对所有类别的,因此每次匹配的时候只要和任意一个真是标注框的IoU>=0.5就认为是正例
  • 在SVM的训练中,是将候选框区域和某一单一类别的真实标注框进行对比,当IoU阈值小于0.3的时候为负例,而正例为真实标注框

而产生两种不同策略的原因在于:

CNN的模型复杂度远远高于SVM,在训练CNN的时候采用上面的策略会使得正例的数目是真正正例(即GT)的数目的30倍,这样一方面可以避免CNN过拟合,另一方面可以为SVM的训练抽取到足够有表现力的特征(因为如果采用SVM那种数据处理方式,会使得CNN得到的数据样本很少)

由于SVM的模型是采用上面训练好的CNN模型输出的4096-D的特征来进行训练,因此SVM不需要采用过多的样本来抽取特征;同时SVM模型的复杂度很低,为了获取到足够大的类间距,所以采用上面训练SVM的策略,这样可以让SVM更容易区分正例和负例的区别

二、为什么不采用CNN后面接SoftMax直接进行分类,而是要在后面使用SVM分类

在上面的训练策略中,为了CNN抽取到训练样本中足够丰富的特征,采用上面介绍的CNN训练数据的生成方法,引入了大量“jittered”样本(与真实标注框的IoU阈值在0.5到1之间的候选框样本)极大的扩充了正例,避免了CNN过拟合,但是由于“jittered”样本与真实标注框之间存在很大的偏差,CNN很难有效的区分正例和负例之间的区别,因此CNN网络在预测精确的定位位置上表现不佳

CNN的训练中采用的是随机选取正负例,保证两者之间的比例为1:3,而没有采用SVM中的hard negative mining方法,同样导致直接使用CNN进行分类的效果没有使用功能SVM的好

Ablation studies

作者通过在上面提出的模型的基础上分别用Pool5、fc6以及fc7产生的特征来训练SVM,并使用SVM进行分类后的mAP指标如下:

在这里插入图片描述

  • 前三行数据说明调优之前的模型中fc7的特征泛化能力不如fc6的特征,同时移除fc6和fc7,仅仅使用pool5的特征,只使用CNN参数的6%也能有非常好的结果。可见CNN的主要表达力来自于卷积层,而不是全连接层
  • 中间三行数据说明调优之后的模型提升非常明显,mAP提升了8个百分点,达到了54.2%。fc6和fc7的提升明显优于pool5,这说明pool5从ImageNet学习的特征通用性很强,在它之上层的大部分提升主要是在学习领域相关的非线性分类器(上面是文中的观点,但是个人觉得这个数据实际上在一定程度上反驳了上边关于全连接层对于模型的特征表达没有作用的观点)

检测错误分析

在这里插入图片描述

(这里没有看的太明白)

Bounding-box回归

通过上面的检测错误分析,作者指出:

As an immediate consequence of this analysis, we demonstrate that a simple bounding-box regression method significantly reduces mislocalizations, which are the dominant error mode.

从而在SVM对每一个候选框进行分类后,针对预测有类别的候选框进行Bounding-box回归。详细参考:https://blog.csdn.net/zijin0802034/article/details/77685438
(个人觉得这篇博客很赞,详细的解释了此处回归的loss函数的设计原理)

自己的一些问题

  • R-CNN中产生候选框位置的算法是Selective Search方法,该方法还是在利用传统特征的思想来提取后面需要检测的位置,但是最后又使用了深卷积网络提取到的特征做Bounding-box回归来进行校正
  • 在产生正负例样本的时候采用的是1:3的比例,感觉后的很多方法都沿用了这一比例

SPP-Net

《Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition》

提出问题以及产生问题的原因

流行的CNN结构通常都需要输入图像的尺寸是固定的,这限制了输入图像的长宽比和缩放尺度。当遇到任意尺寸的图像时,都是先将图像利用裁剪和变形缩放的方式来适应成固定尺寸。但裁剪会导致信息的丢失,变形会导致位置信息的扭曲,就会影响识别的精度。另外,一个预先定义好的尺寸在物体是缩放可变的时候就不适用了。

在这里插入图片描述

产生问题的原因主要来自网络的全连接层,也即是网络的最后阶段。

解决问题的方案

解决上面CNN输入固定问题的解决方案当然是本文的主角SPP了,即空间金字塔池化,论文首先说明了该结构的来历以及优点

SPP的由来

SPP来源于SPM(Spatial Pyramid Matching),是论文《Beyond bags of features: Spatial pyramid matching for recognizing natural scene categories》提出的观点,出现的背景是将BOVW(Bag of visual words)模型被大量地用在了Image representation中,但是BOVW模型完全缺失了特征点的位置信息。
主要参考:https://blog.csdn.net/jwh_bupt/article/details/9625469

SPP介绍

在这里插入图片描述

通过上图中将经典的7层网络结构(如AlexNet或VGGNet)中conv5层产生的特征图进行可视化可以发现,CNN中的滤波器会被一些特定的语义激活,而这些滤波器也会在图像中采集相应的语义信息。这项特性说明CNN也和传统方法一样使用以下步骤:

  1. 将原始图像进行编码(即SIFT特征或者HOG特征表示)后形成特征图(可以看成是一个特征空间)
  2. 将特征图根据不同尺度提取不同大小的图像块(bins),这一个个图像块便可以看成是特征空间中的特征向量
  3. 将2中的特征向量集合利用词袋模型或者空间金字塔进行池化

而CNN作为一种有效的特征提取器便可以替换1中的SIFT特征或者HOG特征来完成特征提取的任务。通过以上的这种方式SPP-Net想要完成的目标是:

卷积层接受任意大小的输入,而分类器固定输出向量的尺寸

在这里插入图片描述

如图所示,SPP结构即针对任意大小的特征图,首先将特征图分为4x4个图像块,然后对每一个图像块取最大值,于是便可以得到一个4x4的特征图(即对每一个图像块做最大池化操作),即图中spatial pyramid pooling layer最左边的16x256-d特征,然后将特征图分为4x4个图像块,然后对每一个图像块取最大值,于是便可以得到一个2x2的特征图,即图中spatial pyramid pooling layer中间的4x256-d特征,最后将特征图整体最大值,于是便可以得到一个1x1的特征图,即图中spatial pyramid pooling layer最右边的256-d特征,将以上的各个特征进行拼接,作为全连接层的输入,通过这种方式,不论输入的大小是多少,输出向量的尺寸都是(16+4+1)x256-d,其中256-d对应着Conv 5输出的特征图即输入SPP结构的特征图的数量

这种处理方式具有以下的优点:

SPP is able to generate a fixed-length output regardless of the input size, while the sliding window pooling used in the previous deep networks cannot

这种方法由于不是像传统的词袋模型那样,直接将图像中所有的图像块作为特征向量放入词袋模型中,所以不会破坏特征图的空间信息

SPP uses multi-level spatial bins, while the sliding window pooling uses only a single window size. Multi-level pooling has been shown to be robust to object deformations

SPP can pool features extracted at variable scales thanks to the flexibility of input scales.

SPP-net not only makes it possible to generate representations from arbitrarily sized images/windows for testing, but also allows us to feed images with varying sizes or scales during training. Training with variable-size images increases scale-invariance and reduces over-fitting.

在检测中,SPP-Net不用像R-CNN那样对每张图片中的上千个变形后的区域的像素反复调用CNN,只需要在整张图片上运行一次卷积网络层(不关心窗口的数量),然后再使用SPP-net在特征图上抽取特征,这里用一张图可以形象的说明:

在这里插入图片描述

SPP-Net的训练

由于GPU的实现(如cuda-convnet和Caffe)更适合运行在固定输入图像上,因此SPP-Net采用下面两种训练方式:

单一尺寸训练

首先考虑接收裁剪成224×224图像的网络。裁剪的目的是数据增强。对于一个给定尺寸的图像,我们先计算空间金字塔池化所需要的块(bins)的大小。试想一个尺寸是axa(也就是13×13)的conv5之后特征图。对于nxn块的金字塔级,我们实现一个滑窗池化过程,窗口大小为win = 上取整[a/n],步幅str = 下取整[a/n]. 对于l层金字塔,我们实现l个这样的层。然后将l个层的输出进行连接输出给全连接层。

多尺寸训练

携带SPP的网络可以应用于任意尺寸,为了解决不同图像尺寸的训练问题,我们考虑一些预设好的尺寸。现在考虑这两个尺寸:180×180,224×224。我们使用缩放而不是裁剪,将前述的224的区域图像变成180大小。这样,不同尺度的区域仅仅是分辨率上的不同,而不是内容和布局上的不同。对于接受180输入的网络,我们实现另一个固定尺寸的网络。本例中,conv5输出的特征图尺寸是axa=10×10。我们仍然使用win = 上取整[a/n],str = 下取整[a/n],实现每个金字塔池化层。这个180网络的空间金字塔层的输出的大小就和224网络的一样了。
这样,这个180网络就和224网络拥有一样的参数了。换句话说,训练过程中,我们通过使用共享参数的两个固定尺寸的网络实现了不同输入尺寸的SPP-net。
为了降低从一个网络(比如224)向另一个网络(比如180)切换的开销,我们在每个网络上训练一个完整的epoch,然后在下一个完成的epoch再切换到另一个网络(权重保留)。依此往复。实验中我们发现多尺寸训练的收敛速度和单尺寸差不多。

SPP-Net用于物体检测

在这里插入图片描述

将SPP-Net应用于检测的步骤如下:

  1. 使用主干网络提取特征,取conv5产生的特征图
  2. 根据Selective Search方法在原始图像中选取到的候选框的位置映射到conv5产生的特征图中,利用该区域的特征图使用SPP产生定长的特征
  3. SVM分类器根据上面的特征进行分类
  4. 利用Bounding Box回归收紧检测框

SPP-Net的测试结果总结

  1. 多尺度训练的效果比单尺度训练的好
  2. 采用整幅图进行训练的效果比只采用图像正中间裁切后的图像块的效果好
  3. 给定两个模型,我们首先使用每个模型对测试图像的候选框进行打分。然后对并联的两个候选框集合上应用最大化抑制。一个方法比较置信的窗口就会压制另一个方法不太置信的窗口。通过这样的结合,mAP得到有效的提升,这意味着双模型是互补的。并且这种互补性主要是因为卷积层,结合卷积模型完全相同的两个模型,则没有任何效果。

Fast R-CNN

《Fast R-CNN》

作为改进之前方法的论文,第一步,当然是水一下之前的论文了:
这里主要针对R-CNN及其改进版本SPP-Net:

R-CNN和SPP-Net的缺点以及Fast R-CNN的贡献

  • R-CNN缺点
    1. 训练过程是多级pipline:即先训练CNN网络,然后根据CNN生成的特征训练SVM分类器
    2. 训练时空间和时间开销大:R-CNN训练时是将每一张图片中的所有RoI区域作为输入网络的图片,而同一张图片中的RoI区域之间存在着很大程度上的重叠,因此对每一个RoI区域进行网络传播会造成大量的冗余计算,同时由于SVM分类器的训练需要CNN提取的特征,因此前面的冗余计算同样会导致存储这些CNN产生的特征会造成空间上的冗余
    3. 测试速度慢:对于每一个候选框都进行一次CNN的正向传播,因此目标检测速度很慢
  • SPP-Net的缺点
    1. 训练过程是多级pipline
    2. 提取特征使用共享计算,但是仍需要将特征文件写入内存,供后面分类器的训练
  • Fast R-CNN的贡献
    1. 训练是使用多任务损失的单阶段训练,可以更新所有网络层参数
    2. 训练时将一站个图片及其对应的RoI区域送入网络中,利用RoI pooling层实现特征的共享,大大的减少了R-CNN中训练时空间和时间上的冗余
    3. 不需要磁盘空间缓存特征,来提供给分类器的训练
    4. 比R-CNN和SPPnet具有更高的目标检测精度

Fast R-CNN的结构

在这里插入图片描述

网络的整体处理步骤为:
Fast R-CNN网络将整个图像和一组候选框作为输入。网络首先使用几个卷积层和最大池化层来处理整个图像,以产生卷积特征图。然后,对于每个候选框,RoI池化层从特征图中提取固定长度的特征向量。每个特征向量被送入一系列全连接(fc)层中,其最终分支成两个同级输出层 :一个输出K个类别加上1个背景类别的Softmax概率估计,另一个为K个类别的每一个类别输出四个实数值。每组4个值表示K个类别的一个类别的检测框位置的修正。

其中RoI池化层使用最大池化将任何有效的RoI内的特征转换成具有H×W(例如,7×7)的固定空间范围的小特征图,其中H和W是层的超参数,独立于任何特定的RoI。在本文中,RoI是卷积特征图中的一个矩形窗口。 每个RoI由指定其左上角(r,c)及其高度和宽度(h,w)的四元组(r,c,h,w)定义。RoI最大池化通过将大小为h×w的RoI窗口分割成H×W个网格,子窗口大小约为h/H×w/W,然后对每个子窗口执行最大池化,并将输出合并到相应的输出网格单元中。同标准的最大池化一样,池化操作独立应用于每个特征图通道。RoI层只是SPPnets中使用的空间金字塔池层的特殊情况,其只有一个金字塔层。

这里采用博客Fast RCNN算法详解中的两幅图来说明Fast R-CNN在上面网络结构下的训练和测试过程:
在这里插入图片描述
下面就具体根据训练和测试两个过程来分别说明Fast R-CNN算法的详细情况

Fast R-CNN的训练

从预训练网络初始化

Fast R-CNN采用了三个ImageNet预训练的网络:AlexNet,VGG_CNN_M_1024以及VGG16,对这些网络进行下面的结构替换:

  1. 将网络的输入改为:图像的列表和这些图像中RoI的列表
  2. 将最后的池化层替换成Rol池化,假设预训练网络的输入图片大小为h和w,池化层之后的全连接层输出为:batchsize×c×1×1batchsize\times c\times 1\times 1,那么Rol池化层中H和W两个超参数设置为(这里假设网络中的特征图长和宽相等):
    H=h/c,W=w/cH=h/\sqrt{c}, W=w/\sqrt{c}
  3. 将网络的最后一格全连接层和Softmax(其被训练用于1000类ImageNet分类)被替换为前面描述的两个同级层(全连接层和K+1个类别的Softmax以及类别特定的检测框回归)

训练配置

训练数据采样方式

不同于R-CNN和SPPNet将图像中每一个RoI区域作为输入来进行反向传播训练,Fast R-CNN采用一种更有效的训练方式:
在Fast R-CNN网络训练中,随机梯度下降的小批量是被分层采样的,首先采样N个图像,然后从每个图像采样R/N个RoI。关键的是,来自同一图像的RoI在向前和向后传播中共享计算和内存。减小N,就减少了小批量的计算。例如,当N=2和R=128时,得到的训练方案比从128幅不同的图采样一个RoI(即R-CNN和SPPnet的策略)快64倍。在微调期间,每个SGD的小批量由N=2个图像构成,均匀地随机选择。我们使用大小为R=128的小批量,从每个图像采样64个RoI。并且这N张图片以0.5的概率水平翻转,其中正例和负例如下表选择方式:

类别 比例 方式
正例 25% 与GT bounding box的IoU在[0.5,1)
负例 75% 与GT bounding box的IoU在[0.1,0.5)

从训练配置中训练数据采样方式的表中可以看出,Fast R-CNN中训练CNN还是采用R-CNN中1:3的正例和负例比例以及训练CNN中区分正例和负例的IoU阈值,因此这里实际上还是引入了R-CNN中讨论的一个问题,采用上面这种IoU值来区分正例和负例会引入“jittered example”,即大量的正例与GT的bounding box之间还是存在一些偏差,不是精确的定位位置,导致CNN学到的分类边界不明显,可是Fast R-CNN采用这种方式来进行训练却比R-CNN和SPPNet中的效果好很多,里面可能存在的原因是什么?论文中给出的答案是:

“one-shot” fine-tuning is sufficient compared to previous multi-stage training approaches. We note that softmax, unlike one-vs-rest SVMs, introduces competition between classes when scoring a RoI.

上面的解释主要说明了直接端到端训练的有效性,并且由于softmax分类器不同于SVM是直接对21个类别进行分类,引入了不同类别之间的竞争(为什么引入不同类别之间的竞争会对最后的分类结果有帮助?)。

多任务损失

Fast R-CNN中将分类和回归损失合并为一个损失函数:
L(p,u,tu,v)=Lcls(p,u)+λ[u1]Lloc(tu,v)L(p,u,t^u,v)=L_{cls}(p,u)+\lambda[u\ge1]L_{loc}(t^u,v)
其中分类损失函数如下,即为softmax预测到的第uu类物体的概率值,负号为了使该概率值越大,LclsL_{cls}值越小
Lcls(p,u)=log(pu)L_{cls}(p,u)=-log(p_u)
回归损失函数如下,其中(tiuvi)(t_i^u-v_i)部分主要参考R-CNN中的检测框回归,主要的不同在于Fast R-CNN中采用的是Smooth L1损失,而R-CNN中采用的是L2损失:
Lloc(tu,v)=i{x,y,w,h}smoothL1(tiuvi)L_{loc}(t^u,v)=\sum_{i\in\{x,y,w,h\}}smooth_{L_1}(t_i^u-v_i)

smoothL1(x)={0.5x2x1x0.5otherwisesmooth_{L_{1}}(x)= \begin{cases} 0.5x^{2} & |x|\leq 1 \cr |x|-0.5 & otherwise \end{cases}

Smooth L1损失相较于L1 loss和L2 loss而言具有以下优点:
在这里插入图片描述

个人觉得这里采用Smooth L1损失主要是因为:根据上面关于R-CNN中loss函数的分析博客https://blog.csdn.net/zijin0802034/article/details/77685438可知,由于R-CNN只挑选出IoU>0.6的检测框来训练回归模型,所以可以控制预测的检测框与GT之间的差值较小,保证其为线性回归问题,但是在Fast R-CNN中由于采用多任务损失进行联合训练,并且从损失函数可以看到,是分类的结果决定了检测的结果(即只有当分类结果u1u\ge1时,检测部分的损失才会大于0),因此如果分类出现了错误导致预测的检测框与实际的检测框相距很远时,使用L2损失很容易导致梯度爆炸,因此采用Smooth L1损失。同时由于采用Smooth L1损失可以避免预测的检测框与实际的检测框相距很远造成的梯度爆炸,便可以省略R-CNN检测框回归中的正则项

RoI池化层的反向传播SVD分解见博客Fast RCNN算法详解

实验结果

  • 使用多尺度的图像金字塔,性能几乎没有提高
  • 倍增训练数据,能够有2%-3%的准确度提升
  • 网络直接输出各类概率(softmax),比SVM分类器性能略好
  • 更多候选窗不能提升性能

Fast R-CNN测试

Fast RCNN测试中region proposal的提取仍然使用selective search,其他过程与训练中前向传播的过程一致,同时目标检测时间大多消耗在这上面(提region proposal 2~3s,而提特征分类只需0.32s)

Faster R-CNN

《Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks》

提出问题:

在之前的SPPNet和Fast-RNN的研究中,利用RoI池化层实现了直接在卷积网络提取的特征上选取候选框区域,并对于每一个不同大小的候选框区域生成相同大小的特征向量,最后对每一个候选框进行分类。因此这类研究已经非常有效的减少了检测网络的运行时间,但是region proposal的提取仍然使用selective search算法,使得区域提出计算成为一个瓶颈。

本文解决方案

提出RPN网络,它是一个全卷积网络,可以同时在每个位置预测目标边界和目标分数。RPN经过端到端的训练,可以生成高质量的区域提出,由Fast R-CNN用于检测。

Faster R-CNN参考博文

通过下面这几篇博文对于Faster R-CNN可以有一个非常全面的了解:

我主要针对上面博文会涉及到的我之前没有弄明白的几个问题做以下的补充。

卷积层感受野的计算

在论文的3.1节介绍RPN网络的内容中,有下面这一段话:

To generate region proposals, we slide a small network over the convolutional feature map output by the last shared convolutional layer. This small network takes as input an n × n spatial window of the input convolutional feature map. Each sliding window is mapped to a lower-dimensional feature (256-d for ZF and 512-d for VGG, with ReLU [33] following). This feature is fed into two sibling fullyconnected layers—a box-regression layer (reg) and a box-classification layer (cls). We use n = 3 in this paper, noting that the effective receptive field on the input image is large (171 and 228 pixels for ZF and VGG, respectively). This mini-network is illustrated at a single position in Figure 3 (left). Note that because the mini-network operates in a sliding-window fashion, the fully-connected layers are shared across all spatial locations. This architecture is naturally implemented with an n×n convolutional layer followed by two sibling 1 × 1 convolutional layers (for reg and cls, respectively).

在这里插入图片描述

(下面主要以VGG为例)结合论文中的示意图片,是解释RPN网络中采用3x3的卷积核在VGG网络的conv5_3产生的feature map上进行滑动,并产生不同大小的anchor box,这里存在的一个问题就是上面加黑的那句话中,在VGG的网络中3x3的卷积核在VGG网络的conv5_3产生的feature map上的区域对应的感受野大小是228,所以这里主要讲解一下感受野的计算。

感受野的计算主要可以分为两种方法,一种是自顶向下的计算方法,一种是自底向上的计算方法,两种方法分别适用于不同的情况:

  • 需要知道整个网络从上到下每一层特征图对应于原始输入图片的感受野大小,采用自顶向下的方式
  • 只需要求解某一层特征图对应的感受野大小,并且不需要知道其上各个层的感受野,采用自底向上的方式
  • 只需要求解某一层特征图对应的感受野大小,并且需要知道其上各个层的感受野,采用自顶向下的方式

从上面的描述中可以发现,自顶向下的计算方法在求解的过程中可以知道每一层的感受野大小,而自底向上的方式不行,只能用于求解某一层特征图对应的感受野大小。可是自底向上的方式相较于自顶向下的方式计算的过程稍微简单一点,不容易弄错,所以当我们只需要求解某一层特征图对应的感受野大小,并且不需要知道其上各个层的感受野,更推荐自底向上的方式

1. 自顶向下的计算方法

这种计算方法是从输入图片开始,向下逐层计算每一层特征图中r0×r0r_0\times r_0的范围内对应在原始输入图片中的感受野大小。主要过程为:

首先假设我们需要求的感受野范围是r0×r0r_0\times r_0,并且输出特征图的jump为jj,该值是卷积核的步长从上到下的累积量,那么有:

{ri+1=ri+(ki+11)×ji ji+1=ji×si+1\left\{ \begin{array}{lr} r_{i+1} = r_i + (k_{i+1} -1)\times j_i & \\\ j_{i+1} = j_i\times s_{i+1} \end{array} \right.

其中kk为卷积核的大小,ss为卷积核的步长。初始情况下:

  • r0×r0r_0\times r_0为我们需要求的感受野范围
  • j0=1j_0 = 1
  • k1×k1k_1 \times k_1为第一层卷积核的尺寸

后面层数的计算以此类推,主要需要注意的是在计算ri+1r_{i+1}的时候,使用的是jij_i而不是ji+1j_{i+1}。正是由于我们自顶向下的求解过程中需要求解卷积核步长的累加量,所以相较于自底向上的方法要稍微复杂一点

上面的内容主要参考:

卷积神经网络中的感受野计算(译)

特征图尺寸和感受野计算详解

下面这个用于实现计算网络感受野的网站也是使用这种方式来进行计算的:

Fomoro AI

2. 自底向上的计算方法

这种方法是从我们需要求解的层开始逐层向上进行计算,采用与上面相同的符号,可以有下面的地推公式:

rn1=sn1×(rn1)+kn1r_{n-1} = s_{n-1}\times (r_{n}-1)+k_{n-1}

由于我们是自底向上进行求解,所以这里的初始值是第nn层的特征图需要求解的感受野范围:

初始情况如下:

  • rn×rnr_n\times r_n为第nn层的特征图需要求解的感受野范围
  • sn1s_{n-1}为产生第nn层的特征图的卷积核对应的步长
  • kn1k_{n-1}为产生第nn层的特征图的卷积核对应的尺寸

这种方式不需要计算步长的累加量,所以更加简洁一些,其计算的中间结果对应于第nn层的特征图对应于其上的各个层次的特征图的感受野范围。

上面的内容主要参考:

CNN:接受视野(Receptive Field)

损失函数详细解释

Faster R-CNN中的损失函数分为两个部分:

  1. RPN网络中判断Anchor是否包含物体的分类损失以及收紧Anchor的回归损失组成的损失函数
  2. Fast R-CNN中判断region proposal中目标类别的分类损失以及收紧检测框的回归损失组成的损失函数

以上两个多任务损失函数中的分类损失均采用交叉熵损失函数,回归损失均采用R-CNN中的Bounding Box Regression损失函数,所以下面主要分成这两部分来进行分析。

1. 交叉熵损失函数

  • 信息熵

为了说明交叉熵,我们从信息熵这个源头来进行解释。

在我们的生活中,信息的作用是为了消除不确定性,不能消除不确定性的信息我们称之为噪声。而信息量就可以被看做是衡量事件不确定性的量。事件的不确定性可以理解为一个事件有多少种等可能的情况可能发生,这个可能性可以用概率来进行描述。那么我们如何衡量这个不确定性的量呢?这里可以由质量的定义来进行类推,我们为了用单位千克来衡量一个物体的质量,会选择一个参照物的质量作为基准,假设这个基准物体的质量为B,待测物体的质量为m,那么有:

m=n×Bm = n\times B

而为了衡量待测物体的质量,就可以用乘法的反函数即除法来进行:

n=m/Bn = m / B

所以待测物体的重量为nn千克。

同样的,为了衡量一个事件不确定的量,我们同样可以找一个参照事件作为基准来进行衡量,假设我们选取的事件是抛硬币,对于一枚硬币的抛硬币事件,有正面和反面两种可能性,即212^1种可能性,而对于两枚硬币则有222^2种可能性。假设待测事件可能发生的情况有m种,那么就有:

m=2nm = 2^n

为了衡量待测事件相当于多少个抛硬币事件,即为指数函数的反函数即对数函数来进行求解:

n=log2mn = log_2m

这里我们用bit来作为单位,所以待测事件的信息量为nnbit。

上面在说明的时候,我们强调上面所有可能发生的情况都是等可能发生的,可是当各个情况不是等可能性的时候该怎样进行衡量呢?

这里假设我们的事件有四种可能发生的情况为A,B,C,D,其中三种情况发生的概率为1/6,第四种情况发生的概率为1/2,按照上面的分析,此时我们计算这个事件的信息量即为(假设四个事件可能发生的情况分别为mAm_AmBm_BmCm_CmDm_D):

n=PA×log2mA+PB×log2mB+PC×log2mC+PD×log2mDn = P_A\times log_2m_A + P_B\times log_2m_B + P_C\times log_2m_C + P_D\times log_2m_D

那么怎样计算mAm_AmBm_BmCm_CmDm_D呢?这里我们首先有PA=1/6P_A = 1/6PB=1/6P_B = 1/6PC=1/6P_C = 1/6PD=1/2P_D = 1/2,对于mAm_A,即A事件可能发生的情况,按照PA=1/6P_A = 1/6,说明A事件有6中可能发生的情况,所以mA=1/PAm_A = 1 / P_A,因此上式可以写为:

n=PA×log2(1/PA)+PB×log2(1/PB)+PC×log2(1/PC)+PD×log2(1/PD)n = P_A\times log_2(1/P_A) + P_B\times log_2(1/P_B) + P_C\times log_2(1/P_C) + P_D\times log_2(1/P_D)

而这里的信息量我们用信息熵H来定义,假设事件有N种情况,情况ii发生的概率为PiP_i,同时我们用于衡量的基准事件有m中可能发生的情况,那么有:

H=i=0NPilogmPiH = - \sum_{i=0}^{N} P_ilog_mP_i

可以发现信息熵的形式与我们最终要讨论的交叉熵形式上非常相似。

参考:学习观10:信息与熵

学习观11:量化信息

​ 《数学之美》第6章:信息的度量和作用

  • 交叉熵

参考【直观详解】信息熵、交叉熵和相对熵

  • 交叉熵损失函数

在Faster R-CNN中分类损失函数为:

  1. RPN中分类前景和背景两个类别的损失函数(NclsN_{cls}是mini-batch的数量):1/Ncls(pilogpi+pilogpi)-1/N_{cls}(p_ilogp_i+p_i^*logp_i^*)
  2. Fast R-CNN中分类多个类别uu的损失函数:logpu-logp_u

1中的损失函数是标准的信息熵的形式,即当分类器预测前景和背景两者的概率分别为1/2时,其信息熵值最大,也即是损失函数值最大,利用梯度下降法进行训练后,让分类器能够改变两种情况的预测概率,当其中一个的概率接近1,另一个接近0时,其信息熵值最小,也即是损失函数值最小。

2中的损失函数则是交叉熵的形式,其函数log前面没有参数,也即是将各个类别的发生概率同等看待,因为在真实的分布下,各个类别是等可能发生的,而我们训练分类器同样是要改变各个类别的分布概率,让分类器尽量使其中一种类别的预测概率接近1,其他的类别预测概率接近0,这样就可以减少损失函数的大小,也即是在给定的真实分布情况下,使用非真实分布指定的策略消除系统的不确定性所需要付出努力的大小。

2. 边框回归损失函数

边框损失函数主要参考:边框回归(Bounding Box Regression)详解

上面的边框回归详解中是解释R-CNN中的边框损失,而Faster R-CNN中的边框回归损失分为两类:

  1. RPN中的边框回归损失,与上面参考博客唯一的不同是这里的Region Proposal采用的是预设的Anchor来生成
  2. Fast R-CNN中的边框回归损失,与上面参考博客唯一的不同是这里的Region Proposal采用的是RPN中生成的结果

而两个边框回归损失为了避免Region Proposal和Ground Truth相差较大,导致损失函数的值过大,于是采用了Smooth L1损失函数,同时引入了λ\lambda参数来平衡多任务损失函数中分类损失函数和边框回归损失函数两者的权重平衡,保证损失函数对于两类损失函数给予相同的关注程度

SoftMax函数实现细节

在上面一文读懂Faster RCNN的博客2.3节softmax判定foreground与background中,RPN网络在预测前景和背景类别的时候,采用下面的结构进行:

在这里插入图片描述

第一次reshape将原始的caffe blob中的存储形式[1, 2x9, H, W]转换为[1, 2, 9xH, W],而softmax层进行多分类时,在caffe中的实现实际上是:

"Number of labels must match number of predictions; "
"e.g., if softmax axis == 1 and prediction shape is (N, C, H, W), "
"label count (number of labels) must be N*H*W, "
"with integer values in {0, 1, ..., C-1}.";

即是将channel的数量作为类别的数量,而N*H*W均为表示这个类别的特征,这里稍微补充一下。

自己还存在的问题

在Faster R-CNN的ROI Pooling步骤中,以VGG作为主干网络为例,用于ROI Pooling的特征图为conv5_3生成的大小为[1,512,14,14],可以发现特征图的大小为14×1414\times 14,可是ROI Pooling中pooledw×poolh=7×7pooled_w\times pool_h = 7\times 7

用于ROI Pooling的特征图也即是用于生成Anchor的特征图,生成Anchor仅仅用3×33\times 3的划窗进行生成,可是pooledw×poolhpooled_w\times pool_h参数却为7×77\times 7,很明显对于aspect ratio为0.5的Anchor,根本就没有7×77\times 7个像素来做ROI Pooling,这个位置到底是怎样设计的,难道此处的ROI Pooling操作是在输入图片上来采集特征?感觉也不对啊。希望有知道的小伙伴能够告知,感恩!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章