The limitation in using F.max_pool2d function

I was going to implement the spatial pyramid pooling (SPP) layer, so I need to use F.max_pool2d function. Unfortunately, I got a problem as the following:

invalid argument 2: pad should be smaller than half of kernel size, but got padW = 2, padH = 1, kW = 3, kH = 2 at /pytorch/torch/lib/THCUNN/generic/SpatialDilatedMaxPooling.cu:39
torch.Size([1, 512, 7, 9])

So I want to ask how to ignore this limitation — “pad should be smaller than half of kernel size”.

I’ve figured out this problem in the following way:

  • we can first mutually padding our data

  • then update the kernel_size and stride

the code to implement the SPP layer:



class SPPLayer(torch.nn.Module):

    def __init__(self, num_levels, pool_type='max_pool'):
        super(SPPLayer, self).__init__()

        self.num_levels = num_levels
        self.pool_type = pool_type
        

    def forward(self, x):
        # num:样本数量 c:通道数 h:高 w:宽
        # num: the number of samples
        # c: the number of channels
        # h: height
        # w: width
        num, c, h, w = x.size() 
#         print(x.size())
        for i in range(self.num_levels):
            level = i+1

            '''
            The equation is explained on the following site:
            http://www.cnblogs.com/marsggbo/p/8572846.html#autoid-0-0-0
            '''
            kernel_size = (math.ceil(h / level), math.ceil(w / level))
            stride = (math.floor(h / level), math.floor(w / level))
            pooling = (math.floor((kernel_size[0]*level-h+1)/2), math.floor((kernel_size[1]*level-w+1)/2))
            
            
            h_new = 2*pooling[0] + h
            w_new = 2*pooling[1] + w
            kernel_size = (math.ceil(h_new / level), math.ceil(w_new / level))
            stride = (math.floor(h_new / level), math.floor(w_new / level))
            
            zero_pad = torch.nn.ZeroPad2d((pooling[1],pooling[1],pooling[0],pooling[0]))
            x_new = zero_pad(x)
            
            # 选择池化方式 
            # choose the way of pooling
            if self.pool_type == 'max_pool':
                try:
                    tensor = F.max_pool2d(x_new, kernel_size=kernel_size, stride=stride).view(num, -1)
                except Exception as e:
                    print(str(e))
                    print(x.size())
                    print(level)
            else:
                tensor = F.avg_pool2d(x_new, kernel_size=kernel_size, stride=stride).view(num, -1)
            
            
              
            # 展开、拼接
            #flatten & cat
            if (i == 0):
                x_flatten = tensor.view(num, -1)
            else:
                x_flatten = torch.cat((x_flatten, tensor.view(num, -1)), 1)
        return x_flatten
2 Likes

Thank s for your SPP codes, it really works!