Confusion au sujet de la transposition conv2d

je reçois ce message d'erreur en utilisant 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)]]

cependant, cela se produit après que le graphique soit construit pendant la compilation de la fonction de perte (Adam). Une idée de ce qui causerait ça? Je pense que c'est lié aux dimensions d'entrée, mais je ne sais pas exactement pourquoi.

message d'erreur: https://gist.github.com/jimfleming/75d88e888044615dd6e3

code pertinent:

# 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)
20
demandé sur Jim 2016-02-18 20:46:09

2 réponses

Merci pour la question! Le problème est que les dimensions d'entrée et de sortie sont passées à tf.nn.conv2d_transpose n'est pas d'accord. (L'erreur peut être détectée lors du calcul des gradients, mais le calcul des gradients n'est pas le problème.)

regardons juste la première partie de votre code, et de le simplifier un peu:

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)

j'ai remplacé les variables par des constantes --- il est plus facile de voir ce qui se passe.

Si vous essayez de exécutez ce code, vous obtenez une erreur similaire:

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)]]

maintenant, l'erreur est un peu trompeuse --- il parle de l'argument "out_backprop" à "Conv2DCustomBackpropInput". La clé, c'est ce tf.nn.conv2d_transpose est en fait juste le gradient de tf.nn.conv2d, donc Tensorflow utilise le même code interne (Conv2DCustomBackpropInput) pour calculer le gradient de tf.nn.conv2d et pour calculer tf.nn.conv2d_transpose.

L'erreur signifie que le "output_shape' que vous avez demandé n'est pas possible, étant donné les formes de " l " et "w".

depuis tf.nn.conv2d_transpose est la contrepartie en arrière (gradient) de tf.nn.conv2d, une façon de voir ce que devraient être les formes correctes est d'utiliser l'opération vers l'avant correspondante:

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)

C'est-à-dire, dans la direction vers l'avant, si vous avez fourni un tenseur de forme 'output_shape', vous obtiendriez un tenseur de forme (3, 4, 4, 4). Donc une façon de résoudre le problème est de changer la forme de 'l' à (3, 4, 4, 4); si vous modifiez l' code ci-dessus à:

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

tout fonctionne bien.

En général, essayez d'utiliser tf.nn.conv2d pour avoir une idée de ce qu'est la relation entre les formes tensorielles. Depuis tf.nn.conv2d_transpose est sa contrepartie en arrière, il a la même relation entre l'entrée, la sortie et les formes du filtre (mais avec les rôles de l'entrée et de la sortie inversés.)

j'Espère que ça aide!

34
répondu Peter Hawkins 2016-06-27 17:05:03

en utilisant padding='SAME'tf.nn.conv2d_transpose() fonction peut trop

1
répondu user6457746 2016-11-08 13:02:36