(七)FPN----2017CVPR论文解读

Feature Pyramid Networks for Object Detection

用于目标检测的特征金字塔网络

Abstract

特征金字塔是识别系统中用于检测不同比例物体的基本组件。但是最近的深度学习对象检测器避免了金字塔表示,部分原因是它们需要大量计算和内存。在本文中,我们利用深层卷积网络固有的多尺度,金字塔层次结构来构建具有边际额外成本的特征金字塔。**开发了具有横向连接的自上而下的体系结构,以构建各种规模的高级语义特征图。这种称为功能金字塔网络(FPN)的体系结构作为多种应用程序中的通用特征提取器,显示出了显着的改进。**在基本的Faster R-CNN系统中使用FPN,我们的方法在COCO检测基准上获得了最新的单模型结果,没有任何花哨的信息,超过了所有现有的单模型条目,包括2016年COCO挑战赛获奖者的条目。此外,我们的方法可以在GPU上以6 FPS的速度运行,因此是一种实用且准确的多尺度目标检测解决方案。代码将公开提供。

1.Introduction

识别尺寸差异很大的对象是计算机视觉的一项基本挑战。建立在图像金字塔上的特征金字塔(简称为特征化的图像金字塔)构成了标准解决方案的基础[1](图1(a))。这些金字塔是尺度不变的,即对象的尺度变化可以通过在金字塔中移动其水平来抵消。直观地,此属性使模型能够通过在位置和金字塔等级上扫描模型来检测大范围的对象。

特征化的图像金字塔在手工设计的特征时代被大量使用[5,25]。它们非常关键,以至于像DPM [7]这样的目标检测器都需要密集采样以取得良好的结果(例如,每倍频程10个缩放)。对于识别任务,工程特征在很大程度上已被深度卷积网络(ConvNets)计算的特征所取代[19,20]。除了能够表示高级语义之外,ConvNet还对规模变化更为健壮,因此有助于从单个输入规模上计算出的特征[15、11、29]进行识别(图1(b))。但是即使具有这种鲁棒性,仍然需要金字塔来获得最准确的结果。 ImageNet [33]和COCO [21]检测挑战中所有最近的热门条目都对特征化的图像金字塔(例如[16,35])进行了多尺度测试。使图像金字塔的每个级别特征化的主要优点是,它会产生多尺度特征表示,其中所有级别在语义上都很强大,包括高分辨率级别。
在这里插入图片描述
图1.(a)使用图像金字塔构建特征金字塔。特征是在每个图像比例尺上独立计算的,这很慢。 (b)最近的检测系统选择仅使用单一比例的功能来加快检测速度。 (c)一种替代方法是重用由ConvNet计算的金字塔特征层次结构,就好像它是特征化的图像金字塔一样。 (d)我们提出的特征金字塔网络(FPN)像(b)和(c)一样快,但是更准确。在此图中,特征图由蓝色轮廓表示,较粗的轮廓表示语义上更强的功能。

然而,使图像金字塔的每个级别均具有特征有明显的局限性。推理时间大大增加(例如,增加了四倍[11]),使得该方法在实际应用中不切实际。此外,就内存而言,在图像金字塔上端到端地训练深度网络是不可行的,因此,如果加以利用,图像金字塔仅在测试时间[15、11、16、35]使用,这会导致训练/测试时间推论之间出现不一致。由于这些原因,“越来越快”的R-CNN [11,29]选择在默认设置下不使用特征化的图像金字塔。

但是,图像金字塔并不是计算多尺度特征表示的唯一方法。深度ConvNet会逐层计算要素层次结构,并且通过子采样层,要素层次结构具有固有的多尺度金字塔形状。这种网络内特征层次结构会产生不同空间分辨率的特征图,但会引入因深度不同而导致的较大语义差距。高分辨率图具有低级特征,会损害其物体识别的表示能力。

单发检测器(SSD)[22]是首次使用ConvNet的金字塔特征层次结构的尝试之一,就好像它是特征化的图像金字塔一样(图1(c))。理想情况下,SSD样式的金字塔将重用前向遍历中计算出的不同图层的多尺度特征图,从而节省成本。但是为了避免使用低级功能,SSD放弃了重用已经计算的层,而是从网络的高层开始构建金字塔(例如,VGG网络的conv4 3 [36]),然后添加几个新层。因此,它错过了重用要素层次结构的高分辨率地图的机会。我们证明了这些对于检测小物体很重要。

本文的目的是自然地利用ConvNet的要素层次结构的金字塔形状,同时创建在各个尺度上具有强大语义的要素金字塔。**为了实现此目标,我们依靠通过自上而下的路径和横向连接将低分辨率,语义上强的特征与高分辨率,语义上弱的特征相结合的体系结构(图1(d))。**结果是一个功能金字塔,它在所有级别上都具有丰富的语义,并且可以从单个输入图像比例快速构建。换句话说,我们展示了如何创建网络内特征金字塔,这些特征金字塔可用于替换特征化的图像金字塔,而不会牺牲表示能力,速度或内存。

