Bienvenue dans ce projet de classification en Machine Learning dont l’objectif est d’analyser et prédire les démissions d’employés (attrition) au sein de l’ESN TechNova Partners, spécialisée dans le conseil en transformation digitale et la vente de solutions SaaS.
Ce dépôt contient l’ensemble du travail réalisé en tant que Consultant Data Scientist pour :
- comprendre les facteurs clés derrière les démissions,
- construire un modèle de prédiction de l’attrition,
- produire des insights actionnables pour les équipes RH
- Contexte & objectifs
- Jeux de données
- Approche
- Structure du dépôt
- Mise en place du modèle
- API(FastAPI)
- Base de donées PostgreSQL
- Installation
- Utilisation
- Workflow Git
- Traçabilité des prédictions
- Tests & Couverture (CI)
- Déploiement(CI/CD)
- Déploiment HF Spaces (Docker)
- Livrables
- Auteur
Problème : anticiper les départs d’employés (attrition) et expliquer les facteurs clés.
Objectifs:
- Construire un pipeline scikit-learn (prétraitements + modèle RF)
- Exposer une **API ** (FastAPI) avec Swagger/OpenAPI.
- Tracer chaque prédiction (inputs/outputs) dans PostgreSQL
- Mettre en place CI (tests) et CD (déploiement automatique).
Trois sources principales sont mises à disposition :
-
SIRH: poste, département, contrat, âge, ancienneté, salaire, etc.
-
Évaluations de performance: notes annuelles, engagement/satisfaction, historiques RH.
-
Sondage annuel employés: bien-être, charge, management, équilibre vie pro/perso.
Variable cible (attrition = 1/0)
Ces différentes sources sont fusionnées et préparées pour construire un dataset modélisable.
Fichier aligné pour l’inférence : data/processed/df_central_norm.csv
(contient le feature engineering attendu par le pipeline et les schémas SQL).
-
Préparation : encodages catégoriels, normalisation, features (
exp_moins_3_years, etc.). -
Modèle :
RandomForestClassifierdans un Pipeline scikit-learn. -
API : FastAPI + endpoints
predict_oneetpredict_proba. -
Traçabilité : table
ml.predictions_log(inputs/outputs/threshold). -
Déploiement : Docker → Hugging Face Spaces (CD GitHub Actions).
-
Qualité : Pytest + couverture, règles de branche et PR.
.
├── src/
│ ├── __init__.py
│ ├── data_preparation.py. # chargement & split X/y (données traitées)
│ ├── train_model.py # entraînement + sauvegarde artefact
│ └── utils.py # utilitaires (chargement modèle, prédiction unitaire)
├── tests/
│ ├── test_data_preparation.py
│ └── test_predict.py
├── models/ # artefact modèle
├── data/
│ ├── raw/ # fichiers brutsv(privé, ignoré) – .gitkeep
│ └── processed/ # données traités (visibles)
├── db/
│ ├── attrition_local.session.sql # schémas hr_staging/hr/ml + indexes + logs
│ ├── create_db.py # création table + exemple
│ └── load_csv.py # chargement CSV → hr.employees
├── notebooks/
│ ├── 01_analyse_exploratoire.ipynb
│ ├── 02_preprocessing.ipynb
│ └── 03_modelisation.ipynb
├── .github/workflows/
│ ├── ci.yml
│ └── deploy-to-hf-space.yml
├── main.py # entraînement
├── pyproject.toml # configuration de l'environnement & dépendances
├── requirements.txt. # exporté depuis uv
├── README.md
├── .gitignore
└── uv.lock
├── Dockerfile # verrouillage précis des versions
-
Entraînement : notebooks 01_analyse_exploratoire.ipynb, 02_preprocessing.ipynb et 03_modelisation.ipynb.
-
Artefact modèle :
model.joblib(hébergé sur Hugging Face Hub, téléchargé à l’inférence). -
Chargement côté API : si
models/model.joblibest absent, l’API télécharge depuisveranoscience/attrition-model. -
Seuil :
THRESHOLD=0.33→pred= (proba >= 0.33)`.
-
Doc Swagger :
/docs -
Endpoints principaux :
GET /health → statut, source du modèle (local ou hub), threshold.
POST /predict_one → prédiction unitaire (retourne proba et pred).
POST /predict_proba → prédictions batch (retourne listes probas et preds).
Exemple :
curl -s -X POST http://127.0.0.1:8000/predict_one \
-H "Content-Type: application/json" \
-d '{
"age":41, "genre":"F", "revenu_mensuel":6000, "statut_marital":"Célibataire",
"departement":"Consulting", "poste":"Consultant",
"nombre_experiences_precedentes":6, "annees_dans_le_poste_actuel":2,
"note_evaluation_precedente":3, "note_evaluation_actuelle":3,
"heure_supplementaires":0, "augementation_salaire_precedente":12,
"nombre_participation_pee":1, "nb_formations_suivies":2,
"distance_domicile_travail":5, "niveau_education":2,
"annees_depuis_la_derniere_promotion":1, "annes_sous_responsable_actuel":2,
"satisfaction_globale":3.0, "exp_moins_3_years":0,
"domaine_etude":"Infra & Cloud", "frequence_deplacement":"Occasionnel"
}'
# → {"threshold":0.33,"proba":0.1443,"pred":0}
Objectif : assurer une traçabilité complète des échanges API ↔ modèle.
- Schémas :
hr_staging : réception brute (employees_raw).
hr : table typée finale (employees) + index.
ml : table de log des inférences (predictions_log) + index.
- Scripts :
db/attrition_local.session.sql → crée schémas/tables/index.
db/load_csv.py → charge data/processed/df_central_norm.csv dans hr.employees.
db/create_db.py → exemple alternatif (table simple predictions + insertion d’une ligne).
Activation du logging DB côté API (local) :
export DATABASE_URL="postgresql+psycopg2://appuser:appuser@localhost:5432/attrition"
uvicorn src.api.server:app --reload
# Chaque appel /predict_* crée une ligne dans ml.predictions_log
Prérequis
-
Python 3.10+
-
git
-
PostgreSQL 15 local
(macOS : brew install postgresql@15)
uv venv && source .venv/bin/activate
uv syncuvicorn src.api.server:app --reload
# Swagger: http://127.0.0.1:8000/docs- Lancer les notebooks
Depuis la racine du projet, avec l’environnement activé :
jupyter notebookPuis ouvrir:
-
notebooks/01_analyse_exploratoire.ipynbpour l’analyse exploratoire -
notebooks/02_preprocessing.ipynbpour le nettoyage & feature engineering -
notebooks/03_modelisation.ipynbpour la modélisation et SHAP
Script (entrai&nement rapide)
python main.pyUn artefact est sauvegardé dans models/model.joblib
Healthcheck
curl -s http://127.0.0.1:8000/health | jqBatch
curl -s -X POST http://127.0.0.1:8000/predict_proba \
-H "Content-Type: application/json" \
-d '{"inputs":[{ ... les mêmes champs que /predict_one ... }]}'- Branche principale :
main(protégée) - Conventions de branches :
<type><-resume->- Types :
feat,fix,docs,refactor,chore,test,data - Examples :
docs/mise-a-jour-readme
- Types :
- Commits descriptifs:
feat: ...,chore: ... - Tags de version :
v0.1.0,v0.2.0, ...- Créer :
git tag -a v0.1.0 -m "v0.1.0: base" - Pousser :
git push origin v0.1.0
- Créer :
Résolution de conflits : utiliser l’outil intégré VS Code
(Accept Current/Incoming → git add . → git rebase --continue).
Activation : définir la variable d’env. DATABASE_URL avant de lancer l’API.
export DATABASE_URL="postgresql+psycopg2://appuser:appuser@localhost:5432/attrition"
uvicorn src.api.server:app --reloadÀ chaque appel réussi : insertion dans ml.predictions_log (date, payload, proba, classe, seuil, statut).
Requête de contrôle :
SELECT created_at, proba, pred, threshold, status
FROM ml.predictions_log
ORDER BY created_at DESC
LIMIT 5;Lancer localement :
uv run pytest
# avec couverture:
uv run pytest --cov=src --cov-report=term-missingCI GitHub Actions (.github/workflows/ci.yml) :
-
installe l’environnement,
-
exécute Pytest,
-
calcule la couverture,
-
bloque la PR si la CI échoue.
-
Dockerfile à la racine.
-
Workflow
deploy-to-hf-space.yml:-
clone le repo du Space,
-
copie
Dockerfile,pyproject.toml,src/, db/, README.md, etc., -
push vers le Space → rebuild automatique → API en ligne.
-
Secrets requis (GitHub → Settings → Secrets and variables → Actions) :
-
HF_TOKEN: token Hugging Face (scope write). -
HF_SPACE_SLUG: slug owner/SpaceName (ex. veranoscience/OpenClassroomsProject).
Cycle CD :
-
Crée une branche → commit → PR.
-
Merge vers
main. -
L’Action CD se lance et déploie sur le Space.
- Dockerfile à la racine. Le Space utilise
sdk: docker.
Port par défaut 7860. L’API est servie par Uvicorn.
Modèle téléchargé au démarrage si absent localement.
Le projet fournit :
-
Dépôt Git structuré : code source,
pyproject.toml, historique (branches/PR/tags), README. -
API FastAPI fonctionnelle, documentée (Swagger), déployée (Docker + HF Spaces).
-
Tests Pytest + rapport de couverture (via CI).
-
Base PostgreSQL : schémas SQL, scripts de création/chargement, logs d’inférence.
-
CI/CD : GitHub Actions (CI PR & CD déploiement auto).
Projet pédagogique - Ksenia Dautel