从R-CNN到Mask R-CNN(二)

这篇文章继续从R-CNN到Mask R-CNN(一) ,接着介绍Faster R-CNN(2015)Mask R-CNN(2017),值得一提的这两篇论文的一作都有上篇文章说到的何凯明大牛,太厉害了。话不多说,直接进入主题。

Faster R-CNN

论文地址:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks

代码地址:https://github.com/rbgirshick/py-faster-rcnn

短评:这篇论文的主要贡献是提出了建立在目标检测模型上的RPN网络(Region Proposal Network,区域提议网络),实现了更高效、更精准的目标检测效果。

简介

在进入正题之前,先纠正一下上篇文章说到的”Fast R-CNN是基于R-CNN和SPP Net提出端到端的方法“,这个说法其实不太严谨,因为Region Proposal其实还是先走了一个规则的方法(selective search),所以严格来说还是两阶段(two-stage),这里的Faster R-CNN也是一样。预告一下,在后面的系列文章中将会谈到的YOLO才算真正意义上的end-to-end。

OK,言归正传,如前所述,目标检测算法有了长足的进步,但是前置的Region Proposal上却迟迟没有更好的做法,成为新的瓶颈(很慢很慢,Selective Search的CPU耗费时间近2秒/张,EdgeBoxes作了改进也要0.2秒/张)。Faster R-CNN正是针对该问题而提出,通过在目标检测模型的卷积特征抽取层基础上,增加少量的卷积层(RPNs)用于同时进行proposal的回归与分类,节省了大量计算(共享底层),也提升了proposal的质量(10ms/张),在单GPU上的整体检测帧率达到5fps(frame per second, includding all steps)。下图展示了和之前方法的直观对比:

image-20191210205659506

R-CNN对应图(a),有大量的重复计算;SPP Net对应图(b);RPN对应图(c),会预先设计一些缩放和宽高比(scales and aspect rations)不同的区域,然后通过算法进行调整。(论文举例不同,这里是个人理解,如有错误,欢迎指正)

模型框架

image-20191210225832431

Faster R-CNN实际上应该叫RPNs with Fast R-CNNs,如上图所示,包含RPN和传统的Fast R-CNN两部分,共享底层的卷积网络,整体上是一个完整的框架。借用当下热门的attention这个词,RPN的作用主要是告诉Fast R-CNN重点应该关注哪里

作者尝试了ZF(5个共享卷积层)和VGG-16(13个共享卷积层)作为底层模型,下图展示了RPN的工作原理:

image-20191210230631766

如左图所示,RPN网络实现上就是两层卷积,一是256个n\times n(论文取n=3,stride为1)的filter,二是两个并列的1\times 1卷积(主要是变换通道数为为预测数)。

注意到每个滑窗位置都预设了不同尺寸和宽高比的k个锚框(anchors,中心点同滑窗中心,论文设置值为3 scales和3 aspect ratios,共计3\times 3=9个锚框),所以需要预测2k个分数区分这些锚框是否为目标框/背景框,以及4k个边框的回归值以便修正边框。对于大小为W\times H(典型地,~2400)的特征图,会有WHk个锚框。(不要被k迷惑了,看起来好像好多,这里的k不是千,而是预设锚框类型数量,取值为9种而已😂)

本方法还有一个重要的性质——translation invariant,即anchors和rpn网络能共同作用以应对变换的输入,达致翻转不变性,相比之下,MultiBox就不具有该性质。此外,采用了更简单的方法来处理多尺度问题(见前图),将之前金字塔滤波器(pyramid of filters)的做法搬移到锚框上(pyramid of anchors),如此一来便可在同一个特征图上实现多尺度(multi-scale)目标的检测定位。

锚框的类别(K+1)分配算法可以参考标注训练集的锚框,写的很明白,贴一下图:

为锚框分配真实边界框

简单而言,就是先为每类目标都至少分配一个IoU最大的锚框(避免直接用阈值可能导致有些稀有类没有正样本),剩下的锚框再结合IoU大于0.7分配对应的目标,IoU小与0.3为背景,介乎中间的不被考虑。损失函数定义如下:

