Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

Migrieren der Verwendung von tf.summary auf TF 2.0

Ansicht auf TensorFlow.org In Google Colab ausführen Quelle auf GitHub anzeigen
import tensorflow as tf

TensorFlow 2.0 enthält wesentliche Änderungen an der tf.summary API, mit der Zusammenfassungsdaten für die Visualisierung in TensorBoard geschrieben werden.

Was hat sich geändert?

Es ist nützlich, sich die tf.summary API als zwei Unter-APIs tf.summary :

  • Eine Reihe von Operationen zum Aufzeichnen einzelner Zusammenfassungen - summary.scalar() , summary.histogram() , summary.image() , summary.audio() und summary.text() -, die von Ihrem Modellcode inline aufgerufen werden.
  • Schreiblogik, die diese einzelnen Zusammenfassungen sammelt und in eine speziell formatierte Protokolldatei schreibt (die TensorBoard dann liest, um Visualisierungen zu generieren).

In TF 1.x.

Die beiden Hälften mussten manuell miteinander verbunden werden - indem die Zusammenfassung der Op-Ausgaben über Session.run() FileWriter.add_summary(output, step) und FileWriter.add_summary(output, step) . Die v1.summary.merge_all() erleichterte dies durch die Verwendung einer Diagrammsammlung zum Aggregieren aller zusammenfassenden Op-Ausgaben. Dieser Ansatz funktionierte jedoch immer noch schlecht für die eifrige Ausführung und den Kontrollfluss, was ihn für TF 2.0 besonders v1.summary.merge_all() machte.

In TF 2.X.

Die beiden Hälften sind eng miteinander verbunden, und jetzt schreiben einzelne tf.summary ops ihre Daten sofort, wenn sie ausgeführt werden. Die Verwendung der API aus Ihrem Modellcode sollte noch vertraut sein, ist aber jetzt für eine eifrige Ausführung geeignet, während der Grafikmodus kompatibel bleibt. Das Integrieren beider Hälften der API bedeutet die Zusammenfassung. summary.FileWriter ist jetzt Teil des TensorFlow-Ausführungskontexts und wird direkt von tf.summary ops tf.summary , sodass die Konfiguration von Writern der Hauptteil ist, der anders aussieht.

Beispiel für eine Verwendung mit eifriger Ausführung, die Standardeinstellung 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

Beispiel für die Verwendung mit der Ausführung von tf.function graph:

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

Beispiel für die Verwendung mit älteren TF 1.x-Diagrammen:

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

Konvertieren Sie Ihren Code

Das Konvertieren der vorhandenen Verwendung von tf.summary in die TF 2.0-API kann nicht zuverlässig automatisiert werden. tf_upgrade_v2 Skript tf_upgrade_v2 schreibt tf_upgrade_v2 einfach alles in tf.compat.v1.summary . Um auf TF 2.0 zu migrieren, müssen Sie Ihren Code wie folgt anpassen:

  1. Ein über .as_default() festgelegter Standardschreiber muss vorhanden sein, um Zusammenfassungsoperationen verwenden zu können

    • Dies bedeutet, dass Operationen eifrig ausgeführt werden oder Operationen in der Diagrammkonstruktion verwendet werden
    • Ohne einen Standardschreiber werden Zusammenfassungsoperationen zu stillen No-Ops
    • Standardschreiber verbreiten sich (noch) nicht über die Ausführungsgrenze von @tf.function - sie werden nur erkannt, wenn die Funktion verfolgt wird. writer.as_default() es sich, writer.as_default() innerhalb des Funktionskörpers writer.as_default() und sicherzustellen, dass das Writer-Objekt vorhanden ist bleibt bestehen, solange die Funktion @tf.function verwendet wird
  2. Der "Schritt" -Wert muss über das Argument step an jede Operation übergeben werden

    • TensorBoard benötigt einen Schrittwert, um die Daten als Zeitreihe zu rendern
    • Eine explizite Übergabe ist erforderlich, da der globale Schritt aus TF 1.x entfernt wurde, sodass jede Operation die gewünschte Schrittvariable zum Lesen kennen muss
    • Um die Boilerplate zu reduzieren, steht die experimentelle Unterstützung für die Registrierung eines Standardschrittwerts als tf.summary.experimental.set_step() . Dies ist jedoch eine vorläufige Funktionalität, die ohne vorherige Ankündigung geändert werden kann
  3. Die Funktionssignaturen der einzelnen Zusammenfassungsoperationen haben sich geändert

    • Der Rückgabewert ist jetzt ein Boolescher Wert (der angibt, ob eine Zusammenfassung tatsächlich geschrieben wurde).
    • Der zweite Parametername (falls verwendet) hat sich von tensor zu data geändert
    • Der collections wurde entfernt. Sammlungen sind nur TF 1.x.
    • Der family wurde entfernt. benutze einfach tf.name_scope()
  4. [Nur für ältere Benutzer im Grafikmodus / in der Sitzungsausführung]

    • Initialisieren Sie zuerst den Writer mit v1.Session.run(writer.init())

    • Verwenden Sie v1.summary.all_v2_summary_ops() , um alle TF 2.0-Zusammenfassungsoperationen für das aktuelle Diagramm Session.run() , z. B. um sie über Session.run() auszuführen.

    • Flush den Writer mit v1.Session.run(writer.flush()) und ebenfalls für close()

