Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
现有的卷积深度神经网络需要固定尺寸的图像输入,这可能会降低图像或子图像识别准确率。本文提出了新的池化策略—“空间金字塔池化”,用来消除对固定尺寸的依赖。SPP-net能够生成与图像尺寸无关的固定长度的表征。该方法能够有效提高分类准确率。在目标检测任务中,仅从整个图像计算一次特征图,然后对任意区域进行池化,生成固定长度的表征用于训练检测器,该方法能够有效避免重复计算卷积特征。
常见的网络结构中大多为卷积-全连接结构,全连接层要求输入维度固定,这使得卷积层的输入也需要固定,为了输入固定尺寸大小的图像,通常采用裁剪或扭曲方法,前者会丢失目标信息,后者会导致几何畸变,降低识别准确率。SPP层位于最后一个卷积层的后面,将特征映射到固定长度的表征,然后再输入到全连接层,以此来避免对固定尺寸的输入。SPP在CNN中的三个特性:
- 生成固定长度的输出不管输入尺寸
- 使用多层空间窗口进行池化,而传统的滑动窗口池化仅使用一种,对目标变形更具有鲁棒性
- 由于输入尺度的灵活性,SPP能够以不同的尺度池化提取的特征。
SPP-net可以在训练阶段输入不同的尺寸,使用多尺度图像训练可以增减尺度不变性、降低过拟合。卷积层使用权值共享,在不同的epoch使用不同的输入尺寸图像。实验显示该训练方法能够提高测试准确率。
SPP能过保持空间信息通过在局部空间范围内池化,池化区域的大小与图像尺寸成比例,因此池化核的数量也是固定的。如图所示,在每一个spatial bin中,对每个核进行池化,spp层输出 k M kM kM维向量,其中 M M M是bin(池化核)的数量, k k k是最后一层卷积层的filters数量(图像通道数)。然后将固定维度的特征向量输入到全连接层。
使用SPP,网络输入图像大小可以任意,可以将输入图像缩放到任意尺寸,然后提取不同此村的特征,这有助于提高深度网络的准确率。
最粗糙的金字塔层使用一个bin覆盖全图,相当于全局池化。
单尺寸训练:对于一张给定大小的图像,可以预先计算出用于spp的bin大小。假设特征图大小维 a × a a\times a a×a,其中一个金字塔层有 n × n n\times n n×n个bins,使用滑动窗口池化对该层进行池化,其中池化窗口的大小为 w i n = ⌈ a / n ⌉ win=\lceil{a/n}\rceil win=⌈a/n⌉,步长为 s t r = ⌊ a / n ⌋ str=\lfloor{a/n}\rfloor str=⌊a/n⌋。全连接层将所有金字塔层的池化结果进行拼接作为输入。
多尺寸训练:SPP可以用任何尺寸的图像,通过切换输入图像的尺寸大小可以进行多尺度训练。
假设特征图的大小为 w × h w\times h w×h,对于一个金字塔层为 n × n n\times n n×n个bin,第 ( i , j ) (i,j) (i,j)个bin的池化作用范围为 [ ⌊ i − 1 n w ⌋ , ⌈ i n w ⌉ ] × [ ⌊ j − 1 n h ⌋ , ⌈ j n h ⌉ ] [\lfloor{\frac{i-1}{n}w}\rfloor, \lceil{\frac{i}{n}w}\rceil]\times[\lfloor{\frac{j-1}{n}h}\rfloor, \lceil{\frac{j}{n}h}\rceil] [⌊ni−1w⌋,⌈niw⌉]×[⌊nj−1h⌋,⌈njh⌉]。
注[1]:求解步长和池化核大小的公式有误,如当 a = 7 , n = 4 a=7,n=4 a=7,n=4时,按照原公式计算 w i n = 2 , s t r = 1 win=2,str=1 win=2,str=1,此时计算出来的输出特征图大小为 o u t = ⌊ a − w i n s t r ⌋ + 1 = 6 out=\lfloor{\frac{a-win}{str}}\rfloor+1=6 out=⌊stra−win⌋+1=6,原因在于未考虑padding,实际上应为 w i n = ⌈ a / n ⌉ , s t r = ⌈ a / n ⌉ , p a d d i n g = ⌊ n ∗ w i n − a + 1 2 ⌋ win = \lceil{a/n}\rceil,str=\lceil{a/n}\rceil,padding=\lfloor{\frac{n*win-a+1}{2}}\rfloor win=⌈a/n⌉,str=⌈a/n⌉,padding=⌊2n∗win−a+1⌋,此时 w i n = s t r = 2 , p a d d i n g = 1 win=str=2,padding=1 win=str=2,padding=1,计算出来的输出特征图大小为 4 4 4。
import math
import torch
import torch.nn.functional as F
class SPPLayer(torch.nn.Module):
def __init__(self, f_sizes=(1, 2, 4), pool_type='max_pool'):
super(SPPLayer, self).__init__()
self.f_sizes = f_sizes
self.pool_type = pool_type
def forward(self, x):
batch, channel, h, w = x.size()
res = None
for i in range(len(self.f_sizes)):
k_size = (math.ceil(h / self.f_sizes[i]), math.ceil(w / self.f_sizes[i]))
stride = k_size
padding = (math.floor((k_size[0]*self.f_sizes[i]-h+1)/2), math.floor((k_size[1]*self.f_sizes[i]-w+1)/2))
if self.pool_type == 'max_pool':
tensor = F.max_pool2d(x, kernel_size=k_size, stride=stride, padding=padding).view(batch, -1)
else:
tensor = F.avg_pool2d(x, kernel_size=k_size, stride=stride, padding=padding).view(batch, -1)
if res is None:
res = tensor
else:
res = torch.cat((res, tensor), dim=1)
return res
R-CNN重复对2000个候选窗口进行卷积操作,导致十分耗时。SPP仅从整个图像提取一次特征图,然后对每一个候选窗口的特征图进行空间金字塔池化,将其池化为固定大小的窗口,能够大大运行时间。
过程:
- SS方法生成2000个候选窗口,对图像进行缩放至最小边满足 min ( h , w ) = s \min(h,w)=s min(h,w)=s,从图像中提取特征。
- 对每一个候选窗口使用空间金字塔池化( 1 × 1 , 2 × 2 , 3 × 3 , 6 × 6 1\times1,2\times2,3\times3,6\times6 1×1,2×2,3×3,6×6,共50个bins),生成一个12800( 256 × 50 256\times50 256×50)维表征向量,然后输入到全连接层。
- 使用这些特征训练一个二类线性SVM,使用GT窗口生成正样本,负样本与正样本IoU不超过0.3,将与其他负样本IoU超过0.7的负样本移除,使用硬负样本挖掘训练SVM。在测试时,SVM 对每个候选窗口进行打分,然后用非极大值抑制(30%)进行删减。
使用多尺度特征能够改善检测性能,将图像缩放至 min ( h , w ) = s , s ∈ { 480 , 576 , 688 , 846 , 1200 } \min(h,w)=s, s\in\{480, 576, 688, 846, 1200\} min(h,w)=s,s∈{480,576,688,846,1200},然后计算每个尺度的特征图,对于每一个候选窗口,选择一个单一尺度 s ∈ S s\in S s∈S,使得缩放后的候选窗口接近 224 × 224 224\times 224 224×224,仅使用该尺度特征图计算该窗口的特征。
候选窗口是给定在图像域上,使用它来对卷积特征图进行裁剪,所以需要在特征图上对候选窗口进行对齐。将候选窗口的角点坐标投影到特征图上,使得该角点接近于特征图像素感受野中心。由于卷积层和池化层使用填充使得该映射变得困难。特征图坐标为 ( x ′ , y ′ ) (x',y') (x′,y′),对应在图像域内的感受野中心为 ( x , y ) = ( S x ′ , S y ′ ) (x,y)=(Sx',Sy') (x,y)=(Sx′,Sy′),其中 S S S是步长的乘积。对于一个在图像域内的候选窗口,投影其left(top)边界: x ′ = ⌊ x / S ⌋ + 1 x'=\lfloor{x/S}\rfloor+1 x′=⌊x/S⌋+1,right(bottom)边界: x ′ = ⌈ x / S − 1 ⌉ x'=\lceil{x/S}-1\rceil x′=⌈x/S−1⌉。
[1]. https://www.cnblogs.com/marsggbo/p/8572846.html