论文:feature pyramid networks for object detection
论文链接

论文概述:

作者提出的多尺度的object detection算法:FPN(feature pyramid networks)。原来多数的object detection算法都是只采用顶层特征做预测,但我们知道低层的特征语义信息比较少,但是目标位置准确;高层的特征语义信息比较丰富,但是目标位置比较粗略。另外虽然也有些算法采用多尺度特征融合的方式,但是一般是采用融合后的特征做预测,而本文不一样的地方在于预测是在不同特征层独立进行的。

特征金字塔

下图展示了4种利用特征的形式:
(a)图像金字塔,即将图像做成不同的scale,然后不同scale的图像生成对应的不同scale的特征。这种方法的缺点在于增加了时间成本。有些算法会在测试时候采用图像金字塔。
(b)像SPP net,Fast RCNN,Faster RCNN是采用这种方式,即仅采用网络最后一层的特征。
(c)像SSD(Single Shot Detector)采用这种多尺度特征融合的方式,没有上采样过程,即从网络不同层抽取不同尺度的特征做预测,这种方式不会增加额外的计算量。作者认为SSD算法中没有用到足够低层的特征(在SSD中,最低层的特征是VGG网络的conv4_3),而在作者看来足够低层的特征对于检测小物体是很有帮助的。
(d)本文作者是采用这种方式,顶层特征通过上采样和低层特征做融合,而且每层都是独立预测的。

如下图所示,我们可以看到图像中存在不同尺寸的目标,而不同的目标具有不同的特征,利用浅层的特征就可以将简单的目标的区分开来;利用深层的特征可以将复杂的目标区分开来;这样我们就需要这样的一个特征金字塔来完成这件事。图中我们在第1层(请看绿色标注)输出较大目标的实例分割结果,在第2层输出次大目标的实例检测结果,在第3层输出较小目标的实例分割结果。检测也是一样,我们会在第1层输出简单的目标,第2层输出较复杂的目标,第3层输出复杂的目标。

作者的主网络采用ResNet。
作者的算法大致结构如下图:一个自底向上的线路,一个自顶向下的线路,横向连接(lateral connection)。图中放大的区域就是横向连接,这里1*1的卷积核的主要作用是减少卷积核的个数,也就是减少了feature map的个数,并不改变feature map的尺寸大小。

自底向上其实就是网络的前向过程。在前向过程中,feature map的大小在经过某些层后会改变,而在经过其他一些层的时候不会改变,作者将不改变feature map大小的层归为一个stage,因此每次抽取的特征都是每个stage的最后一个层输出,这样就能构成特征金字塔。
自顶向下的过程采用上采样(upsampling)进行,而横向连接则是将上采样的结果和自底向上生成的相同大小的feature map进行融合(merge)。在融合之后还会再采用3*3的卷积核对每个融合结果进行卷积,目的是消除上采样的混叠效应(aliasing effect)。并假设生成的feature map结果是P2,P3,P4,P5,和原来自底向上的卷积结果C2,C3,C4,C5一一对应。

利用FPN构建Faster R-CNN检测器

步骤:

  • 首先,选择一张需要处理的图片,然后对该图片进行预处理操作;
  • 然后,将处理过的图片送入预训练的特征网络中(如ResNet等),即构建所谓的bottom-up网络;
  • 接着,如下图所示,构建对应的top-down网络(即对层4进行上采样操作,先用1x1的卷积对层2进行降维处理,然后将两者相加(对应元素相加),最后进行3x3的卷积操作,最后);
  • 接着,在图中的4、5、6层上面分别进行RPN操作,即一个3x3的卷积后面分两路,分别连接一个1x1的卷积用来进行分类和回归操作;
  • 接着,将上一步获得的候选ROI分别输入到4、5、6层上面分别进行ROI Pool操作(固定为7x7的特征);
  • 最后,在上一步的基础上面连接两个1024层的全连接网络层,然后分两个支路,连接对应的分类层和回归层;

    FPN整体架构

注:层1、2、3对应的支路就是bottom-up网络,就是所谓的预训练网络,文中使用了ResNet网络;由于整个流向是自底向上的,所以我们叫它bottom-up;层4、5、6对应的支路就是所谓的top-down网络,是FPN的核心部分,名字的来由也很简单。

FPN构建Faster R-CNN检测器的Faster R-CNN+FPN细节图:

FPN性能评估

  1. FPN效果定量评估


表1 Faster R-CNN+FPN结果

如上表所示,我们可以看到当我们使用相同的预训练网络、相同的RPN网络、Fast R-CNN使用不同的方法时,我们的特征层由原来的C4或者C5变化为现在的特征集合Pk,同时FPN方案使用了横向连接(lateral)和top-down模型,算法的性能有了大幅度上升,与a相比提升了2.2个百分点,与b相比提升了4.0个百分点(AP@0.5);对于APs,提升了5.9个百分点;对于APm,提升了5.3个百分点。这也说明了FPN能够提升小目标的检测效果。

