Faster-RCNN论文中在RoI-Head网络中,将128个RoI区域对应的feature map进行截取,而后利用RoI pooling层输出7*7大小的feature map。在pytorch中可以利用:

  • torch.nn.functional.adaptive_max_pool2d(input, output_size, return_indices=False)
  • torch.nn.AdaptiveMaxPool2d(output_size, return_indices=False)

这个函数很方便调用,但是这个实现有个缺点,就是慢。

所以有许多其他不同的实现方式,借鉴其他人的实现方法,这里借鉴github做一个更加丰富对比实验。总共有4种方法:

方法1. 利用cffi进行C扩展实现,然后利用Pytorch调用:需要单独的 C 和 CUDA 源文件,还需要事先进行编译,不但过程比较繁琐,代码结构也稍显凌乱。对于一些简单的 CUDA 扩展(代码量不大,没有复杂的库依赖),显得不够友好。

方法2.利用Cupy实现在线编译,直接为 pytorch 提供 CUDA 扩展(当然,也可以是纯 C 的扩展)。Cupy实现了在cuda上兼容numpy格式的多维数组。GPU加速的矩阵运算,而Numpy并没有利用GPU。Cupy目前已脱离chainer成为一个独立的库。

方法3.利用chainer实现,相较其他深度学习框架来说,chainer知名度不够高,但是是一款非常优秀的深度学习框架,纯python实现,设计思想简洁,语法简单。chainer中的GPU加速也是通过Cupy实现的。此外,chainer还有其他附加包,例如ChainerCV,其中便有对Faster-RCNN、SSD等网络的实现。

  

图源:Chainer官网slides

方法4.利用Pytorch实现,也就是文章伊始给出的两个函数

从方法1至方法4,实现过程越来越简单,所以速度越来越慢

以下是一个简单的对比试验结果:实验中以输入batch大小图像尺寸(严格讲是特征图尺寸)大小rois数目、是否反向传播为变量来进行对比,注意输出尺寸和Faster原论文一致都是7*7,都利用cuda,且设置scale=1,即特征图和原图同大小。

对比1: 只正向传播

use_cuda: True, has_backward: True
method1: 0.001353292465209961, batch_size: , size: , num_rois:
method2: 0.04485161781311035, batch_size: , size: , num_rois:
method3: 0.06167919635772705, batch_size: , size: , num_rois:
method4: 0.009436330795288085, batch_size: , size: , num_rois: method1: 0.0003777980804443359, batch_size: , size: , num_rois:
method2: 0.001593632698059082, batch_size: , size: , num_rois:
method3: 0.00210268497467041, batch_size: , size: , num_rois:
method4: 0.061138014793396, batch_size: , size: , num_rois: method1: 0.001754002571105957, batch_size: , size: , num_rois:
method2: 0.0047376775741577145, batch_size: , size: , num_rois:
method3: 0.006129913330078125, batch_size: , size: , num_rois:
method4: 0.06233139038085937, batch_size: , size: , num_rois: method1: 0.0018497371673583984, batch_size: , size: , num_rois:
method2: 0.010891580581665039, batch_size: , size: , num_rois:
method3: 0.023005642890930177, batch_size: , size: , num_rois:
method4: 0.5292188739776611, batch_size: , size: , num_rois: method1: 0.09110891819000244, batch_size: , size: , num_rois:
method2: 0.4102628231048584, batch_size: , size: , num_rois:
method3: 0.3902537250518799, batch_size: , size: , num_rois:
method4: 0.6544218873977661, batch_size: , size: , num_rois: method1: 0.09256606578826904, batch_size: , size: , num_rois:
method2: 0.641594967842102, batch_size: , size: , num_rois:
method3: 1.3756087446212768, batch_size: , size: , num_rois:
method4: 4.076273036003113, batch_size: , size: , num_rois:

对比2:含反向传播

use_cuda: True, has_backward: False
method1: 0.000156359672546386, batch_size: , size: , num_rois:
method2: 0.009024391174316406, batch_size: , size: , num_rois:
method3: 0.009477467536926269, batch_size: , size: , num_rois:
method4: 0.002876405715942383, batch_size: , size: , num_rois: method1: 0.00017533779144287, batch_size: , size: , num_rois:
method2: 0.00040388107299804, batch_size: , size: , num_rois:
method3: 0.00085462093353271, batch_size: , size: , num_rois:
method4: 0.02638674259185791, batch_size: , size: , num_rois: method1: 0.00018683433532714, batch_size: , size: , num_rois:
method2: 0.00039398193359375, batch_size: , size: , num_rois:
method3: 0.00234550476074218, batch_size: , size: , num_rois:
method4: 0.02483976364135742, batch_size: , size: , num_rois: method1: 0.0013917160034179, batch_size: , size: , num_rois:
method2: 0.0010843658447265, batch_size: , size: , num_rois:
method3: 0.0025740385055541, batch_size: , size: , num_rois:
method4: 0.2577446269989014, batch_size: , size: , num_rois: method1: 0.0003826856613153, batch_size: , size: , num_rois:
method2: 0.0004550600051874, batch_size: , size: , num_rois:
method3: 0.2729876136779785, batch_size: , size: , num_rois:
method4: 0.0269237756729125, batch_size: , size: , num_rois: method1: 0.0008277797698974, batch_size: , size: , num_rois:
method2: 0.0021707582473754, batch_size: , size: , num_rois:
method3: 0.2724076747894287, batch_size: , size: , num_rois:
method4: 0.2687232542037964, batch_size: , size: , num_rois:

