Path: blob/master/site/es-419/tensorboard/migrate.ipynb
25115 views
Copyright 2019 The TensorFlow Authors.
Cómo migrar el uso de tf.summary a TF 2.x
Nota: Este documento es para personas que ya están familiarizadas con TensorFlow 1.x TensorBoard y que quieren migrar grandes bases de código TensorFlow de TensorFlow 1.x a 2.x. Si es nuevo en TensorBoard, consulte el documento cómo empezar que se encuentra en su página web. Si está utilizando
tf.keras
puede que no necesite realizar ninguna acción para actualizar a TensorFlow 2.x.
TensorFlow 2.x incluye cambios significativos en la API tf.summary
utilizada para escribir datos de resumen para su visualización en TensorBoard.
¿Qué ha cambiado?
Es útil pensar en la API tf.summary
como dos API secundarias:
Un conjunto de operaciones para grabar resúmenes individuales -
summary.scalar()
,summary.histogram()
,summary.image()
,summary.audio()
, ysummary.text()
- que se llaman de forma integrada desde el código de su modelo.Escribir la lógica que recoge estos resúmenes individuales y los escribe en un archivo de registro con un formato especial (que TensorBoard lee después para generar visualizaciones).
En TF 1.x
Las dos mitades tuvieron que conectarse manualmente, es decir, extrayendo las salidas de las operaciones de resumen mediante Session.run()
y llamando a FileWriter.add_summary(output, step)
. La opción v1.summary.merge_all()
facilitaba esta tarea utilizando una colección de grafos para agregar todas las salidas de las operaciones de resumen, pero este enfoque seguía funcionando mal para la ejecución eager y el flujo de control, por lo que era especialmente inadecuado para la TF 2.x.
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 desde su código modelo debería seguir pareciéndole familiar, pero ahora es amigable con la ejecución eager a la vez que sigue siendo compatible con el modo gráfico. La integración de ambas mitades de la API significa que el summary.FileWriter
es ahora 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 ejecución eager, el valor predeterminado en TF 2.x:
Ejemplo de uso con la ejecución del gráfico tf.function:
Ejemplo de uso con ejecución de gráficos TF 1.x heredados:
Cómo convertir su código
La conversión del uso existente de tf.summary
a la API TF 2.x no puede automatizarse de forma segura, por lo que el script tf_upgrade_v2
simplemente reescribe todo a tf.compat.v1.summary
y no habilitará los comportamientos TF 2.x automáticamente.
Migración parcial
Para facilitar la migración a la TF 2.x a los usuarios de código modelo que aún dependen en gran medida de las operaciones de registro de la API de resumen de la TF 1.x como tf.compat.v1.summary.scalar()
, es posible migrar primero sólo las API de escritor, lo que permite que las operaciones de resumen individuales de la TF 1.x dentro de su código modelo se migren completamente en un momento posterior.
Para respaldar este estilo de migración, tf.compat.v1.summary
reenviará automáticamente a sus equivalentes TF 2.x en las siguientes condiciones:
El contexto más externo es el modo eager
Se estableció un escritor de resúmenes TF 2.x predeterminado
Se estableció un valor diferente de paso para el escritor (utilizando
tf.summary.SummaryWriter.as_default
,tf.summary.experimental.set_step
, o alternativamentetf.compat.v1.train.create_global_step
).
Tenga en cuenta que cuando se invoque la implementación de resumen de TF 2.x, el valor que devolverá será un tensor bytestring vacío, para evitar la duplicación de la escritura del resumen. Además, el reenvío de argumentos de entrada es de mejor esfuerzo y no se conservarán todos los argumentos (por ejemplo, el argumento family
se conservará, mientras que collections
se eliminará).
Ejemplo para invocar comportamientos tf.summary.scalar
en tf.compat.v1.summary.scalar
:
Migración completa
Para migrar completamente a TF 2.x, tendrá que adaptar su código como se indica a continuación:
Un escritor predeterminado establecido a través de
.as_default()
debe estar presente para utilizar las operaciones de resumenEsto significa ejecutar las operaciones con avidez o utilizar las operaciones en la creación de gráficos
Sin un escritor predeterminado, las operaciones de resumen se convierten en operaciones silenciosas
Los escritores predeterminados no se propagan (todavía) dentro del límite de ejecución de
@tf.function
- sólo se detectan cuando se rastrea la función - por lo que la práctica recomendada es llamar awriter.as_default()
dentro del cuerpo de la función, y asegurarse de que el objeto del escritor sigue existiendo mientras se esté utilizando@tf.function
El valor "step" debe pasarse a cada operación mediante el argumento
step
TensorBoard requiere un valor escalonado para representar los datos como una serie temporal
El paso explícito es necesario porque se eliminó el paso global del TF 1.x, por lo que cada operación debe determinar la variable de paso que desea leer
Para reducir las repeticiones, se dispone de soporte experimental para registrar un valor de paso predeterminado como
tf.summary.experimental.set_step()
, pero se trata de una funcionalidad provisional que puede modificarse sin previo aviso
Las firmas de función de las operaciones de resumen individuales han cambiado
El valor devuelto ahora es un valor booleano (que indica si realmente se escribió un resumen)
El nombre del segundo parámetro (si se utiliza) cambió de
tensor
adata
Se eliminó el parámetro
collections
; las colecciones son sólo TF 1.xSe eliminó el parámetro
family
; utilice simplementetf.name_scope()
[Sólo para usuarios del modo gráfico heredado / ejecución de la sesión]
Primero inicialice el escritor con
v1.Session.run(writer.init())
Utilice
v1.summary.all_v2_summary_ops()
para obtener todas las operaciones de resumen de TF 2.x para el gráfico actual, por ejemplo para ejecutarlas medianteSession.run()
Purgar el escritor con
v1.Session.run(writer.flush())
y lo mismo paraclose()
Si su código TF 1.x utilizaba en cambio la API tf.contrib.summary
API, es mucho más similar a la API de TF 2.x, por lo que el script tf_upgrade_v2
automatizará la mayoría de los pasos de la migración (y emitirá advertencias o errores para cualquier uso que no pueda migrarse completamente). En su mayor parte, sólo reescribe las llamadas a la API a tf.compat.v2.summary
; si sólo necesita compatibilidad con TF 2.x, puede eliminar el compat.v2
y referenciarlo simplemente como tf.summary
.
Consejos adicionales
Además de las áreas críticas mencionadas, también han cambiado algunos aspectos auxiliares:
El registro condicional (como "registrar cada 100 pasos") tiene un nuevo aspecto
Para controlar las operaciones y el código asociado, puede envolverlas en una sentencia if normal (que funciona en modo eager y en
@tf.function
mediante autógrafo) o en unatf.cond
Para controlar sólo los resúmenes, utilice el nuevo administrador de contexto
tf.summary.record_if()
, y pase la condición booleana de su elecciónEstos sustituyen al patrón TF 1.x:
Sin escritura directa de
tf.compat.v1.Graph
- en lugar de ello utilice funciones de rastreoLa ejecución de los gráficos en TF 2.x utiliza
@tf.function
en vez del gráfico explícitoEn TF 2.x, utilice las nuevas API de seguimiento
tf.summary.trace_on()
ytf.summary.trace_export()
para registrar los gráficos de las funciones ejecutadas
No más caché de escritor global por logdir con
tf.summary.FileWriterCache
Los usuarios deberían implementar su propia caché/compartición de objetos escritores, o simplemente utilizar escritores separados (el soporte de TensorBoard para esto ú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 sólo afecta a los usuarios que analizan manualmente los datos resumidos de los archivos de eventos
Los datos de resumen se almacenan ahora como bytes de tensor; puede utilizar
tf.make_ndarray(event.summary.value[0].tensor)
para convertirlos a numpy