理解Conv2DTranspose的PyTorch实现

9
我试图理解一个例子片段,其中使用了PyTorch的转置卷积函数,并且文档在此处链接。在文档中作者写道:“填充参数有效地向输入的两侧添加了 dilation * (kernel_size - 1) - padding 量的零填充。”考虑下面的代码片段,其中输入一个形状为[1, 1, 4, 4]的样本图像(包含所有元素都为一),并使用参数stride=2padding=1ConvTranspose2D操作,其权重矩阵的形状为(1, 1, 4, 4),其中的元素值在116范围内(在这种情况下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)的结果张量可以看作是下面图片中四个彩色矩阵之和:

enter image description here

问题在于,我似乎找不到使用相同可视化方式来处理步幅和/或填充的示例。按照我的代码片段,我非常难以理解如何将填充应用于样本图像,或者步幅如何起作用以获得此输出。任何见解都将受到赞赏,即使只了解如何计算结果矩阵中(0,0)条目中的6(0,1)条目中的12也将非常有帮助。

2个回答

9
nn.ConvTranspose2d 的输出空间维度由以下公式给出:
out = (x - 1)s - 2p + d(k - 1) + op + 1

其中x是输入的空间维度,out是相应的输出大小,s是步长,d是扩张率,p是填充,k是卷积核大小,op是输出填充。


如果我们保留以下操作数:

enter image description here

对于输入的每个值,我们通过将其与卷积核的每个元素计算乘积来计算相应颜色的缓冲区。

这里是s=1, p=0, s=1, p=1, s=2, p=0, 和 s=2, p=1 的可视化结果:

  • s=1, p=0: 输出为3x3

enter image description here

对于蓝色缓冲区,我们有(1) 2*k_top-left = 2*3 = 6;(2) 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

enter image description here

  • s=2, p=0: 输出为4x4

enter image description here

  • s=2, p=2: 输出为2x2

enter image description here


好的!我认为我的困惑关键在于$p$参数的作用,如果我理解正确的话,当$p=1$时,就好像从四个相加的矩阵的每一侧都删除了一列和一行?几乎像是一种“反”填充。非常感谢你出色的答案,我希望这对未来的某些人有用。 - IntegrateThis
在最后一个例子中,应该是s=2,p=1吗? - Gilad

4

我认为让事情变得混乱的原因是他们在文档中对“输入”或“输出”的含义不够谨慎,并且术语“步幅”和“填充”的重载。

我发现通过问自己以下问题,更容易理解PyTorch中的转置卷积:我会给一个正常的前向卷积层什么参数,使得它能够给出手头的张量,我正在将其馈送到转置卷积层中?

例如,“步幅”应该被理解为正向卷积中的“步幅”,即滑动内核的移动步骤。

在转置卷积中,“步幅”实际上意味着不同的东西:stride-1是输入单元之间交错的空槽的数量,这些单元进入了转置卷积层。这是因为在正向卷积中大于1的“步幅”会创建这样的空洞。请参见下面的图像以获得说明:

enter image description here

这段话讲述了在转置卷积层中,核移动步长始终为1,与"步幅"参数的值无关;对于“填充”参数,应理解为应用于正向卷积的0填充。由于这种填充,正向卷积的输出会比输入多一些单位。因此,如果将此输出馈送到转置卷积中,为了恢复到原始的非填充长度,那些额外的内容应该被去除,因此方程中有"-2p"项。这个原则意味着正常的卷积和转置卷积是相互“反演”的操作,就张量形状变换而言。(但我确实认为文档应该得到改进)。根据这个原则,可以相对容易地计算出“扩张”和“输出填充”参数。我写了一个关于这个问题的博客,如果有人感兴趣的话。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接