了解PyTorch的Conv2DTranspose实现

yvt65v4c  于 2022-11-29  发布在  其他
关注(0)|答案(2)|浏览(181)

我试图理解一个使用PyTorch转置卷积函数的示例代码片段,文档为here,作者在文档中写道:
“padding参数有效地将零填充的dilation *(kernel_size - 1)- padding量添加到两个大小的输入中.”
考虑下面的代码片段,其中包含全1的形状[1, 1, 4, 4]的样本图像被输入到ConvTranspose2D操作,该操作具有参数stride=2padding=1,形状(1, 1, 4, 4)的权重矩阵具有来自116之间的范围的条目(在本例中为dilation=1added_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也是非常有帮助的。

kmbjn2e3

kmbjn2e31#

nn.ConvTranspose2d的输出空间维度由下式给出:

out = (x - 1)s - 2p + d(k - 1) + op + 1

其中,x是 * 输入 * 空间维度,out是对应的 * 输出 * 大小,s是跨距,d是膨胀,p是填充,k是内核大小,以及op是输出填充。
如果我们保留下面的操作数:

对于输入的每个值,我们通过计算与内核的每个元素的乘积来计算(相应颜色的)缓冲区。
以下是s=1, p=0s=1, p=1s=2, p=0s=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指令集

4ngedf3f

4ngedf3f2#

我相信让事情变得混乱的是,他们不是很小心他们在文档中所说的"输入"或"输出"是什么意思,以及术语"步幅"和"填充"的重载。
我发现通过问自己,更容易理解PyTorch中的转置卷积:我应该给一个正常的,正向卷积层什么样的参数,这样它就可以给我手头上的Tensor,我把它馈入到转置的卷积层中?
例如,"stride"应理解为forwardconv中的"stride",即滑动核的移动步长。
在转置的conv中,"stride"实际上有不同的含义:stride-1是进入转置conv层的输入单元之间的交错空槽数。这是因为在forwardconv中产生这种空洞的是大于1的"步幅"。请参见下图的说明:

该图还显示了转置conv层中的内核移动步长始终为1,而与"stride"的值无关。我发现记住这一点非常重要。
类似于padding参数。它应该被理解为应用于
forward
conv的0填充。因为这个填充,我们在forwardconv的输出中得到了一些额外的单元。所以,如果我们把这个输出送入一个转置的conv,为了回到原始的,非填充的长度,这些额外的东西应该被删除。因此是等式中的-2p项。
如需图解,请参阅下图。
总之,在Tensor形状变换的意义上,它们被设计成正规conv和转置conv是彼此的"逆"运算。(但我确实认为doc应该得到改进。)
记住这个原则,我们也可以相对容易地计算出dilationoutput_padding参数。我已经写了一个关于这个的blog,如果有人感兴趣的话。

相关问题