feat(ml): initialise le pipeline d'entrainement LightGBM (ADR 0005)
ML / Lint, typage et tests (push) Successful in 2m2s
ML / Lint, typage et tests (push) Successful in 2m2s
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# ML EnerVision
|
||||
|
||||
Pipeline d'entrainement du modele de prevision de consommation energetique. Contexte complet :
|
||||
[ADR 0005](../docs/adr/0005-modele-prediction-lightgbm.md) (choix du modele) et
|
||||
[ML-START.md](../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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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.
|
||||
|
||||
## Commandes
|
||||
|
||||
```bash
|
||||
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`.
|
||||
Reference in New Issue
Block a user