论文笔记:https://zhuanlan.zhihu.com/p/33158548
论文链接:https://arxiv.org/abs/1711.07264
这篇文章从题目上看就一目了然:捍卫two-stage object detector.
我们知道Object detection分为两大门派:
- 一类是two-stagedetector (Faster RCNN, Mask RCNN等): 第1步是生成proposals,第2步是对这些proposals进行分类、回归.
- 另一类是singel-stagedetector (YOLO, SSD等): 这些算法一步到位,可以理解为把object detection task 简化成了regression problem.
通常来说,前者检测精度高,后者检测速度快。随着YOLO、YOLOv2、SSD等速度极快且精度不错的one stage detector的出现,大家似乎对RCNN family的青睐少了很多。毕竟,真正应用落地的时候,speed 显然是非常重要的一点。讲实话,如果你不是为了刷榜,这些one stage detector 算法的精度也确实够用了,更何况速度真的是快了好多。
但就个人而言,我认为single-stage的上限是低于two-stage的,一直很想看到优化two-stage detector速度的工作,所以非常喜欢这篇文章:idea 虽然不大,但是实验做的非常好,手动点赞!
Abstract
在这篇文章里,作者主要分析了:
- 为什么two-stage detector会慢,主要慢在哪?
- 如何在解决速度慢同时保证精度?
文中,作者把 two-stage 拆解成 body 跟 head:
- body: 生成proposal(RoI)的过程, 即: ROI warping.
- head: 基于proposal的recognition过程, 即: RCNN subnet.
作者认为,目前的算法,为了追求best accurcy,一般都会把head设计的非常heavy,所以即使我们把前面的base model变小,还是无法明显提升检测速度。
这篇文章的重点,就是如何对head进行瘦身。通过light head以及其他trick:
- 作者用Resnet-101作为base model,拿到了COCO-2017的冠军。
- 更重要的是,作者用了轻量级的Xception作为base model,达到了30.7 mmAP,并且速度达到102FPS,从speed到accuracy都全面击败现有的single-stage的算法。
上个图,大家自行感受一下这篇文章在speed与accuracy之间的trade-off做的有多好:
Light-Head R-CNN
上文提到,作者把two-stage分成了body(RoI warping) + head(RCNN subnet),并且指出,head太heavy是造成two-stage效率低的主要原因。我们来看一下典型的two-stage detector结构:
RCNN subnet of Faster RCNN
上图为base mode是Resnet-101的Faster RCNN的网络结构:
- 首先是用Resnet-101提取特征,得到channel数为2048的feature map.
- 然后,由RPN产生的每个RoI经过RoI pooling 得到固定大小的feature map。
- 每个RoI对应的固定大小的feature map,都要通过RCNN-subnet,得到最终的分类、回归结果。
每个RoI都要通过RCNN-subnet计算一次,而且为了保证精度,Faster R-CNN 用的RCNN-subnet通常是两个很大的FC(或者resnet 的第5个stage),这样的做法是非常耗时的。
为了提速,通常RoI feature map后面会采用global average pool. 这样做的目的是为了减少第一个FC层的计算量,但是会丢失一些spatial localization的信息,不利于目标bbox回归。
RCNN subnet of R-FCN
针对Faster-RCNN中每个RoI都要重复计算的情况,R-FCN 做了一些优化。
在R-FCN中:
- 同样地,经过Resnet-101得到channel数为2048的feature map.
- 然后,采用1x1的卷积核,得到Position-sensitive feature map(channel: P^2(C+1)).
- 每个RoI经过一个PSRoI Pooling层得到feature map(size: P*P,channel: C+1). 再经过一个global average pool层得到每个RoI的prediction.
可以看到,R-FCN的RCNN-subnet很小,只包含了global average pool,所以它会比Faster-RCNN快。但是,为了让得到的feature map具有Position-sensitive的特点,需要满足它的channel数是P^2(C+1)。在COCO数据集上,相应的channel数是3969,这就必然还是会造成很大的时间和存储的开销。
RCNN subnet of Light-head RCNN
上图为本文中提出的改进结构,可以看出基本是在R-FCN的基础上进行修改的。不同的地方在于:
- 作者采用large separable convolution生成channel数更少的feature map(从3969减少到490)。
- 用FC层代替了R-FCN中的global average pool,避免空间信息的丢失。
文中所说的large separable convolution 应该是借鉴了Inception 3的思想:
Inception 3中将大小为k_k的卷积核,用1_k和k*1的两层卷积来代替。
使用这种卷积替换之后,可以在计算结果一致的前提下减少计算量。减少的计算量,大致为原来的k/2,文中作者将k取15,因此这里大大减少了计算了。当然,计算复杂度还跟 C_mid 和 C_out 有关。
Experiments
作者在8块Pascal TITAN XP GPUs上跑的COCO的实验。
Implementation Details
- synchronized SGD withweight decay: 0.0001,momentum: 0.9.
- Eachmini-batchhas 2 images per GPU.
- Each image has 2000/1000RoIsfor training/testing.
- Pad images within mini-batch to the same size byfilling zeros into the right-bottomof the image.
- Learning rate: 0.01 for first 1.5M iterations and 0.001 for later 0.5M iterations.
- Adoptatrousalgorithm in stage 5 of Resnet.
- AdoptOHEM.
- Backbone network is initialized based on thepre-trained ImageNet.
- Pooling size: 7.
- Batch normalization is alsofixedfor faster experiment.
- Dataaugmentation: Horizontal image flipping.
Ablation Experiments
这部分是整篇文章我最喜欢的部分,实验做的很好。不过,具体的对比实验还是应该看看原文。这里我简单总结一下实验结论。
Baselines
作者通过R-FCN的开源代码,在COCO mini-validation set上得到了mmAP 32.1%的baseline,记为B1. 又通过一些改进,得到一个更好的R-FCN baseline,记为B2. 主要的改进是:
- 对图像进行resize,将shorter edge设为800,同时限制max size为1200.
- 由于图像变大了,所以采用新的anchor: {322, 642, 1282, 2562, 5122}.
- 发现在R-CNN中,regression loss会比classification loss小很多,因此将regression loss*2.
- Each image has 2000/1000 RoIs for training/testing.
效果非常显著,这些简单的改进之后,R-FCN就提升了3%,如下图:
Thin feature maps for RoI warping
为了研究数量更少的feature map对结果的影响,作者又做了一组实验。除了以下两点,跟R-FCN基本一致:
- 减少feature map channel,从3696(81_7_7)减少到490(10_7_7).
- 由于改变了feature map channel数,导致无法直接通过global average pool进行prediction,因此加了一个FC层。
实验结果如下:
这是符合预期的,channel 数少了必然会导致精度的下降。
Large separable convolution
上述的实验减少了channel数,但用的还是R-FCN中1*1的卷积核。
为了验证Large separable convolution带来的影响,作者在上一组的实验基础之上,将1*1卷积核,换成了Large separable convolution. 同时令:k = 15, Cmid = 256, Cout = 490.
用了large separable convolution,虽然channel数减少了,效果却提升了0.7%.
R-CNN subnet
分别介绍了thin feature map和large separable convolution的效果,下面是将这二者结合后的效果:
精度得到了大幅提升,mmAP达到了37.7%. 更重要的是,由于thin feature map以及light RCNN-subnet,使得即使有数千个RoI,算法仍然很快。
Light-Head RCNN 可以有多精准?
为了提升算法精度,作者又加入了其他trick,分别是:
- 在PSRoI pooling中加入RoIAlign (Mask-RCNN) 中的插值技术,提升了1.7%.
- 将NMS threshold从0.3改成0.5之后,提升了0.6%.
- 使用multi-scale进行training,提升1%.
最终,在COCO test-dev数据集上,达到了如下的performance:
Light-Head RCNN 可以有多快?
为了平衡精度与速度,作者做了如下一些改变:
- 用Xception代替Resnet-101.
- 弃用atrous algorithm.
- 将RPN channel减少一半到256.
- Large separable convolution: kernel size = 15, Cmid = 64, Cout = 490.
- 采用 PSPooling + RoI-align.
采用上述trick之后,能够在COCO上达到102FPS,同时达到30.7% mmAP的精度。可以说是非常厉害了!
Conclusion
总结一下这篇文章,作者主要有以下几个改进点:
- Large separable convolution + Thin feature map 提升算法速度。
- 用FC来代替global average pooliing来减少空间信息的丢失,提高精度。
- 加入其它trick,例如: PSRoI with RoIAlign、multi-scale training、OHEM 等来进一步提升精度。