keras - 理解 keras Conv2DTranspose 的输出形状

标签 keras layer shapes

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

这是原型(prototype):

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
)

在文档( https://keras.io/layers/convolutional/ )中,我读到:
If output_padding is set to None (default), the output shape is inferred.

在代码( 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)

和(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

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

由于将 kernel_size = (3, 3)、strides = (10, 10) 和 padding = "same"的 Conv2D 应用到 200x200 图像将输出 20x20 图像,
我假设将带有 kernel_size = (3, 3)、strides = (10, 10) 和 padding = "same"的 Conv2DTranspose 应用于 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
  • 函数中的各种公式

    有人可以解释一下吗?

    非常感谢,

    朱利安

    最佳答案

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

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

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

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

    22x22, 23x23, ..., 28x28, 22x28, 28x22, 27x24, etc. (7x7 = 49 combinations)



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

    那是因为 output_dimension = 上限(input_dimension/stride)。

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

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

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

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

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

    但是,我仍然不明白的是,当未指定 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-does-output-padding-exactly-do-in-convtranspose2d/2688

    所以回答我自己的问题:
  • “output_padding”参数的含义:见上文
  • 参数“padding”和“output_padding”之间的交互:这些参数是独立的
  • keras.conv_utils.deconv_length 函数中的各种公式
  • 目前,我不明白 output_padding 为 None 的部分;
  • 我忽略了 padding == 'full' 时的情况(Conv2DTranspose 不支持);
  • padding == 'valid' 的公式似乎是正确的(可以通过反转 Conv2D 的公式来计算)
  • 填充 == 'same' 的公式对我来说似乎不正确,以防 kernel_size 是偶数。 (事实上​​,keras 在尝试使用 input_dimension = 5x5、kernel_size = 2x2、stride = 7x7 和 padding = 'same' 构建 Conv2DTranspose 层时崩溃。在我看来,keras 中存在错误,我将开始此主题的另一个线程...)
  • 关于keras - 理解 keras Conv2DTranspose 的输出形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54751574/

    相关文章:

    r - 更改堆叠 ggplot 图例中的几何顺序

    jquery - 使用显示 :block 悬停在链接上时无法显示/隐藏 div

    ios - 在 iOS 中从 PNG 图像中提取形状轮廓点

    python - 为什么 GAN 无法从某些分布中生成样本?

    tensorflow - 如何在 tensorflow 数据集上使用样本权重?

    android - 如何完全覆盖 9-PATCH-PNG?

    javascript - 在谷歌地图 v3 中绘制可拖动形状

    python - Tensorflow in_top_kv

    python - 将 CNN 更改为 LSTM keras tensorflow

    python - Keras:UnboundLocalError:分配前引用了局部变量 'logs'