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 fuente en GitHub
import tensorflow as tf

TensorFlow 2.0 incluye cambios significativos en la API tf.summary usa 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 un formato especial (que luego TensorBoard lee para generar visualizaciones).

En TF 1.x

Las dos mitades tenían que conectarse juntas manualmente, FileWriter.add_summary(output, step) resumen a través de Session.run() y llamando a FileWriter.add_summary(output, step) . La v1.summary.merge_all() facilitó esto al usar una colección de gráficos para agregar todas las salidas de operaciones resumidas, pero este enfoque aún funcionó mal para la ejecución ávida 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 de tf.summary escriben sus datos inmediatamente cuando se ejecutan. El uso de la API del código de su modelo aún debería parecer familiar, pero ahora es fácil de ejecutar con entusiasmo 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 tf.summary ops accede directamente, por lo que la configuración de los escritores es la parte principal que se ve diferente.

Ejemplo de uso con ejecución ávida, 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.1599908770.kokoro-gcp-ubuntu-prod-1849198075.22428.5.v2

Ejemplo de uso con ejecución de 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.1599908771.kokoro-gcp-ubuntu-prod-1849198075.22428.1013.v2

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

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)  
ls /tmp/mylogs/session
events.out.tfevents.1599908771.kokoro-gcp-ubuntu-prod-1849198075.22428.1446.v2

Convirtiendo tu código

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

  1. Debe estar presente un escritor predeterminado establecido a través de .as_default() 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 no operaciones silenciosas
    • Los escritores predeterminados no se propagan (todavía) 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 del escritor continúa existiendo mientras se @tf.function la función @tf.function
  2. El valor de "paso" debe pasarse a cada operación a través de un argumento de step

    • TensorBoard requiere un valor de paso para representar los datos como una serie de tiempo
    • El paso explícito es necesario porque el paso global de TF 1.x se ha eliminado, por lo que cada operación debe conocer la variable de paso deseada para leer
    • Para reducir el estándar, 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 puede cambiarse sin previo aviso.
  3. Las firmas de funciones de operaciones de resumen individuales han cambiado

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

    • 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()

    • v1.Session.run(writer.flush()) el escritor con v1.Session.run(writer.flush()) y lo mismo 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, simplemente reescribe las llamadas API a tf.compat.v2.summary ; si solo necesita compatibilidad con TF 2.0+, puede eliminar compat.v2 y hacer referencia a él como tf.summary .

Consejos adicionales

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

  • La grabación condicional (como "registrar cada 100 pasos") tiene un nuevo aspecto

if condition:
  writer.add_summary()
  • Sin escritura directa de tf.compat.v1.Graph ; en su lugar, use funciones de seguimiento

    • La ejecución de gráficos en TF 2.0 usa @tf.function lugar del gráfico explícito
    • En TF 2.0, use las nuevas API de estilo de seguimiento tf.summary.trace_on() y tf.summary.trace_export() para registrar gráficos de funciones ejecutadas
  • No más almacenamiento en 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 datos de resumen de archivos de eventos
    • Los datos de resumen ahora se almacenan como bytes de tensor; puede usar tf.make_ndarray(event.summary.value[0].tensor) para convertirlo en numpy