Projet Data Science - M1 Mastère Data Engineering & IA - EFREI Paris Panthéon-Assas Université - Année 2025-2026 Bloc - BC2 RNCP40875 - Piloter et implémenter des solutions d'IA en s'aidant notamment de l'IA générative Auteurs - Adam BELOUCIF - Emilien MORICE
- Contexte métier
- Objectifs et livrables
- Stack technique
- Architecture du pipeline
- Installation
- Pipeline d'exécution
- Lancer le dashboard
- Lancer l'API
- Structure du dépôt
- Modèles comparés
- Démarche méthodologique
- Métriques et choix
- Anti-data-leakage
- Interprétabilité des prédictions
- Écoresponsabilité (RNCP C4.3)
- Reproductibilité
- Couverture RNCP40875
- Tâches bonus
- FAQ
- Troubleshooting
- Roadmap
- Remerciements
- License et contributions
Dans les environnements industriels modernes, la panne non planifiée d'une machine engendre des coûts directs et indirects considérables -
- Coût d'arrêt - 5 000 à 50 000 EUR par heure selon le secteur (automotive, chimie, aéronautique).
- Perte de productivité - délais de livraison non respectés, pénalités contractuelles.
- Coûts de dépannage d'urgence - heures supplémentaires, frais de déplacement technicien.
- Perte de qualité - rebuts produits, non-conformités.
| Approche | Coût annuel | Temps d'arrêt | Risque | Status quo |
|---|---|---|---|---|
| Corrective | ~100 EUR/h | Très haut | Très élevé | Réactif |
| Préventive | ~50 EUR/h | Moyen | Moyen | Planifié |
| Prédictive | ~20 EUR/h | Très faible | Faible | Cible |
Développer un système de maintenance prédictive qui exploite les données de capteurs IoT (vibration, température, pression, courant) pour anticiper les pannes dans les 24 heures et recommander une intervention avant la défaillance. Cela permet -
- Réduction du coût d'arrêt non planifié.
- Optimisation du taux d'utilisation des machines.
- Planification optimale des ressources de maintenance.
- Minimisation de l'impact sur la chaîne de production.
- ROI attendu - réduction de 60% du coût global maintenance sur 3 ans.
- Disponibilité machine - augmentation de 20% (panne non planifiées réduites).
- Taux de détection (Recall) - ≥ 85% sur les pannes réelles (minimiser FN).
- Taux de fausses alertes (FP) - ≤ 15% (coût intervention inutile < coût panne).
- Latence d'inférence - < 500 ms (alertes temps réel).
Ce projet livre une plateforme intelligente complète couvrant le cycle de vie data science -
- Ingestion et préparation - dataset 24 042 enregistrements - 15 variables - classes déséquilibrées (~14.8% pannes).
- Analyse exploratoire - 7+ visualisations interactives, distributions capteurs, corrélations.
- Modélisation multi-algorithmes - 4 modèles (Logistic Regression, Random Forest, XGBoost, MLP).
- Évaluation comparative - 6 métriques standardisées (Accuracy, Precision, Recall, F1, ROC-AUC, PR-AUC).
- Interprétabilité - Feature Importance, Permutation Importance, SHAP Explainer (TreeExplainer/KernelExplainer).
- Interface décisionnelle - dashboard Streamlit 5 onglets (vue d'ensemble, EDA, comparaison, simulateur, interprétabilité).
- API REST - endpoints FastAPI + Pydantic (prédiction en temps réel, vérification santé, métadonnées modèle).
- Rapport analytique - PDF généré 20+ pages avec figures, schémas, matrice de confusion, courbes ROC/PR.
- Bonus - classification multi-classe (type de panne), régression (RUL), tuning hyperparamètres, calibration, mesure CO₂.
Dataset officiel - Kaggle v3.0 CC0 - tatheerabbas/industrial-machine-predictive-maintenance (24 042 lignes × 15 colonnes).
| Couche | Outil | Justification |
|---|---|---|
| Langage | Python 3.12 | Standard domaine ML, large écosystème, reproductibilité garantie sur 3 OS majeurs. |
| Data | pandas + numpy | Manipulation tabulaire performante, intégration pandas↔scikit-learn fluide, alternative Polars. |
| Prétraitement | scikit-learn ColumnTransformer | Pipeline immuable évite data-leakage (fit train, transform test/inférence auto). |
| ML classique | scikit-learn (LogReg, RF) | Baseline interprétable (LogReg) + non-linéaire robuste (RF), feature_importances_ native. |
| Boosting | XGBoost 2.x | État de l'art tabulaire, gestion native déséquilibre via scale_pos_weight, tree_method=hist |
| Deep Learning | MLPClassifier scikit-learn (64-32-16) | Réseau dense DL requis par sujet - architecte 3 couches dégressives, ReLU + early stopping. |
| Hypertuning | Optuna 3.x (TPE sampler) | Optimisation bayésienne > GridSearch exhaustif, log trials structuré, pruning adaptatif. |
| Interprétab. | SHAP + permutation_importance | TreeExplainer (XGBoost/RF), KernelExplainer (fallback), Force/Waterfall/Summary plots. |
| Écorespons. | CodeCarbon 2.3+ | Mesure réelle CO₂eq (gCO2) par modèle, pays France (~80 gCO2/kWh), RNCP C4.3 littéral. |
| Visualisation | matplotlib + seaborn + plotly | matplotlib statique (PDF report), plotly interactif (dashboard Streamlit). |
| Dashboard | Streamlit 1.32 + CSS custom EFREI | Prototypage rapide, Streamlit-native st.tabs + st.slider/input, thème bleu institutionnel. |
| API | FastAPI 0.110 + Pydantic v2 + Uvicorn | Validation automatique schémas, Swagger généré, async-ready, performant. |
| Rapport PDF | FPDF2 2.7+ | Génération automatisée figures, tables, numérotation pages, UTF-8 natif. |
| Slides PPTX | python-pptx 0.6.21 | Génération programmatique 11 slides depuis artefacts (EDA, métriques, conclusion). |
| Tests | pytest 8.0 + pytest-cov + httpx TestClient | Suite unittest ML (preprocessing, models), intégration API (TestClient FastAPI). |
| CI/CD | GitHub Actions | Lint (black, isort, prettier) + pytest + build artefact PDF à chaque push main. |
flowchart TB
SENSORS["Capteurs IoT<br/>vibration - temperature - RPM - pression"]
RAW["CSV Bronze<br/>data/raw/predictive_maintenance_v3.csv"]
EDA["02_eda.py<br/>8 graphiques - stats - analyse NaN"]
PREP["Preparation Silver<br/>preprocessing.py - Pandera - imputation - scaling - OHE"]
TRAIN["03_train_models.py<br/>LogReg - Random Forest - XGBoost - MLP - CV 5-fold"]
GOLD["Evaluation Gold<br/>evaluation.py - matrice confusion - ROC - PR - selection F1"]
INTERP["04_interpret.py<br/>SHAP - permutation importance - dependance partielle"]
BONUS["Bonus multi-taches<br/>multiclass - regression RUL - Optuna - calibration"]
REPORT["Livrables<br/>rapport PDF - presentation PPTX - diagrammes"]
DASH["dashboard/app.py<br/>Streamlit - localhost:8501"]
API["api/main.py<br/>FastAPI - localhost:8000"]
SENSORS --> RAW --> EDA --> PREP --> TRAIN --> GOLD --> INTERP
GOLD --> BONUS
INTERP --> REPORT
GOLD --> DASH
GOLD --> API
| Étape | Fichier de sortie | Taille approx. | Contenu |
|---|---|---|---|
| 01 | data/raw/predictive_maintenance_v3.csv |
2.8 MB | 24 042 rows × 15 cols |
| 02 | reports/02/*.png (8 figures + 2 CSV) |
15 MB | Distributions, corrélations, NaN |
| 03 | models/final_model.joblib + reports/03/* |
8 MB | Pipeline compressé (seed=42) + métriques |
| 04 | reports/04/shap_*.png (5 figures) |
12 MB | Force, Waterfall, Summary plots |
| 05 | reports/05/diagram_*.png (4 schémas) |
8 MB | Diagrams pédagogiques |
| Rapport | reports/rapport_projet_data_science.pdf (livré manuellement) |
~22 MB | 20 pages + figures embarquées |
- RAM - ≥ 4 GB (8 GB recommandé pour SHAP KernelExplainer sur tous les modèles).
- Disque - ≥ 500 MB libre (donnée + modèles + rapports).
- CPU - multi-core recommandé (RandomForest/XGBoost parallélisés via
n_jobs=-1). - Temps exécution complet - ~45-60 min sur CPU grand public (i5-10400, 8GB RAM).
Pour la soutenance ou pour démontrer la solution complète, un orchestrateur unique lance tout d'un coup -
python app.pySéquence d'exécution -
- Démarre l'API FastAPI sur
http://127.0.0.1:8000(uvicorn, niveau logwarning) - Attend que
/healthréponde 200 (max 30 s) - Démarre le dashboard Streamlit sur
http://localhost:8501, branché sur l'API via la variable d'environnementAPI_BASE_URL - Ouvre 3 onglets navigateur - Swagger UI (
/docs), dashboard métier, ReDoc (/redoc) - Ouvre
reports/11/presentation.pptxdans PowerPoint etreports/06/rapport_projet_data_science.pdfdans le viewer PDF par défaut
Ctrl+C dans le terminal arrête proprement l'API et le dashboard ; PowerPoint et le PDF restent ouverts pour la suite de la soutenance.
Pendant la démo, le diagnostic dans Streamlit appelle réellement l'API en POST /predict via httpx - un badge "Source - API REST" apparaît sous le résultat. Si l'API est arrêtée, le dashboard bascule en local (joblib) avec un badge "Source - modèle local".
- Python ≥ 3.10 (testé sur 3.12)
- pip (gestionnaire paquets)
- Git
git clone https://github.com/Adam-Blf/maintenance-predictive-industrielle.git
cd "maintenance-predictive-industrielle"# Windows
python -m venv .venv
.venv\Scripts\activate
# macOS / Linux
python3 -m venv .venv
source .venv/bin/activatepip install --upgrade pip setuptools wheel
pip install -r requirements.txtVérification - la commande suivante doit réussir sans erreur -
python -c "import sklearn, xgboost, streamlit, fastapi, shap; print('OK')"Les scripts doivent s'exécuter strictement dans l'ordre - chaque étape produit les artefacts consommés par la suivante.
# Pré-requis - CSV Kaggle officiel placé dans data/raw/predictive_maintenance_v3.csv
# 1. Analyse exploratoire (EDA) - 8 graphiques + stats + analyse NaN
python scripts/02_eda.py
# 2. Entraînement 4 modèles + évaluation comparative + CV stratifiée
python scripts/03_train_models.py
# 4. Interprétabilité (SHAP + Permutation Importance)
python scripts/04_interpret.py
# 5. Génération schémas pédagogiques (4 PNG, à insérer dans le rapport)
python scripts/05_generate_diagrams.pyLes livrables jury sont déjà présents dans le repo -
reports/06/rapport_projet_data_science.pdf- ~30 pages, 2.4 Moreports/11/presentation.pptx- 24 slides charte EFREI, 2.2 Mo
(Pas de script de génération - ces livrables sont versionnés tels quels.)
# Classification multi-classe (5 types de panne)
python scripts/07_train_multiclass.py
# Régression (durée de vie restante en heures)
python scripts/08_train_regression.py
# Hyperparameter tuning (Optuna, 100 trials)
python scripts/09_tune_hyperparams.py
# Calibration probabiliste (reliability diagram, seuil métier)
python scripts/10_calibrate.py| Script | Temps (CPU i5) | CPU Usage | RAM Peak |
|---|---|---|---|
| 01 | ~30 sec | 1 core | 200 MB |
| 02 | ~15 sec | 1 core | 500 MB |
| 03 | ~12 min | 4 cores | 3.2 GB |
| 04 | ~8 min | 2 cores | 4.1 GB |
| 05 | ~2 sec | 1 core | 100 MB |
| 06 | ~4 min | 1 core | 800 MB |
| Total | ~25 min | - | - |
Le dashboard Streamlit est l'interface décisionnelle opérationnelle (EF4 du sujet). Il expose 5 onglets (tabs) permettant à un responsable maintenance d'explorer les données, comparer les modèles, et simuler des scénarios.
streamlit run dashboard/app.pyOuvre automatiquement - http://localhost:8501
Configuration - layout large (wide), sidebar expandu, CSS custom EFREI (bleu/blanc).
Indicateurs clés affichés -
- Nombre total de machines - 1 204 (historique du dataset)
- Taux de pannes - 25.3% (6 081 pannes / 24 042 total)
- Modèle déployé - XGBoost (F1 le plus élevé - 0.886)
- Temps de prédiction - 0.007 ms par échantillon (latence acceptée < 500 ms)
- Métrique F1 du modèle final - 0.886 ± 0.011 (CV 5-fold)
- ROC-AUC - 0.995
- PR-AUC - 0.974 (plus fiable que ROC-AUC en classes déséquilibrées)
Graphes -
- Courbe ROC du modèle final (interactive plotly)
- Distribution des probabilités prédites (train vs test)
- Matrice de confusion du test set
Sélecteur interactif de variables numériques/catégories.
Numériques -
- Histogramme distribution + boxplot (par classe si target binaire)
- KDE plot (kernel density estimation)
- Statistiques descriptives (mean, std, min, max, quantiles)
Catégories -
- Stacked bar chart (répartition machine_type vs operating_mode)
- Contingency table (crosstab)
Corrélations -
- Heatmap corrélation Pearson (14x14 numériques)
- Top 5 corrélations avec la cible
Tableau interactif - 4 modèles × 6 métriques
| Modèle | Accuracy | Precision | Recall | F1 | ROC-AUC | PR-AUC | Temps train (s) |
|---|---|---|---|---|---|---|---|
| Logistic Regress. | 0.910 | 0.641 | 0.895 | 0.747 | 0.959 | 0.838 | 0.062 |
| Random Forest | 0.955 | 0.791 | 0.949 | 0.863 | 0.992 | 0.954 | 0.889 |
| XGBoost | 0.963 | 0.824 | 0.958 | 0.886 | 0.995 | 0.974 | 0.503 |
| MLP (64-32-16) | 0.952 | 0.842 | 0.830 | 0.836 | 0.984 | 0.909 | 2.361 |
Graphes -
- Courbes ROC superposées (4 modèles)
- Courbes PR superposées (4 modèles)
- Barplot F1 par modèle (avec barres d'erreur CV)
Sliders et input fields pour saisir manuellement les capteurs -
Vibration RMS (mm/s) [0.0 ────●──── 15.0] → 4.2
Température moteur (°C) [−20 ────●──── 160] → 78.5
Courant phase moyen (A) [0.0 ────●──── 40] → 12.3
Pression hydraulique (bar) [0.0 ────●──── 120] → 58.7
RPM [0 ─────●──── 5000] → 2100
Heures depuis maintenance [0 ─────●──── 3000] → 320
Température ambiante (°C) [−20 ────●──── 60] → 24.1
Mode opératoire [Dropdown: normal / idle / peak] → peak
Type machine [Dropdown: CNC / Pump / Compressor / Robotic Arm] → CNC
Clic bouton « Prédire » -
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Prédiction : ALERTE - PANNE PROBABLE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Probabilité de panne dans 24h - 78.4%
Niveau de risque - ÉLEVÉ (seuil 60%)
Recommendation - Intervention préventive dans les 2h
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Feature importance triée par impact moyen |SHAP value| -
1. vibration_rms ████████████████ 0.42 (impact moyen)
2. temperature_motor ██████████ 0.28
3. hours_since_maintenance ███████ 0.19
4. rpm ██████ 0.16
5. current_phase_avg ████ 0.11
... (14 features total)
Graphes -
- SHAP Waterfall (pour 1 sample sélectionné)
- SHAP Dependence plot (relation vibration_rms vs SHAP value, couleur par température)
- Permutation importance (comparaison)
L'API REST FastAPI est l'interface d'industrialisation (EF5). Elle expose le modèle final sous forme de web service synchrone, consommable par des tiers (web frontend, mobile, legacy systems).
uvicorn api.main:app --reload --host 127.0.0.1 --port 8000Sortie console -
INFO: Uvicorn running on http://127.0.0.1:8000
INFO: Application startup complete
Accès documentation interactive - http://localhost:8000/docs (Swagger UI).
| Méthode | Route | Code(s) | Description |
|---|---|---|---|
| POST | /predict |
200 / 422 / 500 | Prédiction panne 24h (SensorReading) |
| GET | /health |
200 | Vérification santé du service + modèle chargé |
| GET | /model-info |
200 | Métadonnées modèle (nom, métriques, features) |
| GET | /docs |
200 | Swagger UI (Pydantic JSON schema) |
{
"vibration_rms": 4.2,
"temperature_motor": 78.5,
"current_phase_avg": 12.3,
"pressure_level": 58.7,
"rpm": 2100,
"hours_since_maintenance": 320.0,
"ambient_temp": 24.1,
"operating_mode": "peak",
"machine_type": "CNC"
}Validation -
vibration_rms- float, [0.0 ≤ x ≤ 15.0]temperature_motor- float, [−20 ≤ x ≤ 160]rpm- float, [0 ≤ x ≤ 5000]operating_mode- enum ["normal", "idle", "peak"]machine_type- enum ["CNC", "Pump", "Compressor", "Robotic Arm"]
Si validation échoue → 422 Unprocessable Entity (détails en réponse JSON).
{
"failure_within_24h": 1,
"probability": 0.784,
"risk_level": "high",
"recommendation": "Intervention préventive dans les 2h",
"model_name": "XGBoost",
"timestamp_utc": "2026-04-28T14:32:17.123456Z"
}Champs -
failure_within_24h- 0 (OK) ou 1 (panne probable)probability- [0.0 .. 1.0], probabilité de la classe positiverisk_level- "low" (< 30%) | "moderate" (30-60%) | "high" (> 60%)recommendation- chaîne actionnable pour opérateur maintenancemodel_name- identifiant du modèle servi (ex. "XGBoost_FE")timestamp_utc- ISO 8601, horodatage UTC de la prédiction
{
"status": "healthy",
"model_loaded": true,
"api_version": "2.0.0",
"timestamp_utc": "2026-04-28T14:32:17Z"
}Le champ status passe à "degraded" si le modèle n'est pas chargé (modèle invalide, fichier manquant).
{
"model_name": "XGBoost",
"api_version": "2.0.0",
"metrics": {
"f1": 0.93,
"recall": 0.95,
"precision": 0.91,
"roc_auc": 0.96,
"pr_auc": 0.94
},
"features_required": [
"vibration_rms", "temperature_motor", "current_phase_avg",
"pressure_level", "rpm", "hours_since_maintenance",
"ambient_temp", "operating_mode", "machine_type"
],
"operating_modes": ["normal", "idle", "peak"]
}curl -X POST http://127.0.0.1:8000/predict \
-H "Content-Type: application/json" \
-d '{
"vibration_rms": 1.2,
"temperature_motor": 45.0,
"current_phase_avg": 8.5,
"pressure_level": 30.2,
"rpm": 1500,
"hours_since_maintenance": 50.0,
"ambient_temp": 22.0,
"operating_mode": "normal",
"machine_type": "CNC"
}' | jq .Réponse attendue -
{
"failure_within_24h": 0,
"probability": 0.12,
"risk_level": "low",
"recommendation": "Opération normale. Maintenance prévue dans 3 mois.",
"model_name": "XGBoost",
"timestamp_utc": "2026-04-28T14:35:22.456789Z"
}curl -X POST http://127.0.0.1:8000/predict \
-H "Content-Type: application/json" \
-d '{
"vibration_rms": 8.9,
"temperature_motor": 132.5,
"current_phase_avg": 28.7,
"pressure_level": 105.0,
"rpm": 4200,
"hours_since_maintenance": 850.0,
"ambient_temp": 38.5,
"operating_mode": "peak",
"machine_type": "Compressor"
}' | jq .Réponse attendue -
{
"failure_within_24h": 1,
"probability": 0.89,
"risk_level": "high",
"recommendation": "ALERTE - Intervention préventive immédiate (< 4h)",
"model_name": "XGBoost",
"timestamp_utc": "2026-04-28T14:36:05.789012Z"
}curl -X POST http://127.0.0.1:8000/predict \
-H "Content-Type: application/json" \
-d '{
"vibration_rms": -5.0,
"temperature_motor": 78.5,
...
}'Réponse -
{
"detail": [
{
"type": "greater_than_equal",
"loc": ["body", "vibration_rms"],
"msg": "Input should be greater than or equal to 0.0",
"input": -5.0
}
]
}HTTP 422 Unprocessable Entity.
curl http://127.0.0.1:8000/health | jq .curl http://127.0.0.1:8000/model-info | jq '.metrics'maintenance-predictive-industrielle/
├── api/
│ └── main.py # API FastAPI (3 endpoints + validation Pydantic)
├── assets/
│ ├── logo_efrei.png # Logo EFREI couleur
│ ├── logo_efrei_white.png # Variante blanche
│ └── logo_efrei_noir.png # Variante noir/blanc
├── dashboard/
│ └── app.py # Dashboard Streamlit (5 onglets + CSS custom)
├── data/
│ ├── raw/ # Dataset brut (gitignored, ~2.8 MB)
│ │ └── predictive_maintenance_v3.csv
│ └── processed/ # Splits train/test + artefacts (gitignored)
│ ├── X_train_processed.npz
│ ├── X_test_processed.npz
│ ├── y_train.npy
│ └── y_test.npy
├── docs/
│ └── adr/ # Architecture Decision Records
│ ├── 0001-stack-technique.md
│ ├── 0002-modeles-compares.md
│ ├── 0003-anti-data-leakage.md
│ └── 0004-multi-taches-bonus.md
├── models/ # Pipelines sérialisés sklearn (gitignored)
│ ├── final_model.joblib # Best model (compression 3)
│ ├── final_model_name.txt # Nom du best model
│ ├── logistic_regression.joblib
│ ├── random_forest.joblib
│ ├── xgboost.joblib
│ └── mlp.joblib
├── reports/
│ ├── 02/ # Sorties scripts/02_eda.py (EDA - 8 PNG + 2 CSV)
│ ├── 03/ # Sorties scripts/03_train_models.py (métriques + CM + ROC/PR)
│ ├── 04/ # Sorties scripts/04_interpret.py (SHAP + permutation)
│ ├── 05/ # Sorties scripts/05_generate_diagrams.py (4 schémas)
│ ├── 06/ # Rapport PDF jury (livrable versionné)
│ │ └── rapport_projet_data_science.pdf
│ ├── 07/ # Sorties scripts/07_train_multiclass.py (bonus)
│ ├── 08/ # Sorties scripts/08_train_regression.py (RUL, bonus)
│ ├── 09/ # Sorties scripts/09_tune_hyperparams.py (Optuna, bonus)
│ ├── 10/ # Sorties scripts/10_calibrate.py (calibration, bonus)
│ └── 11/ # Présentation PPTX jury (livrable versionné)
│ └── presentation.pptx
├── scripts/
│ ├── 02_eda.py # Analyse exploratoire (8 graphiques + analyse NaN)
│ ├── 03_train_models.py # Entraînement 4 modèles + CV + évaluation
│ ├── 04_interpret.py # SHAP + Permutation Importance
│ ├── 05_generate_diagrams.py # Schémas pédagogiques (4 PNG)
│ ├── 07_train_multiclass.py # Classification multi-classe (bonus)
│ ├── 08_train_regression.py # Régression RUL (bonus)
│ ├── 09_tune_hyperparams.py # Optuna tuning (bonus)
│ └── 10_calibrate.py # Calibration probabiliste (bonus)
├── src/
│ ├── __init__.py # Version + métadonnées du package
│ ├── bootstrap.py # Auto-install des deps pip au lancement
│ ├── config.py # Chemins + hyperparamètres centralisés
│ ├── data_loader.py # Chargeur du CSV Kaggle officiel (lecture seule)
│ ├── preprocessing.py # ColumnTransformer (Imputer + Scaler + OHE)
│ ├── models.py # 4 factories ML (LogReg, RF, XGB, MLP)
│ ├── models_multiclass.py # Factories multi-classe (bonus)
│ ├── models_regression.py # Factories régression (bonus)
│ ├── evaluation.py # 6 métriques + courbes + barplots
│ ├── interpretability.py # SHAP + Permutation + Feature Importance
│ ├── calibration.py # Reliability diagram + calibration (bonus)
│ ├── tuning.py # Optuna wrapper (bonus)
│ ├── diagrams.py # 4 schémas matplotlib
├── tests/
│ ├── test_preprocessing.py # Tests preprocessing + ColumnTransformer
│ ├── test_models.py # Tests factories + fit + predict
│ ├── test_evaluation.py # Tests métriques
│ └── test_api.py # Tests API (httpx TestClient)
├── .gitignore # Ignore data/, models/, .venv/, etc.
├── LICENSE # Licence MIT
├── README.md # ← Vous êtes ici
└── requirements.txt # Dépendances freezées
# Exclus du repo (gitignored)
├── .venv/ # Environnement virtuel
├── data/raw/*.csv # Dataset brut (fourni externally)
├── data/processed/ # Splits train/test
├── models/*.joblib # Modèles sérialisés
├── reports/NN/*.png # Figures générées (NN = numéro du script qui produit)
├── __pycache__/ # Bytecode compilé
├── .pytest_cache/ # Cache pytest
└── *.egg-info/ # Distribution metadata
Le sujet impose au minimum 4 modèles dont 1 Deep Learning. Nous comparons -
| # | Modèle | Famille | Hyperparamètres exacts | Justification |
|---|---|---|---|---|
| 1 | Logistic Regression | Linéaire | max_iter=1000, class_weight="balanced", solver="lbfgs" |
Baseline interprétable. Coefficients β directement exploitables. Référence faible pour comparer les non-linéaires. |
| 2 | Random Forest | Bagging d'arbres | n_estimators=200, max_depth=None, min_samples_leaf=5, class_weight="balanced", n_jobs=-1 |
Capture non-linéarités. feature_importances_ natif par Gini/Entropy. Robuste aux outliers. Temps train ~45s. |
| 3 | XGBoost | Gradient Boosting | n_estimators=300, learning_rate=0.05, max_depth=6, subsample=0.85, colsample_bytree=0.85, scale_pos_weight=4.0, tree_method="hist" |
État de l'art tabulaire. scale_pos_weight gère le déséquilibre (ratio neg/pos). Bagging stochastique régularise. Temps train ~35s. |
| 4 | MLP (64-32-16) | Deep Learning | hidden_layer_sizes=(64,32,16), activation="relu", solver="adam", alpha=1e-3, early_stopping=True, n_iter_no_change=10, max_iter=200 |
Réseau 3 couches dégressives (pyramide inversée). ReLU anti-vanishing. Early stopping évite overfit. alpha=1e-3 régularise. Temps train ~18s. |
| Modèle | Accuracy | Precision | Recall | F1 | ROC-AUC | PR-AUC | Temps train | CO₂ (mg) |
|---|---|---|---|---|---|---|---|---|
| LogReg | 0.910 | 0.641 | 0.895 | 0.747 | 0.959 | 0.838 | 0.062s | 0.3 |
| RF | 0.955 | 0.791 | 0.949 | 0.863 | 0.992 | 0.954 | 0.889s | 8.2 |
| XGBoost | 0.963 | 0.824 | 0.958 | 0.886 | 0.995 | 0.974 | 0.503s | 6.1 |
| MLP | 0.952 | 0.842 | 0.830 | 0.836 | 0.984 | 0.909 | 2.361s | 3.8 |
Sélection - score de sélection = F1 − 0.5×σ(F1_CV) - XGBoost retenu : F1=0.886, σ_CV=0.011 (le plus stable). CO₂ mesuré via CodeCarbon.
- Charger le CSV Kaggle v3.0 (24 042 rows, 15 cols)
- Vérifier types/domaines (vibration_rms ∈ [0,15], température ∈ [−20, 160])
- Détecter NaN et patterns manquants (~4% capteurs, imputer médiane)
- Visualiser distributions (histograms + KDE)
- Analyser corrélations Pearson (heatmap 14×14)
- Calculer stats descriptives (mean, std, min, max, skewness, kurtosis)
- Visualiser target : 74.7% classe 0 (machine saine), 25.3% classe 1 (panne)
Output - 7 graphiques PNG, stats CSV.
- Validation schema - Pandera (types + ranges)
- Imputation NaN -
SimpleImputer(strategy="median")sur numériques - Standardisation -
StandardScalersur train, transform test (anti-leakage) - Encoding catégories -
OneHotEncoder(drop="first")sur [operating_mode, machine_type] - Feature Engineering bonus - ratios (vibration/rpm), interactions (T×vibration), deviations (z-score)
Outil - sklearn.compose.ColumnTransformer - garantit chaîne immédiate fit train → transform test/inférence.
Output - X_train (18 433 × 23), X_test (5 609 × 23), y_train, y_test, scaler+encoder sérialisés.
- Test size - 20% (5 609 samples) stratifié sur
failure_within_24h - Stratification - préserve ratio 74.7% / 25.3% dans train ET test
- Seed - 42 (reproductibilité bit-à-bit)
- Raison - test sur données invisibles, pas de leakage, comparaison équitable
- Logistic Regression - fit, predict_proba
- Random Forest - fit, OOB score, feature_importances_
- XGBoost - fit, predict_proba, custom
scale_pos_weightpour déséquilibre - MLP - fit avec early stopping (validation split 10%)
Tous dans sklearn.Pipeline avec preprocessor + classifier pour éviter leakage.
- CV stratifiée - 5-fold sur train, calcule 5×6 métriques
- Métriques - Accuracy, Precision, Recall, F1, ROC-AUC, PR-AUC
- Raison PR-AUC - plus pertinent que ROC-AUC en classes déséquilibrées
- Matrices confusion - pour analyser FP/FN par modèle
Output - barplots, courbes ROC/PR superposées, tableaux.
- Reliability diagram - courbe calibration (predicted prob vs empirical freq)
- Brier score - moyenne (y_true − y_proba)²
- Seuil optimisé - minimise coût métier (FN=1000€, FP=100€) plutôt que 0.5 standard
Output - graphique reliability, matrice confusion avec seuil custom.
- Feature Importance native - Gini (RF) ou Gain (XGB)
- Permutation Importance - shuffle une feature, mesure drop performance
- SHAP Explainer - TreeExplainer (RF/XGB) ou KernelExplainer (LogReg/MLP)
- Visualisations - Force plots (top 10 features), Waterfall (1 sample), Summary (moyenne |SHAP|)
Output - PNG SHAP, classement features par impact.
- Score de sélection - F1 − 0.5×σ(F1_CV) = compromis entre F1 moyen et stabilité
- Sauvegarder - joblib + seed en commentaire
- Exposer - FastAPI endpoint
/predict+ Streamlit dashboard
Output - final_model.joblib (~8 MB), final_model_name.txt.
En classification binaire avec classes déséquilibrées (~14.8% pannes), on compare -
| Métrique | Formule | Quand l'utiliser | Pièges |
|---|---|---|---|
| Accuracy | (TP+TN) / (TP+TN+FP+FN) | Rapide vue d'ensemble si classes équilibrées | Trompeuse si déséquilibre (model qui prédit tout 0 = 75% accuracy) |
| Precision | TP / (TP+FP) | Coût d'une fausse alerte (intervention inutile) | Ignore FN (pannes ratées) |
| Recall | TP / (TP+FN) | Coût d'un faux négatif (panne non détectée = production stoppée) | Ignore FP (alertes inutiles) |
| F1 | 2×(Precision×Recall) / (Precision+Recall) | Compromis Precision/Recall quand les deux importants | Donne même poids aux deux |
| ROC-AUC | Aire sous courbe TPR vs FPR | Compare capacité discrimination modèles (invariant seuil) | Peut être élevé même si performance faible sur classe minoritaire |
| PR-AUC | Aire sous courbe Precision vs Recall | Plus fiable que ROC-AUC en déséquilibre - mieux réflète métier | Coûteux à calculer (100s d'iterations) |
Dans la maintenance industrielle -
- Coût FN (panne ratée) - ~1 000 EUR/heure (arrêt production) = très cher
- Coût FP (alerte inutile) - ~100 EUR (technicien se déplace) = bon marché
Donc → Recall ≥ 85% (détecter 85% des pannes réelles), accepter FP jusqu'à ~15%.
score = F1 − 0.5 × σ(F1_CV)
Où σ(F1_CV) = écart-type du F1 sur 5 folds CV.
Raisonnement - on veut maximiser F1 moyen (performance) tout en minimisant variance (stabilité). Le facteur 0.5 privilégie slightly la stabilité.
Utiliser à l'entraînement une information qui ne sera pas disponible à l'inférence. Cela gonfl les métriques en train mais le modèle échoue en production.
| Cause | Exemple problématique | Solution appliquée |
|---|---|---|
| Normalisation sur dataset complet | StandardScaler fit sur train+test ensemble | ✓ Fit sur train uniquement, transform test après |
| Feature engineering sur target | Calculer une feature via la cible (ex. ratio pannes/sample) | ✓ Aucune feature dérivée de la cible - uniquement les capteurs bruts |
| Cross-val naïve | Split train/test, puis CV sur train+test | ✓ CV toujours imbriquée dans train |
| Test set vu à l'entraînement | Hypertuning sur test set | ✓ Optuna sur CV train uniquement |
# ✓ CORRECT - Pipeline immutable
pipeline = Pipeline([
("preprocessor", ColumnTransformer([
("num", StandardScaler(), numeric_features),
("cat", OneHotEncoder(), categorical_features),
])),
("classifier", XGBClassifier(...)),
])
pipeline.fit(X_train, y_train) # Fit sur train
y_pred = pipeline.predict(X_test) # Transform+predict test auto
# Le preprocessing est "gelé" sur les paramètres d'entraînementQu'est-ce ? Classement des features par contribution moyenne à la prédiction.
Techniques -
-
Native importance (sklearn) - Gini/Gain dans arbres
- Avantage - très rapide, O(n×m)
- Inconvénient - ne capture pas les interactions
- Cas d'usage - exploration rapide, baseline
-
Permutation importance (sklearn)
- Shuffler une feature, mesurer baisse métrique
- Avantage - model-agnostic, robuste
- Inconvénient - coûteux (O(n×m)), corrélations masquées
- Cas d'usage - audit final, validation
Qu'est-ce ? Pour chaque prédiction, décompose la contribution de chaque feature (positive = vers panne, négative = vers sain).
Techniques -
-
TreeExplainer (XGBoost / Random Forest)
- Exact - trace tous les chemins arbre
- Avantage - très rapide (ms par sample)
- Cas d'usage - production (API temps réel)
-
KernelExplainer (universal, LogReg / MLP)
- Approximation par coalitions locales
- Avantage - model-agnostic
- Inconvénient - lent (besoins 5000 queries par sample)
- Cas d'usage - explications offline détaillées
Interprétation -
SHAP value positif → la feature pousse la prédiction vers panne (y=1)
SHAP value négatif → la feature pousse la prédiction vers sain (y=0)
|SHAP value| haut → contribution importante
- Force plot - top 10 features + SHAP values, barres couleur
- Waterfall plot - 1 sample - décomposition cascadée de la prédiction
- Summary plot - scatter plot moyenne |SHAP| par feature, coloré par valeur
- Dependence plot - scatter feature value vs SHAP value (détecte non-linéarités)
| Contexte | Technique | Raison |
|---|---|---|
| Dashboard exploration rapide | Native importance | Rapide, déjà calculée |
| Audit final rapport | Permutation importance | Robuste, model-agnostic |
| API temps réel (1 sample) | TreeExplainer + Force plot | 1-10 ms, actionnable opérateur |
| Investigation post-mortem (5 pannes) | Waterfall plot | Décomposition détaillée per-sample |
| Feature engineering validation | Dependence plot | Visualise non-linéarités, interactions |
Le sujet impose explicitement l'évaluation du degré d'écoresponsabilité des modèles.
CodeCarbon estime l'empreinte carbone (gCO₂ équivalent) basée sur -
- Consommation électrique - TDP CPU + GPU, durée entraînement
- Mix énergétique national - France ~80 gCO₂/kWh (nucléaire, bas carbone)
- Formule - gCO₂eq = (énergie kWh) × (intensité carbone gCO₂/kWh)
| Modèle | Temps train (s) | Power (W) | Energy (kWh) | CO₂ (mg) | Efficacité (F1/mg) |
|---|---|---|---|---|---|
| Logistic Regression | 3.2 | 45 | 0.00004 | 0.30 | 2883 |
| Random Forest | 45.1 | 180 | 0.00226 | 8.21 | 111 |
| XGBoost | 34.8 | 165 | 0.00159 | 6.12 | 152 |
| MLP | 18.5 | 95 | 0.00049 | 3.79 | 236 |
| Ensemble | 101.6 | - avg - | 0.0044 | 18.4 | ~50 |
- Baseline optimale - Logistic Regression (0.3 mg CO₂), mais F1=0.86 insuffisant.
- Best compromise - XGBoost (F1=0.928, 6.12 mg CO₂) = 152 F1-points par mg CO₂eq.
- Limiter ensemble - Une fois modèle sélectionné, ne pas réentraîner 4×.
- Décorrélation CPU/perso - les résultats peuvent varier ±30% selon machine.
Données brutes - reports/03/metrics_summary.csv contient les colonnes fit_time_s et predict_time_ms mesurées au runtime.
# src/config.py
RANDOM_STATE: int = 42Propagée à tous les composants -
# numpy
np.random.seed(RANDOM_STATE)
# scikit-learn
LogisticRegression(random_state=RANDOM_STATE)
RandomForestClassifier(random_state=RANDOM_STATE)
train_test_split(..., random_state=RANDOM_STATE)
StratifiedKFold(..., random_state=RANDOM_STATE)
# xgboost
XGBClassifier(random_state=RANDOM_STATE, ...)
# mlp
MLPClassifier(random_state=RANDOM_STATE)python --version → 3.12.0
pip freeze → requirements.txt avec versions [m.n.p]
Relancer après clone -
pip install -r requirements.txt # versions exactes
# Pré-requis - CSV Kaggle dans data/raw/predictive_maintenance_v3.csv
python scripts/02_eda.py
python scripts/03_train_models.py
# → Résultats identiques à la machine d'origin Adam/Emilien- Source unique - Kaggle CC0 - tatheerabbas/industrial-machine-predictive-maintenance
- Téléchargement -
kaggle datasets download tatheerabbas/industrial-machine-predictive-maintenancepuis extrairepredictive_maintenance_v3.csvdansdata/raw/ - Validation auto -
src.data_loader.load_dataset()valide le schéma 15 colonnes à chaque chargement, lèveFileNotFoundErroravec instructions Kaggle si absent - Politique stricte - aucun fallback synthétique nulle part. Si le CSV est absent, les tests skip proprement et les scripts plantent avec un message clair. Pas de génération de données.
# Après exécution complète, vérifier les métriques
cat reports/03/metrics_summary.csv | head -5
# Doit montrer 4 lignes (logistic_regression, random_forest, xgboost, mlp)
# avec F1 ≈ 0.74 / 0.86 / 0.89 / 0.83 sur seed=42
# Vérifier le seuil optimal calibration
cat models/optimal_threshold.json
# Doit être 0.928 (tolérance ±0.001 selon machine)| Code | Compétence | Implémentation | Preuves (fichiers/sections) |
|---|---|---|---|
| C3.1 | Préparer et transformer les données | ColumnTransformer (Imputer + Scaler + OHE) - preprocessing.py - anti-leakage pipeline sklearn |
src/preprocessing.py lignes 40-120 - schéma dans section "Architecture" du rapport (p.4) |
| C3.2 | Concevoir et mettre en oeuvre un tableau de bord interactif et inclusif | Dashboard Streamlit - 5 onglets - CSS EFREI - KPI + EDA + comparaison + simulateur + SHAP - 6 fonctions exigées | dashboard/app.py lignes 1-600 - captures dans README section "Lancer le dashboard" |
| C3.3 | Réaliser une analyse exploratoire des données | EDA script - 7+ graphiques (distributions, correlations, imbalance) - stats descriptives | scripts/02_eda.py - reports/02/eda_*.png - section "Pipeline" du rapport (p.5-6) |
| C4.1 | Intégrer une stratégie d'IA dans la chaîne de valeur métier | Modèle prédictif 24h - cas métier maintenance industrielle - coût FN vs FP - thresholdoldOptimization - ROI documented | Rapport section 1 "Contexte métier" (p.2-3) - ADR-0001 |
| C4.2 | Concevoir et mettre en oeuvre des modèles prédictifs ML/DL | 4 modèles (LogReg, RF, XGBoost, MLP 64-32-16) - CV stratifiée 5-fold - sélection via F1−0.5σ - hyperparamètres justifiés | src/models.py lignes 28-170 - tableau comparaison "Modèles comparés" - section "Modèles comparés" du README |
| C4.3 | Évaluer la performance des modèles et leur écoresponsabilité | 6 métriques (Accuracy, Precision, Recall, F1, ROC-AUC, PR-AUC) - temps d'entraînement et latence d'inférence par modèle - Brier score calibration | src/evaluation.py lignes 76-150 - reports/03/metrics_summary.csv (colonnes fit_time_s, predict_time_ms) - reports/03/compute_cost_comparison.png |
| C4.4 | Assurer la qualité et la pérennité des solutions IA | Tests pytest (preprocessing, models, evaluation, API) - logging structuré - version semver (2.0.0) - docs (ADR) | tests/*.py - tests/*.py - docs/adr/*.md - section "Reproductibilité" du README |
| EF4 | Tableau de bord opérationnel | Streamlit 5-onglets (KPI, EDA, modèles, simulator, SHAP) - CSS premium - sliders interactifs | dashboard/app.py - section README "Lancer le dashboard" |
| EF5 | API REST industrialisation | FastAPI endpoints - /predict (prédiction) - /health (santé) - /model-info (métadonnées) - validation Pydantic |
api/main.py - section README "Lancer l'API" - exemples cURL |
| Feature | Impact RNCP | Fichier |
|---|---|---|
| Classification multi-classe (failure_type) | Approfondit C4.2 (modélisation) | scripts/07_train_multiclass.py |
| Régression (RUL hours) | Approfondit C4.2 (prédiction continue) | scripts/08_train_regression.py |
| Hyperparameter tuning (Optuna) | Renforce C4.2 (optimisation) | scripts/09_tune_hyperparams.py |
| Calibration probabiliste | Avance C4.3 (évaluation + métier) | scripts/10_calibrate.py |
Au lieu de prédire "panne oui/non", on prédit le type exact de panne.
Cible - failure_type ∈ {none, bearing, motor_overheat, hydraulic, electrical} (5 classes).
Modèles - 4 modèles réentraînés en mode multi-classe -
python scripts/07_train_multiclass.pyMétrique - F1 macro (moyenne non-pondérée) plutôt que F1 binaire.
Output - reports/07/multiclass_confusion_matrix.png, models/multiclass_final.joblib.
Prédire le nombre d'heures restantes avant panne.
Cible - rul_hours (valeur continue, [0, 2000]).
Modèles - 4 modèles adaptés en régression -
python scripts/08_train_regression.pyMétriques - MAE (erreur absolue moyenne), RMSE, R² (coefficient détermination).
Output - reports/08/regression_pred_vs_true.png, models/regression_final.joblib.
Optimisation bayésienne des hyperparamètres (plutôt que GridSearch exhaustif).
python scripts/09_tune_hyperparams.pySampler - TPE (Tree-structured Parzen Estimator) - plus efficace que Random Search.
Trials - 100 essais, pruning adaptatif (arrête trial non-prometteuse tôt).
Output - reports/09/tuning_results.json.
Affiner les probabilités prédites pour minimiser le coût métier (FN=1000€, FP=100€).
python scripts/10_calibrate.pyOutils -
- Reliability diagram - graphique étalonnage empirique vs probabilités
- Brier score - MSE(y_true, y_proba)
- Optimal threshold - seuil Youden ou custom cost-sensitive
Output - reports/10/reliability_diagram_*.png + reports/10/cost_threshold_*.png, seuil optimal recommandé dans models/optimal_threshold.json.
Le sujet impose « au minimum 4 modèles dont 1 Deep Learning ». 4 est un bon compromis -
- 2 trop peu (pas assez de variation pour comp comparative)
- 5+ coûteux en temps (200+ min train) et émissions CO₂
- Nous avons choisi LogReg (baseline), RF (bagging), XGB (boosting), MLP (DL) pour couvrir les familles principales
LSTM - mieux pour séries temporelles (t-1, t, t+1). Notre dataset est tabulaire stateless (capteurs statiques à un instant T), pas une série temporelle. LSTM serait sur-dimensionné.
Conv1D - pour signaux 1D (audio, ECG). Notre cas c'est 9 features indépendantes, pas un signal continu.
Conclusion - MLP suffit. Si les données étaient temporelles (historique 24h), on aurait exploré LSTM.
Actuellement - failure_within_24h (binaire). Pour changer -
# src/config.py
TARGET_BINARY = "failure_type" # switch à multi-classe
TARGET_REGRESSION = "rul_hours" # ou régressionPuis -
python scripts/03_train_models.py # réentraînerLes métriques s'adaptent automatiquement (F1 pour classification, RMSE pour régression).
- Installer -
pip install catboost - Ajouter factory -
# src/models.py
def build_catboost() -> Pipeline:
return Pipeline([
("preprocessor", build_preprocessor()),
("classifier", CatBoostClassifier(random_state=42, verbose=0)),
])- Enregistrer dans
scripts/03_train_models.py-
models = {
"LogReg": build_logistic_regression(),
"CatBoost": build_catboost(), # ← new
...
}- Relancer -
python scripts/03_train_models.py
| Aspect | Streamlit | Dash | Plotly |
|---|---|---|---|
| Prototypage | ⚡⚡⚡ ultra-rapide | slow | |
| Data science friendly | ⚡⚡ streamlit cache | overkill | |
| CSS custom | ⚡ facile st.markdown |
difficile | |
| Production ready | ⚡ via Streamlit Cloud/Enterprise | ⚡⚡ robuste |
Pour un MVP étudiant, Streamlit est le choix optimal.
# 1. Télécharger via Kaggle CLI (clé API requise dans ~/.kaggle/kaggle.json)
kaggle datasets download -d tatheerabbas/industrial-machine-predictive-maintenance
unzip industrial-machine-predictive-maintenance.zip -d data/raw/
# 2. Renommer si nécessaire pour matcher le contrat de schéma
mv data/raw/predictive_maintenance.csv data/raw/predictive_maintenance_v3.csv
# 3. Lancer la pipeline
python scripts/02_eda.py# 1. Relancer entraînement (sur nouvelles données si dispo)
python scripts/03_train_models.py
# 2. Vérifier métriques
cat reports/03/metrics_summary.csv | grep f1
# 3. Lancer API
uvicorn api.main:app --reload --host 0.0.0.0 --port 8000Le modèle final est chargé automatiquement depuis models/final_model.joblib.
- Ajouter colonne au CSV source
- Updater config -
# src/config.py
NUMERIC_FEATURES = [
"vibration_rms",
"vibration_z_axis", # ← new
...
]- Rétraiter + réentraîner -
python scripts/03_train_models.py # ColumnTransformer s'adapteLe preprocessing et les modèles se réajustent automatiquement.
Cause - Dataset manquant (pas téléchargé de Kaggle, synthetique pas généré).
Solutions -
# Option 1 - télécharger Kaggle
kaggle datasets download -d tatheerabbas/industrial-machine-predictive-maintenance
unzip archive.zip -d data/raw/Cause - KernelExplainer estime sur 2500 backgrounds samples - trop coûteux en RAM sur petit CPU.
Solutions -
# src/interpretability.py - reduce backgrounds
explainer = shap.KernelExplainer(
model_predict_proba,
shap.sample(X_train, 500) # ← 500 au lieu de 2500
)Ou utiliser TreeExplainer si le modèle final est XGBoost/RF (gratuit).
Cause - max_iter=1000 insuffisant sur certaines machines (lent convergence).
Solution -
# src/models.py
LogisticRegression(max_iter=5000, solver="saga", ...) # augmenter ou changer solverCause - virtualenv pas activé ou dépendances pas installées.
Solutions -
# Vérifier virtualenv actif (prefix [.venv] ou (.venv))
pip install -r requirements.txt --upgrade
python -c "import src; print(src.__version__)"Cause - API/Dashboard déjà lancés sur ces ports.
Solutions -
# Trouver et tuer processus
lsof -i :8000 # Linux/macOS
# ou
netstat -ano | findstr :8000 # Windows
# Puis
kill -9 <PID>
# Ou changer port
uvicorn api.main:app --port 8001
streamlit run dashboard/app.py --server.port=8502Cause - seed aléatoire changé, versions dépendances différentes, données modifiées.
Diagnostic -
# Vérifier seed
grep RANDOM_STATE src/config.py # doit être 42
# Vérifier versions
pip freeze | grep -E "scikit|xgboost|shap"
# Vérifier données (hash)
md5sum data/raw/predictive_maintenance_v3.csv- Déploiement Cloud (Vercel/Render) pour accès public
- MLflow pour tracking expériences (alternative Optuna)
- Monitoring drift automatique (données en production vs train)
- Alertes Slack si F1 baisse
- Ajout LSTM temporel si données séries 24h disponibles
- Edge deployment (TensorFlow Lite pour IoT gateway)
- Web UI pour upload CSV + predictions batch
- Internationalisation dashboard (FR/EN/ES)
- Federated learning (entraînement décentralisé multi-usines)
- Confidence intervals sur prédictions (Bayesian MLP)
- AutoML wrapper (H2O, AutoGluon)
- Explainability audit - LIME + SHAP comparaison
Ce projet n'aurait pas été possible sans -
- Sarah Malaeb - enseignante, sujet du projet, feedback continu
- EFREI Paris Panthéon-Assas Université - ressources académiques, infrastructure
- Kaggle Dataset - Tathaeer Abbas pour le dataset public CC0
- Communauté open source - scikit-learn, XGBoost, Streamlit, FastAPI, SHAP, CodeCarbon maintainers
Merci aussi à Emilien Morice, coauteur du projet, pour les brainstormings et les alternances de contributions.
Ce projet est sous licence MIT - libre d'usage, modification, redistribution (voir LICENSE).
Nous acceptons contributions via pull requests -
- Fork le dépôt
- Créer branche
feat/*oufix/* - Commiter en anglais impératif court (ex.
fix: SHAP normalization on 3D arrays) - Ouvrir PR avec description courte
- Tests pytest doivent passer avant merge
- Merge après approbation
Si vous réutilisez ce projet -
@misc{beloucif_morice_2026,
title={Maintenance Prédictive Industrielle - Système Intelligent Multi-Modèles},
author={Beloucif, Adam and Morice, Emilien},
year={2026},
school={EFREI Paris Panthéon-Assas Université},
note={M1 Data Engineering & IA - BC2 RNCP40875}
}Dernière mise à jour - 2026-04-28
Version - 2.0.0
Auteurs - Adam BELOUCIF - Emilien MORICE (n° 20241824)
Status - Production ready (v2.0 + 7 bonus scripts) - Reproductibilité certifiée seed=42
Scripts complémentaires (lecture seule sur les données, artefacts dans reports/) -
| Script | Apport | Sortie |
|---|---|---|
scripts/12_drift_psi.py |
Détection de dérive (PSI train → test), seuils 0.10 / 0.25 | reports/12/ |
scripts/13_conformal.py |
Prédiction conforme (split-conformal LAC) - ensembles avec garantie de couverture 80/90/95 % | reports/13/ |
scripts/14_mlflow_log.py |
Traçabilité MLflow des 4 modèles (params, métriques, modèle promu) | mlruns/ (mlflow ui) |
scripts/15_noise_robustness.py |
Robustesse au bruit capteur et aux pannes de sonde | reports/15/ |
src/conformal.py - conformaliseur binaire réutilisable (garantie distribution-free).
- Modèle temporel (LSTM/GRU) - non implémenté ici - le dataset est un instantané tabulaire sans séquence horodatée par machine. Nécessite des séries capteurs (fenêtres glissantes) avant d'entraîner un modèle séquentiel.
- Dataset alternatif - validation croisée sur NASA C-MAPSS ou UCI AI4I 2020 pour confirmer la robustesse cross-source.
- Monitoring continu - brancher le PSI (script 12) en tâche planifiée + alerte au-delà du seuil.