L({p_i},{t_i})=\frac{1}{N_{cls}}\sum_{i}L_{cls}(p_i,p_i^\star) + \lambda \frac{1}{N_{reg}}\sum_ip_i^\star L_{reg}(t_i,t_i^\star)

对于RPN网络而言,分类问题是二元分类——背景or目标,p_i^\star表示第i个锚框的是否为目标(1),t_i^\star则是目标的真实框,注意到第2项只对目标框进行计算。分类损失用的是交叉墒,回归损失用的是上篇文章介绍Fast R-CNN时的\mathrm{smooth_{L1}}N_{cls}N_{reg}都是正则项,论文里的取值为N_{cls}=256N_{reg}=2400\lambda = 10。算下来,两个损失项几乎是等权的。不过,后面的实验可以看到,实验结果其实对这些超参数并不敏感(insenitive)。特别的,对于4个坐标相关值的转换方法同上篇R-CNN。

强调一下和之前bounding-box回归方法的不同:之前的方法通常是利用RoI在特征图上得到其对应的特征,然后通过共享权重回归;而这里恰恰相反,特征输入是一样的(如前所述是3\times 3的空间卷积得到的长度为256或512的特征向量),然后k个不同的锚框分别用各自独立的权重回归。

RPNs的基本训练设置:每张图片采样256个anchors,正负比例尽量控制在1:1,底层模型利用ImageNet分类任务预训,新增卷积层使用0均值0.01标准差的高斯分布初始化,前60k步学习率为0.001,后20k步降至0.0001,数据集采用的是PASCAL VOC。

因为RPN和Fast R-CNN是共用的底层网络,所以作者还试验了几种不同的训练方式:

  • 交替训练(Alternating training),就是RPN和Fast R-CNN交替进行训练,这是论文采用的基本训练方法
  • 近似联合训练(Approximate joint training),即RPN和Fast R-CNN的梯度同时回传以更新底层网络,值得注意的时,RPN预测的proposal即属输出,也属于Fast R-CNN的输入,梯度计算是个问题(具体什么问题,不是很理解),所以Fast R-CNN是忽略了框的回归损失的,训练时间相比交替训练节省25%-50%
  • 非近似联合训练(Non-approximate joint training),利用了RoI warping的方法,所有梯度都计算
  • 4阶段交替训练(4-Step Alternating Training),过程有些弯曲,也不知道大神是怎么想出来的,😂
    • 先用ImageNet预训的模型fine-tuned一个RPN模型
    • 还是用ImageNet预训的模型fine-tuned一个Fast R-CNN模型,该模型接收步骤1的RPN模型的proposal
    • 上两步得到的模型是互相独立的,第3步用Fast R-CNN模型初始化RPN训练,并且冻结底层,只fine-tune RPN本身的层
    • 最后,底层还是冻结住,fine-tune Fast R-CNN相关的层

论文使用了3种尺寸(128^2, 256^2, 512^2)和3种宽高比(1:1,1:2,2:1),共计9种组合的锚框。对于一张典型的1000\times 600的图片,原始锚框数目有近20000\approx 60\times 40 \times 9,去掉跨边界(很难预测修正,不去掉训练无法收敛),剩余约6000个,应用非极大值抑制(non-maximum suppression, NMS),留下约2000个proposal提供给Fast R-CNN作最后的检测。

注:非极大值抑制的算法原理可以在gluon-cv找到,就是沐神的《动手学深度学习》课程内容,很多讲的都很清晰,强推。

实验分析

image-20191213204855917

表2中,论文提出的Faster R-CNN(即表里的RPN+ZF, shared)优于SS/EB + Fast R-CNN,为了特别地分析RPN的效果,后面几组实验中RPN和Fast R-CNN是脱钩的,注意到:

  • 训练和测试时的dismatch会带来较大性能损失,后面几组,训练时都用的Selective Search提的proposal,但是测试时用了RPN,可以看到mAP下降明显
  • NMS的加入对性能影响不大,效率提升却明显很多
  • no cls是随机选取RPN的proposal,而不是用Top-N策略,mAP下降明显,表明RPN的打分还是比较有效的,可以大幅减少proposal同时保证最终效果
  • no reg是指直接用对应的锚框,而不是修正后的方框作为proposal,mAP下降明显,也侧面反映了回归对于质量的保证
  • 最后一行结果比较惊喜,用更大的VGG模型,再一次获胜

