代码之家  ›  专栏  ›  技术社区  ›  Mohan Radhakrishnan

使用公式的conv2d转置输出形状

  •  1
  • Mohan Radhakrishnan  · 技术社区  · 7 年前

    我得到 [-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())
    
    2 回复  |  直到 7 年前
        1
  •  5
  •   benjaminplanche    7 年前

    关于 'SAME' 填充 Convolution 文档提供了一些详细的解释(在 notes )尤其是在使用 “同一” 填充,输出形状的定义如下:

    # 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
    

    注: 如果例如 2 * padding_height 是个奇数,那么 padding_height_top = floor(padding_height) padding_height_bottom = ceil(padding_height) (同样适用于Resp. padding_width , padding_width_left 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

        2
  •  1
  •   Mohan Radhakrishnan    7 年前

    我根据@aldream的答案为自己画了一张图表。也许可以想象一下。希望我是对的。但我必须研究如何和在哪里使用这种填充物才能得到最终的形状。

    enter image description here