feat(ml): enregistrer le modèle dans le MLflow Model Registry
This commit is contained in:
+1
-1
@@ -64,7 +64,7 @@ ml/models/*
|
|||||||
!ml/models/.gitkeep
|
!ml/models/.gitkeep
|
||||||
ml/mlruns/
|
ml/mlruns/
|
||||||
ml/mlartifacts/
|
ml/mlartifacts/
|
||||||
ml/mlflow.db
|
ml/mlflow.db*
|
||||||
|
|
||||||
# IDE et OS
|
# IDE et OS
|
||||||
.idea/
|
.idea/
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.venv
|
||||||
|
data
|
||||||
|
mlruns
|
||||||
|
mlflow.db*
|
||||||
|
models
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
FROM python:3.12-slim
|
||||||
|
RUN pip install --no-cache-dir mlflow==3.16.1 psycopg2-binary
|
||||||
|
EXPOSE 5000
|
||||||
@@ -57,6 +57,37 @@ validation. La coupure est **chronologique**, jamais un tirage aleatoire de lign
|
|||||||
aleatoire laisserait des lignes de validation "voir" des lignes d'entrainement via leurs
|
aleatoire laisserait des lignes de validation "voir" des lignes d'entrainement via leurs
|
||||||
lags/moyennes glissantes, une fuite qui masquerait un surapprentissage.
|
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
|
## Commandes
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
services:
|
||||||
|
mlflow-db:
|
||||||
|
image: postgres:16
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: mlflow
|
||||||
|
POSTGRES_PASSWORD: mlflow
|
||||||
|
POSTGRES_DB: mlflow
|
||||||
|
volumes:
|
||||||
|
- mlflow-db-data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U mlflow"]
|
||||||
|
interval: 5s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
|
mlflow:
|
||||||
|
build: .
|
||||||
|
depends_on:
|
||||||
|
mlflow-db:
|
||||||
|
condition: service_healthy
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
volumes:
|
||||||
|
- mlflow-artifacts:/mlartifacts
|
||||||
|
command: >
|
||||||
|
mlflow server
|
||||||
|
--host 0.0.0.0 --port 5000
|
||||||
|
--backend-store-uri postgresql://mlflow:mlflow@mlflow-db:5432/mlflow
|
||||||
|
--artifacts-destination /mlartifacts
|
||||||
|
--serve-artifacts
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mlflow-db-data:
|
||||||
|
mlflow-artifacts:
|
||||||
@@ -77,6 +77,7 @@ def test_train_runs_end_to_end_on_synthetic_data_and_beats_a_dummy_baseline(
|
|||||||
assert baseline_metrics["n_observations"] == model_metrics["n_observations"]
|
assert baseline_metrics["n_observations"] == model_metrics["n_observations"]
|
||||||
assert model_metrics["mae"] < baseline_metrics["mae"]
|
assert model_metrics["mae"] < baseline_metrics["mae"]
|
||||||
|
|
||||||
|
|
||||||
def test_train_raises_when_the_validation_window_is_empty(tmp_path: Path) -> None:
|
def test_train_raises_when_the_validation_window_is_empty(tmp_path: Path) -> None:
|
||||||
depart = datetime(2026, 1, 1, tzinfo=UTC)
|
depart = datetime(2026, 1, 1, tzinfo=UTC)
|
||||||
frame = make_frame("site-a", heures=50, depart=depart) # trop court pour un lag de 168h
|
frame = make_frame("site-a", heures=50, depart=depart) # trop court pour un lag de 168h
|
||||||
|
|||||||
Reference in New Issue
Block a user