除了大模型,大数据也是制胜法宝,不信见下图:

image-20191213210547103

前面说过了,速度上提升更为明显,我们通过数据直观感受一下:

image-20191213210719429

还有很多其他比赛的实验结果,就不一一贴图了。

Mask R-CNN

论文地址:Mask R-CNN

代码地址:https://github.com/facebookresearch/Detectron

短评:通过在Faster R-CNN上增加一个类FCN分支,极大地提升了在实例分割任务上的性能,目标检测任务也得到额外收益,是一篇很好的扩展文章。

简介

有几个概念,之前可能没介绍到,但是和目标检测(object detection,将每个目标用bounding box框出来)其实是密切相关的,其中一个就是这篇论文提到的实例分割(instance segmentation,要用mask标出每个实例的位置),还有语义分割(semantic segmentation,像素级分类,但是不区分同类里的不同个体)、全景分割(panoptic segmentation,区分个体的像素级分类),更多可参考知乎专栏

image-20191213214652711

图一就是Mask R-CNN的基本框架图,看起来是Faster R-CNN一个很直接的扩展。但是设计上有不少细节对于最终效果影响巨大,这就是Kaiming He的功力所在,把简洁的模型框架做的高效优异。有两点被特别拎了出来,一是RoIPool的特征抽取对于实例分割任务而言太粗力度了,不够精细,所以提出了升级版的RoIAlign,二是实验证明将maskclass prediction任务分离(decouple)是很重要的。

模型框架

Mask R-CNN和Faster R-CNN相比,RPN网络是完全一致的,主要存在两点不同:

  1. 新增了一个分支预测RoI的binary mask,用的是FCN网络,但是和FCN网络中采用softmax + multinomial cross-entropy loss不同,这里只用了简单的binary cross-entropy loss,即不和具体分类挂钩,还是让原来Faster R-CNN的目标检测分支去干这个事情(专业分工),虽然如此,需要注意,每个RoI还是会预测出K类的0/1 mask矩阵(以m\times m大小的一个RoI为例,会预测Km^2个概率值),只不过计算loss时只取真实类的mask算平均二元交叉墒损失。所以损失函数总共包含3项,L=L_{cls} + L_{box}+L_{mask}

  2. 要进行像素粒度的判别,原本的RoIPool太粗了(stride量化、bins量化),因此提出了RoIAlign替换,通过双线性插值(bilinear interpolation)更加精确的计算RoI每个bin及其内采样点的值。下图是原理示意:

    image-20191213223301592

    这里显示的是2\times 2的网格划分,每个bin里采样4个点(采样方法一般同样是横竖切成n等分,取中心),计算本bin的特征(4个点取最大值或平均值)。细致看可以看到,左上角的采样点值计算利用了邻近feature map的四个确定点,这正是双线性插值(bilinear interpolation)的特点

底层网络(backbone)尝试了ResNet和FPN,上层网络(head)如下:

image-20191214111049072

实验分析

Mask R-CNN大幅超越之前的sota。一些消融实验结果贴一下:

image-20191214112126009

可以看到之前说到的几个点(Loss的设计、RoIAlign),在系统性能上的重要影响。

系列文章重点关注目标检测,所以目标检测的结果也贴一下:

image-20191214112320022

另外,Mask R-CNN的框架极具灵活性,还可以做更多的事情,例如人的姿态识别(Human Pose Estimation),只需要将K种姿态(例如左肩、右肘)也用K张masks表示即可,结果如下:

image-20191214112957554

至此,R-CNN系列文章已到尾声,感谢收看。接下来开启YOLO系列😁

Published by

admin

天空没有翅膀的痕迹,但我已飞过

Leave a Reply

Your email address will not be published. Required fields are marked *