在最近的研究中,采用自上而下和跳过连接的类似体系结构很流行[28、17、8、26]。他们的目标是制作一个具有高分辨率的单一高级特征图,并在该特征图上进行预测(图2顶部)。相反,我们的方法将架构作为一个特征金字塔,在每个层次上都独立进行预测(例如,对象检测)(图2底部)。我们的模型呼应了一个特征化的图像金字塔,在这些工作中尚未进行探讨。

我们在各种用于检测和分割的系统中评估称为特征金字塔网络(FPN)的方法[11、29、27]。不用花哨,我们仅基于FPN和基本的Faster R-CNN检测器[29]就具有挑战性的COCO检测基准[21]报告了最新的模型结果,超过了所有现有的经过精心设计的单一模型竞赛优胜者的作品。在消融实验中,我们发现对于边界框建议,FPN显着提高了平均召回率(AR)8.0点;对于物体检测,在ResNets上的Faster R-CNN的强大单尺度基线上,它可将COCO风格的平均精度(AP)提高2.3点,将PASCAL风格的AP提高3.8点[16]。我们的方法也很容易扩展为掩盖提案,并且比严重依赖图像金字塔的最新方法提高了实例分割AR和速度。
在这里插入图片描述
图2.顶部:具有跳过连接的自上而下的体系结构,其中的预测是在最高级别进行的(例如[28])。 下:我们的模型具有相似的结构,但将其用作要素金字塔,并且在各个级别均独立进行了预测。

此外,我们的金字塔结构可以在所有比例下进行端到端训练,并且在训练/测试时始终如一地使用,这在使用图像金字塔的情况下是不可行的,因此,FPN可以实现比所有金字塔更高的精度现有的最先进的方法。此外,无需在单比例基准上增加测试时间即可实现此改进。我们相信这些进展将促进未来的研究和应用。我们的代码将公开提供。

2. Related Work

手工设计的特征和早期的神经网络。**SIFT特征[25]最初是在比例空间极值处提取的,用于特征点匹配。 HOG特征[5]和后来的SIFT特征在整个图像金字塔上进行了密集计算。这些HOG和SIFT金字塔已在许多作品中用于图像分类,物体检测,人体姿势估计等。**快速计算特征化图像金字塔也引起了人们极大的兴趣。 Dollár等 [6]通过首先计算稀疏采样(按比例)的金字塔,然后插值缺失级别,展示了快速金字塔计算。在HOG和SIFT之前,早期使用ConvNets [38,32]进行人脸检测的工作是在图像金字塔上计算浅层网络,以检测跨尺度的人脸。

深度ConvNet对象检测器。随着现代深层ConvNets [19]的发展,诸如Over-Feat [34]和R-CNN [12]之类的目标检测器在准确性上有了显着的提高。 OverFeat通过将ConvNet用作图像金字塔上的滑动窗口检测器,采用了类似于早期神经网络人脸检测器的策略。 R-CNN采用了基于区域提案的策略[37],其中每个提案在使用ConvNet进行分类之前都进行了规模标准化。 SPPnet [15]证明了这种基于区域的检测器可以更有效地应用于以单个图像比例提取的特征图。最近的更精确的检测方法,如Fast R-CNN [11]和Faster R-CNN [29]提倡使用从单个比例尺计算出的特征,因为它在精度和速度之间提供了很好的权衡。但是,多尺度检测仍然表现更好,尤其是对于小物体。

方法使用多层。许多最新方法通过在ConvNet中使用不同的层来改善检测和分割。 FCN [24]在多个尺度上对每个类别的部分分数求和,以计算语义细分。超柱[13]使用类似的方法进行对象实例分割。其他几种方法(HyperNet [18],ParseNet [23]和ION [2])在计算预测之前将多层的特征连接起来,这相当于对变换后的特征求和。 SSD [22]和MS-CNN [3]可以在不组合特征或分数的情况下预测特征层次结构中多层的对象。最近有一些利用横向/跳过连接的方法,这些方法将跨分辨率和语义级别的低级特征图关联起来,包括U -Net [31]和Sharp-Mask [28]用于分割,Recombinator网络[17]用于面部检测,Stacked Hourglass网络[26]用于关键点估计。 Ghiasi等。 [8]提出了FCN的拉普拉斯金字塔介绍,以逐步完善细分。尽管这些方法采用具有金字塔形状的体系结构,但它们与特征化的图像金字塔[5、7、34]不同,在特征图像金字塔中,各个级别的预测都是独立进行的,请参见图2。实际上,图2中的金字塔体系结构(顶部) ,仍然需要图像金字塔来识别多个尺度的物体[28]。

3.特征金字塔网络

