Ver en TensorFlow.org | Ejecutar en Google Colab | Ver fuente en GitHub | Descargar cuaderno |
import tensorflow as tf
TensorFlow 2.x incluye cambios significativos en el tf.summary
API se utiliza para escribir los datos de resumen para la visualización en TensorBoard.
Que ha cambiado
Es útil pensar en la tf.summary
API como dos sub-API:
- Un conjunto de operaciones para el registro de los resúmenes individuales -
summary.scalar()
,summary.histogram()
,summary.image()
,summary.audio()
, ysummary.text()
- que se llama línea de su código de modelo. - Lógica de escritura que recopila estos resúmenes individuales y los escribe en un archivo de registro con formato especial (que luego TensorBoard lee para generar visualizaciones).
En TF 1.x
Las dos mitades tenido que ser conectados manualmente juntos - por ir a buscar las salidas Resumen op través Session.run()
y llamar a FileWriter.add_summary(output, step)
. El v1.summary.merge_all()
op hace esto más fácil mediante el uso de una colección gráfica de agregar todas las salidas Resumen op, pero este enfoque todavía funcionaba mal para la ejecución ansiosos y flujo de control, lo que es especialmente mal adaptado para 2.x. TF
En TF 2.X
Las dos mitades están estrechamente integrados, y ahora individuales tf.summary
ops escriben sus datos inmediatamente cuando se ejecuta. El uso de la API desde el código de su modelo aún debería parecer familiar, pero ahora es fácil de ejecutar con entusiasmo sin dejar de ser compatible con el modo gráfico. La integración de las dos mitades de los medios de API del summary.FileWriter
es ahora parte del contexto de ejecución TensorFlow y se accede directamente por tf.summary
operaciones, 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.x:
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.1633086727.kokoro-gcp-ubuntu-prod-1386032077.31590.0.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.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.1.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.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.2.v2
Convirtiendo tu código
La conversión existente tf.summary
el uso de la API de TF 2.x no puede ser fiable automatizado, por lo que el tf_upgrade_v2
guión simplemente reescribe todo a tf.compat.v1.summary
. Para migrar a TF 2.x, deberá adaptar su código de la siguiente manera:
Un conjunto escritor predeterminado a través de
.as_default()
debe estar presente para el uso de 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
- Escritores por defecto no lo hacen (aún) se propagan a través de la
@tf.function
límite de ejecución - que sólo se detectan cuando se traza la función - por lo que la mejor práctica es llamarwriter.as_default()
dentro del cuerpo de la función, y para asegurar que el objeto escritor continúa existiendo siempre que el@tf.function
está siendo utilizado
El valor de "paso" se debe pasar en cada OP a través de un el
step
argumento- 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 repetitivo, soporte experimental para registrar un valor de paso por defecto está disponible como
tf.summary.experimental.set_step()
, pero esta es la funcionalidad provisional que se puede cambiar sin previo aviso
Las firmas de funciones de operaciones sumarias individuales han cambiado
- El valor de retorno ahora es un booleano (que indica si realmente se escribió un resumen)
- El segundo nombre de parámetro (si se utiliza) ha cambiado de
tensor
dedata
- La
collections
parámetro se ha eliminado; las colecciones son solo TF 1.x - La
family
parámetro se ha eliminado; solo usotf.name_scope()
[Solo para usuarios de ejecución de sesión / modo de gráfico heredado]
En primer lugar inicializar el escritor con
v1.Session.run(writer.init())
Use
v1.summary.all_v2_summary_ops()
para obtener todas las operaciones de resumen TF 2.x para el gráfico actual, por ejemplo, para ejecutarlos a través deSession.run()
Enjuague el escritor con
v1.Session.run(writer.flush())
y lo mismo paraclose()
Si el código 1.x TF se usa en lugar tf.contrib.summary
API, que es mucho más similar a la API TF 2.x, por lo tf_upgrade_v2
script automatizar la mayoría de los pasos de migración (y emiten advertencias o errores para cualquier uso que no puede ser migrado por completo). En su mayor parte sólo se reescribe las llamadas a la API a tf.compat.v2.summary
; si sólo se necesita compatibilidad con 2.x TF puede caer el compat.v2
y simplemente hacer referencia a ella 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
- Para operaciones de control y código asociado, envolverlos en una declaración regular si (que funciona en modo ansiosos y en
@tf.function
a través de autógrafos ) o untf.cond
- Para controlar los sumarios solo, utilice la nueva
tf.summary.record_if()
gestor de contexto, y pasarlo al estado booleano de su elección Estos reemplazan el patrón TF 1.x:
if condition: writer.add_summary()
- Para operaciones de control y código asociado, envolverlos en una declaración regular si (que funciona en modo ansiosos y en
Ninguna escritura directa de
tf.compat.v1.Graph
- en vez funciones de uso traza- Ejecución de gráficos en usos TF 2.x
@tf.function
en lugar del gráfico explícita - En 2.x TF, utilice la API de nuevo al estilo de trazado
tf.summary.trace_on()
ytf.summary.trace_export()
para registrar las gráficas de funciones ejecutadas
- Ejecución de gráficos en usos TF 2.x
Sin almacenamiento en caché escritor más global por logdir con
tf.summary.FileWriterCache
- Los usuarios deben implementar ya sea su propio almacenamiento en caché / intercambio de objetos de escritor, o simplemente utilizan los escritores independientes (apoyo TensorBoard para el último es en curso )
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 utilizar
tf.make_ndarray(event.summary.value[0].tensor)
para convertirlo en numpy