我试图理解一个使用PyTorch转置卷积函数的示例代码片段,文档为here,作者在文档中写道:
“padding参数有效地将零填充的dilation *(kernel_size - 1)- padding量添加到两个大小的输入中.”
考虑下面的代码片段,其中包含全1的形状[1, 1, 4, 4]
的样本图像被输入到ConvTranspose2D
操作,该操作具有参数stride=2
和padding=1
,形状(1, 1, 4, 4)
的权重矩阵具有来自1
和16
之间的范围的条目(在本例中为dilation=1
和added_padding = 1*(4-1)-1 = 2
)
sample_im = torch.ones(1, 1, 4, 4).cuda()
sample_deconv = nn.ConvTranspose2d(1, 1, 4, 2, 1, bias=False).cuda()
sample_deconv.weight = torch.nn.Parameter(
torch.tensor([[[[ 1., 2., 3., 4.],
[ 5., 6., 7., 8.],
[ 9., 10., 11., 12.],
[13., 14., 15., 16.]]]]).cuda())
得到:
>>> sample_deconv(sample_im)
tensor([[[[ 6., 12., 14., 12., 14., 12., 14., 7.],
[12., 24., 28., 24., 28., 24., 28., 14.],
[20., 40., 44., 40., 44., 40., 44., 22.],
[12., 24., 28., 24., 28., 24., 28., 14.],
[20., 40., 44., 40., 44., 40., 44., 22.],
[12., 24., 28., 24., 28., 24., 28., 14.],
[20., 40., 44., 40., 44., 40., 44., 22.],
[10., 20., 22., 20., 22., 20., 22., 11.]]]], device='cuda:0',
grad_fn=<CudnnConvolutionTransposeBackward>)
现在,我已经看到了没有步长和填充的转置卷积的简单例子。例如,如果输入是2x2
图像[[2, 4], [0, 1]]
,并且具有一个输出通道的卷积滤波器是[[3, 1], [1, 5]]
,那么得到的(1, 1, 3, 3)
形状的Tensor可以看作是下图中的四个彩色矩阵之和:
问题是,我似乎找不到在同一个可视化中使用stride和/或padding的示例。根据我的代码片段,我很难理解padding是如何应用于示例图像的,或者stride是如何工作以获得此输出的。任何见解都很感谢,即使仅仅理解如何计算结果矩阵的x1M14 N1 x项中的x1M13 N1 x或x1M16 N1 x项中的x1M15 N1 x也是非常有帮助的。
2条答案
按热度按时间kmbjn2e31#
nn.ConvTranspose2d
的输出空间维度由下式给出:其中,
x
是 * 输入 * 空间维度,out
是对应的 * 输出 * 大小,s
是跨距,d
是膨胀,p
是填充,k
是内核大小,以及op
是输出填充。如果我们保留下面的操作数:
对于输入的每个值,我们通过计算与内核的每个元素的乘积来计算(相应颜色的)缓冲区。
以下是
s=1, p=0
、s=1, p=1
、s=2, p=0
和s=2, p=1
的可视化效果:s=1, p=0
:输出为3x3
对于蓝色缓冲器,我们有(1)
2*k_top-left = 2*3 = 6
; ②2*k_top-right = 2*1 = 2
;(3)2*k_bottom-left = 2*1 = 2
;(4)2*k_bottom-right = 2*5 = 10
。s=1, p=1
:输出为1x1
s=2, p=0
:输出为4x4
s=2, p=2
:输出为2x2
x1c4d 1x指令集
4ngedf3f2#
我相信让事情变得混乱的是,他们不是很小心他们在文档中所说的"输入"或"输出"是什么意思,以及术语"步幅"和"填充"的重载。
我发现通过问自己,更容易理解PyTorch中的转置卷积:我应该给一个正常的,正向卷积层什么样的参数,这样它就可以给我手头上的Tensor,我把它馈入到转置的卷积层中?
例如,"stride"应理解为forwardconv中的"stride",即滑动核的移动步长。
在转置的conv中,"stride"实际上有不同的含义:
stride-1
是进入转置conv层的输入单元之间的交错空槽数。这是因为在forwardconv中产生这种空洞的是大于1的"步幅"。请参见下图的说明:该图还显示了转置conv层中的内核移动步长始终为1,而与"stride"的值无关。我发现记住这一点非常重要。
类似于
padding
参数。它应该被理解为应用于forwardconv的0填充。因为这个填充,我们在forwardconv的输出中得到了一些额外的单元。所以,如果我们把这个输出送入一个转置的conv,为了回到原始的,非填充的长度,这些额外的东西应该被删除。因此是等式中的-2p
项。如需图解,请参阅下图。
总之,在Tensor形状变换的意义上,它们被设计成正规conv和转置conv是彼此的"逆"运算。(但我确实认为doc应该得到改进。)
记住这个原则,我们也可以相对容易地计算出
dilation
和output_padding
参数。我已经写了一个关于这个的blog,如果有人感兴趣的话。