我们的目标是利用ConvNet的金字塔特征层次结构,该层次结构具有从低到高的语义,并在整个过程中构建具有高层语义的特征金字塔。由此产生的特征金字塔网络是通用的,在本文中,我们重点关注滑动窗口提议器(区域提议网络,简称RPN)[29]和基于区域的检测器(Fast R-CNN)[11]。我们还将FPN概括为Sec中的实例细分提案。 6。
在这里插入图片描述
​ 图3.构建模块,说明横向连接和自上而下的路径,通过添加合并。

我们的方法将任意大小的单比例图像作为输入,并以完全卷积的方式在多个级别上输出按比例大小的特征图。该过程与骨干卷积体系结构无关(例如[19,36,16]),在本文中,我们使用ResNets提出结果[16]。我们的金字塔的构造涉及自下而上的路径,自上而下的路径和横向连接,如下所述。

自下而上的途径。自下而上的途径是主干ConvNet的前馈计算,它计算由多个比例尺的缩放比例为2的要素映射组成的要素层次结构。通常会有许多层生成相同大小的输出映射图,我们说这些层处于同一网络阶段。对于我们的要素金字塔,我们为每个阶段定义一个金字塔等级。我们选择每个阶段最后一层的输出作为特征图的参考集,我们将对其进行丰富以创建金字塔。这种选择是很自然的,因为每个阶段的最深层都应该具有最强的功能。

具体来说,对于ResNets [16],我们使用每个阶段的最后残差块输出的功能激活。对于conv2,conv3,conv4和conv5输出,我们将这些最后残差块的输出表示为{C2,C3,C4,C5},并注意它们相对于{4、8、16、32}个像素有跨度输入图像。由于conv1占用大量内存,因此我们不将其包含在金字塔中。

自上而下的路径和横向连接。自上而下的路径通过从较高的金字塔等级对空间上较粗糙但语义上更强的特征图进行上采样来使高分辨率的特征产生幻觉。然后通过自下而上的路径通过横向连接来增强这些功能。每个横向连接将自下而上的路径和自上而下的路径合并相同空间大小的特征图。自下而上的特征图具有较低级别的语义,但是由于对其进行了较少次数的二次采样,因此其激活位置更加准确。

图3显示了构建自上而下的特征图的构建块。对于较粗分辨率的特征图,我们将空间分辨率上采样2倍(为简单起见,使用最近的邻居上采样)。然后,通过逐元素加法将upsam-pled贴图与相应的自下而上的贴图(经过1×1卷积层以减小通道尺寸)合并。重复此过程,直到生成最高分辨率的图为止。要开始迭代,我们只需在C 5上附加一个1×1卷积层即可生成最粗糙的分辨率图。最后,我们在每个合并的地图上附加一个3×3卷积以生成最终的特征图,这将减少上采样的混叠效果。这最后一组特征图称为{P2,P3,P4,P5},分别对应于{C2,C3,C4,C5},它们分别具有相同的空间大小。

因为金字塔的所有级别都像传统的特征化图像金字塔一样使用共享的分类器/回归器,所以我们在所有特征图中固定特征维(通道数,表示为d)。我们在本文中将d设置为256,因此所有额外的卷积层都具有256通道输出。在这些额外的层中没有非线性,我们凭经验发现这些非线性影响较小。

简单性是我们设计的核心,我们发现我们的模型对许多设计选择都具有鲁棒性。我们已经试验了更复杂的模块(例如,使用多层残余模块[16]作为连接),并观察到了略微更好的结果。设计更好的连接模块不是本文的重点,因此我们选择上述简单的设计。

4.应用

我们的方法是在深层ConvNets内部构建要素金字塔的通用解决方案。在下面,我们在RPN [29]中采用我们的方法来生成边界框建议,并在Fast R-CNN [11]中采用我们的方法来进行对象检测。为了证明我们方法的简单性和有效性,当使它们适应我们的特征金字塔时,我们对[29,11]的原始系统进行了最小的修改。

4.1用于RPN的功能金字塔网络

RPN [29]是与滑动窗口类无关的对象检测器。在最初的RPN设计中,在单个比例卷积特征图的顶部,在密集的3×3滑动窗口上评估一个小型子网,执行对象/非对象二进制分类和边界框回归,这是通过3×实现的3个卷积层,然后是两个同级1×1卷积,用于分类和回归,我们将其称为网络头。对象/非对象标准和边界框回归目标是相对于称为“锚点”的一组参考框定义的[29]。锚具有多个预定义的比例和长宽比,以覆盖不同形状的对象。

