了解keras Conv2DTranspose的输出形状

问题描述 投票:3回答:2

我很难理解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
)

在文档中(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,但是相反。

由于将Conv2D的kernel_size =(3,3),步幅=(10,10)和padding =“ same”应用于200x200的图像,将输出20x20的图像,我假设将Conv2DTranspose的kernel_size =(3,3),步幅=(10,10)和padding =“ same”应用于20x20图像将输出200x200图像。

此外,将Conv2D的kernel_size =(3,3),步幅=(10,10)和padding =“ same”应用于195x195图像还将输出20x20图像。

所以,我知道在应用带有kernel_size =(3,3),步幅=(10,10)和padding =“ same”的Conv2DTranspose时,输出形状上存在歧义(用户可能希望输出为195x195或200x200或许多其他兼容的形状)。

我假设“推断出输出形状”。表示根据图层的参数计算出默认的输出形状,并且我假设有一种机制可以根据需要指定与默认形状不同的输​​出形状。

这说,我不太了解

  • “ output_padding”参数的含义

  • 参数“ padding”和“ output_padding”之间的相互作用

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

有人可以解释一下吗?

非常感谢,

朱利安

keras layer shapes
2个回答
1
投票

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

我在Pytorch文档中找到了它,似乎比在这个主题上的Keras文档更清晰。

将步长大于1的Conv2D应用于尺寸接近的图像时,我们将获得尺寸相同的输出图像。

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

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

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

这是因为output_dimension =上限(input_dimension /步幅)。

因此,当应用内核大小为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.ConvTranspose2dhttps://discuss.pytorch.org/t/the-output-size-of-convtranspose2d-differs-from-the-expected-output-size/1876/5https://discuss.pytorch.org/t/question-about-the-output-padding-in-nn-convtrasnpose2d/19740https://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不支持);
    • 填充的公式=='有效'似乎正确(可以通过反转Conv2D的公式来计算)
    • 填充公式=='same'对我来说似乎是不正确的,以防kernel_size是偶数。 (事实上​​,当尝试使用input_dimension = 5x5,kernel_size = 2x2,stride = 7x7和padding ='same'构建Conv2DTranspose层时,keras崩溃。在我看来,keras中存在一个错误,我将开始此主题的另一个主题...)

0
投票

Conv2DTranspose中的Outpadding也是我在设计自动编码器时所关心的。

假定跨度始终为1。沿着编码器路径,对于每个卷积层,我选择padding ='valid',这意味着如果我的输入图像为HXW,并且滤镜的大小为mXn,则该层的输出将为(H-(m-1))X(W-(n-1))。

在解码器路径的相应Con2DTranspose层中,如果我使用Theano,为了恢复其相应Con2D的输入大小,我必须选择padding ='full',并且out_padding = None或0(无差异),这意味着输入大小将在其周围扩展[m-1,n-1],即(m-1)/ 2(顶部和底部)和(n-1)/ 2(左侧和右侧)。

如果使用张量流,我将不得不选择padding ='same',并且out_padding = 2 *((filter_size-1)// 2),我认为这是Keras的预期行为。

如果步幅不为1,则必须仔细计算要添加多少输出填充。

在Conv2D中,out_size = floor(in_size + 2 * padding_size-filter_size)/ stride + 1)

如果我们选择padding ='same',Keras将自动设置padding =(filter_size-1)/ 2;而如果我们选择“有效”,padding_size将设置为0,这是所有N-D卷积的约定。

相反,在Con2DTranspose中,out_size =(in_size-1)* stride + filter_size-2 * padding_size

其中padding_size指的是由'padding'选项和out_padding一起实际填充的像素数。基于上面的讨论,张量流上没有'full'选项,我们将不得不使用out_padding来恢复其对应的Con2D的输入大小。

您能不能试一下它是否正常工作,请让我知道?

因此,总的来说,我认为out_padding用于促进不同的后端。

© www.soinside.com 2019 - 2024. All rights reserved.