我对如何在PyTorch中复制Keras(TensorFlow(卷积感到困惑。
在喀拉拉邦,我可以做这样的事情。(输入大小为(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相同的输出大小:
这个前面的问题似乎暗示Keras过滤器是PyTorch的out_channels
,但这就是我所拥有的。我试图在padding=(0,503)
的PyTorch中添加填充,但这给了我torch.Size([256, 1024, 1, 1023])
,但仍然不正确。这也比keras花费的时间长得多,所以我觉得我错误地分配了一个参数。
如何复制Keras在PyTorch中使用卷积所做的操作?
在张量流中,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
,所以padding
必须等于kernel_size//2
(,即padding=2
(,以保持张量的长度。
在您的示例中,由于x
的形状为(256, 237, 1, 21)
,因此在TensorFlow的术语中,它将被视为具有的输入
- 一批CCD_ 24
steps=1
,所以1D输入的长度是1
21
输入通道
而在PyTorch中,(256, 237, 1, 21)
形状的x
将是:
- CCD_ 30的批量形状
1
输入通道- 长度为CCD_ 32
在下面的两个例子中(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])
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)
。。。
PyTorch现在有开箱即用的相同卷积操作,你可以看看这个链接〔相同卷积〕〔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