我们通过用FPN代替单比例尺特征图来适应RPN。我们将特征相同的设计(3×3转换和两个同级1×1转换)的头部附加到功能金字塔上的每个级别。因为头部在所有金字塔等级的所有位置上密集滑动,所以没有必要在特定等级上使用多尺度锚。相反,我们将单个比例的锚分配给每个级别。形式上,我们定义锚点分别在{P2,P3,P4,P5,P6}上具有{32 ^ 2,64 ^ 2,128 ^ 2,256 ^ 2,512 ^ 2}像素的区域。如[29] ],我们还在每个级别使用多个宽高比{1:2、1:1、2:1}的锚点。因此,金字塔上总共有15个锚点。

我们根据[29]中的锚点与地面真实边界框的比例,为锚点分配训练标签。正式地,如果锚点对于给定的地面真相框具有最高的IoU,或者对于任何地面真相框具有超过0.7的IoU,则为其分配正标签;而对于所有地面真相而言,如果其IoU低于0.3,则将为其分配负标签。盒子。请注意,地面真盒子的比例没有明确地用于将它们分配给金字塔的等级。取而代之的是,地面真相框与已分配给金字塔等级的锚点关联。因此,除[29]中的规则外,我们没有引入其他规则。

我们注意到,头部的参数在所有要素金字塔级别之间共享。我们还评估了不共享参数的替代方案,并观察到了相似的准确性。共享参数的良好性能表明我们金字塔的所有级别共享相似的语义级别。此优点类似于使用特征化图像金字塔的优点,其中可以将通用的头部分类器应用于以任何图像比例计算的特征。

通过上述修改,RPN可以用我们的FPN进行自然训练和测试,方法与[29]中的相同。我们在实验中详细说明了实现细节。

4.2快速R-CNN的功能金字塔网络

快速R-CNN [11]是一种基于区域的对象检测器,其中使用了兴趣区域(RoI)池提取特征。快速R-CNN最常在单比例尺特征图上执行。要将其与我们的FPN一起使用,我们需要将不同比例的RoI分配给金字塔级别。

我们将特征金字塔视为是由图像金字塔产生的。因此,当它们在图像金字塔上运行时,我们可以调整基于区域的检测器[15、11]的分配策略。正式地,我们通过以下方式将宽度w和高度h(在输入图像上的RoI)分配给特征金字塔的水平P k:

k = k 0 + log 2 ( w h / 224 ) 1 k=\left\lfloor k_{0}+\log _{2}(\sqrt{w h} / 224)\right\rfloor (1)
这里224是规范的ImageNet预训练大小,而k0是应映射到其中w×h = 224 ^ 2的RoI的目标级别。类似于使用C 4作为单尺度特征图的基于ResNet的Faster R-CNN系统[16],我们将k 0设置为4。 (1)表示如果RoI比例尺变小(例如224的1/2),则应将其映射到更高分辨率的水平(例如k = 3)。

我们将预测变量头(在Fast R-CNN中,该变量头是特定于类的分类器和边界框回归变量)附加到所有级别的所有RoI。同样,这些头均共享参数,无论其级别如何。在[16]中,ResNet的conv5层(一个9层的深度子网)被用作conv4特征之上的头,但是我们的方法已经利用conv5来构建特征金字塔。因此,与[16]不同,我们仅采用RoI池来提取7×7要素,并在最终分类和边界框回归图层之前附加两个隐藏的1,024-d全连接(fc)图层(每个图层后跟ReLU)。这些层是随机初始化的,因为ResNets中没有可用的预训练fc层。请注意,与标准conv5磁头相比,我们的2-fc MLP磁头重量更轻且速度更快。

基于这些修改,我们可以在特征金字塔的顶部训练和测试Fast R-CNN。实现细节在实验部分给出。

5.目标检测实验

我们对80类COCO检测数据集进行了实验[21]。我们使用80k火车图像和val图像的35k子集(trainval35k [2])的联合进行训练,并报告val图像的5k子集的消融(最小)。我们还报告了没有公开标签的标准测试集(test-std)[21]的最终结果。

按照惯例[12],所有网络主干都在ImageNet1k分类集[33]上进行了预训练,然后在检测数据集上进行了微调。我们使用公开提供的经过预先训练的ResNet-50和ResNet-101模型。 2我们的代码是使用Caffe2对py-faster-rcnn 3的重新实现。 4

5.1使用RPN的区域提案

我们按照[21]中的定义评估小型,中型和大型对象(AR s,AR m和AR l)的COCO风格的平均召回率(AR)和AR。我们报告每个图像100和1000个投标的结果(AR 100和AR 1k)。

实施细节。表1中的所有体系结构都是端到端训练的。调整输入图像的大小,使其较短的一面具有800像素。我们在8个GPU上采用了同步SGD培训。迷你批处理包含每个GPU 2个图像和每个图像256个锚点。我们使用0.0001的权重衰减和0.9的动量。前30k迷你批次的学习率是0.02,接下来的10k的学习率是0.002。对于所有RPN实验(包括基线),我们都包括图像外的锚框进行训练,这与[29]不同,这些锚框被忽略。其他实现细节如[29]。在COCO上用FPN在8个GPU上训练RPN大约需要8个小时。

