Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Migrazione dell'utilizzo di tf.summary a TF 2.0

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza sorgente su GitHub
import tensorflow as tf

TensorFlow 2.0 include modifiche significative all'API tf.summary utilizzata per scrivere dati di riepilogo per la visualizzazione in TensorBoard.

Cosa è cambiato

È utile pensare all'API tf.summary come a due API secondarie:

  • Una serie di operazioni per la registrazione di riepiloghi individuali - summary.scalar() , summary.histogram() , summary.image() , summary.audio() e summary.text() - che sono chiamati inline dal codice del modello.
  • Logica di scrittura che raccoglie questi singoli riepiloghi e li scrive in un file di registro appositamente formattato (che TensorBoard legge quindi per generare visualizzazioni).

In TF 1.x

Le due metà dovevano essere cablate manualmente insieme, recuperando gli output Session.run() riepilogo tramite Session.run() e chiamando FileWriter.add_summary(output, step) . L'operazione v1.summary.merge_all() reso tutto più semplice utilizzando una raccolta di grafici per aggregare tutti gli output v1.summary.merge_all() riepilogo, ma questo approccio ha funzionato ancora male per un'esecuzione impaziente e un flusso di controllo, rendendolo particolarmente inadatto per TF 2.0.

In TF 2.X

Le due metà sono strettamente integrate e ora le singole operazioni tf.summary scrivono i propri dati immediatamente quando vengono eseguite. L'uso dell'API dal codice del modello dovrebbe ancora sembrare familiare, ma ora è facile da eseguire con entusiasmo pur rimanendo compatibile con la modalità grafico. L'integrazione di entrambe le metà dell'API significa che il summary.FileWriter fa ora parte del contesto di esecuzione di TensorFlow ed è accessibile direttamente da tf.summary ops, quindi la configurazione dei writer è la parte principale che ha un aspetto diverso.

Utilizzo di esempio con un'esecuzione impaziente, l'impostazione predefinita in 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

Esempio di utilizzo con l'esecuzione del grafico 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

Esempio di utilizzo con l'esecuzione del grafico TF 1.x legacy:

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

Conversione del codice

La conversione tf.summary esistente di tf.summary TF 2.0 non può essere automatizzata in modo affidabile, quindi lo script tf_upgrade_v2 riscrive tutto in tf.compat.v1.summary . Per migrare a TF 2.0, dovrai adattare il tuo codice come segue:

  1. Un writer predefinito impostato tramite .as_default() deve essere presente per utilizzare le operazioni di riepilogo

    • Ciò significa eseguire le operazioni con entusiasmo o utilizzare le operazioni nella costruzione di grafici
    • Senza un writer predefinito, le operazioni di riepilogo diventano no-op silenziose
    • I writer predefiniti non si propagano (ancora) attraverso il limite di esecuzione della funzione @tf.function - vengono rilevati solo quando la funzione viene tracciata - quindi la procedura migliore è chiamare writer.as_default() all'interno del corpo della funzione e assicurarsi che l'oggetto writer continua ad esistere fintanto che viene utilizzata la funzione @tf.function
  2. Il valore "step" deve essere passato in ogni op tramite un argomento the step

    • TensorBoard richiede un valore di passaggio per eseguire il rendering dei dati come serie temporale
    • Il passaggio esplicito è necessario perché il passaggio globale da TF 1.x è stato rimosso, quindi ogni operazione deve conoscere la variabile del passaggio desiderata da leggere
    • Per ridurre il boilerplate, il supporto sperimentale per la registrazione di un valore di passo predefinito è disponibile come tf.summary.experimental.set_step() , ma questa è una funzionalità provvisoria che può essere modificata senza preavviso
  3. Le firme delle funzioni delle singole operazioni di riepilogo sono cambiate

    • Il valore restituito è ora un booleano (che indica se un riepilogo è stato effettivamente scritto)
    • Il nome del secondo parametro (se utilizzato) è cambiato da tensor a data
    • Il parametro delle collections è stato rimosso; le raccolte sono solo TF 1.x.
    • Il parametro della family è stato rimosso; usa solo tf.name_scope()
  4. [Solo per utenti con modalità grafico / esecuzione sessione precedenti]

    • Inizializza prima il writer con v1.Session.run(writer.init())

    • Usa v1.summary.all_v2_summary_ops() per ottenere tutte le operazioni di riepilogo di TF 2.0 per il grafico corrente, ad esempio per eseguirle tramite Session.run()

    • Lavare il writer con v1.Session.run(writer.flush()) e allo stesso modo per close()

Se il codice TF 1.x utilizzava invece l'API tf.contrib.summary , è molto più simile all'API TF 2.0, quindi tf_upgrade_v2 script tf_upgrade_v2 automatizzerà la maggior parte dei passaggi di migrazione (ed emetterà avvisi o errori per qualsiasi utilizzo che non può essere completamente migrato). Per la maggior parte riscrive solo le chiamate API a tf.compat.v2.summary ; se hai bisogno solo della compatibilità con TF 2.0+ puoi eliminare compat.v2 e fare riferimento ad esso come tf.summary .

Suggerimenti aggiuntivi

Oltre alle criticità di cui sopra, sono cambiati anche alcuni aspetti ausiliari:

  • La registrazione condizionale (come "registro ogni 100 passaggi") ha un nuovo aspetto

    • Per controllare le operazioni e il codice associato, racchiudili in una normale istruzione if (che funziona in modalità eager e nella funzione @tf.function tramite autografo ) o un tf.cond
    • Per controllare solo i riepiloghi, usa il nuovo gestore di contesto tf.summary.record_if() la condizione booleana di tua scelta
    • Questi sostituiscono il pattern TF 1.x:
if condition:
  writer.add_summary()
  • Nessuna scrittura diretta di tf.compat.v1.Graph - usa invece le funzioni di traccia

    • L'esecuzione del grafico in TF 2.0 utilizza la funzione @tf.function invece del grafico esplicito
    • In TF 2.0, usa le nuove API in stile tracing tf.summary.trace_on() e tf.summary.trace_export() per registrare i grafici delle funzioni eseguite
  • Niente più memorizzazione nella cache del writer globale per tf.summary.FileWriterCache di tf.summary.FileWriterCache con tf.summary.FileWriterCache

    • Gli utenti devono implementare la propria memorizzazione nella cache / condivisione di oggetti di scrittura o utilizzare solo scrittori separati (il supporto di TensorBoard per quest'ultimo è in corso )
  • La rappresentazione binaria del file di eventi è cambiata

    • TensorBoard 1.x supporta già il nuovo formato; questa differenza riguarda solo gli utenti che stanno analizzando manualmente i dati di riepilogo dai file degli eventi
    • I dati di riepilogo sono ora archiviati come byte tensoriali; puoi usare tf.make_ndarray(event.summary.value[0].tensor) per convertirlo in numpy