美文网首页
RoI Pooling 系列大法(附源码)

RoI Pooling 系列大法(附源码)

作者: CW不要无聊的风格 | 来源:发表于2020-03-29 16:06 被阅读0次

    Date: 2020/03/29

    Author: CW

    前言:

    RoI Pooling 是目标检测任务中的常见手段,最早在 Faster R-CNN 中提出,作用是将一系列大小不同的 RoI 投影至特征图上,然后通过池化操作将它们处理为一致大小,从而方便后面的网络层进行处理(历史原因,以前的网络结构中最后几层往往是全连接层,因此需要固定的输入尺寸),同时起到了加速计算的作用。

    本文先对 RoI Pooling 进行介绍,该方法由于量化误差而带了精度上的损失,后来有大神基于该方法提出了 RoI AlignPrecise RoI Pooling,本文后半部分会让大伙瞧瞧这倆家伙的玩法。

    文末会附上以上三部分相应的源码链接,其中 RoI Pooling 和 RoI Align 是自己手撸的纯 py 实现,作为学习参考使用,Precise RoI Pooling 是作者的原版;基于 cuda 编写,在使用时需要编译。


    Outline

    壹、RoI Pooling -- 将不同的尺寸变为一致

    贰、RoI Align -- 没有量化误差

    叄、Precise RoI Pooling -- 无需超参,每个像素点均有梯度贡献


    壹、RoI Pooling -- 将不同的尺寸变为一致

    先来概述下 RoI Pooling 的操作:

    i). RoI 的尺寸通常是对应输入图像的,特征图是输入图像经过一系列卷积层后的输出,因此,首先将 RoI 映射到特征图上的对应区域位置;

    ii). 最终需要将尺寸不一的 RoI 变为固定的 n x n 大小,于是将 RoI 平均划分为 n x n 个区域;

    iii). 取每个划分而来的区域的最大像素值,相当于对每个区域做 max pooling 操作,作为每个区域的“代表”,这样每个 RoI 经过操作后就变为 n x n 大小

    结合一个例子说明下 RoI Pooling 带来的量化误差:

    如下图,假设输入图像经过一系列卷积层下采样32倍后输出的特征图大小为8x8,现有一 RoI 的左上角和右下角坐标(x, y 形式)分别为(0, 100) 和 (198, 224),映射至特征图上后坐标变为(0, 100 / 32)和(198 / 32,224 / 32),由于像素点是离散的,因此向下取整后最终坐标为(0, 3)和(6, 7),这里产生了第一次量化误差

    假设最终需要将 RoI 变为固定的2x2大小,那么将 RoI 平均划分为2x2个区域,每个区域长宽分别为 (6 - 0 + 1) / 2 和 (7 - 3 + 1) / 2 即 3.5 和 2.5,同样,由于像素点是离散的,因此有些区域的长取3,另一些取4,而有些区域的宽取2,另一些取3,这里产生了第二次量化误差

    RoI Pooling

    贰、RoI Align -- 没有量化误差

    RoI Align 是在 Mask R-CNN 中提出来的,基本流程和 RoI Pooling 一致,但是没有量化误差,下面结合一个例子来说明:

    RoI Align

    如上图,输入图像分辨率为800x800,其中一个 RoI 大小为 665x665,输入图像经过 VGG16 下采样32倍后输出分辨率为25x25的特征图。

    1). 将 RoI 映射至特征图上,大小为 (665/32)x( 665/32) 即 20.78x20.78,注意这里不进行取整

    2). 最终需要将 RoI 输出为7x7大小,因此将 20.78x20.78大小的 RoI 均分为7x7个区域,每个区域大小为2.97x2.97,注意这里也没有取整操作

    3). RoI Align 需要设置一个超参,代表每个区域的采样点数,即每个区域取几个点来计算“代表”这个区域的值,通常为4;

    4). 对每个划分后的区域长宽各划分为一半,“十字交叉”变为4等份,取每份中心点位置作为其“代表”,中心点位置的像素值利用双线性插值计算获得,这样就得到4个中心点像素值,采样点数为4就是这个意思;

    2.97x2.97区域划分为4等份,每份利用双线性插值计算其中心点像素值

    5).每个2.97x2.97的区域都有4个中心点像素值,它们分别取4个中心点像素值中的最大值作为其“代表”,这样7x7个区域就产生7x7个值,最终将 RoI 变为了7x7大小


    叄、Precise RoI Pooling -- 无需超参

    RoI Pooling 系列大法

    RoI Align 虽然没有量化损失,但是却需要设置超参,对于不同大小的特征图和 RoI 而言这个超参的取值难以自适应,于是就有人提出 Precise RoI Pooling 来解决这一问题,真是人才辈出呐!

    Precise RoI Pooling 和 RoI Align 类似,将 RoI 映射到特征图以及划分区域时都没有量化操作,不同的是,Precise RoI Pooling 没有再次划分子区域,而是对每个区域计算积分后取均值来“代表”每个区域,因而不需要进行采样。

    Precise RoI Pooling: 对每个区域计算积分取均值操作

    另外,由上述公式可知,区域内的每点在反向传播中对梯度都是有贡献的,而对 RoI Align 和 RoI Pooling 来说,只有区域内最大值那点才对梯度有贡献,相当于“浪费”了大部分的点。


    #最后

    以上操作的原理不难理解,很多人看完后或许都有这样的feel——咦,挺简单的嘛!但是如果试着从代码层面去实现的话或许就会发现不是那么容易了,特别是,要能应用到生活场景中。

    这里我手撸的 RoI Pooling RoI Align 也仅是基于原理去实现的,用作学习参考,真正业界上应用的通常是用CC++实现和编译的,纯 py 的版本通常由于性能原因难以落地到工程中。

    另外,这里附上的 Precise RoI Pooling 源码是原作者的版本,但是我使用时一直出现编译错误,各位大侠可以试试,如果有类似问题或者解决方案希望可以和我一起探讨,谢谢!

    欢迎大家来围观源码


    参考:

    https://www.cnblogs.com/wangyong/p/8523814.html

    https://blog.csdn.net/m_buddy/article/details/85110124

    相关文章

      网友评论

          本文标题:RoI Pooling 系列大法(附源码)

          本文链接:https://www.haomeiwen.com/subject/jzgsuhtx.html