TensorFlow 与 PyTorch 卷积混淆

awe*_*zmm 2 python deep-learning keras tensorflow pytorch

我对如何在 PyTorch 中复制 Keras (TensorFlow) 卷积感到困惑。

在 Keras 中,我可以做这样的事情。(输入大小为(256, 237, 1, 21),输出大小为(256, 237, 1, 1024).

import tensorflow as tf
x = tf.random.normal((256,237,1,21))
y = tf.keras.layers.Conv1D(filters=1024, kernel_size=5,padding="same")(x)
print(y.shape) 
(256, 237, 1, 1024)
Run Code Online (Sandbox Code Playgroud)

然而,在 PyTorch 中,当我尝试做同样的事情时,我得到了不同的输出大小:

import torch.nn as nn
x = torch.randn(256,237,1,21)
m = nn.Conv1d(in_channels=237, out_channels=1024, kernel_size=(1,5))
y = m(x)
print(y.shape)
torch.Size([256, 1024, 1, 17])
Run Code Online (Sandbox Code Playgroud)

我希望 PyTorch 提供与 Keras 相同的输出大小:

上一个问题似乎暗示 Keras 过滤器是 PyTorch 的out_channels,但这就是我所拥有的。我尝试在 PyTorch 中添加填充padding=(0,503),但这给了我torch.Size([256, 1024, 1, 1023]),但仍然不正确。这也比 keras 花费的时间长得多,所以我觉得我错误地分配了一个参数。

如何在 PyTorch 中复制 Keras 对卷积所做的操作?

Iva*_*van 7

在 TensorFlow 中,tf.keras.layers.Conv1D接受形状为 的张量(batch_shape + (steps, input_dim))。这意味着通常所说的通道出现在最后一个轴上。例如,在 2D 卷积中,您将拥有(batch, height, width, channels). 这与 PyTorch 不同,PyTorch的通道维度位于批处理轴之后:torch.nn.Conv1d采用 的形状(batch, channel, length)。所以你需要排列两个轴。

为了torch.nn.Conv1d

  • in_channels是输入张量中的通道数
  • out_channels是滤波器的数量,输出的通道数
  • stride卷积的步长
  • padding添加到两侧的零填充

在 PyTorch 中没有 的选项padding='same',您需要padding正确选择。这里stride=1,sopadding必须等于kernel_size//2 padding=2)才能保持张量的长度。


在您的示例中,由于x的形状为(256, 237, 1, 21),因此在 TensorFlow 的术语中,它将被视为具有以下内容的输入:

  • 批量形状(256, 237),
  • steps=1,所以一维输入的长度是1
  • 21输入通道。

而在 PyTorch 中,x形状(256, 237, 1, 21)为:

  • 批次形状(256, 237),
  • 1输入通道
  • 长度为21.

在下面的两个示例(TensorFlow与PyTorch)中保留输入,x.shape=(256, 237, 21)假设256是批量大小,237是输入序列的长度,21 是通道数(输入维度,我所看到的每个维度的维度)时间步长)。

在 TensorFlow 中:

>>> x = tf.random.normal((256, 237, 21))
>>> m = tf.keras.layers.Conv1D(filters=1024, kernel_size=5, padding="same")
>>> y = m(x)
>>> y.shape
TensorShape([256, 237, 1024])
Run Code Online (Sandbox Code Playgroud)

在 PyTorch 中:

>>> x = torch.randn(256, 237, 21)
>>> m = nn.Conv1d(in_channels=21, out_channels=1024, kernel_size=5, padding=2)
>>> y = m(x.permute(0, 2, 1))
>>> y.permute(0, 2, 1).shape
torch.Size([256, 237, 1024])
Run Code Online (Sandbox Code Playgroud)

所以在后者中,你只需与x = torch.randn(256, 21, 237)......