Cascade R-CNN
Cascade R-CNN 是 Zhaowei Cai 等人于 2019 年提出的一个检测算法。主要针对 faster rcnn 中 rcnn 部分 IOU 阈值选取对最终检测 bbox 质量的重大影响,而提出一种级联 rcnn 结构,不同级采用不同 IOU 阈值来进行重新定义正负样本和采样来逐渐提高 bbox 质量,效果稳定、特别好,应该说是目前打比赛的 baseline 算法。整篇论文通俗易懂、思路非常清晰,是不可多得的算法。其主要贡献可以归纳为:
深入研究了目标检测中 IoU 阈值选取问题,并通过大量实验分析验证了 IoU 阈值选取对检测器性能的影响。其指的是第二级 rcnn 部分 IOU 阈值,而没有考虑 rpn 部分 IOU 阈值,原因是 rcnn 部分才是决定 mAP 的核心,对于 RPN 部分的 mAP 多提高几个点其实带来的意义不能和 rcnn 相比。
基于上述研究,提出一种迭代 bbox 回归的级联 RCNN 网络,可显著提高 bbox 质量,提供检测精度,效果是非常好的。
1 faster rcnn 性能分析
在两阶段目标检测器中例如 FasterRCNN,RPN 输出 ROI,然后输入到 RCNN 层进行分类和回归,一般 RCNN 部分是设置 IOU=0.5 来进行正负样本划分,通过前面 n 多篇文章我想大概已经知道 IOU 阈值选取其实非常关键了。
论文首先分析 IOU 阈值对检测结果影响,如下图:
直观理解:iou 越大,检测的 bbox 越少,但是普遍质量更好,也就是说 iou 如果设置的比较小,那么在训练过程中可能会带来很多噪声,不利于训练,但是如果 iou 太高,会导致正样本太少出现过拟合。
上图能够反映出很多问题。首先看(a)图,横轴是 rpn 输出的 proposal 于 gt bbox 值的 IoU,纵轴是经过 rcnn 的 box 回归得到的新 IoU,不同线条代表不同阈值训练出来的 detector。以 u=0.5 为例,当对 RPN 输出的 proposal 使用阈值 0.5 来切分正负样本,对于那些 bbox 质量较差(也算正样本,0.5 < Input IOU < 0.55),经过 RCNN 回归后效果提升明显,IOU 可以直接回归到 0.75(应该是和此时正样本分布有关系,在该区间内的正样本应该比较多),且随着 proposal 质量增加,RCNN 回归后的 bbox 质量也会增加,但是 Input IOU 越大的 proposal,回归后提升越来越不明显,虽然精度没有下降。再看 u=0.7,对于低质量 proposal,其提升比较少,因为低质量的 proposal 被滤掉了,没有得到训练,但是对于高质量的 bbox,提升就比较大了。
可以发现,Input IOU 在 0.55~0.6 范围内 proposal 阈值设置为 0.5 时 detector 性能最好,在 0.6~0.75 阈值为 0.6 的 detector 性能最佳,而到了 0.75 之后就是阈值为 0.7 的 detector 了。只有输入 proposal 自身的 IOU 和 detector 训练用的阈值 IOU 较为接近的时候,detector 性能才最好(与其这样说,还不如说说阈值 IOU 设置应该和 rcnn 训练的输入样本 IOU 分布接近的时候,性能最好,其实就是样本重采样而已),如果两个阈值相距比较远,就是 mismatch 问题。简单来说就是如果当前 RPN 输出的 proposal 质量都一般,大部分是 0.5 IOU 的边界框,此时就应该用 IOU=0.5 的阈值进行 RCNN 训练,这样才会达到最佳效果。
再看图(b),其在当前设定的 iou 阈值处分类 loss 会存在一个峰值。这个是非常好理解的,假设 iou 阈值为 0.5,那么说明 proposal 于 gt bbox 值的 IoU 在大于 0.5 时候是正样本,低于 0.5 是背景样本,那么决策边界其实就在 0.5 附近了,那自然分类 loss 最大了。假设一个二分类问题,大于 0 是正样本,小于 0 是负样本,分类目的就是尽可能把 0 附近的正负样本区分开(对于正样本,预测 0 要变成预测 1,对于负样本,预测 0 要变成预测-1,那自然 loss 最大),此时靠近 0 附近的样本 loss 肯定最大,梯度也是最大的。
最后看图(c),在 IOU=0.5 到 0.6 的时候,检测性能下降比较少,但是一旦 IOU=0.7,检测性能就非常差了。这说明不能一味的提高 IOU 来达到输出高质量 bbox 的目的(对应匹配正样本数目不够,会出现过拟合)。
经过上面图示分析,可以得到如下结论:
低 IOU 阈值对质量较差的 bbox 提高较大,高 IOU 预测对质量较好 bbox 提升较大;
不能一味的提高 IOU 来达到输出高质量 bbox 的目的。
那么原因是啥呢?其实原因可以归为两点:
高 IOU 阈值会导致正样本减少,样本减少引发过拟合,后面有实验证明
在 train 和 inference 使用不一样的阈值很容易导致 mismatch
2 算法改进
2.1 原理分析
既然不能一味的提高 IOU 来达到输出高质量 bbox 的目的,那一个很自然的想法是级联结构,在每个层级采用不同的 iou 阈值来提升。
(a)是标准的 Faster RCNN 第二级 bbox 回归;(c)是前向时候不断迭代 bbox 回归,训练时候还是和 faster rcnn 一样(注意是:H1 H1 H1);(d)是对分类概率进行多次分类,使用了不同的阈值来进行分类,然后融合他们的结果进行分类推理,并没有同时进行 Box reg;(b)是作者所提结构,注意 H1 H2 H3,很明显该结构可以保证训练和测试流程完全一样,一致性更强。
对于(d)这种结构,当 IoU 提高的时候,proposal 的比重下降非常迅速,这种方法没有从根本上克服 overfit 问题,另外这种结构使用了多个高阈值的分类器,训练阈值却只能有一个,必然会导致 mismatch 问题而影响性能。
对于(c)这种级联结构存在问题,单一阈值 0.5 是无法对所有 proposal 取得良好效果的,如前面所示,proposal 经过 0.5 阈值的 detector 后 IoU 都在 0.75 以上,再使用这一阈值并不明智。第二个,detector 会改变样本的分布,这时候再使用同一个结构效果也不好,如下图所示:
第一行横纵轴分别是回归目标中 bbox 的 x 方向和 y 方向偏移量;第二行横纵轴分别是回归目标中 bbox 的宽、高偏差量。可以看到,从 1st stage 到 2nd stage,proposal 的分布其实已经发生很大变化了,因为很多噪声样本经过 bbox 回归后实际上也提高了 IoU,2nd 和 3rd 中的那些红色点已经属于 outliers,如果不提高阈值来去掉它们,就会引入大量噪声干扰,对结果很不利。从这里也可以看出,阈值重新选取本质上是一个 resample 过程,它保证了样本质量。
但是这里会有另一个问题,通过不断提高 IOU 阈值,这样子真的不会减少样本数量么?因为样本数量减少,就容易过拟合。作者做了大量实验,结果如下:
可以看出,样本不仅没有减少,而且稍稍有增加。说明本文方法不会减少正样本数量,是有效的。并且可以发现各个阶段那个 IOU 的 bbox 分布最多。
通过上面的深入分析,作者指出级联多个 rcnn 模块,并且不断提高 iou 阈值,在每个阶段不断进行正负样本重采样策略,不仅不会出现过拟合,而且可以实现极大的性能提升。在代码层面实现就非常简单了,就是在 faster rcnn 后面再级联 n 个 rcnn,每个 rcnn 的输入都是前一个 rcnn 的检测输出。
2.2 代码实现
熟悉了 faster rcnn 的代码,那么 cascade rcnn 代码几乎没有啥东西了,就是 copy 几遍 rcnn 代码就行了。
(1) 骨架+fpn+rpn
这三个部分和 fatser rcnn 结构和用法完全相同,要说唯一不同就是 rpn 的 bbox 回归,fatser rcnn 是 l1 loss,而 cascade rcnn 是 smooth l1 loss
(2) 级联 rcnn
假设一共级联 3 个 rcnn head,那个 head 都包括 faster rcnn 里面说的部分:
roi 提取模块 roialign;
Shared2FCBBoxHead
正负样本定义策略和随机采样
loss 计算
每个部分结构都是完全相同的,但是loss 权重、正负样本定义策略中的 iou 阈值、target_stds 不一样。这三个参数要改变是因为随着训练进行,每个部分的正负样本分布不一致了,对应的核心参数就要改变,才能最大程度发挥级联效果,并且因为每次 rcnn 都会更新 proposal,故 roialign 层也需要三个或者说运行三遍。本文为了代码简单,全部是 copy 了三遍。
还有一个细节需要注意:相比 faster rcnn 的 rcnn 部分,reg_class_agnostic 参数不一样,faster rcnn 是 False,对应的回归分支输出 shape 是(batch,4*num_class),在 cascade rcnn 的 rcnn 中为了简单设置为 True,每个 rcnn 的回归分支输出 shape 是(batch,4)。而且 faster rcnn 的 rcnn 部分回归 Loss 是 l1loss,分类 loss 是 sigmoid+ce,而 cascade rcnn 是 smooth l1 loss,分类 loss 是 softmax+ce。
第一个 rcnn 的结构如下:
(3) 训练流程
RPN 输出经过 get_bboxes 函数输出一系列经过 nms 的 proposal_list
假设级联 rcnn 个数是 N,n 初始化为 1。首先利用第 n 个 rcnn 的正负样本定义策略和随机采样对 proposal_list 计算正负样本;然后对 proposal_list 确定其应该切割的特征图层;然后利用第 n 个 rcnn 的 roialign 模块进行统一 size 操作;最后输入到第 n 个 rcnn 的 Shared2FCBBoxHead 模块进行预测输出和 loss 计算,返回原始预测结果和 loss
如果不是最后一个 rcnn 模块,则还需要对利用上述 proposal_list 和原始预测结果进行解码(refine_bboxe 函数),得到新的 refine 后的 proposal_list,然后 n+1,重复(2)-(3)步骤即可,不断 refine 前一个 rcnn 的预测结果
将 n 个 rcnn 的总 loss 按照权重加起来返回即可
(4) 推理流程
其推理流程和 faster rcnn 非常类似,只不过相当于 rcnn 重复了 N 遍而已。作者实验发现推理时如果单独只用 cascade RCNN 的 stage3,效果相比 stage2 和 stage1,确实是最差的,所以在 cascade RCNN 是用三个 stage 的分数取平均作为最后框的分数,这实际上是一种集成。
2.3 实验结果
级联 rcnn 中一个比较核心的问题是应该级联几个最合适?
结论就是级联 3 个最合适,级联太多不仅速度很慢,而且性能也没有提升了。
并且将级联思想应用于各种 two-stage 目标检测算法中都有很大的性能提升。
3 总结
目标检测其实并不是一个很合适的分类问题,没有一个明确的离散正负样本定义,而是通过 IoU 来连续定义的。但是 IoU 这个指标很难通过 gradient descent 来优化,虽然之前也有一些 IoU loss 的工作,但是效果并不理想。Cascade RCNN 便是一个在这个方向上很好的尝试。
论文看起来很炫,其实分析到本质就是一个不断增加的 IOU 来进行正负样本重采样的算法而已。如果不采用迭代级联算法,不管设置何种 IOU 都只能提升相对应 IOU 的 bbox 质量,而且如果一开始就设置很大的 IOU,那么就会导致正样本太少,出现过拟合(只能检测出部分物体)。那么自然就可以设置级联结构,随着 bbox 样本的 Iou 分布从均值 0.5 不断移动到均值 0.9 的过程中,我也不断提高阈值 IOU,对样本进行重采样,否则会引入大量噪声,挑选合适的正样本进行训练。
Last updated