概述:
最新几年的论文都是在单阶段、Transform上进行发掘提升,基本上2020-2021年二阶段论文全军覆没,这篇博文也是总结2016-2019年的发展,最后一篇CenternetV2比较特殊,不能完全算作传统意义的二阶段网络。
目前什么地方还使用二阶段论文?
- 比赛场景,经常使用FasterRCNN的变种+其它网络进行联合预测
- 目标比较小的场景(使用较少,一般用anchor-free、增大输入去代替、分割图像检测)
- 辅助一阶段使用,和(2)类似但不同。比如检测远距离人形+人脸,方案一:先检测人,后检测人脸,两个都是OneStage。方案二:使用TwoStage网络,第一阶段检测人形,第二阶段检测人脸。当然只有第二类别是第一类别的从属,且是唯一关系才能进行!
一. FasterRCNN
以torchvision给出的demo为例子:
- 第一阶段,和基础SSD等一阶段操作类似,但是这一阶段会立刻输出候选区域
-
将候选区域从FPN输出的feature上抠出来
-
使用ROIPooling对齐候选特征的大小
- 第二阶段,直接进行FC细化Reg/Cls,当然这里只能是一个候选区域最多一个目标。
class FastRCNNPredictor(nn.Module):
"""
Standard classification + bounding box regression layers
for Fast R-CNN.
Args:
in_channels (int): number of input channels
num_classes (int): number of output classes (including background)
"""
def __init__(self, in_channels, num_classes):
super(FastRCNNPredictor, self).__init__()
self.cls_score = nn.Linear(in_channels, num_classes)
self.bbox_pred = nn.Linear(in_channels, num_classes * 4)
def forward(self, x):
if x.dim() == 4:
assert list(x.shape[2:]) == [1, 1]
x = x.flatten(start_dim=1)
scores = self.cls_score(x)
bbox_deltas = self.bbox_pred(x)
return scores, bbox_deltas
注释:
- 最后一步FC是参考anchor的做法,首先想到的是\(self.bbox\_pred = nn.Linear(in\_channels,4)\) ,因为已经使用class进行了过滤,没有必要再把regression去使用class再去过滤一遍。当然使用class对回归进行区分,这效果肯定优于单个回归。
- 我们再进一步延伸,如果在不同的class之下,再使用一种手段(长宽、面积、anchor等)对其进一步划分,比如:假设候选区域数量不变为 \(P\),类别为两类(人形、人脸),进一步使用anchor限制(两个anchor,5和20,比例4倍以内使用5,超过4倍使用20),这样会不会更精细?
- 上一步我们限制了候选区域数量,能不能使用输入多个不同组的候选区域,后面连接多个不同的predict?这就是后续改进cascadeRCNN的由来。
二. MaskRCNN
- 第一阶段使用FasterRCNN,RPN网络都相同
- 第二阶段输出多一个分支 \(K\times m\times m\) , 其中 \(K\) 表示种类,\(m\) 表示输出分辨率
注意: 最后输出的mask大小是固定的,设置大小得根据实际种类而定。这个mask分支和FCN有点区别,这里使用K个feature,然后直接进行二分类操作,而FCN使用单个feature进行多分类操作,目前检测的分类loss都是进行单独的二分类操作。
三. CascadeRCNN
-
第一阶段和FasterRCNN完全一样
-
第二阶段使用多个RoiHead层进行级联
下图完全显示了CascadeRCNN的由来
- 下图(C)仅仅在前向计算的时候使用级联finetune操作,精度也得到一定提升,但是有两个缺陷。1)使用共享的Head-H1,不仅时间没降低,而且参数效果还不好。所以在端侧单阶段目标检测中,一般不使用共享的头,虽然参数减少了,但是计算量一点未变,所以都使用不共享的头。2)都是固定的,不能进行训练,后面的阶段已经处于过拟合状态。
- 下图(d)最大的缺点就是候选区域固定,非常容易过拟合。有一个优点,后面的stage仅仅进行分类而不进行reg,这是cascade未考虑的。但是,分类分支花费的代价很小,基本影响不到大局,所以讨论的人很少。
- 下图(b)融合了两者的优点,1)可训练。2)不共享。3)候选区域不同。
四. Libra RCNN
未改变实际的流程结构,文章从均衡的角度对各个模块进行改进。
- \(feature\) 均衡,使用FPN、PAN、BiFPN进行互相链接
- 采样均衡,原始SSD分配使用Max-IOU,采样使用Random-Sample
- loss均衡,原始SSD直接使用独立的分支进行计算
IOU-Balance采样,下图是困难负样本(\(Iou<0.5\) 称为困难负样本)的Iou分布,其中64%样本\(Iou>0.05\),36%的样本\(Iou<0.05\),注意这里是百分比图,不是个数量图!!!下图中使用随机采样,会导致70%的样本\(Iou<0.05\) ,这明显是不符合下图的困难负样本的分布图的。如何将下附图的每个方格采样比例趋于平衡?很明显的想到还是使用方格将IOU进行区域划分(直方图的表示方法),然后按照一定比例进行采样即可。论文给出一些控制参数,使得表达更为通俗易懂。
关于feature部分的平衡,这部分有点玄,意义不大。。。
关于loss的平衡,主要对smooth-L1进行调整,文章分析了loss的贡献率,\(loss<1.0\) 贡献30%,相反贡献70%,既然要平衡,那就要提升 \(loss<1.0\) 的梯度(loss占比),其实和focal-loss一样,都是提升困难样本的比重。
五. GridRCNN
- 第一阶段和FasterRCNN完全一样
- 分类分支相同,回归分支使用关键点
从当前的角度看,这篇论文较为简单,属于简化版的anchor-free模型,因为是对候选区域进行操作,不需要anchor的匹配,不需要进行nms等操作。和top-bottom的pose估计一模一样!!
如果把第一阶段也使用关键点去估计,那这篇二阶段文章就完全是anchor-free+pose的文章了。
需要注意一点,经常出现候选区域把目标截断(二阶段网络都存在的问题),那关键点就不存在(使用0表示),但是对于定位就很不准确。最简单的方式是直接扩大候选区域的截图范围,作者尝试这种方案效果不理想。作者采用候选区域不变,仅对候选回归框做扩大。如下图所示,绿色是目标框,白色实线是候选框,输入白色实线候选区域,在白色虚线的基础上进行回归。
六. GridRCNN-V2
- 第一阶段和FasterRCNN完全一样
- 第二阶段和GridRCNN-V1基本相同
这篇论文主要是对第一版本的速度进行改进:
- keypoint branch 从\(56\times56\)降低到\(28 \times 28\) ,论文说这样做不仅会加快速度,而且还会提高精度。之前在关键点上试验,使用期望定位会有精度损失。
- 减小候选区域的大小,降低channels
- 联合整个batch图像进行计算。之前使用for循环,单次计算单张图像,对于目标数量非常敏感,现在是对batch进行一次计算。
- NMS仅进行一次
七. Double-Head RCNN
- 第一阶段和FasterRCNN完全一样
- 第二阶段ROI-Head使用多个头进行预测
此想法类似多模型W联合预测WBF,使用全连接头+卷积头联合预测,唯一注意的是cls分支使用联合loss,而reg分支使用单独预测。
利用联合预测效果绝对有所提升,但是额外的分支预测占用较多的资源,如何做到Trade-Off是关键。
八. CenterNetV2
在刚开始的概述(3)中,表达了一种二阶段网络的特殊应用,这篇文章将此应用表述成一种方案:我们可以使用任何一阶段的网络作为RPN层(包括anchor-based、anchor-free操作),后面ROI阶段可以使用任何之前的第二阶段网络。这不就是集合前人的大杂烩?搞不懂为啥没有使用YOLOV4作为第一阶段进行比较?
进一步引申:
- 类似人形+人脸的检测组合(概述3)
- 关键点检测模型(Top-Bottom),比如人体关键点估计,可以直接使用二阶段网络。