Conv2D 使用公式转置输出形状
Conv2D transpose output shape using formula
我使用如下所示的转置层得到 [-1,256,256,3]
作为输出形状。我打印输出形状。我的问题具体是关于高度和宽度都是 256
。通道似乎是我代码中最后一个转置层的过滤器数量。
我很简单地假设公式是这样的。我阅读了其他主题。
H = (H1 - 1)*stride + HF - 2*padding
但是当我计算时,我似乎没有得到那个输出。我想我可能错过了填充计算
'SAME'
添加了多少填充?
我的代码是这样的。
linear = tf.layers.dense(z, 512 * 8 * 8)
linear = tf.contrib.layers.batch_norm(linear, is_training=is_training,decay=0.88)
conv = tf.reshape(linear, (-1, 128, 128, 1))
out = tf.layers.conv2d_transpose(conv, 64,kernel_size=4,strides=2, padding='SAME')
out = tf.layers.dropout(out, keep_prob)
out = tf.contrib.layers.batch_norm(out, is_training=is_training,decay=0.88)
out = tf.nn.leaky_relu(out)
out = tf.layers.conv2d_transpose(out, 128,kernel_size=4,strides=1, padding='SAME')
out = tf.layers.dropout(out, keep_prob)
out = tf.contrib.layers.batch_norm(out, is_training=is_training,decay=0.88)
out = tf.layers.conv2d_transpose(out, 3,kernel_size=4,strides=1, padding='SAME')
print( out.get_shape())
关于 'SAME'
填充,Convolution
documentation offers some detailed explanations (further details in those notes)。特别是,当使用 'SAME'
填充时,输出形状定义为:
# for `tf.layers.conv2d` with `SAME` padding:
out_height = ceil(float(in_height) / float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
在这种情况下,输出形状仅取决于输入形状和步幅。从那里计算填充大小以满足此形状要求(而使用 'VALID'
填充时,输出形状取决于填充大小)
现在对于转置卷积...由于此操作是普通卷积(其梯度)的反向对应物,这意味着普通卷积的输出形状对应于其对应转置操作的输入形状。换句话说,虽然 tf.layers.conv2d()
的输出形状除以步幅,但输出形状
tf.layers.conv2d_transpose()
乘以它:
# for `tf.layers.conv2d_transpose()` with `SAME` padding:
out_height = in_height * strides[1]
out_width = in_width * strides[2]
但再次计算填充大小以获得此输出形状,而不是相反(对于 SAME
填充)。由于这些值之间的正常关系(即您找到的关系)是:
# for `tf.layers.conv2d_transpose()` with given padding:
out_height = strides[1] * (in_height - 1) + kernel_size[0] - 2 * padding_height
out_width = strides[2] * (in_width - 1) + kernel_size[1] - 2 * padding_width
重新排列我们得到的方程
padding_height = [strides[1] * (in_height - 1) + kernel_size[0] - out_height] / 2
padding_width = [[strides[2] * (in_width - 1) + kernel_size[1] - out_width] / 2
note: if e.g. 2 * padding_height
is an odd number, then padding_height_top = floor(padding_height)
; and padding_height_bottom = ceil(padding_height)
(same for resp. padding_width
, padding_width_left
and padding_width_right)
用它们的表达式替换 out_height
和 out_width
,并使用您的值(对于第一个转置卷积):
padding = [2 * (128 - 1) + 4 - (128 * 2)] / 2 = 1
因此,您在数据的每一侧都添加了 1
的填充,以获得输出 dim out_dim = in_dim * stride = strides * (in_dim - 1) + kernel_size - 2 * padding = 256
我根据@Aldream的回答给自己画了一张图。可视化可能有用。希望我做对了。但我必须研究如何以及在何处应用此填充以获得最终形状。
我使用如下所示的转置层得到 [-1,256,256,3]
作为输出形状。我打印输出形状。我的问题具体是关于高度和宽度都是 256
。通道似乎是我代码中最后一个转置层的过滤器数量。
我很简单地假设公式是这样的。我阅读了其他主题。
H = (H1 - 1)*stride + HF - 2*padding
但是当我计算时,我似乎没有得到那个输出。我想我可能错过了填充计算
'SAME'
添加了多少填充?
我的代码是这样的。
linear = tf.layers.dense(z, 512 * 8 * 8)
linear = tf.contrib.layers.batch_norm(linear, is_training=is_training,decay=0.88)
conv = tf.reshape(linear, (-1, 128, 128, 1))
out = tf.layers.conv2d_transpose(conv, 64,kernel_size=4,strides=2, padding='SAME')
out = tf.layers.dropout(out, keep_prob)
out = tf.contrib.layers.batch_norm(out, is_training=is_training,decay=0.88)
out = tf.nn.leaky_relu(out)
out = tf.layers.conv2d_transpose(out, 128,kernel_size=4,strides=1, padding='SAME')
out = tf.layers.dropout(out, keep_prob)
out = tf.contrib.layers.batch_norm(out, is_training=is_training,decay=0.88)
out = tf.layers.conv2d_transpose(out, 3,kernel_size=4,strides=1, padding='SAME')
print( out.get_shape())
关于 'SAME'
填充,Convolution
documentation offers some detailed explanations (further details in those notes)。特别是,当使用 'SAME'
填充时,输出形状定义为:
# for `tf.layers.conv2d` with `SAME` padding: out_height = ceil(float(in_height) / float(strides[1])) out_width = ceil(float(in_width) / float(strides[2]))
在这种情况下,输出形状仅取决于输入形状和步幅。从那里计算填充大小以满足此形状要求(而使用 'VALID'
填充时,输出形状取决于填充大小)
现在对于转置卷积...由于此操作是普通卷积(其梯度)的反向对应物,这意味着普通卷积的输出形状对应于其对应转置操作的输入形状。换句话说,虽然 tf.layers.conv2d()
的输出形状除以步幅,但输出形状
tf.layers.conv2d_transpose()
乘以它:
# for `tf.layers.conv2d_transpose()` with `SAME` padding:
out_height = in_height * strides[1]
out_width = in_width * strides[2]
但再次计算填充大小以获得此输出形状,而不是相反(对于 SAME
填充)。由于这些值之间的正常关系(即您找到的关系)是:
# for `tf.layers.conv2d_transpose()` with given padding:
out_height = strides[1] * (in_height - 1) + kernel_size[0] - 2 * padding_height
out_width = strides[2] * (in_width - 1) + kernel_size[1] - 2 * padding_width
重新排列我们得到的方程
padding_height = [strides[1] * (in_height - 1) + kernel_size[0] - out_height] / 2
padding_width = [[strides[2] * (in_width - 1) + kernel_size[1] - out_width] / 2
note: if e.g.
2 * padding_height
is an odd number, thenpadding_height_top = floor(padding_height)
; andpadding_height_bottom = ceil(padding_height)
(same for resp.padding_width
,padding_width_left
andpadding_width_right)
用它们的表达式替换 out_height
和 out_width
,并使用您的值(对于第一个转置卷积):
padding = [2 * (128 - 1) + 4 - (128 * 2)] / 2 = 1
因此,您在数据的每一侧都添加了 1
的填充,以获得输出 dim out_dim = in_dim * stride = strides * (in_dim - 1) + kernel_size - 2 * padding = 256
我根据@Aldream的回答给自己画了一张图。可视化可能有用。希望我做对了。但我必须研究如何以及在何处应用此填充以获得最终形状。