5.1.1消融实验

与基准进行比较。为了与原始RPN [29]进行合理比较,我们使用C4(与[16]相同)或C5的单比例图运行两个基线(表1(a,b)),两者均使用与我们相同的超参数,包括使用{32 ^ 2,64 ^ 2,128 ^ 2,256 ^ 2,512 ^ 2}的5个比例锚。表1(b)没有显示优于(a)的优势,这表明仅凭一个更高级别的特征图是不够的,因为在较粗的分辨率和更强的语义之间需要进行权衡。

将FPN放置在RPN中可使AR 1k提高至56.3(表1(c)),比单尺度RPN基线增加了8.0点(表1(a))。此外,小物体(AR 1ks)的性能可大幅提高12.9点。我们的金字塔表示法大大提高了RPN对物体比例变化的鲁棒性。

自上而下的浓缩有多重要?表1(d)显示了没有自顶向下途径的特征金字塔的结果。通过此修改,将1×1横向连接和3×3卷积连接到自下而上的金字塔。这种架构模拟了重用金字塔特征层次的效果(图1(b))。

表1(d)中的结果与RPN基线相当,并且远远落后于我们的RPN基线。我们推测这是因为自下而上的金字塔(图1(b))的不同级别之间存在较大的语义鸿沟,尤其是对于非常深的ResNet。我们还评估了表1(d)的一种变型,但没有共享磁头的参数,但是观察到性能类似下降。这个问题不能由特定级别的负责人简单地解决。

横向连接有多重要?表1(e)显示了没有1×1横向连接的自顶向下特征金字塔的烧蚀结果。该自上而下的金字塔具有强大的语义特征和良好的分辨率。但是我们认为这些特征的位置不精确,因为这些地图已被下采样和上采样数次。可以通过自上而下的地图的横向连接直接从自下而上的地图的更精细级别传递要素的更精确的位置。结果,FPN的AR 1k得分比表1(e)高10点。

金字塔表示法有多重要?可以不使用金字塔表示,而可以将头部附加到P 2的最高分辨率,强烈语义特征图(即,我们金字塔中的最高级)上。与单尺度基线相似,我们将所有锚点分配给P 2特征图。该变量(表1(f))优于基线,但不如我们的方法。 RPN是具有固定窗口大小的滑动窗口检测器,因此在金字塔等级上进行扫描可以提高其对比例变化的鲁棒性。

此外,我们注意到,单独使用P 2会由于其较大的空间分辨率而导致更多锚点(750k,表1(f))。该结果表明,大量的锚本身本身不足以提高精度。
在这里插入图片描述
表1.使用RPN [29]的边界框建议结果,在COCO minival集合上进行了评估。 所有模型都在trainval35k上进行训练。“横向”和“自上而下”列分别表示存在横向和自上而下的连接。 列“特征”表示附加有头部的特征图。 所有结果均基于ResNet-50并共享相同的超参数。
在这里插入图片描述
表2.在固定建议集(RPN,{P k},表1(c))上使用快速R-CNN [11]进行目标检测的结果,并在最小COCO集合上进行了评估。 在trainval35k集合上训练模型。 所有结果均基于ResNet-50并共享相同的超参数。
在这里插入图片描述

表3.在COCO minival集上评估的使用Faster R-CNN [29]的物体检测结果。 RPN的骨干网与Fast R-CNN一致。 模型在trainval35k集合上训练,并使用ResNet-50。[16]的作者提供。

5.2快速/快速R-CNN的目标检测

接下来,我们研究基于区域(非滑动窗口)检测器的FPN。我们通过COCO型平均精度(AP)和PASCAL型AP(在单个IoU阈值为0.5时)评估对象检测。我们还按照[21]中的定义报告了小,中和大尺寸对象(即AP s,AP m和AP l)的COCO AP。

实施细节。调整输入图像的大小,使其较短的一面具有800像素。同步SGD用于在8个GPU上训练模型。每个迷你批处理涉及每个GPU 2个图像和每个图像512个RoI。我们使用0.0001的权重衰减和0.9的动量。前60k迷你批次的学习率是0.02,接下来20k的学习率是0.002。我们使用每张图片2000 RoIs进行训练,使用1000 RoI进行测试。使用FPN训练快速R-CNN在COCO数据集上大约需要10个小时。

5.2.1快速R-CNN(针对固定提案)

为了更好地调查FPN仅对基于区域的探测器的影响,我们对一组固定的建议进行了Fast R-CNN的消融。我们选择冻结RPN在FPN(表1(c))上计算出的建议,因为它在检测器可以识别的小物体上具有良好的性能。为简单起见,除非另有说明,否则我们在Fast R-CNN和RPN之间不共享功能。

