Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Migración del uso de tf.summary a TF 2.0

Ver en TensorFlow.org Ejecutar en Google Colab Ver código fuente en GitHub
 import tensorflow as tf
 

TensorFlow 2.0 incluye cambios significativos en la API tf.summary utilizada para escribir datos de resumen para su visualización en TensorBoard.

Que ha cambiado

Es útil pensar en la API tf.summary como dos sub-API:

  • Un conjunto de operaciones para grabar resúmenes individuales: summary.scalar() , summary.histogram() , summary.image() , summary.audio() y summary.text() , que se llaman en línea desde el código de su modelo.
  • Lógica de escritura que recopila estos resúmenes individuales y los escribe en un archivo de registro con formato especial (que TensorBoard luego lee para generar visualizaciones).

En TF 1.x

Las dos mitades tuvieron que conectarse manualmente juntas: recuperando los resultados de operaciones de resumen a través de Session.run() y llamando a FileWriter.add_summary(output, step) . La v1.summary.merge_all() hizo más fácil al usar una colección de gráficos para agregar todos los resultados de operaciones de resumen, pero este enfoque todavía funcionó mal para la ejecución ansiosa y el flujo de control, lo que lo hace especialmente inadecuado para TF 2.0.

En TF 2.X

Las dos mitades están estrechamente integradas, y ahora las operaciones individuales tf.summary escriben sus datos inmediatamente cuando se ejecutan. El uso de la API de su código de modelo aún debería ser familiar, pero ahora es amigable para una ejecución entusiasta mientras sigue siendo compatible con el modo gráfico. La integración de ambas mitades de la API significa el summary.FileWriter ahora es parte del contexto de ejecución de TensorFlow y se accede directamente por tf.summary ops, por lo que la configuración de los escritores es la parte principal que se ve diferente.

Ejemplo de uso con ansiosa ejecución, el valor predeterminado en TF 2.0:

 writer = tf.summary.create_file_writer("/tmp/mylogs/eager")

with writer.as_default():
  for step in range(100):
    # other model code would go here
    tf.summary.scalar("my_metric", 0.5, step=step)
    writer.flush()
 
 ls /tmp/mylogs/eager
 
events.out.tfevents.1591960770.kokoro-gcp-ubuntu-prod-57818388.17251.5.v2

Ejemplo de uso con la ejecución del gráfico tf.function:

 writer = tf.summary.create_file_writer("/tmp/mylogs/tf_function")

@tf.function
def my_func(step):
  with writer.as_default():
    # other model code would go here
    tf.summary.scalar("my_metric", 0.5, step=step)

for step in tf.range(100, dtype=tf.int64):
  my_func(step)
  writer.flush()
 
 ls /tmp/mylogs/tf_function
 
events.out.tfevents.1591960771.kokoro-gcp-ubuntu-prod-57818388.17251.1013.v2

Ejemplo de uso con la ejecución de gráficos TF 1.x heredados:

 g = tf.compat.v1.Graph()
with g.as_default():
  step = tf.Variable(0, dtype=tf.int64)
  step_update = step.assign_add(1)
  writer = tf.summary.create_file_writer("/tmp/mylogs/session")
  with writer.as_default():
    tf.summary.scalar("my_metric", 0.5, step=step)
  all_summary_ops = tf.compat.v1.summary.all_v2_summary_ops()
  writer_flush = writer.flush()


with tf.compat.v1.Session(graph=g) as sess:
  sess.run([writer.init(), step.initializer])

  for i in range(100):
    sess.run(all_summary_ops)
    sess.run(step_update)
    sess.run(writer_flush)  
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/resource_variable_ops.py:1666: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.

 ls /tmp/mylogs/session
 
events.out.tfevents.1591960771.kokoro-gcp-ubuntu-prod-57818388.17251.1446.v2

Convertir tu código

