En TensorFlow, qué es tf.¿identidad usada para?


He visto tf.identity usado en algunos lugares, como el tutorial oficial de CIFAR-10 y la implementación de normalización por lotes en stackoverflow, pero no veo por qué es necesario.

¿Para qué se utiliza? ¿Puede alguien dar un caso de uso o dos?

Una respuesta propuesta es que se puede utilizar para la transferencia entre la CPU y la GPU. Esto no está claro para mí. Extensión a la pregunta, basada en este: loss = tower_loss(scope) está bajo el bloque GPU, lo que me sugiere que todos los operadores definidos en tower_loss se asignan a la GPU. Luego, al final de tower_loss, vemos total_loss = tf.identity(total_loss) antes de que sea devuelto. ¿Por qué? ¿Cuál sería el defecto de no usar tf.identity aquí?

 40
Author: Salvador Dali, 2016-01-19

7 answers

Después de algunos tropiezos, creo que he notado un solo caso de uso que se ajusta a todos los ejemplos que he visto. Si hay otros casos de uso, por favor explique con un ejemplo.

Caso de uso:

Supongamos que desea ejecutar un operador cada vez que se evalúa una variable en particular. Por ejemplo, supongamos que desea agregar uno a x cada vez que se evalúa la variable y. Podría parecer que esto funcionará:

x = tf.Variable(0.0)
x_plus_1 = tf.assign_add(x, 1)

with tf.control_dependencies([x_plus_1]):
    y = x
init = tf.initialize_all_variables()

with tf.Session() as session:
    init.run()
    for i in xrange(5):
        print(y.eval())

No lo hace: imprimirá 0, 0, 0, 0, 0. En cambio, parece que necesita agregar un nuevo nodo al gráfico dentro del bloque control_dependencies. Así que usamos este truco:

x = tf.Variable(0.0)
x_plus_1 = tf.assign_add(x, 1)

with tf.control_dependencies([x_plus_1]):
    y = tf.identity(x)
init = tf.initialize_all_variables()

with tf.Session() as session:
    init.run()
    for i in xrange(5):
        print(y.eval())

Esto funciona: imprime 1, 2, 3, 4, 5.

Si en el tutorial CIFAR-10 descartamos tf.identity, entonces loss_averages_op nunca se ejecutaría.

 45
Author: rd11,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-25 17:05:40

tf.identity es útil cuando desea transportar explícitamente tensor entre dispositivos (como, de GPU a una CPU). El op agrega nodos send / recv al gráfico, que hacen una copia cuando los dispositivos de la entrada y la salida son diferentes.

Un comportamiento predeterminado es que los nodos send/recv se agregan implícitamente cuando la operación ocurre en un dispositivo diferente, pero puede imaginar algunas situaciones (especialmente en una configuración multi-threaded/distributed) en las que podría ser útil obtener el valor de la variable varias veces dentro de una sola ejecución del session.run. tf.identity permite un mayor control con respecto a cuándo se debe leer el valor desde el dispositivo de origen. Posiblemente un nombre más apropiado para este op sería read.

También, tenga en cuenta que en la implementación de tf.Variable link , la op de identidad se añade en el constructor, que se asegura de que todos los accesos a la variable copien los datos de la fuente solo una vez. Múltiples copias pueden ser costosas en los casos cuando la variable vive en una GPU pero es leída por múltiples operaciones de CPU (o al revés). Los usuarios pueden cambiar el comportamiento con múltiples llamadas a tf.identity cuando lo deseen.

EDITAR: Respuesta actualizada después de que la pregunta fue editada.

Además, tf.identity se puede usar como un nodo ficticio para actualizar una referencia al tensor. Esto es útil con varias operaciones de flujo de control. En el caso CIFAR queremos exigir que el ExponentialMovingAverageOp actualice las variables relevantes antes de recuperar el valor de la pérdida. Esto se puede implementar como:

with tf.control_dependencies([loss_averages_op]):
  total_loss = tf.identity(total_loss)

Aquí, el tf.identity no hace nada útil aparte de marcar el tensor total_loss a ejecutar después de evaluar loss_averages_op.

 22
Author: Rafał Józefowicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-19 18:04:00

