【问题标题】:TensorFlow vs PyTorch convolution confusionTensorFlow vs PyTorch 卷积混淆
【发布时间】:2021-01-13 19:24:05
【问题描述】:

我对如何在 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)

但是,在 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])

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

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

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

【问题讨论】:

    标签: python tensorflow keras deep-learning pytorch


    【解决方案1】:

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

    对于torch.nn.Conv1d

    • in_channels 是输入张量中的通道数
    • out_channels 是过滤器的数量,输出将具有的通道数
    • stride卷积的步长
    • padding 两边加零

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


    在您的示例中,由于 x 的形状为 (256, 237, 1, 21),在 TensorFlow 的术语中,它将被视为输入:

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

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

    • (256, 237)的批处理形状,
    • 1输入通道
    • 21 的长度。

    在以下两个示例(TensorFlow vs. 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])
    

    在 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])
    

    因此,在后者中,您只需使用 x = torch.randn(256, 21, 237)...

    【讨论】:

      【解决方案2】:

      PyTorch 现在具有开箱即用的相同卷积操作,您可以查看此链接 [Same convolution][1]

      class InceptionNet(nn.Module):
          def __init__(self, in_channels, in_1x1, in_3x3reduce, in_3x3, in_5x5reduce, in_5x5, in_1x1pool):
              super(InceptionNet, self).__init__()
              self.incep_1 = ConvBlock(in_channels, in_1x1, kernel_size=1, padding='same')
      

      请注意,相同的卷积仅支持默认步幅值,即 1 任何其他都不起作用。 [1]:https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html

      【讨论】:

        猜你喜欢
        • 2019-02-15
        • 2015-09-29
        • 2019-08-18
        • 2020-09-19
        • 2020-11-04
        • 2021-04-13
        • 1970-01-01
        • 2021-11-09
        • 2020-02-23
        相关资源
        最近更新 更多