在深度学习出现之前,传统的目标检测方法大概分为区域选择(滑窗)、特征提取(SIFT
、HOG
等)、分类器(SVM
、Adaboost
等)三个部分,其主要问题有两方面:一方面滑窗选择策略没有针对性、时间复杂度高,窗口冗余;另一方面手工设计的特征鲁棒性较差。自深度学习出现之后,目标检测取得了巨大的突破,最瞩目的两个方向有:1. 以RCNN
为代表的基于Region Proposal
的深度学习目标检测算法(RCNN
,SPP-NET
,Fast-RCNN
,Faster-RCNN
等);2 以YOLO
为代表的基于回归方法的深度学习目标检测算法(YOLO
,SSD
等)。本篇对基于Region Proposal
的深度学习目标检测算法进行介绍,后续再对基于回归方法的深度学习目标检测方法进行介绍。
使用Selective Search
提取Proposel
,然后利用CNN
等识别技术进行分类。
使用识别库进行预训练,而后用检测库调优参数。
使用SVM
代替了CNN
网络中最后的Softmax
,同时用CNN
输出的4096维向量进行Bounding Box
回归。
流程前两个步骤(候选区域提取+特征提取)与待检测类别无关,可以在不同类之间共用;同时检测多类时,需要倍增的只有后两步骤(判别+精修),都是简单的线性运算,速度很快。
1 训练分为多个阶段,步骤繁琐: 微调网络+训练SVM
+训练边框回归器。
2 训练耗时,占用磁盘空间大:5000张图像产生几百G的特征文件。
3 速度慢: 使用GPU
,VGG16
模型处理一张图像需要47s。
通过Spatial Pyramid Pooling
解决了深度网络固定输入层尺寸的这个限制,使得网络可以享受不限制输入尺寸带来的好处。
解决了RCNN
速度慢的问题,不需要对每个Proposal
(2000个左右)进行Wrap
或Crop
输入CNN
提取Feature Map
,只需要对整图提一次Feature Map
,然后将Proposal
区域映射到卷积特征层得到全链接层的输入特征。
一、ROI在特征图上的对应的特征区域的维度不满足全连接层的输入要求怎么办?
作者使用Spatial Pyramid Pooling
解决了该问题。如下图所示,假设原图输入是224x224
,对于conv5
出来后的输出是13x13x256
的,可以理解成有256
个这样的Filter
,每个Filter
对应一张13x13
的Reponse Map
。如果像上图那样将Reponse Map
分成1x1
(金字塔底座),2x2
(金字塔中间),4x4
(金字塔顶座)三张子图,分别做Max Pooling
后,出来的特征就是(16+4+1)x256
维度。如果原图的输入不是224x224
,出来的特征依然是(16+4+1)x256
维度。这样就实现了不管输入图像尺寸如何,输出永远是 (16+4+1)x256
维度。
二、原始图像的ROI如何映射到特征图(一系列卷积层的最后输出)
要搞定这个问题,需要首先清楚感受野等概念和计算方法。下面从感受野、感受野上面的坐标映射及原始图像的ROI如何映射三方面阐述。
1. 感受野
① 概念
在卷积神经网络中,感受野的定义是卷积神经网络每一层输出的特征图(Feature Map
)上的像素点在原始图像上映射的区域大小。
② 如何计算
output field size = ( input field size - kernel size + 2*padding ) / stride + 1
其中output field size
是卷积层的输出,input field size
是卷积层的输入,反过来卷积层的输入(也即前一层的感受野) = ?答案必然是:
input field size = (output field size - 1)* stride - 2*padding + kernel size
运行结果如下。从运行结果可以看出论文中ZF-5
网络感受野大小为139是什么得到的了。
2.感受野上的坐标映射
① 计算公式
对于Convolution/Pooling Layer
:
p i = s i ⋅ p i + 1 + [ ( k i − 1 ) / 2 − p a d d i n g ] p_i=s_i⋅p_{i+1}+[(k_i−1)/2−padding] pi=si⋅pi+1+[(ki−1)/2−padding]
对于Neuronlayer(ReLU/Sigmoid/...)
:
p i = p i + 1 p_i=p_{i+1} pi=pi+1
其中 p i p_i pi为第 i i i层感受野上的坐标, s i s_i si为Stride
的大小, k i k_i ki为感受野的大小。
② 例子
上面是计算任意一个Layer
输入输出的坐标映射关系,如果是计算任意Feature Map
之间的关系,只需要用简单的组合就可以得到,下图是一个简单的例子:
③ 简化版本
何凯明在SPP-NET
中使用的是简化版本,将2小节公式中的Padding
都设为 ⌊ k i / 2 ⌋ \lfloor k_i/2 \rfloor ⌊ki/2⌋,公式可进一步简化为: p i = s i ⋅ p i + 1 p_i=s_i⋅p_{i+1} pi=si⋅pi+1
3.原始图像的ROI如何映射
SPP-NET
是把原始ROI
的左上角和右下角映射到Feature Map
上的两个对应点。 有了Feature Map
上的两对角点就确定了对应的Feature Map
区域(下图中橙色)。
左上角取 x ′ = ⌊ x / S ⌋ + 1 , y ′ = ⌊ y / S ⌋ + 1 x′=\lfloor x/S\rfloor+1,y′= \lfloor y/S\rfloor+1 x′=⌊x/S⌋+1,y′=⌊y/S⌋+1;右下角的点取 x ′ = ⌈ x / S ⌉ − 1 , y ′ = ⌈ y / S ⌉ − 1 x′=\lceil x/S \rceil−1,y′=\lceil y/S \rceil−1 x′=⌈x/S⌉−1,y′=⌈y/S⌉−1。其中 S S S为坐标映射的简化计算版本,即 S = ∏ 0 i s i S=∏^i_0s_i S=∏0isi。
Fast-RCNN
直接使用Softmax
替代了RCNN
中SVM
进行分类,同时在网络中加入了多任务函数边框回归,实现了广义的端到端的训练。
借鉴SPP-NET
,提出了一个ROI
层。ROI Pooling Layer
实际上是SPP-NET
的一个精简版,SPP-NET
对每个Proposal
使用了不同大小的金字塔映射,而ROI Pooling Layer
只需要下采样到一个7x7
的特征图。对于VGG16
网络conv5_3
有512个特征图,这样所有Region Proposal
对应了一个7*7*512
维度的特征向量作为全连接层的输入。
使用了不同于SPP-NET
的训练方式,训练时,把同张图片的Prososals
作为一批进行学习,而Proposals
的坐标直接映射到conv5
层上,这样相当于一张图片的所有训练样本只卷积了一次。
论文在回归问题上并没有用很常见的2范数
作为回归,而是使用所谓的鲁棒L1
范数作为损失函数。
论文将比较大的全链接层用SVD
分解了一下,使得检测的时候更加迅速。
一、联合训练
联合训练(Joint Training
)指如何将分类和边框回归联合到一起在CNN
阶段训练,主要难点是损失函数的设计。Fast-RCNN
中,有两个输出层:第一个是针对每个ROI
区域的分类概率预测, p = ( p 0 , p 1 , ⋯ , p K ) p=(p_0,p_1,⋯,p_K) p=(p0,p1,⋯,pK);第二个则是针对每个ROI
区域坐标的偏移优化, t k = ( t x k , t y k , t w k , t h k ) , 0 ≤ k ≤ K t^k=(t^k_x,t^k_y,t^k_w,t^k_h),0≤k≤K tk=(txk,tyk,twk,thk),0≤k≤K是多类检测的类别序号。每个训练ROI
都对应着真实类别 u u u和边框回归目标 v = ( v x , v y , v w , v h ) v=(v_x,v_y,v_w,v_h) v=(vx,vy,vw,vh),对于类别 u u u预测边框为 t u = ( t x u , t y u , t w u , t h u ) t^u=(t^u_x,t^u_y,t^u_w,t^u_h) tu=(txu,tyu,twu,thu),使用多任务损失 L L L来定义ROI
上分类和边框回归的损失:
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)+λ[u≥1]L_{loc}(t^u,v) L(p,u,tu,v)=Lcls(p,u)+λ[u≥1]Lloc(tu,v)
其中 L c l s ( p , u ) = − l o g p u L_{cls}(p,u)=−logp_u Lcls(p,u)=−logpu表示真实类别的 l o g log log损失,当 u ≥ 1 u≥1 u≥1时, [ u ≥ 1 ] [u≥1] [u≥1]的值为1,否则为0。下面将重点介绍多任务损失中的边框回归部分(对应坐标偏移优化部分)。
二、边框回归
假设对于类别 u u u,在图片中标注的真实坐标和对应的预测值理论上两者越接近越好,相应的损失函数为:
其中
Fast-RCNN
在上面用到的鲁棒 L 1 L1 L1函数对外点比RCNN
和SPP-NET
中用的 L 2 L2 L2函数更为鲁棒,该函数在(−1,1)之间为二次函数,其他区域为线性函数,函数直观图如下图所示。
使用Selective Search
提取Region Proposals
,没有实现真正意义上的端对端,操作也十分耗时。
提出了Region Proposal Network(RPN)
,将Proposal
阶段和CNN
分类融到了一起,实现了一个完全的End-To-End
的CNN
目标检测模型。RPN
可以快速提取高质量的Proposal
,不仅加快了目标检测速度,还提高了目标检测性能。
将Fast-RCNN
和RPN
放在同一个网络结构中训练,共享网络参数。
一、Region Proposal Network
Region Proposal Network(RPN)
的核心思想是使用卷积神经网络直接产生Region Proposal
,使用的方法本质上就是滑动窗口。RPN
的设计比较巧妙,RPN
只需在最后的卷积层上滑动一遍,借助Anchor
机制和边框回归可以得到多尺度多长宽比的Region Proposal
。下图是RPN
的网络结构图。
在ZF
网络模型下,给定输入图像(假设分辨率为600*1000
),经过卷积操作得到最后一层的卷积特征图(大小约为40*60
)。在这个特征图上使用3*3
的卷积核(滑动窗口)与特征图进行卷积,最后一层卷积层共有256个Feature Map
,那么这个3*3
的区域卷积后可以获得一个256维的特征向量,后边接Cls Layer
和Reg Layer
分别用于分类和边框回归(跟Fast-RCNN
类似,只不过这里的类别只有目标和背景两个类别)。3*3滑窗对应的每个特征区域同时预测输入图像3种尺度(128,256,512
),3种长宽比(1:1
,1:2
,2:1
)的Region Proposal
,这种映射的机制称为Anchor
。 所以对于这个40*60
的Feature Map
,总共有约20000(40*60*9)
个Anchor
,也就是预测20000个Region Proposal
。下图是51*39
个Anchor
中心,以及9种Anchor
示例。
这样设计的好处是什么?
虽然现在也是用的滑动窗口策略,但是,滑动窗口操作是在卷积层特征图上进行的,维度较原始图像降低了16*16
倍(16如何得到的可参见前文);多尺度采用了9种Anchor
,对应了三种尺度和三种长宽比,加上后边接了边框回归,所以即便是这9种Anchor
外的窗口也能得到一个跟目标比较接近的Region Proposal
。
二、RPN
的损失函数
损失函数定义为:
其中 i i i表示一次Mini-Batch
中Anchor
的索引, p i p_i pi是Anchor
, i i i是否是一个物体, L r e g L_{reg} Lreg即为上面提到的 s m o o t h L 1 ( x ) smooth_{L1}(x) smoothL1(x)函数, N c l s N_{cls} Ncls和 N r e g N_{reg} Nreg是两个归一化项,分别表示Mini-Batch
的大小和Anchor
位置的数目。
三、网络的训练
如果是分别训练两种不同任务的网络模型,即使它们的结构、参数完全一致,但各自的卷积层内的卷积核也会向着不同的方向改变,导致无法共享网络权重,Faster-RCNN
提出了三种可能的方式:
Alternating Training
:此方法其实就是一个不断迭代的训练过程,既然分别训练RPN
和Fast-RCNN
可能让网络朝不同的方向收敛,那么我们可以先独立训练RPN
,然后用这个RPN
的网络权重对Fast-RCNN
网络进行初始化,并且用之前RPN
输出Proposal
作为此时Fast-RCNN
的输入,之后不断迭代这个过程,即循环训练RPN
、Fast-RCNN
。
Approximate Joint Training
:这里与前一种方法不同,不再是串行训练RPN
和Fast-RCNN
,而是尝试把二者融入到一个网络内,具体融合的网络结构如下图所示,可以看到,Proposals
是由中间的RPN
层输出的,而不是从网络外部得到。需要注意的一点,名字中的"Approximate"
是因为“This solution ignores the derivative w.r.t. the proposal boxes' coordinates that are also network responses”
,也就是说,反向传播阶段RPN
产生的Cls Score
能够获得梯度用以更新参数,但是Proposal
的坐标预测则直接把梯度舍弃了,这个设置可以使Backward
时该网络层能得到一个解析解(Closed Results)
,并且相对于Alternating Traing
减少了25-50%的训练时间。
Non-approximate Training
:上面的Approximate Joint Training
把Proposal
的坐标预测梯度直接舍弃,所以被称作Approximate
,那么理论上如果不舍弃是不是能更好的提升RPN
部分网络的性能呢?作者把这种训练方式称为“ Non-approximate Joint Training”
,但是此方法只是一笔带过,表示“This is a nontrivial problem and a solution can be given by an “RoI warping” layer as developed in [15], which is beyond the scope of this paper”
。
作者没有用上面提到的三种可能方法,而是使用了4-Step Alternating Training
,具体步骤如下。
用ImageNet
模型初始化,独立训练一个RPN
网络;
仍然用ImageNet
模型初始化,但是使用上一步RPN
网络产生的Proposal
作为输入,训练一个Fast-RCNN
网络,至此,两个网络每一层的参数完全不共享;
使用第二步的Fast-RCNN
网络参数初始化一个新的RPN
网络,但是把RPN
、Fast-RCNN
共享的那些卷积层的Learning Rate
设置为0,也就是不更新,仅仅更新RPN
特有的那些网络层,重新训练,此时,两个网络已经共享了所有公共的卷积层;
仍然固定共享的那些网络层,把Fast-RCNN
特有的网络层也加入进来,形成一个Unified Network
,继续训练,Fine Tune Fast-RCNN
特有的网络层,此时,该网络已经实现我们设想的目标,即网络内部预测Proposal
并实现检测的功能。
至此,介绍完了以RCNN
为代表的基于Region Proposal
的深度学习目标检测算法(RCNN
,SPP-NET
,Fast-RCNN
,Faster-RCNN
),主要介绍了算法的核心思想和要点难点,代码可以从GitHub
得到,更多实现细节可以阅读原论文和代码。接下来会写另一篇文章来介绍以YOLO
为代表的基于回归方法的深度学习目标检测算法(YOLO
,SSD
)。
[1] RCNN:“Rich feature hierarchies for accurate object detection and semantic segmentation”
[2] SPP-NET:“Spatial pyramid pooling in deep convolutional networks for visual recognition”
[3] Fast-RCNN:“Fast R-CNN”
[4] Faster-RCNN:“Faster R-CNN: Towards real-time object detection with region proposal networks”
[5] RCNN, Fast-RCNN, Faster-RCNN的一些事
[6] 卷积神经网络物体检测之感受野大小计算
[7] 原始图片中的ROI如何映射到到Feature Map
[8] Fast R-CNN
[9] 通过代码理解Faster-RCNN中的RPN
[10] Faster R-CNN
[11] 基于深度学习的目标检测研究进展