Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/tensorboard/migrate.ipynb
25115 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

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.

import tensorflow as tf

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(), y summary.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:

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

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

Ejemplo de uso con 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)
ls /tmp/mylogs/session

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:

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:

# Enable eager execution. tf.compat.v1.enable_v2_behavior() # A default TF 2.x summary writer is available. writer = tf.summary.create_file_writer("/tmp/mylogs/enable_v2_in_v1") # A step is set for the writer. with writer.as_default(step=0): # Below invokes `tf.summary.scalar`, and the return value is an empty bytestring. tf.compat.v1.summary.scalar('float', tf.constant(1.0), family="family")

Migración completa

Para migrar completamente a TF 2.x, tendrá que adaptar su código como se indica a continuación:

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

    • Esto 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 a writer.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

  2. 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

  3. 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 a data

    • Se eliminó el parámetro collections; las colecciones son sólo TF 1.x

    • Se eliminó el parámetro family; utilice simplemente tf.name_scope()

  4. [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 mediante Session.run()

    • Purgar el escritor con v1.Session.run(writer.flush()) y lo mismo para close()

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 una tf.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ón

    • Estos sustituyen al patrón TF 1.x:

      if condition: writer.add_summary()
  • Sin escritura directa de tf.compat.v1.Graph - en lugar de ello utilice funciones de rastreo

    • La ejecución de los gráficos en TF 2.x utiliza @tf.function en vez del gráfico explícito

    • En TF 2.x, utilice las nuevas API de seguimiento tf.summary.trace_on() y tf.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