██████╗ █████╗ ██╗██╗ ██████╗ █████╗ ███████╗████████╗
██╔══██╗██╔══██╗██║██║ ██╔════╝██╔══██╗██╔════╝╚══██╔══╝
██████╔╝███████║██║██║ ██║ ███████║███████╗ ██║
██╔══██╗██╔══██║██║██║ ██║ ██╔══██║╚════██║ ██║
██║ ██║██║ ██║██║███████╗╚██████╗██║ ██║███████║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝
Mixture of Experts Pipeline for SNCF Train Delay Prediction
La SNCF nous confie 7 ans de données de régularité (2018–2025). Notre mission : prédire le retard moyen à l'arrivée d'un train, en minutes, à partir des caractéristiques de la liaison.
Notre réponse : un pipeline Mixture of Experts à 2 étages qui bat le baseline de 25% et expose ses prédictions via un dashboard Streamlit interactif.
┌─────────┐ ┌───────────┐ ┌──────────┐ ┌─────┐ ┌─────────────┐
│ Data │───▶│ Clustering│───▶│ Experts │───▶│ OOF │───▶│ Méta-modèle │
│ Cleaning │ │ KMeans │ │ 1/cluster│ │ │ │ Stacking │
└─────────┘ └───────────┘ └──────────┘ └─────┘ └─────────────┘
| Approche | RMSE | MAE | R² | vs Baseline |
|---|---|---|---|---|
| Baseline (moyenne) | 3.99 | — | — | — |
| Experts seuls | 2.97 | 2.08 | 0.42 | −25% |
| Stacking | 2.98 | 2.05 | 0.42 | −25% |
L'erreur moyenne est d'environ 2 minutes. Le R² de 0.42 reflète l'imprévisibilité inhérente aux retards — météo, grèves, incidents — des facteurs absents du dataset.
Les liaisons sont regroupées par profil similaire (durée, fréquence, retard moyen, variabilité, taux d'annulation) via KMeans. Le nombre optimal de clusters est déterminé par le score de silhouette.
Pour chaque cluster, 3 modèles candidats sont entraînés et évalués :
| Modèle | Type | Rôle |
|---|---|---|
| ElasticNet | Linéaire | Stable, interprétable |
| XGBoost | Boosting (arbres) | Capte les non-linéarités |
| LightGBM | Boosting (arbres) | Rapide, performant |
Le meilleur modèle par RMSE est sélectionné pour chaque cluster.
Un méta-modèle reçoit les prédictions out-of-fold des experts + des features de contexte et apprend à corriger leurs biais. Les prédictions OOF sont générées en 7-fold CV (sans shuffle) pour éviter le data leakage.
| Feature | Source | Pourquoi |
|---|---|---|
retard_mois_precedent |
shift(1) par liaison | Autorégressivité — le meilleur prédicteur du retard c'est le retard précédent |
retard_moyenne_3_mois |
rolling(3).mean() shifté | Tendance récente de la liaison |
saison |
mois | Saisonnalité (hiver/été = plus de retards) |
cluster |
KMeans | Profil de la liaison |
Durée moyenne du trajet |
dataset | Les trajets longs accumulent plus de retard |
Nombre de circulations |
dataset | Fréquence de la liaison |
Train : 2018 ─────────────────────── 2023
Test : 2024 ── 2025
Pas de split aléatoire. On simule la réalité : le modèle apprend du passé pour prédire le futur.
Le dashboard Streamlit expose le pipeline complet :
- Prédiction — Sélection gare départ/arrivée, mois, année → prédiction en temps réel via le pipeline MoE
- Visualisations — Distribution des retards, top liaisons, évolution temporelle, saisonnalité (4 tabs)
- KPIs — Total trains, retard moyen, ponctualité, nombre de liaisons
- Filtres — Sidebar multi-gares qui filtre toutes les vues
User Input (gares, mois)
│
▼
Récupère l'historique de la liaison
│
▼
Calcule les lag features (retard_mois_precedent, moyenne_3_mois)
│
▼
Détermine le cluster → Appelle l'expert du cluster
│
▼
Expert prédit → Méta-modèle corrige → Résultat final
railcast/
├── data/
│ ├── project_dataset.csv # Dataset brut SNCF
│ ├── cleaned_dataset.csv # Dataset après nettoyage
│ └── df_cluster.csv # Dataset avec labels de clusters
│
├── models/
│ ├── kmeans.joblib # Modèle KMeans (clustering)
│ ├── scaler_cluster.joblib # StandardScaler du clustering
│ ├── le_service.joblib # LabelEncoder du service
│ ├── encoders.joblib # Dict {service, depart, arrivee}
│ ├── meta_model.joblib # Méta-modèle (stacking)
│ └── experts/
│ ├── expert_cluster_0.joblib # Expert cluster 0
│ └── expert_cluster_1.joblib # Expert cluster 1
│
├── src/
│ ├── cleaner.py # Module de nettoyage des données
│ ├── clustring.py # Clustering KMeans des liaisons
│ ├── expert.py # Entraînement des experts par cluster
│ └── stacking.py # Pipeline de stacking OOF
│
├── railcast_eda.ipynb # Notebook EDA (nettoyage + visualisations + clustering)
├── railcast_model.ipynb # Notebook modélisation (experts + stacking + évaluation)
├── railcast_dashboard.py # Dashboard Streamlit interactif
├── requirements.txt # Dépendances Python
└── README.md
git clone <repo-url>
cd railcast
python -m venv venv
source venv/bin/activate
pip install -r requirements.txtpython src/expert.py
python src/stacking.pystreamlit run railcast_dashboard.pyLe dashboard s'ouvre sur http://localhost:8501.
pandas>=2.0
numpy>=1.24
matplotlib>=3.7
seaborn>=0.12
scikit-learn>=1.3
xgboost>=2.0
lightgbm>=4.0
streamlit>=1.28
joblib>=1.3
| Notebook | Contenu |
|---|---|
railcast_eda.ipynb |
Nettoyage (8 étapes détaillées), feature engineering, 6 visualisations avec interprétations, clustering KMeans avec optimisation silhouette, export des données nettoyées |
railcast_model.ipynb |
Lag features, encodage, split temporel, experts par cluster (3 candidats × n clusters), stacking OOF 7-fold, évaluation comparative, scatter plot prédictions vs réalité, distribution des erreurs |
Built with ☕ and too many delayed trains.