我想知道为什么conv1d工作在2d功能(批处理,通道,高度,宽度)。nn.Conv1d(channel,channel,kernel_size=(1,1))在我放置2D特征时工作,但给出的结果与nn.Conv2d(channel,channel,kernel_size=1)不同。我想知道conv1d为什么工作,以及在一维卷积中二维内核大小意味着什么。
8yparm6h1#
它没有任何理由不起作用。在引擎盖下,所有这些“卷积”意味着“点积”,现在它可以是矩阵和向量之间,矩阵和矩阵之间,向量和向量之间,等等。简单地说,1D和2D卷积之间的真实的区别是人们可以沿着输入的空间维度移动。这意味着如果你看1D卷积**,它只能沿着一个方向移动,也就是说,输入的时间维(注意,内核可以是向量,矩阵,不管是什么)。另一方面,2D卷积可以自由地沿着输入的2维(高度和宽度)移动,也就是空间维。如果它仍然看起来令人困惑,请看下面的gif。
3x3
我想现在很清楚1D和2D conv之间的实际区别是什么,以及为什么它们对相同的输入会产生不同的结果。
gkn4icbw2#
目前公认的答案是不正确的,所以我写这一个。在提问者给出的例子中,两个卷积是相同的,直到参数的随机初始化。这是因为两者都使用相同的底层实现,只是传递不同的参数,如内核大小。nn.Conv1d、nn.Conv2d和nn.Conv3d对它们的输入的解释不同。例如,对于nn.Conv2d,kernel_size=3将变成(3,3),但是对于nn.Conv1d,(3,)将变成nn.Conv1d。但是,您可以强制这些参数为正确的形状。请注意,在下面的一些示例中,需要指定跨距和扩张:
nn.Conv1d
nn.Conv2d
nn.Conv3d
kernel_size=3
(3,3)
(3,)
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在问题的注解中指出的那样。
2条答案
按热度按时间8yparm6h1#
它没有任何理由不起作用。在引擎盖下,所有这些“卷积”意味着“点积”,现在它可以是矩阵和向量之间,矩阵和矩阵之间,向量和向量之间,等等。简单地说,1D和2D卷积之间的真实的区别是人们可以沿着输入的空间维度移动。这意味着如果你看1D卷积**,它只能沿着一个方向移动,也就是说,输入的时间维(注意,内核可以是向量,矩阵,不管是什么)。另一方面,2D卷积可以自由地沿着输入的2维(高度和宽度)移动,也就是空间维。如果它仍然看起来令人困惑,请看下面的gif。
1D卷积的实际应用:
3x3
,请看它如何仅向下移动输入,即时间维。*2D卷积的作用:
3x3
,请看它如何沿着输入的宽度和高度移动,这是空间维度。*我想现在很清楚1D和2D conv之间的实际区别是什么,以及为什么它们对相同的输入会产生不同的结果。
gkn4icbw2#
目前公认的答案是不正确的,所以我写这一个。
在提问者给出的例子中,两个卷积是相同的,直到参数的随机初始化。这是因为两者都使用相同的底层实现,只是传递不同的参数,如内核大小。
nn.Conv1d
、nn.Conv2d
和nn.Conv3d
对它们的输入的解释不同。例如,对于nn.Conv2d
,kernel_size=3
将变成(3,3)
,但是对于nn.Conv1d
,(3,)
将变成nn.Conv1d
。但是,您可以强制这些参数为正确的形状。请注意,在下面的一些示例中,需要指定跨距和扩张:
如果nn.Conv1d只能“仅沿一个方向移动”(如当前接受的答案中所述),则此等式将不起作用,因为两个空间维度都比内核大小大得多。如果nn.Conv1d被锁定为仅沿一个方向移动,则它不可能生成完整的100 x100输出。
您可以在https://discuss.pytorch.org/t/conv1d-kernel-size-explained/84323/4中阅读更多内容,正如@trialNerror在问题的注解中指出的那样。