Además de lo anterior, simplemente lo uso cuando necesito asignar un nombre a ops que no tienen un argumento de nombre, al igual que cuando inicializo un estado en RNN:

rnn_cell = tf.contrib.rnn.MultiRNNCell([cells])
# no name arg
initial_state = rnn_cell.zero_state(batch_size,tf.float32)
# give it a name with tf.identity()
initial_state = tf.identity(input=initial_state,name="initial_state")
 7
Author: ahmedhosny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-24 06:07:44

Me encontré con otro caso de uso que no está completamente cubierto por las otras respuestas.

def conv_layer(input_tensor, kernel_shape, output_dim, layer_name, decay=None, act=tf.nn.relu):
    """Reusable code for making a simple convolutional layer.
    """
    # Adding a name scope ensures logical grouping of the layers in the graph.
    with tf.name_scope(layer_name):
        # This Variable will hold the state of the weights for the layer
        with tf.name_scope('weights'):
            weights = weight_variable(kernel_shape, decay)
            variable_summaries(weights, layer_name + '/weights')
        with tf.name_scope('biases'):
            biases = bias_variable([output_dim])
            variable_summaries(biases, layer_name + '/biases')
        with tf.name_scope('convolution'):
            preactivate = tf.nn.conv2d(input_tensor, weights, strides=[1, 1, 1, 1], padding='SAME')
            biased = tf.nn.bias_add(preactivate, biases)
            tf.histogram_summary(layer_name + '/pre_activations', biased)
        activations = act(biased, 'activation')
        tf.histogram_summary(layer_name + '/activations', activations)
        return activations

La mayor parte del tiempo al construir una capa convolucional, solo desea que se devuelvan las activaciones para que pueda alimentarlas en la siguiente capa. Sin embargo, a veces, por ejemplo, al construir un codificador automático, desea los valores de preactivación.

En esta situación una solución elegante es pasar tf.identity como la función de activación, no activando efectivamente la capa.

 4
Author: Arthelais,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-25 09:33:22

Encontré otra aplicación de tf.identidad en Tensorboard. Si usa tf.shuffle_batch, devuelve varios tensores a la vez, por lo que puede ver una imagen desordenada al visualizar el gráfico, no puede dividir la canalización de creación de tensores desde tensores de entrada actiual: messy

Pero con tf.identidad puede crear nodos duplicados, que no afectan el flujo de cómputo: nice

 3
Author: grihabor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-23 10:25:16

Cuando nuestros datos de entrada se serializan en bytes, y queremos extraer entidades de este conjunto de datos. Podemos hacerlo en formato clave-valor y luego obtener un marcador de posición para ello. Sus beneficios se realizan más cuando hay múltiples características y cada característica tiene que leerse en un formato diferente.

  #read the entire file in this placeholder      
  serialized_tf_example = tf.placeholder(tf.string, name='tf_example')

  #Create a pattern in which data is to be extracted from input files
  feature_configs = {'image': tf.FixedLenFeature(shape=[256], dtype=tf.float32),/
                     'text': tf.FixedLenFeature(shape=[128], dtype=tf.string),/
                     'label': tf.FixedLenFeature(shape=[128], dtype=tf.string),}

  #parse the example in key: tensor dictionary
  tf_example = tf.parse_example(serialized_tf_example, feature_configs)

  #Create seperate placeholders operation and tensor for each feature
  image = tf.identity(tf_example['image'], name='image')
  text  = tf.identity(tf_example['text'], name='text')
  label = tf.identity(tf_example['text'], name='label')
 1
Author: Shyam Swaroop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-08 22:37:25

En el entrenamiento de distribución, debemos usar tf.identidad o los trabajadores colgarán a la espera de la inicialización del trabajador jefe:

vec = tf.identity(tf.nn.embedding_lookup(embedding_tbl, id)) * mask
with tf.variable_scope("BiRNN", reuse=None):
    out, _ = tf.nn.bidirectional_dynamic_rnn(fw, bw, vec, sequence_length=id_sz, dtype=tf.float32)

Para detalles, sin identidad, el trabajador jefe trataría algunas variables como variables locales de manera inapropiada y los otros trabajadores esperarían una operación de inicialización que no pueda terminar

 0
Author: Ju Xuan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-25 14:29:40