赞
踩
2014 CVPR 录用了 Ross Girshick 的论文《Rich feature hierarchies for accurate object detection and semantic segmentation 》,文章提出了经典目标检测模型——区域卷积神经网路(R-CNN, Regions with CNN features)。R-CNN 是一种两阶段(two-stage)的目标检测模型,即先在图片上生成候选区域(region proposals),而后对候选区域进行识别。
R-CNN 在图片上进行目标检测的测试流程大致如下:
SS 算法来自于 J. Uijlings 在 IJCV 2013 上的论文《Selective search for object recognition》。算法首先将图片划分成很多小区域,而后计算区域之间的相似度进行合并。不了解 SS 算法并不影响对 R-CNN 的理解,所以我们在此不进行详细讨论。
R-CNN 使用 SS 算法为每张图片生成
2000
2000
2000 个候选区域(region proposal)。
R-CNN 使用的 CNN 限制输入的图片必须是固定的尺寸 227 × 227 227\times227 227×227,由于候选区域的比例和大小各异,所以必须必须对其进行缩放操作。作者提出了两种缩放方法:
作者发现:各项异性缩放且 p a d d i n g = 16 padding=16 padding=16 的效果最好。
R-CNN 使用了 AlexNet8 作为 CNN。 AlexNet8 包含了
5
5
5 层卷积、
2
2
2 层全连接隐层和
1
1
1 层使用 softmax 的输出层,其中每层卷积后都有一个最大池化层。R-CNN 并未使用 AlexNet 的 softmax 输出层作为分类器,而是将其替代为多个 SVM 二分类器。换句话说,应用在 R-CNN 上的 CNN 只有
5
5
5 层卷积和
2
2
2 层全连接层。作者为什么不使用 softmax 层而使用 SVM 作分类器?这个问题,我们将在下文的训练过程中讨论。
网络的输入格式是
227
×
227
227\times227
227×227 RGB 图像,输出的是
4096
4096
4096 维的特征向量。
作者为每一类事物都训练了一个 SVM 二分类器。假如要检测 n n n 类事物,那么就需要 n + 1 n+1 n+1 个 SVM 二分类器,其中一个用于检测图片中的背景。每个 SVM 分类器都会输出一个概率,如果某类输出的概率值大于或等于阈值(常设为 0.5 0.5 0.5),那么该候选区域会被留在该类并记录其概率值;小于则被抛弃。
每个类别独立地运行 NMS 算法,进一步筛选被留在本类的候选区域。算法的运行过程大致如下:
交并比(Intersection-over-Union, IoU):两个区域交叉的面积与合并的面积之比
下面给出举例:
上一步输出的预测框(包围预测区域的框)与真实框(ground truth bounding-box)之间仍然存在些许差距,因此作者使用 Bound-box regression 来对预测框进行修正,使之尽可能的接近真实框。不同类事物的修正方式也是不同的,所以每个类别的事物都有其特定的 BBR。如下图,
P
P
P 是预测框,
G
G
G 是真实框,
G
^
\widehat{G}
G
是 BBR 对
P
P
P 修正后生成的预测真实框。
BBR 底层使用了
4
4
4 个线性回归模型,它们都以预测区域在 CNN 中第
5
5
5 个池化层的输出(
9216
9216
9216 维的向量)作为输入,分别预测
d
x
(
P
)
d_x(P)
dx(P)、
d
y
(
P
)
d_y(P)
dy(P)、
d
w
(
P
)
d_w(P)
dw(P) 和
d
h
(
P
)
d_h(P)
dh(P) 四个量。这四个量分别与预测框的水平平移、垂直平移、水平缩放和垂直缩放有关。我们将预测框的水平坐标、垂直坐标、水平边长和垂直边长记作
P
x
P_x
Px、
P
y
P_y
Py、
P
w
P_w
Pw 和
P
h
P_h
Ph,预测真实框的对应数据记作
G
^
x
\widehat{G}_x
G
x、
G
^
y
\widehat{G}_y
G
y、
G
^
w
\widehat{G}_w
G
w 和
G
^
h
\widehat{G}_h
G
h,则 BBR 的修正公式如下:
G
^
x
=
P
x
+
P
w
d
x
(
P
)
G
^
y
=
P
y
+
P
h
d
y
(
P
)
G
^
w
=
P
w
exp
[
d
w
(
P
)
]
G
^
h
=
P
h
exp
[
d
h
(
P
)
]
(1)
图像尺寸的缩放系数必须是个正数,而
e
x
e^x
ex 具有恒正和单调递增的特性,所以作者将
d
w
(
P
)
d_w(P)
dw(P) 和
d
h
(
P
)
d_h(P)
dh(P) 做了指数运算。
R-CNN 模型并不是整体进行训练的,而是分模块、分步骤进行训练。模型中需要训练的有 CNN、SVM 和 BBR 三个模块。训练过程按照如下顺序进行:准备正负样本、CNN 预训练(pre-training)、CNN 微调(fine-tuning)、SVM 训练、BBR 训练。
针对训练集中的所有图片使用 Selective Search 算法在每张图片上生成 2000 2000 2000 个候选区域(region proposal)。在每张图片上,令所有候选区域分别与真实区域(ground truth)做 IoU 运算,而后记录下来。在训练过程中,作者以 IoU 值作为划分依据,来为不同的模型创造训练样本集。
CNN 模型大、参数多,如果训练集较小,将会导致训练不充分,易发生过拟合。所以作者使用大型的图像分类数据集(ImageNet 比赛数据集)对 CNN 进行预训练,然后将训练好的参数值保存下来。需要注意的是,在训练中 CNN 中的 softmax 输出层并未被 SVM 替换,而是按照一个完整的 CNN 图像分类器进行训练。
在完成预训练的基础上,使用我们之前准备的样本再对 CNN 进行训练(仍然不替换 softmax),并使用一个极低的学习率
0.001
0.001
0.001(这是预训练时学习率的十分之一)。这也就是针对我们当前需要的分类任务进行的一个网络微调。
对于训练需要的样本,作者将
I
o
U
⩾
0.5
IoU \geqslant 0.5
IoU⩾0.5 的候选区域打上与真实区域相同的类别标签,这被作者称为正样本;其余的被打上背景标签,这被作者称为负样本。 需要注意的是,这些样本需要经过 warp 操作后才能送入网络进行训练。
对于 SVM 的训练样本,作者仅将
I
o
U
=
1
IoU = 1
IoU=1 即真实区域作为正样本;仅将
I
o
U
<
0.3
IoU < 0.3
IoU<0.3 的作为负样本。这些样本需要先经过 warp 操作,再经过 CNN 提取出
4096
4096
4096 维的特征向量,才能用于 SVM 的训练。
下面我们先来回答一下为什么使用 SVM 作为分类器。其实归根结底就是使用 softmax 做分类的效果不理想。首先,softmax 输出层是跟随 CNN 一同进行训练的,CNN 的正负样本划分标准是
I
o
U
⩾
0.5
IoU \geqslant 0.5
IoU⩾0.5 和
I
o
U
<
0.5
IoU < 0.5
IoU<0.5,而 SVM 的标准是
I
o
U
=
1
IoU = 1
IoU=1 和
I
o
U
<
0.3
IoU < 0.3
IoU<0.3,所以 CNN 样本的区分度不如 SVM 的区分度大,训练出的效果自然不好。那我们难道不可以将 CNN 的样本区分度做的也大一点?一方面,区分度做大的同时,样本数量也随之减少;样本数量减少,CNN 整体的效果也会被拉低。另一方面,SVM 就是为了小样本集而生的,SVM 在小样本集上的泛化性能要优于其它模型。所以区分度做大,样本集变小是适合于 SVM 的。
此外,作者为了增强分类能力,在训练 SVM 时使用了难负例挖掘(hard negetive mining)方法。
难负例挖掘的基本思路是:在目标检测中负样本的数量是相对较多的,分类器很容易将负样本预测成正样本。所以我们需要挖掘出具有代表性的负样本,即容易让分类器犯错的负样本(难负例),然后让机器反复学习这些负样本。难负例挖掘的过程大致如下:
- 使用正样本集和负样本集的一个子集(负样本训练集)对分类器进行初始训练。
- 让分类器对负样本集进行预测,将分类器预测错误那些负样本加入负样本训练集。
- 使用正样本集和新的负样本训练集再次对分类器进行训练。
- 返回到 2,直到准确率不再提升。
作者仅选用了
I
o
U
⩾
0.6
IoU \geqslant 0.6
IoU⩾0.6 的候选框和真实框来训练 BBR。因为只有预测框和真实框十分接近时,我们才可以近似的认为预测框到真实框的修正是线性变换。我们继续使用上文中的符号,并增加
G
x
G_x
Gx、
G
y
G_y
Gy、
G
w
G_w
Gw 和
G
h
G_h
Gh 代表真实框的四个参数。通过上文我们知道,BBR 预测
d
x
(
P
)
d_x(P)
dx(P)、
d
y
(
P
)
d_y(P)
dy(P)、
d
w
(
P
)
d_w(P)
dw(P) 和
d
h
(
P
)
d_h(P)
dh(P) 四个量,所以在训练过程中我们需要给出这四个量的目标值
t
x
(
P
)
t_x(P)
tx(P)、
t
y
(
P
)
t_y(P)
ty(P)、
t
w
(
P
)
t_w(P)
tw(P) 和
t
h
(
P
)
t_h(P)
th(P),以完成监督训练。下面给出表达式:
t
x
(
P
)
=
G
x
−
P
x
P
w
t
y
(
P
)
=
G
y
−
P
y
P
h
t
w
(
P
)
=
ln
(
G
w
P
w
)
t
h
(
P
)
=
ln
(
G
h
P
h
)
(2)
R-CNN 《Rich feature hierarchies for accurate object detection and semantic segmentation 》
《目标检测概述》博客
《目标检测算法之R-CNN》博客
《边框回归:BoundingBox-Regression(BBR)》博客
《R-CNN中的SVM理解》博客
《什么是hard negative mining》博客
以下是生成 NMS 章节中示意图的代码:
import matplotlib.pyplot as plt import matplotlib.image image = matplotlib.image.imread(r'1.jpeg') ax = plt.gca() ax.axis(False) ax.imshow(image) def box(axes, x, y, width, height, text): rect = plt.Rectangle((x, y), width, height, fill=False, color='blue') axes.text(x, y, text, color='red') axes.add_patch(rect) box(ax, 220, 190, 130, 85, 'a 0.95') box(ax, 170, 185, 190, 110, 'b 0.70') box(ax, 250, 215, 100, 50, 'c 0.52') box(ax, 185, 145, 95, 35, 'd 0.85') box(ax, 240, 130, 70, 45, 'e 0.65') plt.show()
以下是生成 BBS 章节中示意图的代码:
from matplotlib import pyplot as plt
ax = plt.gca()
ax.axis(False)
rect = plt.Rectangle((0.10, 0.10), 0.60, 0.60, fill=False, color='red')
ax.text(0.4, 0.7, '$P$', color='red')
ax.add_patch(rect)
rect = plt.Rectangle((0.15, 0.15), 0.65, 0.65, fill=False, color='green')
ax.text(0.475, 0.8, r'$\widehat{G}$', color='green')
ax.add_patch(rect)
rect = plt.Rectangle((0.20, 0.20), 0.70, 0.70, fill=False, color='blue')
ax.text(0.55, 0.9, '$G$', color='blue')
ax.add_patch(rect)
plt.show()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。