了解 keras Conv2DTranspose 的输出形状

Jul*_*ULD 7 layer shapes keras

我很难理解 keras.layers.Conv2DTranspose 的输出形状

这是原型:

keras.layers.Conv2DTranspose(
    filters,
    kernel_size,
    strides=(1, 1),
    padding='valid',
    output_padding=None,
    data_format=None,
    dilation_rate=(1, 1),
    activation=None,
    use_bias=True,
    kernel_initializer='glorot_uniform',
    bias_initializer='zeros',
    kernel_regularizer=None,
    bias_regularizer=None,
    activity_regularizer=None,
    kernel_constraint=None,
    bias_constraint=None
)
Run Code Online (Sandbox Code Playgroud)

在文档(https://keras.io/layers/convolutional/)中,我读到:

If output_padding is set to None (default), the output shape is inferred.
Run Code Online (Sandbox Code Playgroud)

在代码(https://github.com/keras-team/keras/blob/master/keras/layers/convolutional.py)中,我读到:

out_height = conv_utils.deconv_length(height,
                                      stride_h, kernel_h,
                                      self.padding,
                                      out_pad_h,
                                      self.dilation_rate[0])
out_width = conv_utils.deconv_length(width,
                                     stride_w, kernel_w,
                                     self.padding,
                                     out_pad_w,
                                     self.dilation_rate[1])
if self.data_format == 'channels_first':
    output_shape = (batch_size, self.filters, out_height, out_width)
else:
    output_shape = (batch_size, out_height, out_width, self.filters)
Run Code Online (Sandbox Code Playgroud)

和(https://github.com/keras-team/keras/blob/master/keras/utils/conv_utils.py):

def deconv_length(dim_size, stride_size, kernel_size, padding, output_padding, dilation=1):

    """Determines output length of a transposed convolution given input length.
    # Arguments
        dim_size: Integer, the input length.
        stride_size: Integer, the stride along the dimension of `dim_size`.
        kernel_size: Integer, the kernel size along the dimension of `dim_size`.
        padding: One of `"same"`, `"valid"`, `"full"`.
        output_padding: Integer, amount of padding along the output dimension, can be set to `None` in which case the output length is inferred.
        dilation: dilation rate, integer.
    # Returns
        The output length (integer).
    """

    assert padding in {'same', 'valid', 'full'}
    if dim_size is None:
        return None

    # Get the dilated kernel size
    kernel_size = kernel_size + (kernel_size - 1) * (dilation - 1)

    # Infer length if output padding is None, else compute the exact length
    if output_padding is None:
        if padding == 'valid':
            dim_size = dim_size * stride_size + max(kernel_size - stride_size, 0)
        elif padding == 'full':
            dim_size = dim_size * stride_size - (stride_size + kernel_size - 2)
        elif padding == 'same':
            dim_size = dim_size * stride_size
    else:
        if padding == 'same':
            pad = kernel_size // 2
        elif padding == 'valid':
            pad = 0
        elif padding == 'full':
            pad = kernel_size - 1

        dim_size = ((dim_size - 1) * stride_size + kernel_size - 2 * pad + output_padding)

    return dim_size
Run Code Online (Sandbox Code Playgroud)

我知道 Conv2DTranspose 是一种 Conv2D,但相反。

由于对 200x200 图像应用具有 kernel_size = (3, 3), strides = (10, 10) 和 padding = "same" 的 Conv2D 将输出 20x20 图像,因此我假设应用具有 kernel_size = (3, 3) 的 Conv2DTranspose , strides = (10, 10) 和 padding = "same" 到 20x20 图像将输出 200x200 图像。

此外,将具有 kernel_size = (3, 3)、strides = (10, 10) 和 padding = "same" 的 Conv2D 应用于 195x195 图像也将输出 20x20 图像。

因此,我知道在应用具有 kernel_size = (3, 3), strides = (10, 10) 和 padding = "same" 的 Conv2DTranspose 时,输出形状存在某种歧义(用户可能希望输出为 195x195,或 200x200,或许多其他兼容的形状)。

我假设“输出形状是推断出来的”。意味着根据层的参数计算默认输出形状,并且我假设有一种机制可以指定与默认输出形状不同的输​​出形状(如有必要)。

这个说的我不是很懂

  • “output_padding”参数的含义

  • 参数“padding”和“output_padding”之间的交互

  • 函数 keras.conv_utils.deconv_length 中的各种公式

有人可以解释一下吗?

非常感谢,

于连

Jul*_*ULD 4

我可能找到了(部分)答案。

我在 Pytorch 文档中找到了它,该文档似乎比关于此主题的 Keras 文档清晰得多。

当将步幅大于 1 的 Conv2D 应用到尺寸接近的图像时,我们得到具有相同尺寸的输出图像。

例如,当应用内核大小为 3x3、步幅为 7x7 且填充“相同”的 Conv2D 时,以下图像尺寸

22x22、23x23、...、28x28、22x28、28x22、27x24 等(7x7 = 49 种组合)

全部都会产生 4x4 的输出尺寸。

这是因为输出维度 = 上限(输入维度 / 步幅)。

因此,当应用内核大小为 3x3、步幅为 7x7 且填充“相同”的 Conv2DTranspose 时,输出维度存在模糊性。

49 个可能的输出维度中的任何一个都是正确的。

参数output_padding是一种通过显式选择输出维度来解决歧义的方法。

在我的示例中,最小输出大小为 22x22,output_padding 提供了要在输出图像底部添加的多行(0 到 6 之间)以及要在输出图像右侧添加的多列(0 到 6 之间)。输出图像。

所以如果我使用 outout_padding = (2, 3) 我可以获得 output_dimensions = 24x25

然而,我仍然不明白的是,当未指定output_padding时(当它“推断”输出形状时),keras用来选择某个输出图像尺寸的逻辑

几点提示:

https://pytorch.org/docs/stable/nn.html#torch.nn.ConvTranspose2d https://discuss.pytorch.org/t/the-output-size-of-convtranspose2d-differs-from-the-expected -output-size/1876/5 https://discuss.pytorch.org/t/question-about-the-output-padding-in-nn-convtrasnpose2d/19740 https://discuss.pytorch.org/t/what -输出填充-精确执行-in-convtranspose2d/2688

所以回答我自己的问题:

  • “output_padding”参数的含义:见上文
  • 参数“padding”和“output_padding”之间的相互作用:这些参数是独立的
  • 函数 keras.conv_utils.deconv_length 中的各种公式
    • 目前,我不明白当output_padding为None时的部分;
    • 我忽略 padding == 'full' 时的情况(Conv2DTranspose 不支持);
    • padding == 'valid' 的公式似乎是正确的(可以通过反转 Conv2D 的公式来计算)
    • 如果 kernel_size 是偶数,则 padding == 'same' 的公式对我来说似乎不正确。(事实上​​,当尝试使用 input_dimension = 5x5、kernel_size = 2x2、stride = 7x7 和 padding = 'same' 构建 Conv2DTranspose 层时,keras 崩溃了。在我看来,keras 中存在错误,我将开始该主题的另一个线程...)