Faster R-CNN 简介
RBG 团队在 2015 年, 与 Fast R-CNN 同年推出了 Faster R-CNN, 我们先从头回顾下 Object Detection 任务中各个网络的发展, 首先 R-CNN 用分类 + bounding box 解决了目标检测问题, SPP-Net 解决了卷积共享计算问题, Fast R-CNN 解决了 end-to-end 训练的问题, 那么最后还能下一个 ss 算法, 依旧 ** 于网络, 是一个单独的部分, 然而这个算法需要大概 2 秒的时间, 这个点是 R-CNN 系列的性能瓶颈, 所有 Fast R-CNN 是没有什么实时性的. 那么 Faster R-CNN 的出现就是为了解决这个瓶颈问题.
在 Faster R-CNN 中提出了 RPN 网络, Region Proposal Network(区域建议网络)以代替原来的 ss 算法, 可以简单的理解为:
Faster R-CNN =Fast R-CNN+RPN-ss 算法
所以, 可以说除了 RPN,Faster R-CNN 剩下的地方与 Fast R-CNN 是一样的, 那么理解 Faster R-CNN 的关键其实理解 RPN.
RPN 网络结构
首先, 上面这张图说明了 RPN 在 Faster R-CNN 中的位置, 它在 CNN 卷积后的特征图上做区域建议(大约 300 个), 并根据 RPN 生成的区域建议对 feature maps 做提取, 并对提取后的特征做 RoI pooling. 在 RoI pooling 之后的东西就和 Fast R-CNN 一样了.
所以 RPN 的输入是卷积后的特征图, 输出是多个打过分的建议框, 所谓打分是对框中是否是物体打分, 建议框是四个值(x,y,w,h).
RPN 是一种全卷积网络, 它的前几层卷积层和 Faster R-CNN 的前五层是一样的, 所以 RPN 是在进一步的共享卷积层的计算, 以降低区域建议的时间消耗.
也是因为共享卷积的原因, 所以我们一般认为 RPN 只有两层. 而 RPN 前面到底有几层, 决定于 Faster R-CNN 选择哪种初始模型, 如果是 AlexNet 的话, 那就是 5 层, 如果是 ZFNet 的话, 也是 5 层, 如果是 VGG16 的话, 就是 13 层, 等等.
那么我们还是用 AlexNet 举例好了, 此时的 conv5 特征图的尺寸为 1313256, 也就是这一层的特征别送入到 RPN 中, RPN 在这个特征图上用 33256 的卷积核, 一共用了 256 个. 那么卷积核一次卷积之后的特征就是 11256, 也就是下图中的 256-d, 之后该特征出两个分支:
第一个分支 (reg layer) 用 4k 个 11256 的卷积核卷积, 最后输出 4k 个数, 这里的 4 是一个建议框的参数, 即(x,y,w,h);
第二个分支 (cls layer) 用 2k 个 11256 的卷积核卷积, 最后输出 2k 个数, 这里的 2 是该区域到底有没有物体, 即(object,non-object).
那么, k 是什么呢? k 是 Anchor box(参考框)的类型数, 在 Faster R-CNN 中 k=9, 分别是 3 个尺度 scale 和 3 个比例 ratio, 其中:
scale 为(128,256,512)
ratio 为 1:1,1:2,2:1
参考框的中心就是卷积核的中心.
所以, 在 conv5 层上, 用 33 卷积核每卷积一次, 都会生成 k 个参考框, 那么参考框的总数就应该是 WHK, 如上所说, conv5 的尺寸为 1313 的话, 那么生成的 Anchor box 的总数就是 1521 个.
然后我们就会发现通过上面的解释, RPN 有一些地方是说不通的, 下面我们一一解释下这些坑:
**1. 上面提到 Anchor box 的总数是 1521 个, 那为什么说 RPN 生成 300 个左右的区域建议呢? **
每一个参考框都会有一个是不是物体的打分, 在检测过程中 RPN 计算所有的参考框后会选择其中 300 个得分最高的区域.
2. 参考框中的尺寸为(128,256,512), 但是 conv5 的尺寸只有 13*13, 在哪里生成这些参考框呢?
这些参考框不是在特征图上生成, 而是在原图上, 而原图之前的尺寸也不是 224*244, 这个尺寸是原图经过压缩得到的, 所以 anchor size 的选择一定是要考虑缩放前的原图的尺寸, 因为最后 anchor 超过的图像大小, 并没有意义. 所以 RPN 在做的是将每个点产生的 9 个参考框来映射原始图像, 也就是通过 4k 个位置偏移输出和 k 个参考框, 得到参考框在原始图像中的位置. 就像 Fast R-CNN 中 ss 算法, 其实也是在原图上生成的, 最后只是经过了坐标变化才能在 conv5 上提取.
**3. 在卷积核卷积到一个点的时候, 输出了 9 个参考框, 但是这 9 个建议框的特征是相同的, 都是 256 个 33256 卷积核卷积得到的 11256 的特征, 那么这 9 个参考框在哪里引导的 RPN 关注这些区域呢? **
特征确实是相同的, 但是得到的特征最终是要向原图做映射的, 以得到最终的区域建议, 而相同的特征对应了 9 种不同的参考映射方式, 于是相同的特征, 映射给不同的参考框时, loss 是不同的. 那么哪种方式是做好的呢, 当然是 loss 最小的那个. 所以不同的 9 个参考框, 它们的区别并不体现在特征上, 而是在 loss 上, 我们下面就看下 RPN 的损失函数.
RPN 损失函数
首先给出函数的公式:
这个公式和 Fast R-CNN 的多任务损失其实很像, 同样是一个在做分类, 一个在做回归, 然后把两个函数加在一起. i 是一个 batch 中 anchor box 的索引.
用于分类的 loss:
这依然是一个负的 log 值,,Pi 为第 i 个参考框是物体的预测概率, Pi 是一个指示函数, 如果 anchor 是物体的话, Pi 就是 1; 如果 anchor 是背景, 那么 Pi* 就是 0.
那么如果某一个区域是物体的话, 如果 pi=1,pi*=1, 此时的损失函数为 0; 同理 pi=0 的话, 损失函数为正无穷.
用于回归的 loss:
其中 R 还是 smooth L1 平滑方程:
同样的背景没有边界框, 所以需要 Pi* Lreg.
而 ti 与 ti * 分布对应四个值, 分别是 x,y,w,h 的坐标偏差, 其中:
x,y,w,h 是预测框(就是 reg layer 的输出);
xa,ya,wa,ha 是 anchor 参考框;
x*,y*,w*,h * 是 ground truth 框;
ti 是预测框与 anchor 之间的偏差, ti 是 ground truth 与 anchor 之间的偏差, 那么我们考虑一种情况, 那就是 ti 与 ti 与相同了, 此时损失函数就是 0, 那么这意味着:
预测值与 anchor 之间的偏差 = ground truth 与 anchor 之间的偏差
也就是说预测值完全等于 ground truth. 这就是上面提到的注意机制引导 RPN 关注 anchor 的过程, 当 anchor 不同的时候, loss 函数是不同的. 所以这是一个反向的过程, 我们选择出来了某一个点上 3*3 范围内的特征, 那么这个特征是物体还是背景呢, 还有就是它对应原图中哪个区域的时候, 效果是最好的呢? 这就是 RPN 要解决的问题.
在这里顺便说一下个人的一个想法, 会更方便理解, RPN 在 conv5 上用 33 的卷积核卷积, 那么如果原图上某一个区域在 conv5 上的大小恰好就是 33 呢? 那么这个卷积就相当于一个全尺寸卷积了, 显然它是可以学习到这个区域内的所有特征的, 然后我们再看下这些尺寸, 这方便我们理解为什么 RPN 选择了 3*3 卷积.
conv5 的尺寸为 13*13;
卷积为 3*3;
原图大小如果是 1024;
那么 anchor 选择为 256 的时候, 它们的比例非常接近:
13/3 = 1024/256
但是原图的尺寸不一定都是 1024*1024, 所以为了考虑形变与缩放, anchor 有 9 个选择.
Faster R-CNN 训练
Faster R-CNN 的训练时分步的, 但是不是分阶段的, 因为 end-to-end 的问题在 fast R-CNN 就已经解决了. 前面说了 Faster R-CNN =Fast R-CNN +RPN, 所以训练的过程需要分步来完成, 但是每一步都是 end-to-end.
Step 1: 训练 RPN 网络; 用的是 ImageNet 上的初始模型, 因为 RPN 是由自己的损失函数的, 所以在这里可以先把 RPN 训练起来, 但是在组合 mini-batch 做梯度回传的时候为了避免负样本 (背景) 偏多的情况, 会人为的我们随机地在一个图像中选择 256 个 anchor, 其中采样的正负 anchor 的比例是 1:1. 如果一个图像中的正样本数小于 128, 我们就用负样本填补这个 mini-batch.
Step 2: 训练 Fast R-CNN; 训练好 RPN 之后, 单独训练 Fast R-CNN, 此时 Fast R-CNN 是不与 RPN 共享卷积层的, 也就是初始模型还是 ImageNet 上得到的, 用的区域建议是 RPN 生成的, 训练的过程在之前的文章就就介绍了.
Step 3: 调优 RPN, 在这一步中将再次训练 RPN, 这不过这次的前五层卷积核与 Fast R-CNN 共享, 用 Step2 中的结果初始化 RPN, 并固定卷积层, finetune 剩下的层.
Step 4: 调优 Fast R-CNN, 此时用的区域建议是 Step3 中调优后的 RPN 生成的, 同样是固定了卷积层, finetune 剩下的层.
Faster R-CNN 性能评价
上面这张图说明了 Faster R-CNN 的单图测试时间与 mAP, 可以看到, Fast R-CNN 与 R-CNN 的时间与 Object Detection 系列(三) Fast R-CNN 的说法不一样了, 这是因为后者加上了 ss 算法的时间, 大概 2s 左右的样子.
单图测试时间的大幅缩减, 让 Fast R-CNN 能够真正意义上实现实时检测任务. 但是吧, Faster R-CNN 的性能评价是在 8 个 K40 GPU 上做出来的.
来源: https://juejin.im/post/5ba0a585f265da0a8e6d78bf