Fast R-CNN 简介
在之前的两个文章中, 我们分别介绍了 R-CNN 与 SPP-Net, 于是在 2015 年 RBG(Ross B. Girshick)等结合了 SPP-Net 的共享卷积计算思想, 对 R-CNN 做出改进, 于是就有了 Fast R-CNN. 首先简单介绍下 Fast R-CNN. 相比于之前两种算法, Fast R-CNN 提出了:
多任务损失函数(Multi-task loss)
感兴趣区域池化(RoI pooling layer)
它由以下几个部分组成: ss 算法
CNN 网络
- SoftMax
- bounding box
首先在 SPP-Net 与 R-CCN 一直使用的 SVM 分类器被换成了 SoftMax,SPP-Net 中的 SPP 换成了 RoI pooling, 多任务损失函数的引入整合了分类网络的损失函数与 bounding box 回归模型的损失函数, 使任务不需要分阶段训练, 区域建议依然使用 ss 算法生成, 并在卷积后的特征图上提取(充分共享卷积计算), 初始模型从 AlexNet 换成了 VGG16.
感兴趣区域池化
上面这张图说明了 SPP 与 RoI pooling 的区别, 其实 RoI pooling 是 SPP 的一种简化, 原本 SPP 是一种多尺度的池化操作, 最后将三个尺度的特征做串接作为全连接层的输入, 而 RoI pooling 只选择了其中一种尺度, 将 ss 算法的建议框做坐标变化后的尺寸的长和宽, 平均分为 w 份和 h 份, 在每一份中使用最大池化, 最后产生 w*h 个 bin, 这样做有下面几个好处:
1. 统一输出维度, 这个是必须的.
2. 相比于 SPP-Net,RoI pooling 的维度更少, 假设 RoI pooling 选择了 4*4 的话, 那么维度就可以从 21 个 bin 降低为 16 个, 虽然这样看来降低的并不多, 但是不要忘了特征还有厚度, 如果厚度是 256 的话, 那么降维就比较可观了.
3.RoI pooling 不再是多尺度的池化, 这样一来梯度回传就会更方便, 有利于 Fast R-CNN 实现 end-to-end 的训练.
感兴趣区域池化的梯度回传 在上说提到了, RoI pooling 是单层的 SPP, 也就是只用一层金字塔并在区域内做 Max pooling, 所以如何说在卷积层上提取特征的时候, 特征的位置没有出现重叠, RoI pooling 就是一个 Max pooling, 梯度回传也是一样的, 而出现位置重叠的时候, 梯度回传才会发生变化.
那么先解释一下什么是重叠:
我们知道 Fast R-CNN 的区域建议同样是 ss 算法生成的, 那么一幅图片在生成多个建议框时 (假设是 2 个) 可能会出现一些像素重叠的情况, 就像下面这样:
而这种情况就没有重叠:
显然, 重叠的区域经过相同的坐标变换之后在卷积特征图上同样是有重叠的, 那么这部分重叠的像素梯度应该如何让计算呢? 是多个区域的偏导之和:
上图中有 r0 与 r1 两个区域, 每个区域都通过 RoI pooling 之后生成 4 个 bin,x23 的意思是第 23 个像素, 那么计算 x23 位置的梯度就可以根据上图中左侧的公式, 其中 r 是包含有这一点的区域, j 是某个区域内的所有位置.
但是 x23 的梯度计算显然不需要 r0,r1 内的所有位置的梯度信息, 它只需要包含 x23 这一点的, 或者说是 x23 这一点有贡献的点的梯度, 所以这里需要一个阈值函数 - i*(r,j), 它的作用就是如果需要 RoI pooling 后的这一点的梯度, 那么 i*(r,j)=1, 否则 i*(r,j)=0.
这样一来, RoI pooling 层的梯度回传只需要在 Max pooling 上简单修改即可.
多任务损失函数
Multi-task loss 是 Fast R-CNN 最重要的改进了, 它将分类模型的损失函数与 bounding box 模型的损失函数加到了一起, 这样一来就不再需要分阶段的训练了, 而是实现了 end-to-end.
首先分类模型的 loss:
其中 p 是每个 RoI 的概率分布:
而 u 是 Ground truth 的类别, 显然 u 的范围为(0,...,k)
显然, 这就是损失函数一个交叉熵, 只是它简写了, 或者说换了一种形式.
**Bounding box 回归模型的 loss: ** 这个 loss 和 R-CNN 中的 Bounding box 的 loss 没啥区别, 都是在用实际的边界框信息与 ss 算法给出的边界框信息构建一个 L1 距离. 如下:
其中平滑方程的具体形式如下:
而平滑方程里面的东西, 就和 R-CNN 一样了. 最后, 组合的多任务损失函数为:
这里有一个
, 它是一个指示函数, 作用就是背景类不需要 bounding box 修正, 也就没有回归 loss.
Fast R-CNN 训练与测试
上面这张图解释了 Fast R-CNN 的训练与测试过程, 前面两部分说明了 RoI pooling 层的梯度回传与多任务损失函数的构建, 所以 Fast R-CNN 的梯度可以一直传到卷积层, 实现 end-to-end 的训练.
此外, 为了在训练事得到更好的效果, 作者提出了一种分级抽样法, 如果 batch-size 为 128 的话, 那么这 128 个 RoI 由 2 张图片, 各生产 64 个区域.
而 Fast R-CNN 的测试过程和之前没啥区别.
Fast R-CNN 性能评价
上面这张图对比了 R-CNN,SPP-Net 与 Fast R-CNN 的训练时间, 单张图片的测试时间与 mAP, 可以看到由于 Fast R-CNN 可以 end-to-end 的训练, 它的 mAP 比 R-CNN 还要高一些, 这样就不会出现像 SPP-Net 那样 mAP 降低的情况, 而在训练时间与测试时间上, 又一次有了较大进步.
那么为什么 Fast R-CNN 比 SPP-Net 更快呢, 最重要的原因就是 end-to-end 的训练, 这样训练不再是分阶段的.
Fast R-CNN 的问题
虽然上面那张图上写的, Fast R-CNN 的单图测试时间为 0.32s, 但是其实这样说并不准确, 0.32 为了和 R-CNN 的 47.0s 做对比. 是的 Fast R-CNN 依然没有脱离 ss 算法, 但是 ss 算法跑一张图的时间, 大概是 2s, 所以讲道理的话, Fast R-CNN 依然是达不到实时检测的要求的, 好在 ss 算法在 Faster R-CNN 中被换成 RPN(区域建议网络), 这个我们后面再说.
来源: https://juejin.im/post/5b9f560fe51d450e735e44ff