Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there really no padding=same option for PyTorch's Conv2d?

Tags:

pytorch

I'm currently working on building a convolutional neural network (CNN) that will work on time series data.

More specifically, the data is financial data of shape (100, 40), with 100 meaning 100 time stamps and 40 meaning 40 features.

The CNN that I'm using uses asymmetric kernel sizes (i.e. 1 x 2 and 4 x 1) and also asymmetric strides (i.e. 1 x 2 for the 1 x 2 layers and 1 x 1 for the 4 x 1 layers).

In order to maintain the height dimension to stay 100, I needed to apply some padding to the data. I was looking into ways to do this and noticed that people who use TensorFlow or Keras simply do padding='same', but this option is apparently unavailable in PyTorch according to many resources I've found including this thread on Github.

What I've found is that according to some answers in this question and also this answer on the PyTorch discussion forum, I can manually calculate how I need to pad my data and can use torch.nn.ZeroPad2d to solve my problem, as it seems that normal torch.nn.Conv2d layers don't support asymmetric padding (I believe that the total padding I need is 3 in height and 0 in width).

The experimental code that I've written to test this out is like this:

import torch
import torch.nn as nn

conv = nn.Conv2d(1, 1, kernel_size=(4, 1))
pad = nn.ZeroPad2d((0, 0, 2, 1)) # Add 2 to top and 1 to bottom.

x = torch.randint(low=0, high=9, size=(100, 40))
x = x.unsqueeze(0).unsqueeze(0)

y = pad(x)

x.shape # (1, 1, 100, 40)
y.shape # (1, 1, 103, 40)

print(conv(x.float()).shape)
print(conv(y.float()).shape)

# Output
# x -> (1, 1, 97, 40)
# y -> (1, 1, 100, 40)

As you can see, it does work in the sense that the size of dimensions is remaining the same. However, I've been wondering is there really no padding='same' option out there? Also, how do we know whether to apply the padding 2 to the top or to the bottom?

Thank you.


Edit

This is a little late, but in case anyone's curious how I solved this issue I basically manually added padding in order to emulate the padding=same option.

like image 773
Sean Avatar asked Oct 09 '19 14:10

Sean


People also ask

How do you get the same padding in PyTorch?

PyTorch does not support same padding the way Keras does, but still you can manage it easily using explicit padding before passing the tensor to convolution layer. Here, symmetric padding is not possible so by padding only one side, in your case, top bottom of tensor, we can achieve same padding.

What does padding =' same mean in keras?

SAME Padding: it applies padding to the input image so that the input image gets fully covered by the filter and specified stride.It is called SAME because, for stride 1 , the output will be the same as the input.

What is true about padding in convolution?

Padding is a term relevant to convolutional neural networks as it refers to the amount of pixels added to an image when it is being processed by the kernel of a CNN. For example, if the padding in a CNN is set to zero, then every pixel value that is added will be of value zero.

What is the difference between valid and same padding in a CNN?

To sum up, 'valid' padding means no padding. The output size of the convolutional layer shrinks depending on the input size & kernel size. On the contrary, 'same' padding means using padding.


2 Answers

I had the same issue some time ago, so I implemented it myself using a ZeroPad2d layer as you are trying to do. Here is the right formula:

from functools import reduce
from operator import __add__

kernel_sizes = (4, 1)

# Internal parameters used to reproduce Tensorflow "Same" padding.
# For some reasons, padding dimensions are reversed wrt kernel sizes,
# first comes width then height in the 2D case.
conv_padding = reduce(__add__, 
    [(k // 2 + (k - 2 * (k // 2)) - 1, k // 2) for k in kernel_sizes[::-1]])

pad = nn.ZeroPad2d(conv_padding)
conv = nn.Conv2d(1, 1, kernel_size=kernel_sizes)

print(x.shape) # (1, 1, 103, 40)
print(conv(y.float()).shape) # (1, 1, 103, 40)

Also, as mentioned by @akshayk07 and @Separius, I can confirm that it is the dynamic nature of pytorch that makes it hard. Here is a post about this point from a Pytorch developper.

like image 131
milembar Avatar answered Sep 17 '22 12:09

milembar


It looks like there is now, in pytorch 1.9.1, according to the docs.

padding='valid' is the same as no padding. padding='same' pads the input so the output has the shape as the input. However, this mode doesn't support any stride values other than 1.

like image 39
lucidbrot Avatar answered Sep 19 '22 12:09

lucidbrot