作为基于ResNet的Fast R-CNN基线,[16],我们采用RoI池,输出大小为14×14,并将所有conv5层附加为头部的隐藏层。这在表2中给出了31.9的AP (一种)。表2(b)是使用具有2个隐藏fc层的MLP磁头的基线,类似于我们架构中的磁头。它的AP为28.8,表明2-fc头没有给我们任何超过表2(a)中基线的正交优势。

表2(c)显示了FPN在Fast R-CNN中的结果,与表2(a)的基线相比,我们的方法将AP提高了2.0点,将小物体AP提高了2.1点。一个2fc头(表2(b)),我们的方法将AP提高了5.1点。 5这些比较表明,对于基于区域的物体检测器,我们的特征金字塔优于单尺度特征。
在这里插入图片描述
表4.在COCO检测基准上单模型结果的比较。 一些结果在test-std集合上不可用,因此我们也包括test-dev结果(以及minival上的Multipath [40])。†:http://image-net.org/challenges/talks/2016/ GRMI-COCO-slidedeck.pdf。‡:http://mscoco.org/dataset/#detections-leaderboard。 §:AttractioNet [10]的条目采用VGG-16进行提议,而Wide Wide Net [39]进行对象检测,因此严格来说不是单模型结果。

表2(d)和(e)显示,删除自上而下的连接或删除横向连接会导致较差的结果,类似于我们在上述小节中对RPN的观察。值得注意的是,删除自上而下的连接(表2(d))会大大降低精度,这表明Fast R-CNN会在高分辨率地图上使用低级功能。

在表2(f)中,我们在P 2的单个最佳尺度特征图上采用Fast R-CNN。其结果(33.4 AP)比使用所有金字塔等级(33.9 AP,表2(c))的结果略差。我们认为,这是因为投资回报率池化是一种类似翘曲的操作,因此对区域规模不那么敏感。尽管此变体的准确性很高,但它基于{P k}的RPN建议,因此已经从金字塔表示中受益。

5.2.2更快的R-CNN(在一致的提案上)

在上面,我们使用了一组固定的建议来研究探测器。但是在Faster R-CNN系统[29]中,RPN和Fast R-CNN必须使用相同的网络主干才能使功能共享成为可能。表3显示了我们的方法与两个基线之间的比较,所有基线均使用RPN和Fast R-CNN的一致主干架构。表3(a)显示了我们对[Faster R-CNN]基线系统的再现,如[16]中所述。在受控设置下,我们的FPN(表3(c))比该强基准要好2.3点AP和3.8点[email protected]

请注意,表3(a)和(b)是比He等人提供的基线强得多的基线。表3()中的[16]。我们发现以下实现方式可以弥补这一差距:(i)我们使用800像素的图像比例代替[11,16]中的600像素; (ii)与[11,16]中的64 RoI相比,每个图像以512 RoI进行训练以加速收敛;(iii)我们使用5个比例锚代替[16]中的4个RoI(加32 ^ 2); (iv)在测试时,每张图片我们使用1000个提案,而不是[16]中的300个提案。因此,与表3()中He等人的ResNet-50 Faster R-CNN基线相比,我们的方法将AP改善了7.6点,将[email protected]改善了9.6点。
在这里插入图片描述
表5.使用Faster R-CNN和我们的FPN进行的更多物体检测结果,均经过最小化评估。 共享功能使训练时间增加了1.5倍(使用4步训练[29]),但减少了测试时间。

共享功能。在上面,为简单起见,我们不共享RPN和Fast R-CNN之间的功能。在表5中,我们按照[29]中所述的4步训练评估共享功能。类似于[29],我们发现共享功能可以提高准确性。功能共享还可以减少测试时间。

运行时间。借助功能共享,我们基于FPN的Faster R-CNN系统在ResNet-50的单个NVIDIA M40 GPU上每个图像的推理时间为0.148秒,对于ResNet-101的推理时间为0.172秒。 6作为比较,表3(a)中的单比例ResNet-50基线运行时间为0.32秒。我们的方法通过FPN中的额外层引入了少量的额外成本,但头部重量更轻。总体而言,我们的系统比基于ResNet的Faster R-CNN更快。我们相信我们方法的效率和简便性将使未来的研究和应用受益。

5.2.3与COCO竞赛获胜者进行比较

我们发现,表5中的ResNet-101模型没有使用默认的学习率时间表进行充分的训练。因此,在训练Fast R-CNN步骤时,在每个学习速率下,迷你批次的数量增加2倍。这将AP上的minival增加到35.6,而没有共享功能。此模型是我们提交给COCO检测排行榜的模型,如表4所示。由于时间有限,我们尚未评估其功能共享版本,因此应该更好一些。表5暗示。
在这里插入图片描述
图4.对象细分提案的FPN。 特征金字塔的构造与对象检测的构造相同。 我们在5×5的窗口上应用一个小的MLP,以生成输出尺寸为14×14的密集对象段。 用橙色显示的是每个金字塔级别(此级别显示为P 3-5)时,蒙版所对应的图像区域的大小。 同时显示了相应的图像区域大小(浅橙色)和规范的对象大小(深橙色)。 半个八度由MLP在7x7窗口(7≈5√2)上处理,此处未显示。 细节在附录中。

