PyTorch的Conv2d真的没有padding = same选项吗?

时间:2019-10-09 14:59:44

标签: pytorch

我目前正在构建一个可用于时间序列数据的卷积神经网络(CNN)。

更具体地说,数据是形状为(100, 40)的财务数据,其中100表示100个时间戳,40表示40个特征。

我正在使用的CNN使用不对称的内核大小(即1 x 24 x 1)以及不对称的步幅(例如1 x 2用于1 x 2层和{{ 1}}(用于1 x 1层)。

为了保持高度尺寸保持4 x 1,我需要对数据应用一些填充。我正在研究这样做的方法,并注意到使用TensorFlow或Keras的人只是做100,但根据我发现的包括this thread on Github在内的许多资源,PyTorch中显然没有此选项。

我发现根据some answers in this question以及this answer on the PyTorch discussion forum,我可以手动计算填充数据的方式,并可以使用torch.nn.ZeroPad2d解决我的问题,例如似乎正常的torch.nn.Conv2d图层不支持不对称填充(我认为我需要的填充总高度为3,宽度为0)。

我编写的用于对此进行测试的实验代码如下:

padding='same'

如您所见,它确实在尺寸尺寸保持不变的意义上起作用。但是,我一直想知道那里真的没有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) 选项吗?另外,我们如何知道是将填充2应用于顶部还是底部?

谢谢。

2 个答案:

答案 0 :(得分:4)

前段时间我遇到了同样的问题,所以我自己尝试使用ZeroPad2d层来实现它。这是正确的公式:

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)

此外,正如@ akshayk07和@Separius所提到的,我可以确认pytorch的动态特性使它变得困难。 Here是Pytorch开发人员关于这一点的帖子。

答案 1 :(得分:2)

看起来现在在 pytorch 1.9.1 中,根据 docs

<块引用>

padding='valid' 与无填充相同。 padding='same' 垫 输入因此输出具有作为输入的形状。不过这种模式 不支持除 1 以外的任何步幅值。