【目标检测】Fast RCNN算法详解

Girshick, Ross. “Fast r-cnn.” Proceedings of the IEEE International Conference on Computer Vision. 2015.

继2014年的RCNN, SPP-Net,Ross Girshick在15年推出Fast RCNN,构思精巧,流程更为紧凑,大幅提升了目标检测的速度。在Github上提供了源码

同样使用最大规模的网络,Fast RCNN和RCNN相比,训练时间从84小时减少为9.5小时,测试时间从47秒减少为0.32秒。在PASCAL VOC 2007上的准确率相差无几,约在66%-67%之间.

思想

基础:R-CNN + SPP-Net

R-CNN

  • R-CNN具有几个显著的缺点:
    • 训练分为多个阶段,步骤繁琐 : 微调网络+训练SVM+训练边框回归器
    • 训练耗时,占用磁盘空间大:5000张图像产生几百G的特征文件
    • 速度慢:因为其要将每一张图片约2000个region proposals,都输入网络执行正向传递+SVM分类+边框回归,而不共享计算。其实际上对一张图像进行了约2000次提取特征和分类的过程。在使用GPU, VGG16模型处理一张图像需要47s。
      (具体细节请看这篇博客

SPP-Net

  • SPP-Net利用sharing computation对 RCNN进行了加速:

    • 提出一种将region proposals,映射到 conv5_3+relu5_3输出的feature map上的映射关系。只需要将一张图片输入网络,提取一次卷积层特征,然后通过这种映射关系,可将region proposals映射到对应的feature map上,即可获取每个region proposals的卷积特征。无需重复使用CNN提取特征,从而大幅度缩短训练时间。
    • 由于FC层需要固定长度的输入,作者通过使用SPP(Spatial Pyramid Pooling)层,可以接受任意大小的卷积特征向量,并输出固定长度的输出向量,就可以直接输入到FC层进行后续操作。即SPP-Net可接受任意大小的输入图片,不需要对图像做crop/wrap操作。
      (即经过 映射+SPP转换 ,共享了计算,速度和进度都有一定提升) 具体细节请看这篇博客
  • SPP-Net 也有明显的缺点:

    • 像R-CNN一样,训练分为多个阶段,步骤繁琐, : 微调网络+训练SVM+训练训练边框回归器
    • SPP-NET在微调网络的时候固定了卷积层,只对全连接层进行微调,而对于一个新的任务,有必要对卷积层也进行微调。(分类的模型提取的特征更注重高层语义,而目标检测任务除了语义信息还需要目标的位置信息)

    针对以上两个问题,RBG提出了该Fast R-CNN,一个精简快速的检测框架。

改进:Fast RCNN这里写图片描述

与R-CNN框架图对比,可以发现主要有两处不同:一是最后一个卷积层后加了一个ROI pooling layer,二是损失函数使用了多任务损失函数(multi-task loss),将边框回归直接加入到CNN网络中训练。

  • ROI pooling layer实际上是SPP-Net的一个精简版,SPP-Net对每个proposal使用了不同大小的金字塔映射,而ROI pooling layer只需要下采样到一个7x7的特征图。对于VGG16网络conv5_3有512个特征图,这样所有region proposal对应了一个7x7x512维度的特征向量作为全连接层的输入。
  • R-CNN训练过程分为了三个阶段,而Fast R-CNN直接使用softmax替代SVM分类,同时利用多任务损失函数边框回归也加入到了网络中,这样整个的训练过程是端到端的(除去region proposal提取阶段)。
  • Fast R-CNN在网络微调的过程中,将部分卷积层也进行了微调,取得了更好的检测效果。

特征提取网络

基本结构

图像归一化为224×224直接送入网络。
前五阶段是基础的conv+relu+pooling形式,在第五阶段结尾,输入P个候选区域(图像序号×1+几何位置×4,序号用于训练)?。
这里写图片描述

注:文中给出了大中小三种网络,此处示出最大的一种。三种网络基本结构相似,仅conv+relu层数有差别,或者增删了norm层。

roi_pool层的测试(forward)

roi_pool层将每个候选区域均匀分成M×N块,对每块进行max pooling。将特征图上大小不一的候选区域转变为大小统一的数据,送入下一层。
这里写图片描述

代码层理解:ROI Pooling层解析

roi_pool层的训练(backward)

首先考虑普通max pooling层。设 xi 为输入层的节点,yj 为输出层的节点。

yxi={0δ(i,j)=falseLyjδ(i,j)=true

其中判决函数 δ(i,j) 表示i节点是否被j节点选为最大值输出。不被选中有两种可能: xi 不在 yj 范围内,或者xi 不是最大值。

对于roi max pooling,一个输入节点可能和多个输出节点相连。设 xi 为输入层的节点,yrj 为第 r 个候选区域的第 j 个输出节点。
这里写图片描述

Lxi=r,jδ(i,r,j)Lyrj

判决函数 δ(i,r,j) 表示 i 节点是否被候选区域 r 的第 j 个节点选为最大值输出。代价对于 xi 的梯度等于所有相关的后一层梯度之和。

网络参数训练

参数初始化

网络除去末尾部分如下图,在ImageNet上训练1000类分类器。结果参数作为相应层的初始化参数。
这里写图片描述
其余参数随机初始化。

分层数据

在调优训练时,每一个mini-batch中首先加入N张完整图片,而后加入从N张图片中选取的R个候选框。这R个候选框可以复用N张图片前5个阶段的网络特征。
实际选择N=2, R=128。

训练数据构成

N张完整图片以50%概率水平翻转。
R个候选框的构成方式如下:

类别 比例 方式
前景 25% 与某个真值重叠在[0.5, 1]的候选框
背景 75% 与真值重叠的最大值在[0.1, 0.5)的候选框

分类与位置调整

数据结构

第五阶段的特征输入到两个并行的全连层中(称为multi-task)。
这里写图片描述
cls_score层用于分类,输出K+1维数组 p ,表示属于K类和背景的概率。对每个RoI(Region of Interesting)输出离散型概率分布 p=(p0, p1, ..., pk)
bbox_prdict层用于调整候选区域位置,输出bounding box回归的位移,输出4*K维数组 t ,表示分别属于K类时,应该平移缩放的参数。tk=(txk, tyk, twk, thk)

k表示类别的索引, txk, tyk 是指相对于object proposal的ground truth尺度不变的平移, twk, thk 是指对数空间中相对于object proposal的ground truth的高与宽。

代价函数

loss_cls层评估分类代价。由真实分类 u 对应的概率决定:

Lcls= log pu

loss_bbox层评估检测框定位代价。比较真实分类对应的预测参数 tu 和真实平移缩放参数为 v 的差别:
Lloc=i=14g(tiuvi)

gSmoothL1 误差,函数图像如下,其在(-1, 1)之间为二次函数,其他区域为线性函数。作者这样设置的目的是想让loss对于离群点更加鲁棒,相比于 L2 损失函数,其对利群点,异常值(outlier)不敏感,可控制梯度的量级使训练时不容易跑飞。
g(x)={0.5x2|x|<1|x|0.5otherwise
这里写图片描述
总代价为两者加权和,如果分类为背景则不考虑定位代价:
L={Lcls+λLlocuLclsu

规定 u=0 为背景类(也就是负标签),那么艾弗森括号指数函数 [u1] 表示背景候选区域即负样本不参与回归损失,不需要对候选区域进行回归操作。λ 控制分类损失和回归损失的平衡。Fast R-CNN论文中,所有实验λ=1

艾弗森括号指数函数为:

[u1]={1u10otherwise

源码中几个参数说明:

cls_score : cls_score分类层的输出结果,CNN计算的每个rois (bbox)属于[K类前景+1背景]的概率得分。 [1x(K+1)]
label : 原始输入的每个rois所属的类别标签。 [1*1]
bbox_pred : bbox_prdict层输出的,CNN计算的每个rois需要进行bounding box回归的平移缩放参数。[1x4x(K+1)] (注意,这是源码中的维度,上图中的写成了维度[1x4]是为了易于理解损失loss的计算)
bbox_targets : 使用原始数据rois和ground truth计算好了的,每个前景rois回归到其对应的ground truth所需要做的平移尺度变换,背景不需要bounding box回归,对应的值为0。 [1x4x(K+1)]
bbox_loss_weights : 标记每个rois是否属于某一个类。 [1x4x(K+1)]:属于的类别4个位置标志为1,不属于的为都为0

全连接层提速

分类和位置调整都是通过全连接层(fc)实现的,设前一级数据为 x 后一级为 y ,全连接层参数为 W ,尺寸u×v 。一次前向传播(forward)即为:

y=Wx
计算复杂度为 u×v
W 进行SVD分解,并用前t个特征值近似:
W=UΣVTU(:,1:t)Σ(1:t,1:t)V(:,1:t)T
原来的前向传播分解成两步:
y=Wx=U(ΣVT)x=Uz
计算复杂度变为 u×t+v×t
在实现时,相当于把一个全连接层拆分成两个,中间以一个低维数据相连。
这里写图片描述

在github的源码中,这部分似乎没有实现。

实验与结论

实验过程不再详述,只记录结论
- 网络末端同步训练的分类和位置调整,提升准确度
- 使用多尺度的图像金字塔,性能几乎没有提高
- 倍增训练数据,能够有2%-3%的准确度提升
- 网络直接输出各类概率(softmax),比SVM分类器性能略好
- 更多候选窗不能提升性能

同年作者团队又推出了Faster RCNN,进一步把检测速度提高到准实时,可以参看这篇博客
关于RCNN, Fast RCNN, Faster RCNN这一系列目标检测算法,可以进一步参考作者在15年ICCV上的讲座Training R-CNNs of various velocities

Reference:

【目标检测】Fast RCNN算法详解
ROI Pooling层解析
深度学习论文笔记:Fast R-CNN
http://chuansong.me/n/353443351445

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