Files
ENI-projet-piscine/ml

ML EnerVision

Pipeline d'entrainement du modele de prevision de consommation energetique. Contexte complet : ADR 0005 (choix du modele) et ML-START.md (mecanisme d'acces aux donnees).

Element Choix
Python 3.14
Gestionnaire uv (uv.lock fait foi)
Modele LightGBM (regression, un seul modele global)
Suivi MLflow (parametres, metriques, artefact)
Lint/format ruff
Typage mypy en mode strict
Tests pytest, donnees synthetiques uniquement

Projet Python independant de apps/backend : le service FastAPI n'a aucune raison d'embarquer LightGBM/MLflow en dependance de production juste pour un script d'entrainement lance a la main.

Installation

uv sync --all-groups

Donnees

Deux sources, qui produisent le meme schema en sortie de enervision_ml.data (voir le module pour le detail) :

  • CSV (--csv), chemin de demarrage : lit directement ml/data/all_sites_combined.csv, le jeu de donnees fourni pour le jalon J3. Ce dossier est ignore par git (gros fichier, local a chaque poste) : recuperer le CSV et dataset_metadata.json aupres de l'equipe et les placer dans ml/data/ avant d'entrainer sur cette source.
  • PostgreSQL (par defaut, sans --csv) : connexion directe a reading + site via ML_DATABASE_URL, le chemin cible decrit dans ML-START.md. Le role PostgreSQL dedie enervision_ml (lecture seule) n'est pas encore provisionne (dette assumee, cf. ADR 0003 et ADR 0005) ; en attendant, pointer ML_DATABASE_URL vers la meme base que le backend suffit en developpement.

Entrainement

uv run python -m enervision_ml.train --csv data/all_sites_combined.csv
# ou, une fois la base peuplee et ML_DATABASE_URL positionnee :
uv run python -m enervision_ml.train

Ecrit le modele entraine dans models/lightgbm-consumption.txt (Booster.save_model(), dossier ignore par git) et journalise la run dans MLflow : parametres, MAE/RMSE/MAPE du modele et de la baseline de persistance saisonniere (consommation de la meme heure, une semaine avant), et l'artefact modele. Sans MLFLOW_TRACKING_URI, MLflow ecrit dans un magasin SQLite local (./mlflow.db, ignore par git) : uv run mlflow ui pour le consulter.

--test-fraction (0.15 par defaut) fixe la part la plus recente de l'historique reservee a la validation. La coupure est chronologique, jamais un tirage aleatoire de lignes : un tirage aleatoire laisserait des lignes de validation "voir" des lignes d'entrainement via leurs lags/moyennes glissantes, une fuite qui masquerait un surapprentissage.

Serveur MLflow (conteneur)

Un serveur MLflow (PostgreSQL pour les metadonnees, volume pour les artefacts) se lance avec Docker. Prerequis : Docker Desktop demarre.

cd ml
docker compose -f docker-compose.mlflow.yml up -d --build

Interface : http://localhost:5000. Entrainer vers ce serveur :

uv run python -m enervision_ml.train --csv data/all_sites_combined.csv --mlflow-tracking-uri http://localhost:5000

Arreter : docker compose -f docker-compose.mlflow.yml down (ajouter -v pour effacer aussi les runs et les modeles).

Pour voir les runs dans l'interface (MLflow 3.x) :

  • Passer le selecteur en haut a gauche sur Model training. Le mode GenAI affiche des traces LLM et reste vide pour un entrainement LightGBM.
  • Runs liste les entrainements, Models les artefacts de modele de chaque run (tous nommes model), et Model registry les versions numerotees de consumption-forecast-lightgbm.

Limites : les identifiants PostgreSQL (mlflow / mlflow) du compose ne conviennent qu'au developpement local. Un deploiement partage demandera des secrets, de l'authentification et un stockage d'artefacts dedie (S3/MinIO). Le port 5000 doit etre libre : arreter mlflow ui avant, ou changer le mapping ("5001:5000") dans le compose.

Commandes

uv run ruff check .                       # lint
uv run ruff format .                      # format
uv run mypy enervision_ml tests           # typage strict
uv run pytest                             # tests

Depuis la racine du monorepo, via le Makefile : make install-ml, make ml-lint, make ml-typecheck, make ml-test, make ml-check, make ml-train (CSV=chemin optionnel).

Ou ecrire les tests

Aucun test ne touche PostgreSQL ni un serveur MLflow distant : enervision_ml.data.load_from_csv et le chargement CSV de test suffisent a exercer build_features sur des donnees reelles ou synthetiques, et enervision_ml.train.train() accepte un tracking_uri SQLite isole (tmp_path pytest) pour un test de bout en bout sans effet de bord. enervision_ml.data.load_from_database n'est pas encore couvert : il n'existe aucune base PostgreSQL a interroger en CI ni dans cet environnement de developpement pour le moment.

Piege a connaitre

enervision_ml.features.build_features est le seul endroit qui doit construire les features du modele, a l'entrainement comme au futur scoring (service #37, pas encore construit). Si les deux divergent meme legerement (une fenetre de moyenne glissante calculee differemment, par exemple), le modele recoit en production des features qui ne ressemblent plus a ce qu'il a appris, et ses predictions deviennent silencieusement mauvaises sans qu'aucune erreur ne se declenche. Ne jamais reecrire cette logique ailleurs : importer enervision_ml.features.