Visualizza su TensorFlow.org | Esegui in Google Colab | Visualizza la fonte su GitHub | Scarica taccuino |
import tensorflow as tf
Tensorflow 2.x include modifiche significative alla tf.summary
API utilizzata per i dati di riepilogo scrittura per la visualizzazione in TensorBoard.
Cosa è cambiato?
E 'utile pensare alla tf.summary
API come due sotto-API:
- Un insieme di ops di registrazione singoli sommari -
summary.scalar()
,summary.histogram()
,summary.image()
,summary.audio()
, esummary.text()
- che sono chiamati in linea 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à dovuto essere collegati insieme manualmente - recuperando le uscite sintesi op via Session.run()
e chiamando FileWriter.add_summary(output, step)
. Il v1.summary.merge_all()
op reso questo più facile utilizzando una raccolta dati per aggregare tutte le uscite sintesi op, ma questo approccio ancora lavorato poco per l'esecuzione ansiosi e flusso di controllo, il che rende particolarmente inadatta per 2.x. TF
In TF 2.X
Le due metà sono strettamente integrati, e ora singoli tf.summary
op scrivere i dati immediatamente quando viene eseguito. L'utilizzo dell'API dal codice del modello dovrebbe ancora sembrare familiare, ma ora è amichevole per l'esecuzione impaziente pur rimanendo compatibile con la modalità grafico. Integrando le due metà dei mezzi API del summary.FileWriter
è ora parte del contesto di esecuzione tensorflow e viene accede direttamente tf.summary
OPS, quindi configurare scrittori è la parte principale che aspetto differente.
Esempio di utilizzo con esecuzione ansiosa, l'impostazione predefinita in 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
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.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.1.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.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.2.v2
Conversione del codice
Conversione esistente tf.summary
utilizzo all'API TF 2.x non può essere attendibilmente automatizzato, in modo che il tf_upgrade_v2
sceneggiatura appena riscrive tutto a tf.compat.v1.summary
. Per migrare a TF 2.x, dovrai adattare il tuo codice come segue:
Un insieme writer predefinito tramite
.as_default()
deve essere presente per uso ops sommarie- Ciò significa eseguire operazioni con entusiasmo o utilizzare operazioni nella costruzione di grafici
- Senza uno scrittore predefinito, le operazioni di riepilogo diventano no-op silenziose
- Scrittori di default non lo fanno (ancora) si diffondono in tutto il
@tf.function
esecuzione di confine - vengono rilevati solo quando è tracciata la funzione - così le migliori prassi è quella di chiamarewriter.as_default()
all'interno del corpo della funzione, e per garantire che l'oggetto scrittore continua ad esistere fintanto che il@tf.function
viene utilizzato
Il valore "step" deve essere passato in ciascun op tramite il
step
argomento- TensorBoard richiede un valore di passaggio per eseguire il rendering dei dati come serie temporali
- Il passaggio esplicito è necessario perché il passaggio globale da TF 1.x è stato rimosso, quindi ogni operazione deve conoscere la variabile di passaggio desiderata da leggere
- Per ridurre boilerplate, supporto sperimentale per la registrazione di un valore del passo di default è disponibile come
tf.summary.experimental.set_step()
, ma questa è la funzionalità provvisoria che possono essere modificate senza preavviso
Le firme delle funzioni delle singole operazioni di riepilogo sono cambiate
- Il valore restituito è ora un booleano (che indica se è stato effettivamente scritto un riepilogo)
- Il secondo nome del parametro (se utilizzato) è cambiato da
tensor
didata
- Il
collections
parametro è stato rimosso; le raccolte sono solo TF 1.x - La
family
dei parametri è stato rimosso; solo usotf.name_scope()
[Solo per utenti in modalità grafico legacy/esecuzione sessione]
In primo luogo inizializzare la scrittrice con
v1.Session.run(writer.init())
Utilizzare
v1.summary.all_v2_summary_ops()
per ottenere tutti ops sintesi TF 2.x per il grafico corrente, ad esempio per eseguirli tramiteSession.run()
Lavare lo scrittore con
v1.Session.run(writer.flush())
e allo stesso modo per ilclose()
Se il codice 1.x TF è stato invece utilizzato tf.contrib.summary
API, è molto più simile alla API TF 2.x, quindi tf_upgrade_v2
script automatizzare la maggior parte dei passaggi della migrazione (ed emettere avvisi o errori per qualsiasi utilizzo che non possono essere completamente migrato). Per la maggior parte solo riscrive le chiamate API al tf.compat.v2.summary
; se avete solo bisogno di compatibilità con 2.x TF si può cadere la compat.v2
e proprio riferimento come tf.summary
.
Ulteriori suggerimenti
Oltre alle criticità di cui sopra, sono cambiati anche alcuni aspetti ausiliari:
La registrazione condizionale (come "Registra ogni 100 passaggi") ha un nuovo aspetto
- Per ops di controllo e codice associato, avvolgerli in un normale if (che funziona in modalità desiderosi e in
@tf.function
via autografo ) o untf.cond
- Per controllare solo sommario, utilizzare il nuovo
tf.summary.record_if()
direttore di contesto, e passarlo la condizione booleana di vostra scelta Questi sostituiscono il modello TF 1.x:
if condition: writer.add_summary()
- Per ops di controllo e codice associato, avvolgerli in un normale if (che funziona in modalità desiderosi e in
No scrittura diretta del
tf.compat.v1.Graph
- invece funzioni di utilizzo in tracce- Esecuzione grafico in uso TF 2.x
@tf.function
al posto del grafico esplicito - In 2.x TF, utilizzare le API nuovo tracciato stile
tf.summary.trace_on()
etf.summary.trace_export()
per registrare grafici di funzioni eseguite
- Esecuzione grafico in uso TF 2.x
Non caching scrittore più globale per logdir con
tf.summary.FileWriterCache
- Gli utenti dovrebbero implementare sia la propria caching / condivisione di oggetti scrittore, o semplicemente usare scrittori separati (supporto TensorBoard per quest'ultimo è in corso )
La rappresentazione binaria del file evento è 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 di eventi
- I dati di riepilogo sono ora archiviati come byte di tensore; è possibile utilizzare
tf.make_ndarray(event.summary.value[0].tensor)
per convertirlo in NumPy