Подтвердить что ты не робот

Confused about conv2d_transpose

Я получаю это сообщение об ошибке при использовании 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)]]

Однако это происходит после построения графика при компиляции функции потерь (Adam). Любые идеи о том, что может вызвать это? Я подозреваю, что это связано с входными параметрами, но я не уверен, почему именно.

Полная ошибка: https://gist.github.com/jimfleming/75d88e888044615dd6e3

Соответствующий код:

# 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)
4b9b3361

Ответ 1

Спасибо за вопрос! Вы совершенно правы - проблема в том, что входные и выходные измерения передаются в 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" и "w".

Так как 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 является его обратной копией, он имеет одинаковую зависимость между форматами ввода, вывода и фильтра (но с изменением ролей ввода и вывода).

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

Ответ 2

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