Confundido acerca de conv2d_transpose

Que estoy recibiendo este mensaje de error cuando se utiliza 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)]]

Sin embargo, se produce después de que el gráfico está construido al compilar la función de pérdida (Adam). Alguna idea sobre lo que haría que este? Sospecho que esta relacionado con la entrada de dimensiones, pero no estoy seguro exactamente por qué.

De error completo: https://gist.github.com/jimfleming/75d88e888044615dd6e3

Código correspondiente:

# 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)
InformationsquelleAutor Jim | 2016-02-18

2 Kommentare

  1. 38

    Gracias por la pregunta! Tienes toda la razón—el problema es que la entrada y salida de las dimensiones que se pasa a tf.nn.conv2d_transpose no están de acuerdo. (El error puede ser detectado en el cómputo de los degradados, pero el gradiente de la computación no es el problema.)

    Veamos la primera parte de su código, y para simplificar un poco:

    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)

    He sustituido las variables con constantes — es más fácil ver lo que está pasando.

    Si intenta ejecutar este código, usted obtiene un mensaje de error similar:

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

    Ahora, el error es un poco engañoso — habla de la ‘out_backprop’ argumento ‘Conv2DCustomBackpropInput’. La clave es que tf.nn.conv2d_transpose es en realidad sólo el gradiente de la tf.nn.conv2d, así Tensorflow utiliza el mismo código internamente (Conv2DCustomBackpropInput) para el cálculo del gradiente de la tf.nn.conv2d y para calcular la tf.nn.conv2d_transpose.

    El error significa que el ‘output_shape’ has solicitado no es posible, dada la forma de ‘l’ y ‘w’.

    Desde tf.nn.conv2d_transpose es el de retroceso (gradiente) de contrapartida de la tf.nn.conv2d, una manera de ver lo que las formas correctas debe ser es el uso de la correspondiente operación directa:

    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)

    Que es, en la dirección de avance, si usted proporciona un tensor de forma ‘output_shape’, que iba a salir un tensor de forma (3, 4, 4, 4).
    Así que una manera de solucionar el problema es cambiar la forma de ‘l’ a (3, 4, 4, 4); si cambia el código de arriba para:

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

    todo funciona bien.

    En general, trate de usar tf.nn.conv2d para tener una idea de cuál es la relación entre el tensor de formas es. Desde tf.nn.conv2d_transpose hacia atrás es su contraparte, tiene la misma relación entre entrada, salida y formas de filtros (pero con las funciones de entrada y de salida se invierte.)

    Espero que ayude!

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea