Voir sur TensorFlow.org | Exécuter dans Google Colab | Voir la source sur GitHub | Télécharger le cahier |
import tensorflow as tf
Tensorflow 2.x inclut des changements importants à la tf.summary
API utilisée pour les données de synthèse d'écriture pour la visualisation en TensorBoard.
Qu'est-ce qui a changé
Il est utile de penser à la tf.summary
API comme deux sous-API:
- Un ensemble d'opérations pour des résumés individuels d' enregistrement -
summary.scalar()
,summary.histogram()
,summary.image()
,summary.audio()
, etsummary.text()
- qui sont appelés en ligne à partir de votre code modèle. - Logique d'écriture qui collecte ces résumés individuels et les écrit dans un fichier journal spécialement formaté (que TensorBoard lit ensuite pour générer des visualisations).
Dans TF 1.x
Les deux moitiés devaient être câblées ensemble manuellement - en allant chercher les sorties op sommaire via Session.run()
et appeler FileWriter.add_summary(output, step)
. Le v1.summary.merge_all()
op a fait cela plus facile en utilisant une collection de graphique pour regrouper toutes les sorties op sommaire, mais cette approche a encore mal à l' exécution avide et flux de contrôle, ce qui rend particulièrement mal adapté pour TF 2.x.
Dans TF 2.X
Les deux moitiés sont étroitement intégrées, et maintenant chaque tf.summary
ops écrivent leurs données immédiatement lors de l' exécution. L'utilisation de l'API à partir de votre code de modèle devrait toujours sembler familière, mais elle est désormais conviviale pour une exécution rapide tout en restant compatible avec le mode graphique. L' intégration des deux moitiés des moyens API la summary.FileWriter
fait maintenant partie du contexte d'exécution de tensorflow et s'accéder directement tf.summary
ops, donc la configuration des écrivains est la partie principale qui est différent.
Exemple d'utilisation avec exécution rapide, la valeur par défaut dans 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
Exemple d'utilisation avec l'exécution du graphe 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
Exemple d'utilisation avec l'exécution du graphique TF 1.x hérité :
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
Conversion de votre code
La conversion existante tf.summary
utilisation de l'API TF 2.x ne peut pas être fiable automatisé, de sorte que le tf_upgrade_v2
scénario réécrit tout juste à tf.compat.v1.summary
. Pour migrer vers TF 2.x, vous devrez adapter votre code comme suit :
Un ensemble par défaut écrivain via
.as_default()
doit être présent à l' utilisation ops sommaires- Cela signifie exécuter des opérations avec empressement ou utiliser des opérations dans la construction de graphes
- Sans un rédacteur par défaut, les opérations récapitulatives deviennent des opérations silencieuses
- Écrivains défaut ne pas (encore) se propagent à travers le
@tf.function
limite d'exécution - ils ne sont détectés que lorsque la fonction est tracée - si la meilleure pratique est d'appelerwriter.as_default()
dans le corps de la fonction, et de faire en sorte que l'objet écrivain continue d'exister tant que le@tf.function
est utilisé
La valeur « étape » doit être passé dans chaque op via une l'
step
arguments- TensorBoard nécessite une valeur de pas pour afficher les données sous forme de série temporelle
- Le passage explicite est nécessaire car l'étape globale de TF 1.x a été supprimée, donc chaque opération doit connaître la variable d'étape souhaitée à lire
- Pour réduire boilerplate, un support expérimental pour l' enregistrement d' une valeur de pas par défaut est disponible sous forme
tf.summary.experimental.set_step()
, mais cela est une fonctionnalité provisoire qui peut être modifié sans préavis
Les signatures de fonction des opérations de résumé individuelles ont changé
- La valeur de retour est maintenant un booléen (indiquant si un résumé a été réellement écrit)
- Le deuxième nom de paramètre ( le cas échéant) a changé de
tensor
dedata
- Les
collections
paramètre a été supprimé; les collections sont uniquement TF 1.x - La
family
paramètre a été supprimé; juste utilisationtf.name_scope()
[Uniquement pour les utilisateurs en mode graphique hérité/exécution de session]
Tout d' abord initialiser l'écrivain avec
v1.Session.run(writer.init())
Utilisez
v1.summary.all_v2_summary_ops()
pour obtenir toutes les opérations sommaires TF 2.x pour le graphique actuel, par exemple les exécuter viaSession.run()
Purger l'écrivain avec
v1.Session.run(writer.flush())
et de même pourclose()
Si votre code 1.x TF a été au lieu d' utiliser tf.contrib.summary
API, il est beaucoup plus semblable à l'API TF 2.x, donc tf_upgrade_v2
script automatiser la plupart des étapes de migration (et émettent des avertissements ou des erreurs pour toute utilisation qui ne peut pas être entièrement migré). Pour la plupart , il réécrit seulement les appels API à tf.compat.v2.summary
; si vous avez seulement besoin de compatibilité avec TF 2.x vous pouvez laisser tomber le compat.v2
et référence tout comme tf.summary
.
Conseils supplémentaires
En plus des domaines critiques ci-dessus, certains aspects auxiliaires ont également changé :
L'enregistrement conditionnel (comme « journal toutes les 100 étapes ») a un nouveau look
- Pour ops de contrôle et le code associé, les envelopper dans une régulière instruction if (qui fonctionne en mode avide et
@tf.function
via autographe ) ou untf.cond
- Pour contrôler seulement des résumés, utilisez la nouvelle
tf.summary.record_if()
gestionnaire de contexte, et transmettre la condition booléenne de votre choix Ceux-ci remplacent le modèle TF 1.x :
if condition: writer.add_summary()
- Pour ops de contrôle et le code associé, les envelopper dans une régulière instruction if (qui fonctionne en mode avide et
Aucune écriture directe de
tf.compat.v1.Graph
- au lieu des fonctions de trace l' utilisation- Graphique exécution dans les utilisations TF 2.x
@tf.function
au lieu de l'explicite graphique - Dans TF 2.x, utilisez la nouvelle API de style de traçage
tf.summary.trace_on()
ettf.summary.trace_export()
pour enregistrer les graphiques de fonctions exécutées
- Graphique exécution dans les utilisations TF 2.x
Aucune mise en cache plus globale de l' écrivain par logdir avec
tf.summary.FileWriterCache
- Les utilisateurs doivent soit mettre en œuvre leur propre mise en cache / partage d'objets écrivain, ou tout simplement utiliser des écrivains indépendants (soutien TensorBoard pour ce dernier est en cours )
La représentation binaire du fichier d'événement a changé
- TensorBoard 1.x prend déjà en charge le nouveau format ; cette différence n'affecte que les utilisateurs qui analysent manuellement les données récapitulatives des fichiers d'événements
- Les données récapitulatives sont désormais stockées sous forme d'octets tenseurs ; vous pouvez utiliser
tf.make_ndarray(event.summary.value[0].tensor)
pour le convertir en numpy