Aller au contenu principal

Module 7 — TensorBoard : suivre pertes, poids et histogrammes

Les journaux de fit donnent deux nombres par époque. C'est suffisant pour savoir qu'un entraînement se passe mal, et très insuffisant pour savoir pourquoi. TensorBoard répond à la seconde question.

Brancher le suivi

Le rappel s'ajoute à la liste du module 6, avec un répertoire distinct par exécution.

import datetime
from tensorflow import keras

horodatage = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
journal = f"journaux/{horodatage}-adam-lr1e3"

suivi = keras.callbacks.TensorBoard(
log_dir=journal,
histogram_freq=1,
write_graph=True,
update_freq="epoch",
)

modele.fit(jeu, validation_data=jeu_val, epochs=50, callbacks=[suivi])

Puis, depuis un terminal ou une cellule de carnet :

tensorboard --logdir journaux

Le nom du répertoire est le seul mécanisme d'identification des exécutions. Un nom qui décrit la configuration — optimiseur, taux, architecture — vous évite de comparer douze courbes anonymes une semaine plus tard. C'est un investissement de dix secondes qui se rentabilise systématiquement.

update_freq="batch" coûte cher

Écrire à chaque lot produit des courbes très détaillées et des journaux énormes, et l'écriture elle-même devient un goulot : sur un petit modèle, elle peut doubler la durée d'une époque. Réservez ce réglage à un diagnostic ponctuel sur quelques centaines de pas, jamais à un entraînement complet.

Comparer des exécutions, pas les regarder une par une

C'est l'usage qui apporte le plus de valeur. Avec un répertoire par configuration sous un même parent, TensorBoard superpose les courbes et rend les comparaisons immédiates.

journaux/
20260810-1420-adam-lr1e3/
20260810-1455-adam-lr1e4/
20260810-1530-sgd-momentum/

Trois lectures apparaissent alors d'un coup d'œil. L'écart entre perte d'entraînement et perte de validation donne le surajustement, exactement comme au module 9 du cours 07. La pente initiale indique si le taux d'apprentissage est trop faible. Et un décrochage brutal de la validation situe l'époque où l'entraînement a divergé.

Les histogrammes de poids, l'outil sous-employé

histogram_freq=1 enregistre la distribution des poids et des activations à chaque époque. C'est le seul moyen de voir les pathologies décrites au module 6 du cours 07 pendant qu'elles se produisent.

Ce que montre l'histogrammeDiagnostic
distribution qui s'aplatit vers zéro couche après couchegradient qui s'évanouit
valeurs qui s'étalent sur plusieurs ordres de grandeurgradient qui explose
activations concentrées en zéro dans une couche ReLUneurones morts
distribution figée d'une époque à l'autrecouche qui n'apprend pas

Le dernier cas mérite une attention particulière, car il est silencieux. Une couche dont les poids ne bougent plus peut signaler une couche gelée par erreur, un tf.Variable créé sans add_weight comme au module 4, ou un gradient qui n'atteint plus cette profondeur. Aucune de ces trois causes ne produit de message.

Journaliser ses propres grandeurs

Toute grandeur scalaire peut rejoindre TensorBoard, ce qui est utile pour les métriques métier que Keras ignore.

import tensorflow as tf

redacteur = tf.summary.create_file_writer(journal + "/metier")

with redacteur.as_default():
tf.summary.scalar("cout_faux_positifs", cout, step=epoque)
tf.summary.histogram("scores_predits", scores, step=epoque)
tf.summary.image("erreurs", images_mal_classees, step=epoque, max_outputs=8)

L'argument step est obligatoire et sert d'axe des abscisses. Le journal d'images est particulièrement instructif : afficher à chaque époque les huit exemples les plus mal classés révèle souvent un problème d'étiquetage plutôt qu'un problème de modèle.

Le profileur répond à « pourquoi c'est lent »

Le profileur mesure la répartition du temps entre préparation des données et calcul, ce qui tranche la question laissée ouverte au module 5.

suivi = keras.callbacks.TensorBoard(
log_dir=journal,
profile_batch="10,20", # profile les lots 10 a 20
)

Profiler dès le premier lot mesure surtout l'initialisation et le traçage, pas le régime permanent : d'où l'intervalle décalé. L'onglet du profileur affiche ensuite le temps d'attente du dispositif de calcul. Au-delà de quelques pourcents, le pipeline de données est en cause et le module 5 s'applique.

La séquence de diagnostic

Face à un entraînement qui ne converge pas, regardez dans cet ordre : les courbes pour situer le moment du problème, les histogrammes de la couche concernée pour en identifier la nature, puis le graphe pour vérifier que l'architecture construite est bien celle que vous croyez avoir écrite. Cette dernière vérification surprend plus souvent qu'on ne l'admet, surtout avec l'API fonctionnelle où une branche peut rester débranchée sans provoquer d'erreur.

En résumé

  • Un répertoire par exécution, nommé d'après sa configuration, est ce qui rend les comparaisons exploitables ; c'est le seul mécanisme d'identification disponible.
  • La superposition des courbes donne d'un coup d'œil le surajustement, la qualité du taux d'apprentissage et l'époque d'une divergence.
  • Les histogrammes rendent visibles gradient évanescent, gradient explosif, neurones morts et couche figée — quatre pathologies qui ne produisent aucun message d'erreur.
  • Le profileur tranche entre goulot de données et goulot de calcul, à condition de profiler en régime permanent et non dès le premier lot.

Module suivant : l'apprentissage par transfert, qui permet d'obtenir de bons résultats sans entraîner un réseau de zéro.