表4将我们的方法与COCO竞赛获奖者的单模结果进行了比较,包括2016年的G-RMI获奖者和2015年的Faster R-CNN +++获奖者。在测试开发环境下,我们的方法比现有的最佳结果提高了0.5点AP(36.2 vs.35.7)和3.4点[email protected](59.1 vs.55.7)。值得注意的是,我们的方法不依赖于图像金字塔,仅使用单个输入图像比例,但在小尺寸物体上仍具有出色的AP。这只能通过使用先前方法的高分辨率图像输入来实现。

而且,我们的方法没有利用许多流行的改进,例如迭代回归[9],硬否定挖掘[35],上下文建模[16],更强大的数据增强[22]等。这些改进是对FPN的补充,应该会有所发展精度更高。

最近,FPN已在COCO竞争的所有轨道上实现了新的顶级成绩,包括检测,实例分割和关键点估计。 有关详细信息,请参见[14]。

6.扩展:细分提案

我们的方法是通用的金字塔表示,可以用于除对象检测之外的其他应用程序。在本节中,我们将根据DeepMask / SharpMask框架[27,28]使用FPN生成分段建议。

DeepMask / SharpMask在图像裁剪上进行训练,以预测实例片段和对象/非对象得分。推理时,这些模型被卷积运行以在图像中生成密集的建议。为了产生多个尺度的分段,图像金字塔是必要的[27,28]。

调整FPN以生成掩膜方案很容易。我们使用完全卷积的设置进行训练和推理。我们像在Sec中一样构造要素金字塔。 5.1并设置d =128。在要素金字塔的每个级别之上,我们应用5×5的MLP以完全卷积的方式预测14×14的蒙版和对象分数,请参见图4。在[27,28]的图像金字塔中,每个八度使用2个音阶,我们使用输入大小为7×7的第二个MLP处理半个八度。这两个MLP在RPN中起着锚的作用。该架构经过端到端的培训;完整的实现细节在附录中给出。
在这里插入图片描述
表6.在前5k COCO val图像上评估的实例分割建议。 所有模型都在火车上进行训练.DeepMask,SharpMask和FPN使用ResNet-50,而Instance-FCN使用VGG-16。 DeepMask和SharpMask的性能是通过https://github.com/facebookresearch/deepmask提供的模型计算的(两者都是“ zoom”变体)。†运行时间是在NVIDIA M40 GPU上测得的,但InstanceFCN计时基于 较慢的K40。

6.1细分提案结果

结果显示在表6中。我们报告AR区段和AR区段在小型,中型和大型对象上的情况,始终有1000个投标。我们的具有单个5×5 MLP的基准FPN模型实现了43.4的AR。切换到稍大的7×7 MLP会使精度基本保持不变。同时使用两个MLP可以将精度提高到45.7 AR。掩码输出大小从14×14增加到28×28,AR会增加另一点(较大的大小会开始降低精度)。最后,将训练迭代次数加倍,AR就会增加到48.1。

我们还报告了与DeepMask [27],SharpMask [28]和InstanceFCN [4](掩膜方案生成中的现有技术的最新状态)的比较。我们比这些方法的准确性高出8.3分AR。特别是,我们在小物体上的精度几乎翻了一番。

现有的掩模提议方法[27、28、4]基于密集采样的图像金字塔(例如,[27、28]中的scaledby2 {-2:0.5:1}),使得它们在计算上昂贵。我们基于FPN的方法要快得多(我们的模型以6到7 FPS运行)。这些结果表明,我们的模型是通用的特征提取器,可以代替其他多种多尺度检测问题的图像金字塔。

7.结论

我们提供了一个干净而简单的框架,用于在ConvNets中构建要素金字塔。我们的方法相对于几个强大的基准和竞争优胜者而言,显示出显着的改进。因此,它为特征金字塔的研究和应用提供了一种实用的解决方案,而无需计算图像金字塔。最后,我们的研究表明,尽管深层卷积网络具有强大的表示能力,并且隐含了对尺度变化的鲁棒性,但是使用金字塔表示法明确解决多尺度问题仍然至关重要。

部分网络实现代码如下:


class Bottleneck(nn.Module):
    expansion = 4

    def __init__(self, in_planes, planes, stride=1):
        super(Bottleneck, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False)
        self.bn3 = nn.BatchNorm2d(self.expansion*planes)

        self.shortcut = nn.Sequential()
        if stride != 1 or in_planes != self.expansion*planes:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(self.expansion*planes)
            )

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = F.relu(self.bn2(self.conv2(out)))
        out = self.bn3(self.conv3(out))
        out += self.shortcut(x)
        out = F.relu(out)
        return out


