Confused about conv2d_transpose

Refresh

December 2018

Views

16.4k time

21

I'm getting this error message when using conv2d_transpose:

W tensorflow/core/common_runtime/executor.cc:1102] 0x7fc81f0d6250 Compute status: Invalid argument: Conv2DBackpropInput: Number of rows of out_backprop doesn't match computed: actual = 32, computed = 4
 [[Node: generator/g_h1/conv2d_transpose = Conv2DBackpropInput[T=DT_FLOAT, padding="SAME", strides=[1, 2, 2, 1], use_cudnn_on_gpu=true, _device="/job:localhost/replica:0/task:0/cpu:0"](generator/g_h1/conv2d_transpose/output_shape, generator/g_h1/w/read, _recv_l_0)]]

However, it occurs after the graph is built while compiling the loss function (Adam). Any ideas on what would cause this? I suspect it's related to the input dimensions but I'm not sure exactly why.

Full error: https://gist.github.com/jimfleming/75d88e888044615dd6e3

Relevant code:

# l shape: [batch_size, 32, 32, 4]

output_shape = [self.batch_size, 8, 8, 128]
filter_shape = [7, 7, 128, l.get_shape()[-1]]
strides = [1, 2, 2, 1]
with tf.variable_scope("g_h1"):
    w = tf.get_variable('w', filter_shape, initializer=tf.random_normal_initializer(stddev=0.02))
    h1 = tf.nn.conv2d_transpose(l, w, output_shape=output_shape, strides=strides, padding='SAME')
    h1 = tf.nn.relu(h1)

output_shape = [self.batch_size, 16, 16, 128]
filter_shape = [7, 7, 128, h1.get_shape()[-1]]
strides = [1, 2, 2, 1]
with tf.variable_scope("g_h2"):
    w = tf.get_variable('w', filter_shape, initializer=tf.random_normal_initializer(stddev=0.02))
    h2 = tf.nn.conv2d_transpose(h1, w,output_shape=output_shape,  strides=strides, padding='SAME')
    h2 = tf.nn.relu(h2)

output_shape = [self.batch_size, 32, 32, 3]
filter_shape = [5, 5, 3, h2.get_shape()[-1]]
strides = [1, 2, 2, 1]
with tf.variable_scope("g_h3"):
    w = tf.get_variable('w', filter_shape, initializer=tf.random_normal_initializer(stddev=0.02))
    h3 = tf.nn.conv2d_transpose(h2, w,output_shape=output_shape,  strides=strides, padding='SAME')
    h3 = tf.nn.tanh(h3)
Jim

2 answers

1

Использование padding='SAME'в tf.nn.conv2d_transpose()функции может также работать

35

Спасибо за вопрос! Вы совершенно правы --- проблема заключается в том, что входные и выходные размеры передается в tf.nn.conv2d_transpose не согласны. (Эта ошибка может быть обнаружена при вычислении градиентов, но вычисление градиента не является проблемой.)

Давайте посмотрим на только первую часть вашего кода и упростить его немного:

sess = tf.Session()
batch_size = 3
output_shape = [batch_size, 8, 8, 128]
strides = [1, 2, 2, 1]

l = tf.constant(0.1, shape=[batch_size, 32, 32, 4])
w = tf.constant(0.1, shape=[7, 7, 128, 4])

h1 = tf.nn.conv2d_transpose(l, w, output_shape=output_shape, strides=strides, padding='SAME')
print sess.run(h1)

Я заменил переменные с константами --- это легче увидеть, что происходит.

Если вы попытаетесь запустить этот код, вы получите подобную ошибку:

InvalidArgumentError: Conv2DCustomBackpropInput: Size of out_backprop doesn't match computed: actual = 32, computed = 4
  [[Node: conv2d_transpose_6 = Conv2DBackpropInput[T=DT_FLOAT, data_format="NHWC", padding="SAME", strides=[1, 2, 2, 1], use_cudnn_on_gpu=true, _device="/job:localhost/replica:0/task:0/cpu:0"](conv2d_transpose_6/output_shape, Const_25, Const_24)]]

Теперь, ошибка немного вводит в заблуждение --- это говорит о «out_backprop» аргумент «Conv2DCustomBackpropInput». Ключ в том, что tf.nn.conv2d_transpose на самом деле просто градиент tf.nn.conv2d, так Tensorflow использует тот же код внутри (Conv2DCustomBackpropInput) для вычисления градиента tf.nn.conv2d и вычисления tf.nn.conv2d_transpose.

Ошибка означает, что «output_shape» Запрошенный не представляется возможным, учитывая формы «L» и «ш».

Так как tf.nn.conv2d_transpose это назад (градиент) аналог tf.nn.conv2d, один из способов, чтобы увидеть, что правильные формы должны быть, чтобы использовать соответствующую операцию вперед:

output = tf.constant(0.1, shape=output_shape)
expected_l = tf.nn.conv2d(output, w, strides=strides, padding='SAME')
print expected_l.get_shape()
# Prints (3, 4, 4, 4)

То есть, в прямом направлении, если вы обеспечили тензор формы «output_shape», вы бы выйти тензор формы (3, 4, 4, 4). Таким образом, один из способов решения этой проблемы заключается в изменении формы «L» (3, 4, 4, 4); если изменить код выше:

l = tf.constant(0.1, shape=[batch_size, 4, 4, 4])

все работает отлично.

В общем, попробуйте использовать tf.nn.conv2d, чтобы получить чувство для того, что отношения между тензорными формами есть. Так как tf.nn.conv2d_transpose является его аналогом в обратном направлении, он имеет такое же соотношение между входными, выходными и фильтрами формами (но с переменой ролей на входе и выходе наоборот.)

Надеюсь, это поможет!