Wenn Ihr TF 1.x-Code stattdessen die API tf.contrib.summary , ähnelt er viel mehr der TF 2.0-API, sodass tf_upgrade_v2 Skript tf_upgrade_v2 die meisten Migrationsschritte automatisiert (und Warnungen oder Fehler für jede Verwendung tf_upgrade_v2 , die nicht vollständig sein kann migriert). Zum größten Teil werden nur die API-Aufrufe in tf.compat.v2.summary . Wenn Sie nur Kompatibilität mit TF 2.0+ benötigen, können Sie die compat.v2 compatible.v2 compat.v2 und einfach als tf.summary .

Zusätzliche Tipps

Zusätzlich zu den oben genannten kritischen Bereichen haben sich auch einige zusätzliche Aspekte geändert:

  • Die bedingte Aufzeichnung (wie "Alle 100 Schritte protokollieren") sieht neu aus

    • Um Operationen und den zugehörigen Code zu steuern, schließen Sie sie in eine reguläre if-Anweisung (die im eifrigen Modus und in der Funktion @tf.function per Autogramm @tf.function ) oder eine tf.cond
    • Um nur Zusammenfassungen zu steuern, verwenden Sie den neuen tf.summary.record_if() und übergeben Sie ihm die boolesche Bedingung Ihrer Wahl
    • Diese ersetzen das TF 1.x-Muster:
if condition:
  writer.add_summary()
  • Kein direktes Schreiben von tf.compat.v1.Graph - verwenden Sie stattdessen Trace-Funktionen

    • Die Diagrammausführung in TF 2.0 verwendet @tf.function anstelle des expliziten Diagramms
    • Verwenden Sie in TF 2.0 die neuen APIs im Tracing-Stil tf.summary.trace_on() und tf.summary.trace_export() , um ausgeführte Funktionsdiagramme aufzuzeichnen
  • Kein globales Writer-Caching mehr pro Protokollverzeichnis mit tf.summary.FileWriterCache

    • Nutzer sollten ihre eigenen Caching / Austausch von Writer - Objekte implementieren, oder einfach nur getrennte Schriftsteller (TensorBoard Unterstützung für letzteres verwenden im Gange )
  • Die binäre Darstellung der Ereignisdatei hat sich geändert

    • TensorBoard 1.x unterstützt das neue Format bereits. Dieser Unterschied betrifft nur Benutzer, die Zusammenfassungsdaten aus Ereignisdateien manuell analysieren
    • Zusammenfassungsdaten werden jetzt als Tensorbytes gespeichert. Sie können tf.make_ndarray(event.summary.value[0].tensor) , um es in numpy zu konvertieren