简单来说,FPN 的整体目标就是使用卷积网络的从高到低的具有语义的特征金字塔,构建一个具有高层次语义的金字塔;提出了自上而下和横向连接来连接丰富的语义特征和高分辨率,使网络适应与分类和定位的任务。
论文:Feature pyramid networks for object detection
论文链接:https://arxiv.org/abs/1612.03144
Code:https://github.com/DetectionTeamUCAS/FPN_Tensorflow/tree/master/libs/networks
先来膜拜一下大佬们!FPN是2017年的CVPR论文,我们来看一下前三位作者的简介(如下):
卷积网络输出的特征图具有高水平的语义特征和低水平的分辨率,虽然有利于分类,但是同时有害于定位。
一般的图像金字塔具有尺度不变性,这种性质在图像的分类的任务中是很重要的。传统的图像处理也很喜欢用图像金字塔,然后再从图像金字塔中提出特征金字塔,比如SIFT就是使用图像金字塔的。
卷积网络提取的图像特征对比传统的手工特征而言,更加稳定准确,并且各个尺度的特征图都具有较强的语义特征,你说是不是很好用~ 所以目前的传统提取特征的方法都被网络提取特征取代。
但是图像金字塔非常耗时,根据我们往常的网络那种数据增强的方法,这个图像金字塔算起来非常浪费时间,还因为网络深度很占内存,所以之前大家一般都是用在测试阶段(SPPnet,Fast RCNN),但是这种做法会让测试集和训练集之间产生一定的不平衡。
先计算图像金字塔再计算特征金字塔的方法也不是唯一方法,可以通过在不同层进行计算金字塔型的特征图,然后对特征图进行降采样,但是每个层级的特征图之间语义有一定的差距,假设用第二层的特征图降采样推断第五层的特征图,就会出现语义鸿沟。并且低层的图像具有低水平的特征,这种特征损害对于目标识别的表达能力。
SSD这一类的网络对于每一层的卷积网络都生成特征图,并对不同的特征图进行重复利用,但是为了避免使用低级的特征图,SSD直接从网络高层开始进行计算特征图,并且构建特征金字塔,SSD没有利用到低级的特征图的高分辨率的特点。
所以FPN提出了自上而下和横向连接来连接丰富的语义特征和高分辨率,使网络适应与分类和定位的任务。建立一个镶嵌在网络中的网络特征图金字塔,同时不牺牲时间内存和表达力。类似的网络结构还有Hourglass(2016年MPII姿态分析竞赛达到89.4%,达到过第一名)。
【补充】简要介绍Hourglass的结果,之所以介绍这个是因为他们是同一个思路的
Hourglass针对的多尺度特征识别姿态,在此之前的姿态估计网络大多使用最后一层的卷积网络,造成信息丢失,事实上,全身不同的关节点在不同的特征图上有不同的识别效果。
降采样使用max pooling,升采样使用最近邻插值。
Hourglass一阶结构如上图,整体结构就是上图结果堆砌起来的。
如下四条准则基本上和FPM的横向连接相似:
1)每次降采样之前,分出上半路保留原尺度信息;2)每次升采样之后,和上一个尺度的数据相加;3)两次降采样之间,使用三个Residual模块提取特征;4)两次相加之间,使用一个Residual模块提取特征。
四个一阶Hourglass堆砌成一个Hourglass模块,等于说内部是并联的,而外部是串联的,串联结构如下图:
第二个Hourglass的输入包含三路: 第一个Hourglass的输入数据;第一个Hourglass的输出数据;第一级预测结果;这三路数据通过串接(concat)和相加进行融合,它们的尺度不同,体现了当下流行的跳级结构思想。每一个hourglass级都会生成一个H/2×W/2×K的响应图。 对于每个响应图,都比较其与真值的误差作为代价。每个层都计算一次loss。这种做法体现了 中继监督(intermediate supervision)的思想。
本文FPN目的在于弥补特征金字塔语义特征不太连贯的缺点,形成一个多尺度(有利于分类) 的具有丰富语义特征并且可以准确定位 的网络内的特征金字塔。针对这一目标提出了两个结构:1.自上而下的通路;2.横向连接。 在网络中,每个level的合成特征金字塔的层级都要进行预测。同时提高了计算效率和减少了内存占用。作者以Faster RCNN作为基础框架进行实验,实验结果表明经过结构改进的网络性能超越当时的所有网络的性能,并且弥补了SSD的训练和测试时的数据集之间的不平衡(说的就是在训练时使用single scale,在测试时使用multi-scale)。
重复一下我们FPN目标:使用卷积网络的从高到低的具有语义的特征金字塔,构建一个具有高层次语义的金字塔。
输入的图像是单一尺度的任意尺寸的图像,以完全卷积的方式在多个level上输出按比例大小排列的特征图。这个过程和基础卷积网络结构是独立开来的,这篇文章使用的基础网络是resnet。作者描述的金字塔结构还包括自底向上的通路,自顶向下的通路和横向连接。
【自底向上通路】 这个通路实际上就是前向传播网络,按照基础网络的层次计算得到各个level的前向特征图。Resnet一般有很多层,每层都会产生特征图,每层都对输出进行提取不太实际,所以将产生相同尺寸的特征图的层归结为一个stage,将每个stage最后产生的特征图作为特征金字塔的一个层。每个stage的最后产生的特征图有该阶段最强的语义特征。
对于resnet,使用每个残差模块最终激活的输出作为特征图,将这些输出标记为Ci,i=2,3,4,5.它们的步长为4,8,16,32像素(应该是映射换算回到原图的步长)。对于第一个卷积层由于占用较大内存而不去使用。
【自顶向下通路和横向连接】 自顶向下的通路通过对粗糙的高层次的特征图进行上采样 得到具有更高分辨率的强语义特征的特征图。这些特征通过横向连接和自定向上通路产生的特征相结合,从而得到增强。自底向上的特征具有高像素低语义的特点,而高像素的特点更有利于定位任务的进行。
实际的上采样工作是通过采样因子为2的最近邻采样完成的,两列特征图的结合是通过元素对元素的相加完成,(为了避免维度不匹配,通过1X1卷积进行降维)。直接在网络C5上连接一个1X1的卷积层进行生成具有最粗糙像素的特征图。最终在每个生成的特征图上使用3X3卷积进行生成最终的特征图(可以消除上采样带来的混叠效应)。最终生成的特征图为Pi,i=2,3,4,5,Pi和Ci具有相同的空间尺寸。
传统图像提取的特征金字塔的各层使用相同的分类器和回归器,所以在本文的金字塔上输出的特征图保持相同的通道数:256。分类器和回归器的层没有用非线性的,个人认为非线性容易损害信息。使用残差块作为横向连接会有一定的好处,但是本文意不在此,所以选择最简单的结构。
在RPN上应用FPN结构用于产生proporsal region+在Fast RCNN上应用FPN结构用于目标检测。
【在RPN上应用FPN】 RPN使用滑窗进行目标检测(不区分类)。在RPN的原始设计中,在单尺度的卷积网络上进行3X3的小窗滑动,进行二分类和bounding box回归。通过3X3的卷积网络+2个1X1的滑动卷积进行分类和回归——head(这两个模块的集合)。基于锚定义的框进行目标判定和回归。锚具有多个预先定义的尺度和纵横比,这样可以覆盖各个尺寸的物体。
在RPN每层都连上3X3卷积和1X1卷积(X2),就是连上head。由于head在本文的特征金字塔的而每个层都密集滑动,所以不用在特定层上有多个尺度的锚。所以一个尺度的锚可以安排到多个层的特征图上进行映射。所以在5个特征图上使用3个不同纵横比的锚,这样特征金字塔上就有15个锚。
本文通过锚的框和ground-truth的框之间IOU的值对锚进行标记label。正样本:和任意的ground-truth的IOU超过0.7,负样本:和所有的ground-truth的IOU小于0.3。ground-truth的尺度不直接应用到各层的金字塔上;而是通过锚点的标签间接地被安排到各层金字塔上。
注意到head的参数在RPN的各层之间是共享的,作者的实验表明使用不同的参数将获得类似的结果。这样的实验结果表明金字塔各层的语义特征是相似的,一个普通的head分类器可以应用于任意尺度的图像计算得到的特征。(这个结论还是比较有意思的)
【在Fast-RCNN上应用FPN】
Fast-RCNN是基于区域的检测器,在这个检测器上使用ROI 池化提取特征。因此需要将ROI池化和金字塔的不同层级进行关联,才能应用FPN组件。
假设将特征金字塔看作是有图像金字塔生成的,这样就可以建基于区域的检测器和金字塔关联起来:还记得faster-RCNN的公式如下:
k = ⌊ k 0 + l o g 2 ( w h / 224 ) ⌋ k=\lfloor k_0 + log_2( \sqrt{wh}/224) \rfloor k=⌊k0+log2(wh/224)⌋
224X224是典型的输入图像的尺寸,k0是最终映射得到的特征图的level,在这里设为4,因此k越小,图也越精细(像素高,例如k=3,则log(~) = -1, w ∗ h = 224 ∗ 224 / 4 w*h =224*224/4 w∗h=224∗224/4)。
类比与RPN,Fast-RCNN也有head,就是针对所有levelde所有ROI的,特定类的预测期和bounding box的回归器。Head仍然参数共享。在最高层的输出使用ROI池化提取7X7的特征并连接上两个FC在分类和回归层之前。这些层的参数是随机初始化的。对比标准的conv5的head(我猜作者这里指代的是用更高级的卷积层作为低一级卷积层的head),2FC MLP head更加轻便,快速。
最终得到的结构是这样的:
为什么在RPN后面加-15,因为这里是上面提及的5个特征图*3个纵横比的anchor的操作。(这里的图是实验室小姐姐画的,疯狂给她打call,两层FC实际上在代码中是串联的,注意: 在train过程中,代码上是两个loss一起训练的,同时在横向连接中没有BN和Relu,但是在FC层中有Relu,卷积层使用的是resnet_1_block,第一层卷积层是自定义的,在P5之前还构建了一层P6,保证整体结构的一致性)
【补充】下面的模型是DSSD,和FPN非常相似
【使用RPN提取proporsal region】
使用AR衡量改进后的RPN在小,中,大三种尺寸的目标的检测效果,每张的proporsal控制在100和1000上,即 A R 100 {AR}^{100} AR100 and A R 1000 {AR}^{1000} AR1000。
输入图像数据的最短边为800,在8GPU上使用同步SGD(我现在看到GPU的数量超过4就开始头疼,我可能要开始做梦了,梦里有好多GPU!还有好用的集群容器管理器!)每个GPU上的mini-batch有2张图,每张图上有256个anchor,权重衰减为0.0001,动量0.9,学习率0.02(前30k mini-batch,后10k mini-batch使用学习率=0.002)。对于超出图像边界的anchor,本文也用上了。训练COCO数据集用了8h。
【实验模型和baseline进行比较】
Baseline有两个,分别使用单一尺度的conv4或conv5的特征图。
实验结果表明,单一尺度的高层的特征图对于定位的表现不好,因为具有较强的语义特征,但是分辨率特征比较粗糙。在RPN上使用FPN的模型对于小物体检测的效果较好,提高了12.9%,并且提高了模型对于目标尺寸变化的鲁棒性。
1.自上向下通路的重要性: 消除自上而下的通路得到的结果和baseline相近但是不如完整的FPN结构。原因是:较深的ResNet的网络结构的各层级的特征图之间的语义差别较大。原文在这里提了一句:对head进行参数不共享的实验得到性能下降的表现。
2.横向连接的重要性: 自顶向下的金字塔具有较强的语义特征和精细的分辨率,但是作者认为这些特征图的定位信息由于经过多次采样而不是很准确,而自底向上的特征图能将准确的定位信息通过横向连接传递给自顶向下的特征图,这也是FPN比e性能好的原因。
3.金字塔表现力的重要性: 表1中的f方法是只在P2上加上anchor,f方法优于baseline,但还是逊色于FPN。RPN是一个具有固定大小窗口的滑窗检测器,所以遍历金字塔各个层级能增加对于目标变化尺度的鲁棒性。
并且只用P2会因为P2的精细的空间分辨率而产生更多的anchor,但这个结果表明anchor越多不一定会提高准确率。
【使用Fast/Faster RCNN的目标检测】
这一部分固定FPN作为区域检测器的部分。输入图像的最小边为800,使用同步SGD,8GPU,每个mini-batch在每个GPU上两张图,每张图上有512个ROI,权重衰减为0.0001,动量为0.9,前60k mini-batch的学习率为0.02,后20k mini-batch的学习率为0.002。在训练阶段的ROI设为2000每张图, 测试时设为1000每张图。
Proporsal固定(fast):Fast RCNN和RPN之间不进行特征共享(除非特定情况下)。经过实验对比2FC的层作为head vs conv5作为head并没有明显优势。
将FPN的结果和(以conv5为头的)baseline、(以2FC为头的)baseline对比,得到FPN的结构优于单尺度特征的基于区域的目标检测。移除掉自顶向下的结构或者横向结构得到的结果和之前的结果一样。当只在P2上使用Fast RCNN,结果只比FPN差一点,说明ROI池化对于区域的尺度不那么敏感。
Proporsal不固定,使用相同的基础网络(faster):faster RCNN的网络需要使用和RPN相同的基础网络,进行参数共享。
(a)方法的效果就是复制的Faster RCNN的结果,加了FPN的总体效果比Baseline要好。(a),(b)与(*)方法同样是baseline但是效果却不同,原因在于:(1)使用最小边为800,而非600;(2)每张图有512个ROI,加速了收敛的过程
特征共享: 特征共享能够对网络模型有细微的改善,并且能够减少测试时间
运行时间: 基于FPN的Faster RCNN系统在单个NVIDIA M40的GPU上使用resnet50运行一张图需要0.148s,使用resnet101运行一张图需要0.172s。对比单尺度的resnet50使用0.32s。就是很快啦!
对比COCO比赛的冠军: 作者认为在默认的学习率的设定下,没有将resnet101充分训练,所以在每个学习率中将mini-batch乘以两倍。结果在没有共享特征的情况下,提高了AP。
FPN同样也可以用在分割上。效果也很好。
跪谢Github上的大佬!跪谢百度前5页的大佬们!跪谢知乎上的大佬!
跪谢!感恩!