class FPN(nn.Module):
    '''
    继承nn.Module,实现自定义网络模型
    '''
    def __init__(self, block, num_blocks):
        super(FPN, self).__init__()
        # 输入通道数
        self.in_planes = 64
        # nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

        # 原论文网络结构 in_channels=3  out_channels=64
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
        # 通道数BN层的参数是输出通道数out_channels=64
        self.bn1 = nn.BatchNorm2d(64)

        # Bottom-up layers
        # 自底向上的网络   resnet网络
        self.layer1 = self._make_layer(block,  64, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)

        # Top layer (最顶层只有侧边连接,kernel_size=1目的减少通道数,形状不变)
        self.toplayer = nn.Conv2d(2048, 256, kernel_size=1, stride=1, padding=0)  # Reduce channels  减少通道数

        # Smooth layers   平滑层
        # 作用:在融合之后还会再采用3*3的卷积核对每个融合结果进行卷积,目的是消除上采样的混叠效应
        self.smooth1 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.smooth2 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.smooth3 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)

        # Lateral layers   侧边层
        # (1*1的卷积核的主要作用是减少卷积核的个数,也就是减少了feature map的个数,并不改变feature map的尺寸大小。)
        self.latlayer1 = nn.Conv2d(1024, 256, kernel_size=1, stride=1, padding=0)
        self.latlayer2 = nn.Conv2d( 512, 256, kernel_size=1, stride=1, padding=0)
        self.latlayer3 = nn.Conv2d( 256, 256, kernel_size=1, stride=1, padding=0)

    def _make_layer(self, block, planes, num_blocks, stride):
        '''
        resnet网络
        '''
        strides = [stride] + [1]*(num_blocks-1)
        layers = []
        for stride in strides:
            layers.append(block(self.in_planes, planes, stride))
            self.in_planes = planes * block.expansion
        return nn.Sequential(*layers)

    def _upsample_add(self, x, y):
        '''
        Upsample and add two feature maps.
        上采样 并 将两个feature maps求和
        Args:
          x: (Variable) top feature map to be upsampled.  将要上采样的 上层feature map
          y: (Variable) lateral feature map.    侧边的feature map

        Returns:
          (Variable) added feature map.

        Note in PyTorch, when input size is odd, the upsampled feature map
        with `F.upsample(..., scale_factor=2, mode='nearest')`
        maybe not equal to the lateral feature map size.
        在PyTorch中,当输入大小为奇数时,请注意上采样的特征映射
    用'F.upsample(...,scale_factor = 2,mode ='nearest')`
    可能不等于横向特征地图尺寸。

        e.g.
        original input size: [N,_,15,15] ->
        conv2d feature map size: [N,_,8,8] ->
        upsampled feature map size: [N,_,16,16]

        So we choose bilinear upsample which supports arbitrary output sizes.
        所以我们选择支持任意输出大小的双线性上采样。
        '''
        _,_,H,W = y.size()
        # 使用 双线性插值bilinear对x进行上采样,之后与y逐元素相加
        return F.upsample(x, size=(H,W), mode='bilinear') + y

    def forward(self, x):
        # Bottom-up  自底向上   conv -> batchnmorm -> relu  ->maxpool
        c1 = F.relu(self.bn1(self.conv1(x)))
        c1 = F.max_pool2d(c1, kernel_size=3, stride=2, padding=1)

        # resnet网络
        c2 = self.layer1(c1)
        c3 = self.layer2(c2)
        c4 = self.layer3(c3)
        c5 = self.layer4(c4)

        # Top-down  自顶向下并与侧边相连
        p5 = self.toplayer(c5)  #减少通道数
        p4 = self._upsample_add(p5, self.latlayer1(c4))
        p3 = self._upsample_add(p4, self.latlayer2(c3))
        p2 = self._upsample_add(p3, self.latlayer3(c2))

        # Smooth  平滑层(在融合之后还会再采用3*3的卷积核对每个融合结果进行卷积,目的是消除上采样的混叠效应)
        p4 = self.smooth1(p4)
        p3 = self.smooth2(p3)
        p2 = self.smooth3(p2)
        return p2, p3, p4, p5


def FPN101():
    # [2,4,23,3]为FPN101的参数
    # return FPN(Bottleneck, [2,4,23,3])

    #[2,2,2,2]为FPN18的参数
    return FPN(Bottleneck, [2,2,2,2])


def test():
    # 新建FPN101网络
    net = FPN101()
    print('网络结构为')
    print(net)
    # 前向传播,得到网络输出值 fms即为p2, p3, p4, p5
    fms = net(Variable(torch.randn(1,3,224,224)))
    print('网络输出的内容为')
    for fm in fms:
        print(fm.size())
发布了66 篇原创文章 · 获赞 23 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_18315295/article/details/104111003