可以观察到最后一种方法总是最慢的,因为对于所有的num_roi依次循环迭代,效率极低。

对比3:固定1个batch(一张图),size假设为50*50(特征图大小,所以原图为800*800),特征图通道设为512,num_rois设为300,这是近似于 batch为1的Faster-RCNN的测试过程,看一下用时情况:此时输入特征图为(1,512,50,50),rois为(300,5)。rois的第一列为batch index,因为是1个batch,所以此项全为0,没有实质作用。

use_cuda: True, has_backward: True
method0: 0.0344547653198242, batch_size: , size: , num_rois:
method1: 0.1322056961059570, batch_size: , size: , num_rois:
method2: 0.1307379817962646, batch_size: , size: , num_rois:
method3: 0.2016681671142578, batch_size: , size: , num_rois:

可以看到,方法2和方法3速度几乎一致,所以可以使用更简洁的chainer方法,然而当使用多batch训练Faster时,最好利用方法1,速度极快。

代码已上传:github

Pytorch中RoI pooling layer的几种实现的更多相关文章

  1. 到底什么是 ROI Pooling Layer ???

    到底什么是 ROI Pooling Layer ??? 只知道 faster rcnn 中有 ROI pooling, 而且其他很多算法也都有用这个layer 来做一些事情,如:SINT,检测的文章等 ...

  2. pytorch中的Linear Layer(线性层)

    LINEAR LAYERS Linear Examples: >>> m = nn.Linear(20, 30) >>> input = torch.randn(1 ...

  3. pytorch 中改变tensor维度的几种操作

    具体示例如下,注意观察维度的变化 #coding=utf-8 import torch """改变tensor的形状的四种不同变化形式""" ...

  4. 关于RoI pooling 层

    ROIs Pooling顾名思义,是pooling层的一种,而且是针对ROIs的pooling: 整个 ROI 的过程,就是将这些 proposal 抠出来的过程,得到大小统一的 feature ma ...

  5. 详解Pytorch中的网络构造,模型save和load,.pth权重文件解析

    转载:https://zhuanlan.zhihu.com/p/53927068 https://blog.csdn.net/wangdongwei0/article/details/88956527 ...

  6. ROI POOLING 介绍

    转自 https://blog.csdn.net/gbyy42299/article/details/80352418 Faster rcnn的整体构架: 训练的大致过程: 1.图片先缩放到MxN的尺 ...

  7. 【转】ROI Pooling

    Faster rcnn的整体构架: 训练的大致过程: 1.图片先缩放到MxN的尺寸,之后进入vgg16后得到(W/16,H/16)大小的feature map: 2.对于得到的大小为(W/16,H/1 ...

  8. pytorch中网络特征图(feture map)、卷积核权重、卷积核最匹配样本、类别激活图(Class Activation Map/CAM)、网络结构的可视化方法

    目录 0,可视化的重要性: 1,特征图(feture map) 2,卷积核权重 3,卷积核最匹配样本 4,类别激活图(Class Activation Map/CAM) 5,网络结构的可视化 0,可视 ...

  9. ROI Pooling层详解

    目标检测typical architecture 通常可以分为两个阶段: (1)region proposal:给定一张输入image找出objects可能存在的所有位置.这一阶段的输出应该是一系列o ...

随机推荐

  1. 9、字符串转数字用int、因为input里面接受的全部是字符串

    #!/user/bin/python# -*- coding:utf-8 -*-num = int(input('请输入数字:'))if num == 1: print(666)elif num == ...

  2. GlusterFS 分布式文件系统的使用入门-管理GlusterFS卷

    GlusterFS 分布式文件系统的使用入门-管理GlusterFS卷 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.卷的扩容 您可以根据需要在群集联机且可用时扩展卷.例如,您 ...

  3. SQL语法基础之ALTER语句

    SQL语法基础之ALTER语句 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查看ALTER的帮助信息 mysql> ? ALTER Many help items fo ...

  4. 面向对象【day08】:异常处理-断言(七)

    本节内容 1.概述 2.知识点回顾 3.断言 一.概述 python中断言,这个我是第一次听说到的,断言有什么用呢?断言就是做一些程序的检查工作,就是在执行之前需要做的一些检查,比如类似于安检一样,合 ...

  5. netty的对象传输

    pom <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <grou ...

  6. git的那些事

    前言:记得在想学习git的时候,一直停留在思想的层面,总没有弄清楚它的运行机制,经常与github混淆,还好找到了一个好的教程,带我领略了git的风采 (一)git的优点 git的优点:版本控制在本地 ...

  7. css 绝对定位实现水平垂直居中

    负margin实现水平垂直居中 width: 500px; height: 500px; position: absolute; left: 50%; top :50%; margin-left: - ...

  8. OPC和DCOM配置

    本文为Java实现OPC通信的一部分 系统:使用win10 64位专业版 PDF文件: 本文,链接:  百度网盘 密码: reht, Win7和Win7_SP1网络OPC配置,链接:  百度网盘 密码 ...

  9. 【leetcode-69】 x 的平方根

    (主要是越界问题) 实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4 ...

  10. spring中获取dao或对象中方法的实例化对象

    spring中获取dao的中方法的实例化对象: //获取应用上下文对象 ApplicationContext ctx = new ClassPathXmlApplicationContext(&quo ...