引言
Cascade R-CNN作为目前主流常用的高性能目标检测算法中最广为人知的算法之一。它基于经典的Faster R-CNN架构,通过引入级联式的多阶段检测器来逐层提升检测精度,从而显著提高了模型在困难样本上的表现。
模型算法下载
在 Coovally AI Hub 公众号后台回复 「 模型算法 」, 即可获取!
背景
在Faster R-CNN算法中,RPN输出指定数量的RoI候选框,然后输入到R-CNN层进行分类和回归,一般R-CNN部分是设置IoU=0.5来进行正负样本划分。
直观上训练时设置IoU越大,检测的bbox越少,但是普遍质量更好,也就是说 IoU如果设置的比较小,那么在训练过程中可能会带来很多噪声,不利于训练,但是如果IoU太高,会导致正样本太少出现过拟合,结合如下曲线可以进一步验证。
针对不同IoU阈值的regressor和detector进行了实验。从图c可以看出,不同IoU阈值的detector对不同水平的bndbox的优化程度不同,bndbox IoU与detecor的训练阈值越接近,box regress提升越高。而在图c中,detector(u=0.5)在低IoU水平下比detector(u=0.6)表现优异,而在高IoU水平下则反之,而当u=0.7时,由于正样本的不足以及推理时输入的样本IoU较低,detector(u=0.7)的整体表现都降低了。只有输入proposal自身的 IoU分布和detector训练用的阈值IoU较为接近的时候,detector性能才最好,或者说阈值IoU设置应该和R-CNN训练的输入样本IoU分布接近的时候,性能最好,如果两个阈值相距比较远就是mismatch问题。 但图 (c)又说明不能一味的提高IoU来达到输出高质量bbox的目的(对应匹配正样本数目不够,会出现过拟合)。
模型介绍
因此,提出了Cascade R-CNN来解决上面的问题。Cascade R-CNN是一个顺序的多阶段extension,利用前一个阶段的输出进行下一阶段的训练,阶段越往后使用更高的IoU阈值,产生更高质量的bndbox。Cascade R-CNN简单而有效,能直接添加到其它R-CNN型detector中,带来巨大的性能提升(2-4%)
既然在Faster R-CNN中不能一味的提高IoU来达到输出高质量bbox的目的,那一个很自然的想法是级联结构,在每个层级采用不同的 IoU 阈值来提升。
Faster R-CNN
目前经典的two-stage架构如上图(a)。第一阶段是一个提框的子网H0,用于生成初步的bndbox。第二阶段为特定区域处理的检测子网H1,给定bndbox最终的分类分数C和bndbox坐标B。
Iterative BBox
有的研究者认为单次的box regress是不足以产生准确的位置信息的,因此需要进行多次迭代来精调bndbox,这就是iterative bounding box regression:
Integral Loss
IoU阈值(u)决定了正样本(positive)和负样本(negative)的划分。如果一个假设(hypothesis)与真实框(GT)的IoU高于u,则视为正样本;否则视为负样本。当u值较高时,正样本的数量较少,但背景区域(background)较少;而当u值较低时,可以获得更多样化的正样本,但这会导致检测器难以抑制接近的假阳性(close false positives)。因此,很难找到一个适用于所有IoU水平的分类器。
Cascade R-CNN
Cascaded BBox Regression
由于很难训练一个能应付所有IoU水平的regressor,可以把回归任务分解成一个级联的regression问题。
- iteravtive BBox是后处理的方法,而cascaded regression是能够改变bndbox分布的重采样过程。
- cascaded regression在训练和推理时是一致的,不存在区别。
- cascaded regression的多个regressor对于对应阶段的输入分布是最优的,而iterative BBox仅对初始分布是最优的。
Cascaded Detection
产生Cascade R-CNN的启发点主要有两个:
- 初始的bndbox分布大多落在低质量的区域,这对于高质量classifiers来说是无效的学习。
- 所有的曲线都高于对角线,即regressor都倾向于能够提升bndbox的IoU。
因此,以集合作为开始,通过级联regress来产生高IoU的集合。这种方法能在提升样本整体IoU水平的同时,使得样本的总数大致维持在一个水平,这会带来两个好处:
- 不会存在某个阈值的regressor过拟合
- 高阶段的detector对于高IoU阈值是最优的
随着阶段的深入,一些离群点会被过滤,这保证了特定阈值的detector的训练
def forward_train(self,
x,
img_metas,
proposal_list,
gt_bboxes,
gt_labels,
gt_bboxes_ignore=None,
gt_masks=None):
losses = dict()
# 对每个 R-CNN 阶段单独操作( 相比 Faster R-CNN 多了这一层循环)
for i in range(self.num_stages):
self.current_stage = i
# 注意每个 stage 的训练参数不一样,典型的例如 Iou 阈值
rcnn_train_cfg = self.train_cfg[i]
lw = self.stage_loss_weights[i]
sampling_results = []
# n 个 stage, 就会有 n 个 bbox_assigner 和 bbox_sampler
if self.with_bbox
bbox_assigner = self.bbox_assigner[i]
bbox_sampler = self.bbox_sampler[i]
num_imgs = len(img_metas)
# 对每张图片单独分配正负样本和采样
for j in range(num_imgs):
assign_result = bbox_assigner.assign(
proposal_list[j], gt_bboxes[j], gt_bboxes_ignore[j],
gt_labels[j])
sampling_result = bbox_sampler.sample(
assign_result,
proposal_list[j],
gt_bboxes[j],
gt_labels[j],
feats=[lvl_feat[j][None] for lvl_feat in x])
sampling_results.append(sampling_result)
# 按顺序,对每个 stage 进行 train
# 相比 Faster R-CNN,不仅仅要输出当前 stage 的 loss,还需要额外输出
# 预测后分类和 bbox 值,方便用于后续 stage refine
bbox_results = self._bbox_forward_train(i, x, sampling_results,
gt_bboxes, gt_labels,
rcnn_train_cfg)
# 记录当前 stage 输出的 loss
for name, value in bbox_results['loss_bbox'].items():
losses[f's{i}.{name}'] = (
value * lw if 'loss' in name else value)
# 如果不是最后一个 stage,则表示需要进行迭代训练
if i < self.num_stages - 1:
# pos_is_gts 表示哪些正样本是 gt bbox ( 因为在 R-CNN 阶段会注入 gt bbox 当做额外的
# RoI 以加速收敛和防止训练不稳定),在 refine 阶段要把这部分正样本剔除
pos_is_gts = [res.pos_is_gt for res in sampling_results]
# roi_labels 是在当前 stage 中定义的每个 proposal 的 label, 背景类别是 num_classes
roi_labels = bbox_results['bbox_targets'][0]
with torch.no_grad():
# 对于 label 为背景的 proposal 可能预测后依然是背景,也可能不是背景
# 为了能够保证一致性,需要将标注为背景的 roi_labels 替换为网络真正预测类别值
roi_labels = torch.where(
roi_labels == self.bbox_head[i].num_classes,
bbox_results['cls_score'][:, :-1].argmax(1),
roi_labels)
# 利用 rois bbox_pred 可以得到新的 proposals,用于下个 stage 训练
proposal_list = self.bbox_head[i].refine_bboxes(
bbox_results['rois'], roi_labels,
bbox_results['bbox_pred'], pos_is_gts, img_metas)
return losses
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/CooVally_AI/article/details/145210873
实验结果
作者在通用目标检测、实例分割数据集COCO上进行了实验,换上骨干网ResNeXt-152的Cascade R-CNN又刷出了新高度!AP达到50.9。如下图:
使用不同的检测器和骨干网,级联后都能获得大幅度的精度提升,如下图:
同时可见,级联后推断速度有少许变慢,但在可接受的范围内。
下图是将Cascade Mask R-CNN与基线版本比较的结果,在实例分割任务中,也取得了明显的精度提升。
Coovally AI模型训练与应用平台
Coovally AI模型训练与应用平台,它整合了整合30+国内外开源社区1000+模型算法。
平台已部署Cascade R-CNN系列模型算法
在Coovally平台上,无需配置环境、修改配置文件等繁琐操作,可****一键另存为我的模型,上传数据集,即可使用Cascade R-CNN****等热门模型进行训练与结果预测,全程高速零代码! 而且模型还可分享与下载,满足你的实验研究与产业应用。
总结
Cascade R-CNN通过引入多阶段级联结构,成功突破了传统目标检测方法在复杂样本处理上的局限性。它在小物体、遮挡物体和复杂背景下的表现尤为突出,成为了一种具有重要意义的目标检测算法。随着技术的不断发展,Cascade R-CNN也为后来的模型算法提供了非常好的创新思路。