《OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks》
在早期方法中,通常使用以下的传统框架进行目标检测任务(这里以人脸检测作为一个例子):
可以看到传统的框架通常使用下面的步骤进行检测任务:
在上面的步骤中很明显可以发现传统检测方法是将分类和定位任务分开进行,并利用滑窗策略来对图像中的所有位置进行定位(后面简称为滑窗定位策略),即将分类和滑窗定位策略合并起来最终完成检测任务。
上面的传统方法检测框架中直觉上主要的改进可以朝着两个方向进行:
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整体流程图如下所示:
Offset pooling可以看做是一种特征图滑窗策略,用于针对同一尺度下的输入图片产生的特征图中不同位置进行分类和检测,用于替代传统方法中在输入图片上进行密集滑窗策略这种耗时的操作。在论文中的解释如下:
具体操作步骤为:
其中的layer5即对应OverFeat整体流程图中特征图2
OverFeat论文中的特征提取模型是在AlexNet的基础上进行改进(注意后面的分析均是基于高精度模型):
在此基础上,作者构造出了快速模型和高精度模型两种架构:
在分类任务的训练阶段,OverFeat采用AlexNet的图像增强方法:
再将上述图像增强后的图片输入网络进行训练
AlexNet在模型测试阶段的方法为:
由于AlexNet的测试方法对于检测任务来说,存在以下缺点:
针对以上问题OverFeat采用以下测试方法:
保持分类模型中训练好的OverFeat模型参数不变,在模型后面加上定位任务的网络进行训练,从而得到最终的定位网络(文中并没有给出训练回归任务的loss函数)
从上图可以看到,以281x317的输入尺寸为例,OverFeat论文中对于上面OverFeat整体流程图中特征图2首先进行一个5x5的pooling层得到2x3的特征图,然后经过4096x1x1和1000x1x1的全连接层(这里使用FCN实现)之后最终输出每一个尺度产生的每一个特征图中的每一个像素点映射到原图中的检测框的坐标值,即图中的(top, left, right, right box edges)。对此,作者通过下面的几组图片分析了多尺度策略,offset pooling策略对模型产生检测框的密集度:
整体上OverFeat利用OverFeat特征提取器来提取特征,将该特征运用于后面的分类和定位任务,即可以看作对于后面产生的特征图中的每一个像素点映射到原始图中的区域,在该区域预测出分类任务中各个类别的概率以及回归任务中检测框的坐标值,下面同样以281x317的输入尺寸为例,给出网络同时进行两项任务的示意图:
https://zhum.in/blog/project/TrafficSignRecognition/OverFeat论文阅读笔记/
《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挑战的物体检测任务上?
针对这个问题,本文主要关注两个方面:
下面就上面两个问题进行分析R-CNN的脉络
在图像中定位物体通常使用一下两种方法:
下面具体说明R-CNN的具体构造:
如上图所示,R-CNN的测试部分主要分为三个模块:
R-CNN采用论文《Selective search for object recognition》中的Selective Search方法来产生2000个后面需要的候选框,这个方法主要有三个优势:
Selective Search算法主要包含两个内容
Hierarchical Grouping Algorithm
Diversification Strategies
这个部分涉及到多样性的一些策略,使得抽样多样化,主要有下面三个不同方面:
主要参考:https://zhuanlan.zhihu.com/p/39927488
上图中展示了作者在附录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个百分点
通过对每个类别训练出来的SVM对以上每个候选框产生的4096维特征向量进行打分,然后给出一张图像中所有的打分区域,然后使用NMS(每个类别是独立进行的),拒绝掉一些和高分区域的IOU大于阈值的候选框。
由于目标检测的数据集标注数据较少,训练AlexNet这样的大型网络较为困难,于是产生了上面提到的第二个问题:
training a high-capacity model with only a small quantity of annotated detection data
与上面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的负例
一、 为什么使用不同的正负例IoU阈值
首先,两者的不同在于
而产生两种不同策略的原因在于:
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的好
作者通过在上面提出的模型的基础上分别用Pool5、fc6以及fc7产生的特征来训练SVM,并使用SVM进行分类后的mAP指标如下:
(这里没有看的太明白)
通过上面的检测错误分析,作者指出:
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函数的设计原理)
《Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition》
流行的CNN结构通常都需要输入图像的尺寸是固定的,这限制了输入图像的长宽比和缩放尺度。当遇到任意尺寸的图像时,都是先将图像利用裁剪和变形缩放的方式来适应成固定尺寸。但裁剪会导致信息的丢失,变形会导致位置信息的扭曲,就会影响识别的精度。另外,一个预先定义好的尺寸在物体是缩放可变的时候就不适用了。
产生问题的原因主要来自网络的全连接层,也即是网络的最后阶段。
解决上面CNN输入固定问题的解决方案当然是本文的主角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
通过上图中将经典的7层网络结构(如AlexNet或VGGNet)中conv5层产生的特征图进行可视化可以发现,CNN中的滤波器会被一些特定的语义激活,而这些滤波器也会在图像中采集相应的语义信息。这项特性说明CNN也和传统方法一样使用以下步骤:
而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在特征图上抽取特征,这里用一张图可以形象的说明:
由于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应用于检测的步骤如下:
《Fast R-CNN》
作为改进之前方法的论文,第一步,当然是水一下之前的论文了:
这里主要针对R-CNN及其改进版本SPP-Net:
网络的整体处理步骤为:
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采用了三个ImageNet预训练的网络:AlexNet,VGG_CNN_M_1024以及VGG16,对这些网络进行下面的结构替换:
训练数据采样方式
不同于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 , t u , v ) = L c l s ( p , u ) + λ [ u ≥ 1 ] L l o c ( t u , v ) L(p,u,t^u,v)=L_{cls}(p,u)+\lambda[u\ge1]L_{loc}(t^u,v) L(p,u,tu,v)=Lcls(p,u)+λ[u≥1]Lloc(tu,v)
其中分类损失函数如下,即为softmax预测到的第 u u u类物体的概率值,负号为了使该概率值越大, L c l s L_{cls} Lcls值越小
L c l s ( p , u ) = − l o g ( p u ) L_{cls}(p,u)=-log(p_u) Lcls(p,u)=−log(pu)
回归损失函数如下,其中 ( t i u − v i ) (t_i^u-v_i) (tiu−vi)部分主要参考R-CNN中的检测框回归,主要的不同在于Fast R-CNN中采用的是Smooth L1损失,而R-CNN中采用的是L2损失:
L l o c ( t u , v ) = ∑ i ∈ { x , y , w , h } s m o o t h L 1 ( t i u − v i ) L_{loc}(t^u,v)=\sum_{i\in\{x,y,w,h\}}smooth_{L_1}(t_i^u-v_i) Lloc(tu,v)=i∈{x,y,w,h}∑smoothL1(tiu−vi)
s m o o t h L 1 ( x ) = { 0.5 x 2 ∣ x ∣ ≤ 1 ∣ x ∣ − 0.5 o t h e r w i s e smooth_{L_{1}}(x)= \begin{cases} 0.5x^{2} & |x|\leq 1 \cr |x|-0.5 & otherwise \end{cases} smoothL1(x)={0.5x2∣x∣−0.5∣x∣≤1otherwise
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中由于采用多任务损失进行联合训练,并且从损失函数可以看到,是分类的结果决定了检测的结果(即只有当分类结果 u ≥ 1 u\ge1 u≥1时,检测部分的损失才会大于0),因此如果分类出现了错误导致预测的检测框与实际的检测框相距很远时,使用L2损失很容易导致梯度爆炸,因此采用Smooth L1损失。同时由于采用Smooth L1损失可以避免预测的检测框与实际的检测框相距很远造成的梯度爆炸,便可以省略R-CNN检测框回归中的正则项
RoI池化层的反向传播和SVD分解见博客Fast RCNN算法详解
Fast RCNN测试中region proposal的提取仍然使用selective search,其他过程与训练中前向传播的过程一致,同时目标检测时间大多消耗在这上面(提region proposal 2~3s,而提特征分类只需0.32s)
《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可以有一个非常全面的了解:
我主要针对上面博文会涉及到的我之前没有弄明白的几个问题做以下的补充。
在论文的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. 自顶向下的计算方法
这种计算方法是从输入图片开始,向下逐层计算每一层特征图中 r 0 × r 0 r_0\times r_0 r0×r0的范围内对应在原始输入图片中的感受野大小。主要过程为:
首先假设我们需要求的感受野范围是 r 0 × r 0 r_0\times r_0 r0×r0,并且输出特征图的jump为 j j j,该值是卷积核的步长从上到下的累积量,那么有:
{ r i + 1 = r i + ( k i + 1 − 1 ) × j i j i + 1 = j i × s i + 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. {ri+1=ri+(ki+1−1)×ji ji+1=ji×si+1
其中 k k k为卷积核的大小, s s s为卷积核的步长。初始情况下:
后面层数的计算以此类推,主要需要注意的是在计算 r i + 1 r_{i+1} ri+1的时候,使用的是 j i j_i ji而不是 j i + 1 j_{i+1} ji+1。正是由于我们自顶向下的求解过程中需要求解卷积核步长的累加量,所以相较于自底向上的方法要稍微复杂一点
上面的内容主要参考:
卷积神经网络中的感受野计算(译)
特征图尺寸和感受野计算详解
下面这个用于实现计算网络感受野的网站也是使用这种方式来进行计算的:
Fomoro AI
2. 自底向上的计算方法
这种方法是从我们需要求解的层开始逐层向上进行计算,采用与上面相同的符号,可以有下面的地推公式:
r n − 1 = s n − 1 × ( r n − 1 ) + k n − 1 r_{n-1} = s_{n-1}\times (r_{n}-1)+k_{n-1} rn−1=sn−1×(rn−1)+kn−1
由于我们是自底向上进行求解,所以这里的初始值是第 n n n层的特征图需要求解的感受野范围:
初始情况如下:
这种方式不需要计算步长的累加量,所以更加简洁一些,其计算的中间结果对应于第 n n n层的特征图对应于其上的各个层次的特征图的感受野范围。
上面的内容主要参考:
CNN:接受视野(Receptive Field)
Faster R-CNN中的损失函数分为两个部分:
以上两个多任务损失函数中的分类损失均采用交叉熵损失函数,回归损失均采用R-CNN中的Bounding Box Regression损失函数,所以下面主要分成这两部分来进行分析。
1. 交叉熵损失函数
为了说明交叉熵,我们从信息熵这个源头来进行解释。
在我们的生活中,信息的作用是为了消除不确定性,不能消除不确定性的信息我们称之为噪声。而信息量就可以被看做是衡量事件不确定性的量。事件的不确定性可以理解为一个事件有多少种等可能的情况可能发生,这个可能性可以用概率来进行描述。那么我们如何衡量这个不确定性的量呢?这里可以由质量的定义来进行类推,我们为了用单位千克来衡量一个物体的质量,会选择一个参照物的质量作为基准,假设这个基准物体的质量为B,待测物体的质量为m,那么有:
m = n × B m = n\times B m=n×B
而为了衡量待测物体的质量,就可以用乘法的反函数即除法来进行:
n = m / B n = m / B n=m/B
所以待测物体的重量为 n n n千克。
同样的,为了衡量一个事件不确定的量,我们同样可以找一个参照事件作为基准来进行衡量,假设我们选取的事件是抛硬币,对于一枚硬币的抛硬币事件,有正面和反面两种可能性,即 2 1 2^1 21种可能性,而对于两枚硬币则有 2 2 2^2 22种可能性。假设待测事件可能发生的情况有m种,那么就有:
m = 2 n m = 2^n m=2n
为了衡量待测事件相当于多少个抛硬币事件,即为指数函数的反函数即对数函数来进行求解:
n = l o g 2 m n = log_2m n=log2m
这里我们用bit来作为单位,所以待测事件的信息量为 n n nbit。
上面在说明的时候,我们强调上面所有可能发生的情况都是等可能发生的,可是当各个情况不是等可能性的时候该怎样进行衡量呢?
这里假设我们的事件有四种可能发生的情况为A,B,C,D,其中三种情况发生的概率为1/6,第四种情况发生的概率为1/2,按照上面的分析,此时我们计算这个事件的信息量即为(假设四个事件可能发生的情况分别为 m A m_A mA, m B m_B mB, m C m_C mC, m D m_D mD):
n = P A × l o g 2 m A + P B × l o g 2 m B + P C × l o g 2 m C + P D × l o g 2 m D n = P_A\times log_2m_A + P_B\times log_2m_B + P_C\times log_2m_C + P_D\times log_2m_D n=PA×log2mA+PB×log2mB+PC×log2mC+PD×log2mD
那么怎样计算 m A m_A mA, m B m_B mB, m C m_C mC, m D m_D mD呢?这里我们首先有 P A = 1 / 6 P_A = 1/6 PA=1/6, P B = 1 / 6 P_B = 1/6 PB=1/6, P C = 1 / 6 P_C = 1/6 PC=1/6, P D = 1 / 2 P_D = 1/2 PD=1/2,对于 m A m_A mA,即A事件可能发生的情况,按照 P A = 1 / 6 P_A = 1/6 PA=1/6,说明A事件有6中可能发生的情况,所以 m A = 1 / P A m_A = 1 / P_A mA=1/PA,因此上式可以写为:
n = P A × l o g 2 ( 1 / P A ) + P B × l o g 2 ( 1 / P B ) + P C × l o g 2 ( 1 / P C ) + P D × l o g 2 ( 1 / P D ) 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) n=PA×log2(1/PA)+PB×log2(1/PB)+PC×log2(1/PC)+PD×log2(1/PD)
而这里的信息量我们用信息熵H来定义,假设事件有N种情况,情况 i i i发生的概率为 P i P_i Pi,同时我们用于衡量的基准事件有m中可能发生的情况,那么有:
H = − ∑ i = 0 N P i l o g m P i H = - \sum_{i=0}^{N} P_ilog_mP_i H=−i=0∑NPilogmPi
可以发现信息熵的形式与我们最终要讨论的交叉熵形式上非常相似。
参考:学习观10:信息与熵
学习观11:量化信息
《数学之美》第6章:信息的度量和作用
参考【直观详解】信息熵、交叉熵和相对熵
在Faster R-CNN中分类损失函数为:
1中的损失函数是标准的信息熵的形式,即当分类器预测前景和背景两者的概率分别为1/2时,其信息熵值最大,也即是损失函数值最大,利用梯度下降法进行训练后,让分类器能够改变两种情况的预测概率,当其中一个的概率接近1,另一个接近0时,其信息熵值最小,也即是损失函数值最小。
2中的损失函数则是交叉熵的形式,其函数log前面没有参数,也即是将各个类别的发生概率同等看待,因为在真实的分布下,各个类别是等可能发生的,而我们训练分类器同样是要改变各个类别的分布概率,让分类器尽量使其中一种类别的预测概率接近1,其他的类别预测概率接近0,这样就可以减少损失函数的大小,也即是在给定的真实分布情况下,使用非真实分布指定的策略消除系统的不确定性所需要付出努力的大小。
2. 边框回归损失函数
边框损失函数主要参考:边框回归(Bounding Box Regression)详解
上面的边框回归详解中是解释R-CNN中的边框损失,而Faster R-CNN中的边框回归损失分为两类:
而两个边框回归损失为了避免Region Proposal和Ground Truth相差较大,导致损失函数的值过大,于是采用了Smooth L1损失函数,同时引入了 λ \lambda λ参数来平衡多任务损失函数中分类损失函数和边框回归损失函数两者的权重平衡,保证损失函数对于两类损失函数给予相同的关注程度
在上面一文读懂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 × 14 14\times 14 14×14,可是ROI Pooling中 p o o l e d w × p o o l h = 7 × 7 pooled_w\times pool_h = 7\times 7 pooledw×poolh=7×7。
用于ROI Pooling的特征图也即是用于生成Anchor的特征图,生成Anchor仅仅用 3 × 3 3\times 3 3×3的划窗进行生成,可是 p o o l e d w × p o o l h pooled_w\times pool_h pooledw×poolh参数却为 7 × 7 7\times 7 7×7,很明显对于aspect ratio为0.5的Anchor,根本就没有 7 × 7 7\times 7 7×7个像素来做ROI Pooling,这个位置到底是怎样设计的,难道此处的ROI Pooling操作是在输入图片上来采集特征?感觉也不对啊。希望有知道的小伙伴能够告知,感恩!