The current accepted answer is incorrect, so I write this one.
In the example the asker gives, the two convolutions are the same, up to random initialization of parameters.
This is because both use the same underlying implementation, and just pass different parameters such as kernel size. nn.Conv1d
, nn.Conv2d
and nn.Conv3d
interpret their input differently, e.g. kernel_size=3
will become (3,3)
for nn.Conv2d
but (3,)
for nn.Conv1d
.
However, you can force these parameters to be the correct shape.
Note that stride and dilation need to be specified in some of the instances below:
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()
This equality would not work if, as is stated in the currently accepted answer, nn.Conv1d could only "move along one direction only", as both spatial dimensions are much larger than the kernel size. nn.Conv1d could not have generated the full 100x100 output if it were locked to move only in one direction.
You can read more in https://discuss.pytorch.org/t/conv1d-kernel-size-explained/84323/4, as pointed out by @trialNerror in a comment to the question.