La conversión del uso existente de tf.summary a la API TF 2.0 no puede automatizarse de manera confiable, por lo que el script tf_upgrade_v2 simplemente lo reescribe en tf.compat.v1.summary . Para migrar a TF 2.0, deberá adaptar su código de la siguiente manera:

  1. Un escritor predeterminado establecido a través de .as_default() debe estar presente para usar operaciones de resumen

    • Esto significa ejecutar operaciones con entusiasmo o usar operaciones en la construcción de gráficos
    • Sin un escritor predeterminado, las operaciones de resumen se convierten en operaciones no silenciosas
    • Los escritores predeterminados (todavía) no se propagan a través del límite de ejecución de la @tf.function , solo se detectan cuando se rastrea la función, por lo que la mejor práctica es llamar a writer.as_default() dentro del cuerpo de la función y asegurarse de que el objeto escritor continúa existiendo mientras se @tf.function la función @tf.function
  2. El valor "paso" debe pasarse a cada operación a través del argumento step

    • TensorBoard requiere un valor de paso para representar los datos como una serie de tiempo
    • El paso explícito es necesario porque se ha eliminado el paso global de TF 1.x, por lo que cada operación debe conocer la variable de paso deseada para leer
    • Para reducir las repeticiones, el soporte experimental para registrar un valor de paso predeterminado está disponible como tf.summary.experimental.set_step() , pero esta es una funcionalidad provisional que se puede cambiar sin previo aviso
  3. Las firmas de funciones de operaciones de resumen individuales han cambiado

    • El valor de retorno ahora es un valor booleano (que indica si realmente se escribió un resumen)
    • El segundo nombre del parámetro (si se usa) ha cambiado de tensor a data
    • El parámetro de collections ha sido eliminado; las colecciones son solo TF 1.x
    • El parámetro de family ha sido eliminado; solo use tf.name_scope()
  4. [Solo para usuarios de modo gráfico / ejecución de sesión heredados]

    • Primero inicialice el escritor con v1.Session.run(writer.init())

    • Use v1.summary.all_v2_summary_ops() para obtener todas las operaciones de resumen de TF 2.0 para el gráfico actual, por ejemplo, para ejecutarlas a través de Session.run()

    • Vaciar el escritor con v1.Session.run(writer.flush()) y del mismo modo para close()

Si su código TF 1.x estaba usando la API tf.contrib.summary , es mucho más similar a la API TF 2.0, por tf_upgrade_v2 script tf_upgrade_v2 automatizará la mayoría de los pasos de migración (y emitirá advertencias o errores para cualquier uso que no pueda ser completamente migrado). En su mayor parte, solo reescribe las llamadas de API a tf.compat.v2.summary ; si solo necesita compatibilidad con TF 2.0+, puede soltar el compat.v2 y simplemente hacer referencia a él como tf.summary .

Consejos adicionales

Además de las áreas críticas anteriores, algunos aspectos auxiliares también han cambiado:

  • La grabación condicional (como "registrar cada 100 pasos") tiene una nueva apariencia

 if condition:
  writer.add_summary()
 
  • No hay escritura directa de tf.compat.v1.Graph - en su lugar use funciones de rastreo

    • La ejecución del gráfico en TF 2.0 utiliza @tf.function lugar del gráfico explícito
    • En TF 2.0, use las nuevas API de estilo de rastreo tf.summary.trace_on() y tf.summary.trace_export() para registrar gráficos de funciones ejecutadas
  • No más caché de escritor global por logdir con tf.summary.FileWriterCache

    • Los usuarios deben implementar su propio almacenamiento en caché / compartir objetos de escritor, o simplemente usar escritores separados (el soporte de TensorBoard para este último está en progreso )
  • La representación binaria del archivo de eventos ha cambiado.

    • TensorBoard 1.x ya es compatible con el nuevo formato; esta diferencia solo afecta a los usuarios que analizan manualmente los datos de resumen de los archivos de eventos
    • Los datos de resumen ahora se almacenan como bytes tensoriales; puede usar tf.make_ndarray(event.summary.value[0].tensor) para convertirlo en numpy