pytorch 为什么nn.Conv1d对2D特征[B,c,h,w]起作用?

crcmnpdw  于 2022-11-09  发布在  其他
关注(0)|答案(2)|浏览(162)

我想知道为什么conv1d工作在2d功能(批处理,通道,高度,宽度)。
nn.Conv1d(channel,channel,kernel_size=(1,1))在我放置2D特征时工作,但给出的结果与nn.Conv2d(channel,channel,kernel_size=1)不同。
我想知道conv1d为什么工作,以及在一维卷积中二维内核大小意味着什么。

8yparm6h

8yparm6h1#

  • “我想知道conv1d工作原理以及一维卷积中的二维内核大小的含义”*

它没有任何理由不起作用。在引擎盖下,所有这些“卷积”意味着“点积”,现在它可以是矩阵和向量之间,矩阵和矩阵之间,向量和向量之间,等等。简单地说,1D和2D卷积之间的真实的区别是人们可以沿着输入的空间维度移动。这意味着如果你看1D卷积**,它只能沿着一个方向移动,也就是说,输入的时间维(注意,内核可以是向量,矩阵,不管是什么)。另一方面,2D卷积可以自由地沿着输入的2维(高度和宽度)移动,也就是空间维。如果它仍然看起来令人困惑,请看下面的gif。

1D卷积的实际应用:

  • 注意:这是一个1D卷积,内核大小为3x3,请看它如何仅向下移动输入,即时间维。*

2D卷积的作用:

  • 注意:这是一个2D卷积,核大小为3x3,请看它如何沿着输入的宽度和高度移动,这是空间维度。*

我想现在很清楚1D和2D conv之间的实际区别是什么,以及为什么它们对相同的输入会产生不同的结果。

gkn4icbw

gkn4icbw2#

目前公认的答案是不正确的,所以我写这一个。
在提问者给出的例子中,两个卷积是相同的,直到参数的随机初始化。这是因为两者都使用相同的底层实现,只是传递不同的参数,如内核大小。nn.Conv1dnn.Conv2dnn.Conv3d对它们的输入的解释不同。例如,对于nn.Conv2dkernel_size=3将变成(3,3),但是对于nn.Conv1d(3,)将变成nn.Conv1d
但是,您可以强制这些参数为正确的形状。请注意,在下面的一些示例中,需要指定跨距和扩张:

import torch
from torch import nn

conv1d = nn.Conv1d(1, 1, 3, padding='same', bias=False)
conv2d = nn.Conv2d(1, 1, (3,), stride=(1,), dilation=(1,), padding='same', bias=False)
conv3d = nn.Conv3d(1, 1, (3,), stride=(1,), dilation=(1,), padding='same', bias=False)
conv1d.weight.data.fill_(1)
conv2d.weight.data.fill_(1)
conv3d.weight.data.fill_(1)
x = torch.rand(1, 1, 100)
assert (conv1d(x) == conv2d(x)).all() and (conv1d(x) == conv3d(x)).all()

conv1d = nn.Conv1d(1, 1, (3,3), padding='same', bias=False)
conv2d = nn.Conv2d(1, 1, 3, padding='same', bias=False)
conv3d = nn.Conv3d(1, 1, (3,3), stride=(1,1), dilation=(1,1), padding='same', bias=False)
conv1d.weight.data.fill_(1)
conv2d.weight.data.fill_(1)
conv3d.weight.data.fill_(1)
x = torch.rand(1, 1, 100, 100)
assert (conv1d(x) == conv2d(x)).all() and (conv1d(x) == conv3d(x)).all()

conv1d = nn.Conv1d(1, 1, (3,3,3), stride=(1,1,1), dilation=(1,1,1), padding='same', bias=False)
conv2d = nn.Conv2d(1, 1, (3,3,3), stride=(1,1,1), dilation=(1,1,1), padding='same', bias=False)
conv3d = nn.Conv3d(1, 1, 3, padding='same', bias=False)
conv1d.weight.data.fill_(1)
conv2d.weight.data.fill_(1)
conv3d.weight.data.fill_(1)
x = torch.rand(1, 1, 100, 100, 100)
assert (conv1d(x) == conv2d(x)).all() and (conv1d(x) == conv3d(x)).all()

如果nn.Conv1d只能“仅沿一个方向移动”(如当前接受的答案中所述),则此等式将不起作用,因为两个空间维度都比内核大小大得多。如果nn.Conv1d被锁定为仅沿一个方向移动,则它不可能生成完整的100 x100输出。
您可以在https://discuss.pytorch.org/t/conv1d-kernel-size-explained/84323/4中阅读更多内容,正如@trialNerror在问题的注解中指出的那样。

相关问题