Module 3 — Suivi des expériences avec MLflow
Le mercredi, Alice a lancé 37 entraînements pour comparer trois algorithmes, sept jeux de variables et cinq valeurs de régularisation. Le vendredi, on lui demande : « celui qui donnait 0,84, c'était avec quel jeu de variables ? » Elle ne sait plus. Sans suivi, la moitié du travail expérimental est jetée le vendredi soir.
Le vocabulaire de MLflow
MLflow Tracking organise les essais en trois niveaux :
- Une expérience est un projet, par exemple
churn-telecom-v3. - Une exécution (
run) est un entraînement individuel : un identifiant, un moment, une graine. - Une exécution porte des paramètres (choix figés avant l'entraînement), des métriques (mesures issues de l'entraînement) et des artefacts (fichiers produits : modèle, courbe ROC, matrice de confusion).
Cette séparation compte. Les paramètres sont ce qu'on choisit ; les métriques sont ce qu'on mesure. Confondre les deux dans un même dictionnaire rend l'interface de comparaison inutilisable.
Le squelette d'un entraînement suivi
import mlflow
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score
mlflow.set_tracking_uri("http://mlflow.interne:5000")
mlflow.set_experiment("churn-telecom-v3")
with mlflow.start_run(run_name="rf-100-arbres-var-v7") as run:
params = {"n_estimators": 100, "max_depth": 12, "graine": 42}
mlflow.log_params(params)
mlflow.log_param("jeu_variables", "v7")
modele = RandomForestClassifier(
n_estimators=params["n_estimators"],
max_depth=params["max_depth"],
random_state=params["graine"],
)
modele.fit(X_apprentissage, y_apprentissage)
auc = roc_auc_score(y_validation, modele.predict_proba(X_validation)[:, 1])
mlflow.log_metric("auc_validation", auc)
mlflow.sklearn.log_model(modele, artifact_path="modele")
mlflow.log_artifact("rapports/matrice_confusion.png")
Cinq appels suffisent à rendre l'exécution comparable, retrouvable et
rejouable. L'interface web de MLflow affiche alors un tableau des
37 essais, triable par métrique, filtrable par paramètre, avec un bouton
« comparer » qui superpose les courbes.
La journalisation automatique
Pour scikit-learn, PyTorch Lightning, XGBoost ou LightGBM, MLflow
propose la journalisation automatique :
mlflow.sklearn.autolog()
with mlflow.start_run():
modele.fit(X_apprentissage, y_apprentissage)
Elle capture tous les hyperparamètres passés à fit, le modèle
sérialisé, la signature (types et formes des entrées et sorties) et un
exemple d'entrée. Elle évite les oublis, mais elle capture aussi beaucoup
de bruit. En pratique, on active autolog puis on ajoute à la main les
métriques métier (taux_faux_positifs_a_5_pourcent, AUC_sur_le_segment_pro)
qui n'ont aucune raison d'être connues d'un cadre général.
Le serveur partagé
Par défaut, MLflow écrit dans un dossier local mlruns/. Ce mode convient
pour explorer seul, jamais pour une équipe. Deux personnes qui pointent
chacune sur leur dossier local perdent la comparabilité au premier échange.
Un serveur partagé se monte en une commande :
mlflow server \
--backend-store-uri postgresql://mlflow:xxx@bdd:5432/mlflow \
--default-artifact-root s3://mon-bucket/mlflow-artifacts/ \
--host 0.0.0.0 --port 5000
Deux stockages sont impliqués. La base relationnelle porte les paramètres et
les métriques (petits, structurés, interrogeables en SQL). Le stockage
objet porte les artefacts (modèles, images, gros fichiers). Séparer les
deux est ce qui rend MLflow capable de tenir des centaines de milliers
d'exécutions sans étouffer la base.
Nommer et étiqueter, une hygiène qui paie
Un nom d'exécution comme run_2026_09_03_14h27 n'aide personne. Un nom
comme rf-100arbres-var-v7-graine42 se lit à froid. Les étiquettes
(mlflow.set_tag("branche_git", "feat/nouvelle-var")) attachent le
contexte technique à l'exécution ; on retrouve six mois plus tard le
commit précis qui a produit un artefact.
Trois étiquettes rendent une équipe autonome :
branche_gitetcommit_git: la version exacte du codejeu_donnees_version: identifiant du snapshotDVC(module 4)auteur: la personne qui a lancé l'entraînement
Comparer trente exécutions en cinq minutes
Une fois la journalisation en place, l'interface MLflow permet quatre
gestes qui remplacent des heures de tableur :
- Trier par métrique et voir les cinq meilleures exécutions.
- Filtrer sur un paramètre (
jeu_variables = v7) pour isoler l'effet des variables du reste. - Comparer deux exécutions côte à côte : différences de paramètres mises en évidence, courbes superposées.
- Charger l'artefact d'un ancien essai en une ligne :
mlflow.pyfunc.load_model("runs:/<run_id>/modele").
MLflow ne rend pas un modèle meilleur. Il rend le travail expérimental
capitalisable : ce qu'on a essayé, ce qui a marché, ce qui n'a pas marché,
tout reste accessible pour la personne qui prendra le relais dans six mois.
C'est la différence entre un dépôt de connaissances et un souvenir.
En résumé
- Trois niveaux : expérience, exécution, artefacts ; ne confondez jamais paramètres (choisis) et métriques (mesurées).
- Cinq appels
log_params,log_metric,log_model,log_artifact,log_paramsuffisent à rendre une exécution retrouvable. - La journalisation automatique évite les oublis ; ajoutez à la main les métriques métier.
- Un serveur partagé (base SQL + stockage objet) est ce qui rend le suivi utile à plus d'une personne.
Le module 4 ajoute le versionnage des données et du modèle, pour que
branche_git et jeu_donnees_version deviennent des identifiants
opposables.