我目前正在构建一个可用于时间序列数据的卷积神经网络(CNN)。
更具体地说,数据是形状为(100, 40)
的财务数据,其中100
表示100个时间戳,40
表示40个特征。
我正在使用的CNN使用不对称的内核大小(即1 x 2
和4 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应用于顶部还是底部?
谢谢。
答案 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 以外的任何步幅值。