这篇论文提出了针对目标识别的Fast Region-based Convolution Network(Fast R-CNN)方法。Fast R-CNN训练速度要比R-CNN快9倍,测试速度要快213倍,而且在PASCAL VOC2012数据集上的mAP要更高。与SPPnet相比,Fast R-CNN训练速度快3倍,测试速度快10倍,而且更准确。
目标检测要比图像分类麻烦很多,当前的方法一般都是通过多阶段流程来训练,不仅慢还不优雅。
识别物体需要精确的定位,这就有两个麻烦之处。首先要得到粗糙的候选目标位置(叫proposals);其次,这些候选位置仅是提供了大概的位置,需要精确定位它们。这篇论文提出了一个单阶段训练算法,结合地学习目标候选位置,并优化其空间位置。
R-CNN慢因为它需要在每个proposal上都跑一遍CNN,没有共享计算。SPPnet(空间金字塔池化网络)则共享了计算,测试速度快了10到100倍,训练速度也快了3倍。SPPnet先对每张图像计算一个卷积特征图,然后再用特征图里提取的特征向量来对每个proposal做分类。在特征图上max-pooling每个proposal对应的部分,提取特征作为一个固定长度的输出。多个不同大小的输出然后在空间金字塔池化中拼接起来。
SPPnet的问题:它也是多阶段流程训练,需要提取特征,微调网络,训练SVM,最后还要bounding-box regressors. 而且何凯明论文中的SPPnet无法更新空间金字塔池化层之前的卷积层,这也影响了深度网络的准确度。
提出新的训练算法,解决R-CNN和SPPnet的问题,Fast R-CNN有以下几个优势:
上图就是Fast R-CNN的结构。网络的输入是一整张图像和目标proposals的集合。网络首先通过几个卷积层和max pooling层处理图像,产生一张卷积特征图。然后对于每一个目标proposal,region of interest(RoI)池化层从特征图里提取一个固定长度的特征向量。每个特征向量都被输入进2个sibling全连接层:一个输出(K个类别+1个背景类别的)softmax概率,另一个输出四个实数值,代表bounding-box位置。
RoI池化层使用max pooling把RoI内的特征转为固定范围( H × W H\times W H×W)的小特征图。RoI是卷积特征图上的一个矩形窗口,由4值的元组(r, c, h, w)决定位置,(r, c)决定左上角位置,(h, w)决定高和宽。RoI max pooling 把 h × w h\times w h×w的窗口分割为 H × W H \times W H×W个子窗口,每个子窗口大小为 h / H × w / W h/H \times w/W h/H×w/W,然后max-pool每个子窗口,把得到的值放进对应的输出网格中。RoI层其实就是空间金字塔池化层的特例,RoI只有一个金字塔level。
作者通过3个pre-trained ImageNet网络做实验,每个网络有5个max pooling层和5-13个卷积层,还要改动3个地方才能做Fast R-CNN:
不同于SPPnet,Fast R-CNN整个网络可以被使用反向传播训练是一个极大的优点,而SPPnet无法更新SPP(空间金字塔池化)层以下的层。论文中作者提到SPP层中的感受野非常大,使用BP算法训练时效率低。也就是说,在一个batch训练中,你一开始RoI源于这张图片,而下一个RoI源于另一张图片。如此往复,如果ROI很大的话,这就导致在BP效率会很低。
为了解决这个问题,作者利用特征分享的优势,提出一个更加有效的训练方法:SGD mini-batches分层采样方法。在同一个batch中,为了减少图像使用量,首先选择N张图像,然后从每张图像中选择 R / N R/N R/N个RoI。同一个图像里的RoI,在前向和反向传播过程中共享计算和内存。这样就很好地解决了上述问题。
前面提到了,Fast R-CNN训练是在single-stage中完成,但实际中它包含了:multi-task loss, mini-batch sampling, RoI pooling, BP throungh RoI pooling layers, SGD hyper-parameters.
Fast R-CNN网络有两个sibling输出层,第一个输出层针对每个RoI输出离散的概率分布, 在 K + 1 K+1 K+1个类上有 p = ( p 0 , ⋯   , p K ) p=(p_0, \cdots, p_K) p=(p0,⋯,pK)。 p p p是通过softmax计算出来的。第二个sibling层输出bounding-box回归位移, t k = ( t x k , t y k , t w k , t h k ) , k ∈ K t^k=(t^k_x, t^k_y, t^k_w, t^k_h), k \in K tk=(txk,tyk,twk,thk),k∈K。
每个训练RoI都被标上其真值类别 u u u和真值bounding-box回归目标 v v v。作者用一个多任务损失函数 L L L,在每一个标注好的RoI上共同训练分类和bounding-box回归:
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 \geq 1]L_{loc}(t^u, v). L(p,u,tu,v)=Lcls(p,u)+λ[u≥1]Lloc(tu,v).
[ u ≥ 1 ] [u \geq 1] [u≥1]是Iverson bracket指标函数,当 u ≥ 1 u \geq 1 u≥1,它等于1,否则为0。对于背景proposal来说, u = 0 u=0 u=0。
L c l s ( p , u ) = − l o g p u . L_{cls}(p,u) = -logp_u. Lcls(p,u)=−logpu.是类 u u u的log loss。
第二个损失任务,对于类 u u u, L l o c L_{loc} Lloc定义于bounding-box回归目标的元组(真值)上, 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)。
对于bounding-box回归,使用:
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 if |x|<1 ∣ x ∣ − 0.5 otherwise smooth_{L_1} (x) = \begin{cases} 0.5x^2& \text{if |x|<1}\\ |x|-0.5& \text{otherwise} \end{cases} smoothL1(x)={0.5x2∣x∣−0.5if |x|<1otherwise
L ( p , u , t u , v ) L(p, u, t^u, v) L(p,u,tu,v)中的 λ \lambda λ是个超参数,控制两个loss tasks的平衡。所有的实验中, λ = 1 \lambda=1 λ=1。
在微调时,每个SGD mini-batch都通过随机选择 N = 2 N=2 N=2张图像构建,然后从每张图片中选择64个RoIs。选取25%的RoIs,这些RoIs与真值bounding-box的IoU(Intersection over union)不少于0.5。这些RoIs构成了前景目标类, u = 1 u=1 u=1。剩下的RoIs与真值bounding-box的IoU最大也就0.5,它们也就构成了背景目标类, u = 0 u=0 u=0。
从这篇借鉴理解RoI池化层:Fast R-CNN论文详解
首先看普通max pooling层如何求导,设 x i x_i xi为输入层节点, y i y_i yi为输出层节点,那么损失函数 L L L对输入层节点 x i x_i xi的梯度为:
δ L δ x i = { 0 , δ ( i , j ) = f a l s e δ L δ y j , δ ( i , j ) = t r u e \frac{\delta L}{\delta x_i} = \left\{ \begin{aligned} 0,& & \delta(i, j)=false \\ \frac{\delta L}{\delta y_j}, & & \delta(i, j) = true \end{aligned} \right. δxiδL=⎩⎪⎨⎪⎧0,δyjδL,δ(i,j)=falseδ(i,j)=true
δ ( i , j ) \delta(i, j) δ(i,j)表示输入 i i i节点是否被输出 j j j节点选为最大值输出。
不被选中 δ ( i , j ) = f a l s e \delta (i,j)=false δ(i,j)=false有两种可能:xi不在yi范围内,或者xi不是最大值。
若选中 δ ( i , j ) = t r u e \delta(i,j)=true δ(i,j)=true则由链式规则可知损失函数 L L L相对 x i x_i xi的梯度等于损失函数 L L L相对 y i y_i yi的梯度 × \times × y i y_i yi对 x i x_i xi的梯度(恒等于1),故可得上述所示公式;
对于RoI max pooling层,设 x i x_i xi为输入层的节点, y r j y_{rj} yrj 为第 r r r个候选区域的第 j j j个输出节点,一个输入节点可能和多个输出节点相关连,如下图所示,输入节点7和两个候选区域输出节点相关连:
该输入节点7的反向传播如下图所示:
对于不同候选区域,节点7都存在梯度,所以反向传播中损失函数 L L L 对输入层节点 x i x_i xi的梯度为损失函数 L L L 对各个有可能的候选区域 r r r 【 x i x_i xi 被候选区域 r r r的第 j j j个输出节点选为最大值 】输出 y r j y_{rj} yrj 梯度的累加,具体如下公式所示:
δ L δ x i = ∑ r ∑ j [ i = i ∗ ( r , j ) ] δ L δ y r j \frac{\delta L}{\delta x_i} = \sum_{r} \sum_{j} [i=i^*(r, j) ] \frac{\delta L}{\delta y_{rj}} δxiδL=r∑j∑[i=i∗(r,j)]δyrjδL
[ i = i ∗ ( r , j ) ] = { 1 , i = i ∗ ( r , j ) ≥ 1 0 , o t h e r w i s e [i=i^*(r, j) ] = \left\{ \begin{aligned} 1,& & i=i^*(r, j) \geq 1 \\ 0, & & otherwise \end{aligned} \right. [i=i∗(r,j)]={1,0,i=i∗(r,j)≥1otherwise
判决函数 [ i = i ∗ ( r , j ) ] [i=i^*(r,j)] [i=i∗(r,j)]表示第 i i i个节点是否被候选区域 r r r 的第 j j j 个输出节点选为最大值输出,若是,则由链式规则可知损失函数 L L L相对 x i x_i xi 的梯度等于损失函数 L L L 相对 y r j y_{rj} yrj的梯度 × \times × y r j y_{rj} yrj 对 x i x_i xi的梯度(恒等于1),上图已然解释该输入节点可能会和不同的 y r j y_{rj} yrj 有关系,故损失函数 L L L相对 x i x_i xi 的梯度为求和形式。
除了修改增加的层,原有的层参数已经通过预训练方式初始化:
用于分类的全连接层以均值为0、标准差为0.01的高斯分布初始化;
用于回归的全连接层以均值为0、标准差为0.001的高斯分布初始化。
偏置都初始化为0;
针对PASCAL VOC 2007和2012训练集,前30k次迭代全局学习率为0.001,每层权重学习率为1倍,偏置学习率为2倍,后10k次迭代全局学习率更新为0.0001。动量设置为0.9,权重衰减设置为0.0005。
实现尺度不变有两种方式:
在检测的时候,RoI的数量很大,接近一半的前向时间都花在了全连接层上。全连接层可以通过SVD压缩来加速。
假设有一个层,它的权值矩阵是 u × v u\times v u×v形状的 W W W,它可以用SVD分解为
W ≈ U Σ t V T W \approx U\Sigma_t V^T W≈UΣtVT.
U U U是形状为 u × t u\times t u×t的矩阵,包含着 W W W的前 t t t个左奇异向量, Σ t \Sigma_t Σt是形状为 t × t t\times t t×t的对角线矩阵,由 W W W的前 t t t个奇异值组成, V V V是形状为 v × t v \times t v×t的矩阵,对应着 W W W的前 t t t个右奇异向量。SVD方法把参数个数由 u v uv uv减少到 t ( u + v ) t(u+v) t(u+v)个。为了压缩一个网络,用两个全连接层来代替对应着 W W W的单个全连接层。第一个层使用权值矩阵 Σ t V T \Sigma_t V^T ΣtVT,第二个使用 U U U。