SPP-Net与空间金字塔池化详解

R-CNN的问世让卷积神经网络在目标检测领域崭露头角,尽管它具有不俗的准确率,但是其检测效率过于低下,以至于很难得到实际的应用。为了提高R-CNN的检测效率,SPP-Net与空间金字塔池化Spatial Pyramid Pooling, SPP应运而生。

一、R-CNN的不足与改进

  R-CNN模型进行目标检测的效率很低,不仅训练过程十分繁琐,检测过程也是非常的慢。其原因之一就是生成的约2000个候选区域需要一个一个地输入卷积神经网络以进行特征提取,而这一过程则相当的耗时。

  为了解决这一问题,SPP-Net提出将分割区域步骤与提取特征步骤的顺序进行颠倒。即,先通过CNN对原图进行一次卷积以生成一个特征图,然后再从特征图中提取每个候选区域对应的子特征图,从而大大减少卷积的次数以提高模型效率。

  想要实现上述改进,SPP-Net主要面临着两个难题:

  如何在特征图中找到候选区域映射的子特征图?

  提取的子特征图尺度不一,如何统一输入全连接层?

二、从特征图找到候选区域的映射

  关于如何从特征图上找出候选区域映射的子特征图,只需要找到原图像上坐标到特征图上坐标的映射即可。而这一映射关系作者已经在论文中给出:

  对于原图像上的坐标 ( x ,   y ) (x,\ y) (x, y) 和特征图上的坐标 ( x ′ ,   y ′ ) (x',\ y') (x, y) ,它们之间有如下映射关系: ( x ,   y ) = ( S x ′ ,   S y ′ ) (x,\ y)=(Sx',\ Sy') (x, y)=(Sx, Sy) 。反过来则有:
( x ′ ,   y ′ ) l e f t ,   t o p = ⌊ ( x ,   y ) / S ⌋ + 1 , ( x ′ ,   y ′ ) r i g h t ,   b o t t o m = ⌈ ( x ,   y ) / S ⌉ − 1 (x',\ y')_{left,\ top}=\lfloor(x,\ y)/S\rfloor+1,\quad (x',\ y')_{right,\ bottom}=\lceil(x,\ y)/S\rceil-1 (x, y)left, top=(x, y)/S+1,(x, y)right, bottom=(x, y)/S1
其中, S S SCNN中所有卷积层和池化层的stride的乘积

  那么上述映射是怎么来的呢?对于如下卷积变换:

在这里插入图片描述

  已知卷积变换的尺度公式如下( k k k 为卷积核大小, p p ppadding s s sstride):
w ′ = w + 2 p − k s + 1 w'=\frac{w+2p-k}{s}+1 w=sw+2pk+1
变形可得:
w = ( w ′ − 1 ) s − 2 p + k w=(w'-1)s-2p+k w=(w1)s2p+k
对于卷积后的某一像素点,则其 w ′ = 1 w'=1 w=1 ,计算可得这个像素点在上一层的感受野大小如下:
w = ( 1 − 1 ) s − 2 p + k = k − 2 p w=(1-1)s-2p+k=k-2p w=(11)s2p+k=k2p
假设卷积核大小为奇数,则感受野中心点的相对坐标为(未考虑感受野的偏移量 d d d):
( k − 2 p − 1 ) / 2 (k-2p-1)/2 (k2p1)/2
如果卷积后的这个像素点的坐标为 x x x(从0开始计),那么可以计算感受野的偏移量 d d d 为:
d = x ′ s d=x's d=xs
结合起来可以得到,卷积后某一像素点坐标 x ′ x' x 到卷积前感受野中心点坐标 x x x 的映射为
x = x ′ s + ( k − 2 p − 1 ) 2 x=x's+\frac{(k-2p-1)}{2} x=xs+2(k2p1)

  以上便是卷积前后坐标的映射关系。在SPP-Net中,为了简化上述映射,将 p p p 固定为了 ⌊ k / 2 ⌋ \lfloor k/2\rfloor k/2,则有:
x = x ′ s + ( k − 2 ⌊ k / 2 ⌋ − 1 ) 2 = { x ′ s − 0.5 , if  k = 2 n ,   n ∈ N x ′ s , if  k = 2 n + 1 ,   n ∈ N x=x's+\frac{(k-2\lfloor k/2\rfloor-1)}{2}= \begin{cases} x's-0.5,\quad &\text{if}\ k=2n,\ n\in N\\ x's,&\text{if}\ k=2n+1,\ n\in N \end{cases} x=xs+2(k2k/21)={xs0.5,xs,if k=2n, nNif k=2n+1, nN
又因为坐标 x x x 必须为整数,所以便可以近似认为 x = x ′ s x=x's x=xs 。当有多层卷积时,则有:
( x ,   y ) = ( S x ′ ,   S y ′ ) , S = s 1 s 2 s 3 . . . (x,\ y)=(Sx',\ Sy'),\quad S=s_1s_2s_3... (x, y)=(Sx, Sy),S=s1s2s3...
由此便得到了SPP-Net中卷积变换坐标的映射关系。

三、空间金字塔池化

  空间金字塔池化Spatial Pyramid Pooling, SPPSPP-Net的第二个核心内容。当从特征图上提取到每个候选区域对应的特征子图后,这些特征子图的尺度可能并不一致,从而无法直接输入到全连接层。因此,SPP-Net在全连接层前添加了一个特殊的池化层,即空间金字塔池化,能够将不同尺度的输入图像池化为相同长度的向量。

  所谓空间金字塔池化,就是对一张输入图像同时进行三种池化,分别输出[c, 4, 4], [c, 2, 2], [c, 1, 1]三个特征图,再将这三个特征图展平,最后得到一个长度固定为c * (16 + 4 + 1)的特征向量。

在这里插入图片描述

  具体做法是,假设输入图像形状为[c, h, w],池化输出为[c, n, n],那么池化层的kernel_size则可以设置为[ceil(h / n), ceil(w / n)]stride可以设置为[floor(h / n), floor(w / n)]。代码示例如下所示:

import torch
from torch import nn
from math import ceil, floor

a = torch.rand([4, 3, 15, 63])
size = [ceil(a.shape[2] / 4), ceil(a.shape[3] / 4)]
stride = [floor(a.shape[2] / 4), floor(a.shape[3] / 4)]
print(size)
print(stride)
pool = nn.MaxPool2d(kernel_size=size, stride=stride)
b = pool(a)
print(b.shape)

如上示例便可以将不同尺度的图片统一池化为[c, 4, 4]的形状。

四、写在最后

  以上便是SPP-Net最核心的内容,剩余的部分则和R-CNN一样了,详见博客目标检测模型(一):R-CNNSPP-Net主要是在特征提取阶段对R-CNN进行了优化,通过计算卷积前后坐标的映射关系和空间金字塔池化大大减少了卷积提取特征的次数,从而大幅地提高了模型进行目标检测的效率。除此之外,SPP-Net的思想还被后来的Fast R-CNN所借用,让目标检测的效率更上了一个阶梯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值