表2 FPN高效训练结果

观察表2,我们可以看到使用FPN的Fast R-CNN+FPN和没有使用FPN的Fast R-CNN方案之间的差别,首先我们的特征维度由1024减少到256维(这样可以大大的减少一些运算量,包括前向和反向运算);我们利用2个MLP层取代了Conv5,作为我们的头分类器;我们的训练时间由原来的44.6小时减少到现在的10.6小时,速度大概提升了4倍;我们的推理时间由原来的0.32s减少到现在的0.15s;最后,我们的准确率提升了2.0个百分点。主要的原因是因为我们通过FPN获得了更加鲁邦的高层语义特征,它使得我们的学习过程更加高效。


表3 COCO数据集结果展示

如上表所示,我们测试了FPN算法在COCO数据集上面的性能表现,使用了FPN的Faster R-CNN方法获得了很多的最佳指标,尤其是在APs指标上面。总之,获得了最好的单模型准确率。

表4 使用了FPN的RPN效果

如上表所示,我们比较了比较了FPN+RPN和RPN这两种方案,我们可以看到我们的性能有了大幅度的提升。

表5 top-down和lateral的重要性

在表5中,我们验证了top-down模型和Lateral连接的重要性,同时使用两者的FPN方案取得了最好的结果。相对来讲,Lateral连接起到了更好的效果。

表7 FPN在实例分割上面的效果

由于FPN是一个特征金字塔,具有很好地泛华能力,可以利用到很多利用深度学习网络的方法中去,包括目标检测、实例分割等。如上表所示,使用了FPN的DeepMask方法可以不仅可以获得性能的提升,同时可以获得速度的提升。(不同的目标在不同的层上面生成对应的Mask)!

总结
作者提出的FPN(Feature Pyramid Network)算法同时利用低层特征高分辨率和高层特征的高语义信息,通过融合这些不同层的特征达到预测的效果。并且预测是在每个融合后的特征层上单独进行的,这和常规的特征融合方式不同。

自己实现的代码,仅供参考:

import torch.nn as nn
import torch.nn.functional as F
import math__all__ = ['FPN']class Bottleneck(nn.Module):expansion = 4#这里,我们先实现的是Bottleneck的左半边(1*1->3*3->1*1),expansion = 最后一层的输出通道数/第一层的输入通道数def __init__(self,in_planes,planes,stride=1,downsample=None):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,stride=stride,bias=False)self.bn3 = nn.BatchNorm2d(self.expansion*planes)self.relu = nn.ReLU(inplace=True)self.downsample = downsampleself.stride = stride#这里加上了residualdef forward(self,x):residual = x            #右边的short_cutout = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)out = self.relu(out)out = self.con3(out)out = self.bn3(out)out = self.relu(out)if self.downsample is not None:residual = self.downsample(x)out += residualout += self.relu(out)return outclass FPN(nn.Module):#这里传入的参数block用于传入Bottleneckdef __init__(self,block,layers):super(FPN, self).__init__()self.inplanes = 64#这部分是FPN最开始的一个Conv1,为了节省内存,没有将这部分纳入金字塔self.conv1 = nn.Conv2d(3,64,kernel_size=7,stride=2,padding=3,bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3,stride=2,padding=1)#Bottom-up layersself.layer1 = self._make_layer(block,layers[0])self.layer2 = self._make_layer(block,layers[1],stride=2)self.layer3 = self._make_layer(block,layers[2],stride=2)self.layer4 = self._make_layer(block,layers[3],stride=2)#Top layerself.toplayer = nn.Conv2d(2048,256,kernel_size=1,stride=1,padding=0)#FPN朝右边延伸的,Smooth layersself.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)#FPN的左边的特征金字塔连接到右边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)#这部分是初始化conv的值,还有BN的值for m in self.modules():if isinstance(m,nn.Conv2d):n = m.kernel_size[0]*m.kernel_size[1]*m.out_channelsm.weight.data.normal_(0,math.sqrt(2./n))elif isinstance(m,nn.BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()#blocks是Bottleneck的数量def _make_layer(self,block,planes,blocks,stride=1):downsample = Noneif stride != 1 or self.inplanes!= block.expansion*planes:#这里的downsample用来实现Bottleneck的右边downsample = nn.Sequential(nn.Conv2d(self.inplanes,block.expansion*planes,kernel_size=1,stride=stride,bias=False),nn.BatchNorm2d(block.expansion*planes))layers = []layers.append(block(self.inplanes,planes,stride,downsample))self.inplanes = planes * block.expansionfor i in range(1,blocks):layers.append(block(self.inplanes,planes))return nn.Sequential(*layers)#通过这个操作来结合左边过来的1*1+top-bottomdef _upsample_add(self,x,y):_,_,H,W = y.size()return F.upsample(x,size=(H,W),mode='bilinear')+ydef forward(self,x):#Bottom-upx = self.conv1(x)x = self.bn1(x)x = self.relu(x)c1 = self.maxpool(x)c2 = self.layer1(c1)c3 = self.layer2(c2)c4 = self.layer3(c3)c5 = self.layer4(c4)#top-bottomp5 = 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))#smoothp4 = self.smooth1(p4)p3 = self.smooth2(p3)p2 = self.smooth3(p2)return p2,p3,p4,p5#101以上的才为Bottleneck
def FPN101():return FPN(Bottleneck,[2,2,2,2])

