我很难理解 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,或许多其他兼容的形状)。
我假设“输出形状是推断出来的”。意味着根据层的参数计算默认输出形状,并且我假设有一种机制可以指定与默认输出形状不同的输出形状,如果需要的话。
说了这么多,不是很懂
有人可以解释一下吗?
非常感谢,
朱利安
最佳答案
我可能找到了(部分)答案。
我在 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
所以回答我自己的问题:
关于keras - 理解 keras Conv2DTranspose 的输出形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54751574/