12 KiB
TP05 - Synthèse : monitoring, dérive et redéploiement
Fil rouge : prédiction de la consommation électrique (kWh, 128 clients portugais, pas de 15 min).
Scénario : un modèle a été entraîné sur 2011 et tourne toujours en production plusieurs années plus tard. En ingénieur MLOps, on vérifie si les données 2014 observées en production ont dérivé par rapport à l'entraînement, on analyse cette dérive avec Evidently, puis on mesure son impact sur les performances (2012 -> 2014) pour décider d'une stratégie de maintenance.
Ce qui a été construit
tp_module5_monitoring_derive.ipynb(notebook exécuté) : Partie 1 (moyennes + histogrammes delag_30d2011 vs 2014), Partie 2 (rapport de dérive EvidentlyDataDriftPreset), Partie 3 (modèle linéaire entraîné sur 2011, évalué sur 2011-2014). Réutiliselab/constants.py(chemins, cible, features).tp05_evidently_drift_2011_vs_2014.html: rapport Evidently interactif complet (à ouvrir dans un navigateur).- Choix technique : la feature
lag_365d(consommation 365 jours plus tôt) est exclue car elle est indéfinie (NaN) sur toute l'année 2011 (première année, pas d'historique 2010). On travaille donc sur les 5 features définies sur les deux périodes :lag_1d, lag_7d, lag_30d, rolling_mean_7d, rolling_mean_30d. Cet ensemble sert à la fois au rapport de dérive et au modèle entraîné sur 2011.
Partie 1 - Observer une dérive
Feature lag_30d, sur les années complètes 2011 (train) et 2014 (production) :
| Année | Moyenne lag_30d |
Effectif |
|---|---|---|
| 2011 (train) | 62.041 kWh | 4 116 352 |
| 2014 (prod) | 54.054 kWh | 4 485 120 |
| Écart | -7.986 kWh | -12.9 % |
1.1 - Les deux distributions semblent-elles similaires ? Non. Elles gardent la même forme générale (distribution asymétrique étalée vers la droite : beaucoup de petites consommations, une longue queue de fortes valeurs), mais l'histogramme 2014 est décalé vers les valeurs plus faibles et sa moyenne est nettement plus basse. Visuellement, le décalage est net.
1.2 - La moyenne a-t-elle évolué entre 2011 et 2014 ?
Oui, franchement : de 62.04 kWh à 54.05 kWh, soit -7.99 kWh (-12.9 %). La consommation moyenne
(observée via lag_30d) a baissé d'environ 13 % entre l'entraînement et la production.
1.3 - Cette évolution paraît-elle suffisamment importante pour parler de dérive ? Une baisse de ~13 % de la moyenne est un signal fort et cohérent d'un changement de distribution : c'est un indice sérieux de dérive des données. Attention toutefois : la moyenne seule ne prouve pas une dérive statistique (deux distributions peuvent avoir des moyennes proches et des formes différentes, ou l'inverse). Il faut confirmer avec une analyse sur toute la distribution, avec un test et un seuil objectifs (Partie 2).
1.4 - Cette première analyse est-elle suffisante pour conclure sur l'état du modèle ? Pourquoi ?
Non. Elle ne porte que sur une feature (lag_30d), via un seul indicateur (moyenne + comparaison
visuelle), sans test statistique ni seuil, et elle ne dit rien des autres features ni de l'impact
réel sur la performance du modèle. C'est un premier indice, pas une conclusion. Il faut (a) un outil de
monitoring qui teste toutes les features (Partie 2) et (b) mesurer la performance dans le temps (Partie 3).
Partie 2 - Analyse avec un outil de monitoring (Evidently)
Rapport DataDriftPreset comparant 2011 (référence) et 2014 (courant), échantillon de 200 000 lignes par
période (seed fixe). Test choisi automatiquement par Evidently pour de grands échantillons numériques :
distance de Wasserstein normalisée, seuil 0.1.
| Feature | Test | Drift score | Seuil | Dérive ? |
|---|---|---|---|---|
| lag_1d | Wasserstein distance (normed) | 0.165 | 0.1 | Oui |
| lag_7d | Wasserstein distance (normed) | 0.167 | 0.1 | Oui |
| lag_30d | Wasserstein distance (normed) | 0.167 | 0.1 | Oui |
| rolling_mean_7d | Wasserstein distance (normed) | 0.188 | 0.1 | Oui |
| rolling_mean_30d | Wasserstein distance (normed) | 0.191 | 0.1 | Oui |
Verdict global : dataset_drift = True, 5 / 5 features en dérive (100 %).
2.1 - Combien de features présentent une dérive ? Les 5 features analysées présentent une dérive (5 / 5, soit 100 %). Toutes dépassent le seuil de 0.1.
2.2 - Toutes les features évoluent-elles de la même manière ?
Toutes dérivent, mais pas avec la même intensité. Les distances de Wasserstein vont de 0.165
(lag_1d) à 0.191 (rolling_mean_30d). Les moyennes glissantes (rolling_mean_7d 0.188,
rolling_mean_30d 0.191) dérivent un peu plus que les lags bruts (0.165-0.167) : les indicateurs
lissés/tendanciels captent davantage la baisse durable du niveau de consommation.
2.3 - Identifiez deux métriques ou indicateurs du rapport. À quoi servent-ils ?
- Le drift score par feature (ici la distance de Wasserstein normalisée) : il quantifie l'écart entre la distribution de référence (2011) et la distribution courante (2014) pour chaque variable, et le compare à un seuil (0.1). Il sert à détecter et localiser la dérive, feature par feature.
- Le verdict global "Dataset Drift" + la part de colonnes en dérive : il agrège les décisions par feature (nombre / pourcentage de colonnes dérivées, ici 5/5 = 100 %) en une conclusion au niveau du dataset entier. Il sert à trancher globalement (le dataset a-t-il dérivé, oui/non). (Le rapport affiche aussi, par feature, les histogrammes de distribution référence vs courant, utiles pour visualiser la nature du décalage.)
2.4 - Le rapport conclut-il à une dérive globale du dataset ? Justifiez.
Oui. dataset_drift = True. Le critère par défaut d'Evidently (déclarer une dérive du dataset quand la
part de colonnes en dérive dépasse 50 %) est largement franchi : 100 % des colonnes dérivent.
Le rapport conclut donc sans ambiguïté à une dérive globale des données d'entrée.
Partie 3 - Mesurer l'impact sur les performances
Modèle (régression linéaire) entraîné sur 2011 uniquement, évalué sur chaque année complète :
| Année | Rôle | RMSE (kWh) | MAE (kWh) |
|---|---|---|---|
| 2011 | train (référence) | 7.904 | 4.450 |
| 2012 | évaluation (prod) | 7.595 | 4.178 |
| 2013 | évaluation (prod) | 7.486 | 4.095 |
| 2014 | évaluation (prod) | 7.101 | 3.911 |
Résultat marquant : l'erreur ne se dégrade pas, elle diminue légèrement d'année en année.
3.1 - Peut-on comparer 2011 vs 2012 au même titre que 2012 vs 2013 ? Non. 2011 est l'année d'entraînement : l'erreur y est mesurée in-sample (le modèle a déjà vu ces données), donc optimiste. Comparer 2011 (in-sample) à 2012 (hors échantillon) mélange deux régimes différents, alors que 2012 vs 2013 compare deux années hors échantillon entre elles (comparaison homogène). De plus, le niveau de consommation change d'une année à l'autre : comparer des RMSE bruts est biaisé par l'échelle de la cible (voir 3.3). 2011 doit donc être traité comme référence de train, pas comme un point de comparaison équivalent aux années de production.
3.2 - Observe-t-on une dégradation progressive ? Non. En valeur absolue, la performance s'améliore légèrement : RMSE 7.90 -> 7.60 -> 7.49 -> 7.10 et MAE 4.45 -> 4.18 -> 4.10 -> 3.91 de 2011 à 2014. Aucune dégradation observée sur ces métriques.
3.3 - Cette (absence de) dégradation est-elle cohérente avec la dérive détectée ?
À première vue c'est surprenant (dérive nette en Partie 2, mais pas de perte de performance), et c'est
instructif : une dérive des données ne signifie pas automatiquement une dégradation du modèle.
Explication : la consommation a baissé (~-13 % sur lag_30d, Partie 1), donc la cible (kWh) est plus
petite en 2014 ; comme RMSE et MAE sont des erreurs absolues en kWh, elles diminuent mécaniquement
quand l'échelle de la cible diminue. Pendant ce temps, la relation features -> cible (les lags prédisent
la consommation courante) est restée stable. On a donc une dérive des données sans dérive de la
relation. Pour comparer rigoureusement les années, il faudrait une métrique indépendante de l'échelle
(MAPE, R², RMSE normalisé).
3.4 - Peut-on conclure que le modèle 2011 est encore fiable en 2014 ? Sur la base des erreurs absolues, il ne s'est pas dégradé (il fait même un peu mieux en kWh). Mais on ne peut pas conclure à sa pleine fiabilité sur ces seuls chiffres : (1) les métriques absolues sont trompeuses quand l'échelle de la cible change ; (2) on n'a mesuré que l'amplitude de l'erreur, pas un éventuel biais systématique (sur/sous-estimation) ni la performance par segment (client, saison). Verdict prudent : pas de signe de dégradation, mais à confirmer avec des métriques relatives et une analyse des résidus avant de déclarer le modèle fiable.
3.5 - Que faudrait-il faire ensuite : surveiller, réentraîner, ou redéployer ? Surveiller. La dérive des données est réelle, mais sans impact mesuré sur la performance : rien n'impose un réentraînement ou un redéploiement immédiat (ce serait du travail et du risque pour un gain non démontré). On met en place un monitoring continu (dérive des features + performance suivie avec une métrique relative + dérive des prédictions et de la cible dès que la vérité terrain arrive) et on déclenche un réentraînement seulement si/quand la performance se dégrade réellement ou qu'un concept drift apparaît.
3.6 - Quel type de dérive semble en jeu ? Quelles analyses préconisez-vous ? Type : data drift (dérive des covariables / covariate shift). Les distributions des features d'entrée ont changé (baisse durable du niveau de consommation), tandis que la relation features -> cible semble stable (pas de perte de performance) : pas de concept drift évident. Analyses préconisées :
- suivre une métrique de performance indépendante de l'échelle (MAPE, R², nRMSE) dans le temps, plutôt que le RMSE brut ;
- monitorer aussi la dérive des prédictions et de la cible (target drift), pas seulement des features en entrée ;
- analyser les résidus (biais moyen, hétéroscédasticité) et segmenter (par client, par saison) ;
- surtout, dès que la vérité terrain est disponible (avec délai), recalculer la performance réelle en production pour détecter précocement un éventuel concept drift : c'est la fermeture de la feedback loop MLOps (surveiller -> alerter -> réentraîner -> redéployer).
Reproduire
Sur la VM, dans ~/tp (venv /opt/venvs/mlops). Le TP05 est 100 % local (données /data/modelling) :
aucun secret réseau (MLflow, S3) n'est nécessaire.
# Ré-exécuter le notebook (régénère les sorties + le rapport HTML)
/opt/venvs/mlops/bin/jupyter nbconvert --to notebook --execute --inplace tp_module5_monitoring_derive.ipynb
Consultation interactive (service jupyter-tp, token mlops) :
https://jupyter.192-168-122-143.nip.io/lab/tree/tp_module5_monitoring_derive.ipynb?token=mlops