Spatial Pyramid Pooling (SPP) layer 常用于 CNN 中,处理不定长大小的图片。

如上图所示,假设经过一些列 conv layers 后,得到一个 [256, x, y] 的 vector。其中 256 是上一个卷积层 filter 的数量,x和y 可取任意大小。
假设 256 为 1,即 input 为 [x, y]
- Step 1. 把 [x, y] 分成 16 份,每份取 max,即可得到 [1, 16] 的 vector。
- Step 2. 把 Step 1 中的 16 换成 4,即可得 [1, 4] 的 vector 。
- Step 3. 把 Step 1 中的 16 换成 1,即可得 [1, 1] 的 vector 。
- Step 4. 把 Step 1,2,3 中的 vector 拼接起来,即得 [1, 21] 的 vetor。
如果 filters 为 256 的话,即可得 [1, 256 * 21] 的 vector。
代码如下:
import torchimport torch.nn as nnfrom torch.nn import initimport functoolsfrom torch.autograd import Variableimport numpy as npimport torch.nn.functional as Fimport mathdef spatial_pyramid_pool(previous_conv, num_sample, previous_conv_size, out_pool_size):'''previous_conv: a tensor vector of previous convolution layernum_sample: an int number of image in the batchprevious_conv_size: an int vector [height, width] of the matrix features size of previous convolution layerout_pool_size: a int vector of expected output size of max pooling layerreturns: a tensor vector with shape [1 x n] is the concentration of multi-level pooling'''# print(previous_conv.size())for i in range(len(out_pool_size)):# print(previous_conv_size)h_wid = int(math.ceil(previous_conv_size[0] / out_pool_size[i]))w_wid = int(math.ceil(previous_conv_size[1] / out_pool_size[i]))h_pad = int((h_wid*out_pool_size[i] - previous_conv_size[0] + 1)/2)w_pad = int((w_wid*out_pool_size[i] - previous_conv_size[1] + 1)/2)# print("h_pad:",h_pad)# print("w_pad:",w_pad)maxpool = nn.MaxPool2d((h_wid, w_wid), stride=(h_wid, w_wid), padding=(h_pad, w_pad))x = maxpool(previous_conv)if(i == 0):spp = x.view(num_sample,-1)# print("spp size:",spp.size())else:# print("size:",spp.size())spp = torch.cat((spp,x.view(num_sample,-1)), 1)return spp
测试结果:
参考:
https://github.com/yueruchen/sppnet-pytorch
https://arxiv.org/abs/1804.02047