代码的话有以下参考:
fpn.pytorch
FPN_Tensorflow

FPN:feature pyramid networks for object detection相关推荐

  1. (FPN)Feature Pyramid Networks for Object Detection

    摘要 特征金字塔是识别系统中用于检测不同尺度目标的基本组件.但最近的深度学习目标检测器已经避免了金字塔表示,部分原因是它们是计算和内存密集型的.在本文中,我们利用深度卷积网络内在的多尺度.金字塔分级来 ...

  2. Feature Pyramid Networks for Object Detection 总结

    最近在阅读FPN for object detection,看了网上的很多资料,有些认识是有问题的,当然有些很有价值.下面我自己总结了一下,以供参考. 1. FPN解决了什么问题? 答: 在以往的fa ...

  3. 【深度学习】FPN(特征金字塔)简介:Feature Pyramid Networks for Object Detection

    [深度学习]FPN(特征金字塔):Feature Pyramid Networks for Object Detection 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 博文 ...

  4. 目标检测--Feature Pyramid Networks for Object Detection

    CVPR2017 Feature Pyramid Networks for Object Detection https://arxiv.org/abs/1612.03144 Code will be ...

  5. Feature Pyramid Networks for Object Detection 论文笔记

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Jesse_Mx/article/details/54588085 论文地址:Feature Pyra ...

  6. Feature pyramid networks for object detection

    具体分析请见: https://medium.com/@jonathan_hui/understanding-feature-pyramid-networks-for-object-detection ...

  7. 《Feature Pyramid Networks for Object Detection》论文阅读笔记

    FPN 很多论文中都会采用含有FPN的backbone进行特征提取,因为FPN使用特征金字塔结构,将low-level的特征和high-level的特征进行融合,能提取更加准确的位置等特征信息. 所以 ...

  8. Feature Pyramid Networks for Object Detection论文翻译——中文版

    文章作者:Tyan 博客:noahsnail.com  |  CSDN  |  简书 声明:作者翻译论文仅为学习,如有侵权请联系作者删除博文,谢谢! 翻译论文汇总:https://github.com ...

  9. Feature Pyramid Networks for Object Detection论文翻译——中英文对照

    文章作者:Tyan 博客:noahsnail.com  |  CSDN  |  简书 声明:作者翻译论文仅为学习,如有侵权请联系作者删除博文,谢谢! 翻译论文汇总:https://github.com ...

最新文章

  1. 使用 PEAR的Text_CAPTCHA保护Web表单[翻译]
  2. java分层命名_JAVA基础篇(5)-POJO的命名规则
  3. 如何限制用户的内存使用量
  4. Linux 基础I/O :文件描述符,重定向,文件系统,软链接和硬链接,动态库和静态库
  5. 要多大内存才满足_佛龛的尺寸要多大?
  6. ACM将一个十进制的数转换为一个十六进制的数输出
  7. 在 Delphi 下使用 DirectSound (6): 按文件自己的格式(TWaveFormatEx)播放
  8. .NET性能系列文章二:Newtonsoft.Json vs System.Text.Json
  9. “绿坝—花季护航”使用全攻略
  10. Java Excel转图片
  11. 朴素贝叶斯中拉普拉斯平滑算法
  12. 数据挖掘之Spark学习
  13. Android中singleTask模式没起作用!!
  14. 各种奇葩3389连接不上的解决方法
  15. Android支付接入(七):Googlenbsp;In-app-Billing
  16. Linux系统学习笔记二
  17. OpenX系列标准介绍(5):OpenDRIVE和OpenSCENARIO的中文版本
  18. object.assign()是深拷贝?还是浅拷贝?
  19. 去除谷歌地图api上的各种默认标记
  20. Backprop Induced Feature Weighting for Adversarial Domain Adaptation with Iterative Label Distributi

热门文章

  1. TensorFlow js. 官方教程
  2. arcgis地图加载离线地图
  3. java中释放空间_一个释放java 空间的方法
  4. WAP(手机网站)基础知识
  5. 感谢!《夜空守望者》
  6. Vijos - 佳佳的魔法药水(最短路)
  7. node-red教程 5.4 context global与函数节点的其它功能
  8. Fast R-CNN论文原理+目标检测笔记(二)
  9. 在excel中使用插值法补全数据
  10. GitBook 告别文档共享烦恼