Étude courte de machine learning causal appliquée au ciblage marketing.
L'objectif est de montrer, avec un pipeline reproductible, pourquoi un modèle de propension classique ne répond pas à la même question qu'un modèle d'uplift.
Un modèle de propension répond à :
Qui a le plus de chances de convertir ?
Un modèle d'uplift répond à :
Pour qui la campagne change-t-elle réellement le comportement ?
Ces deux classements peuvent être différents. Pour décider qui cibler avec un budget marketing limité, le projet compare donc :
P(Y=1 | X): probabilité d'outcome ;P(Y=1 | X,T=1) - P(Y=1 | X,T=0): uplift / effet incrémental ;P(T=1 | X): propension à recevoir le traitement.
L'accuracy n'est pas une métrique principale ici. Les métriques suivies sont Qini AUC, AUUC, uplift@k, incremental outcome@k, policy value, déciles d'uplift, overlap top-k et intervalles bootstrap.
Le dépôt contient maintenant une passe dev reproductible sur 1 000 000 lignes
du dataset Criteo Uplift :
- audit dataset et EDA ;
- baselines random et propension ;
- T-Learner Logistic Regression et HistGradientBoosting ;
- baseline uplift
scikit-uplift; - outcomes
visitetconversion; - sélection de politique sur validation uniquement ;
- test set verrouillé après sélection ;
- table consolidée versionnée dans
reports/tables/experiment_results.csv; - intervalles bootstrap propagés dans la table consolidée ;
- tests de sensibilité reader-first dans
reports/sensitivity_analysis_dev.md; - rapport complet dans
reports/final_report.md.
Résultats dev à k=20 % :
| Outcome | Politique sélectionnée | Split test uplift@20 % | Lecture rapide |
|---|---|---|---|
visit |
propensity_logistic_regression |
0.0406 | La propension gagne ce run, mais l'overlap montre que les politiques ne ciblent pas toujours les mêmes lignes. |
conversion |
propensity_hist_gradient_boosting |
0.00504 | Le signal est rare ; les intervalles bootstrap doivent être lus avec prudence. |
Ce résultat ne force pas une conclusion "uplift gagne toujours". Le point du projet est de comparer les politiques avec des métriques incrémentales et de montrer pourquoi l'AUC ROC seule ne suffit pas pour décider d'un ciblage.
| Besoin | Fichier |
|---|---|
| Rapport complet lisible | reports/final_report.md |
| Sensibilité et robustesse | reports/sensitivity_analysis_dev.md |
| Table consolidée des expériences | reports/tables/experiment_results.csv |
| Reproductibilité du run dev | reports/reproducibility_dev.md |
| Schéma du pipeline | docs/14_pipeline_schema.md |
| Audit dataset dev | reports/data_audit_dev_visit.md |
| EDA dev | reports/eda_dev_visit.md |
Pipeline dev sur visit |
reports/minimal_pipeline_dev_visit.md |
Pipeline dev sur conversion |
reports/minimal_pipeline_dev_conversion.md |
| Rapport smoke court | reports/smoke_study_report.md |
| Roadmap d'implémentation | docs/09_implementation_roadmap.md |
| Backlog / issues | docs/12_backlog_issues.md |
| Checklist reproductibilité | docs/13_reproducibility_checklist.md |
| Cadre causal | docs/03_causal_framework.md |
| Plan de modélisation | docs/04_modeling_plan.md |
| Métriques | docs/05_metrics_evaluation.md |
Dataset cible : Criteo Uplift Modeling Dataset.
Le loader essaie scikit-uplift, puis bascule vers le CSV officiel Criteo v2.1
si le miroir est indisponible :
https://go.criteo.net/criteo-research-uplift-v2.1.csv.gz
Les données brutes ne doivent pas être commitées. Les scripts écrivent seulement
des agrégats, figures et rapports dans reports/.
Traitement principal : treatment.
exposure est une variable post-traitement : elle est reportée comme diagnostic,
pas utilisée comme traitement principal.
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,uplift]"Dans l'environnement utilisé pour le run dev, scikit-uplift est installé et
les modèles avancés optionnels econml, causalml et lightgbm ne sont pas
requis pour reproduire le rapport actuel.
Pour reconstruire le projet dev de bout en bout :
make reproduceCette commande relance audit, EDA, pipelines visit et conversion, diagnostic
de sensibilité, rapport final, table consolidée, figures et tests.
Tests :
make testSmoke run rapide :
python scripts/00_data_audit.py --mode smoke --outcome visit --treatment treatment --random-state 42
python scripts/02_run_eda.py --mode smoke --outcome visit --treatment treatment --random-state 42
python scripts/01_run_minimal_pipeline.py --mode smoke --outcome visit --treatment treatment --random-state 42 --bootstrap-iterations 50 --selection-metric qini_auc --selection-k 0.20
python scripts/03_build_smoke_report.py --selection-k 0.20Reconstruction partielle depuis les artefacts existants :
make sensitivity
make final-report
make experiment-results
make figuresCommandes utilisées pour les runs dev principaux :
python scripts/00_data_audit.py --mode dev --outcome visit --treatment treatment --random-state 42
python scripts/02_run_eda.py --mode dev --outcome visit --treatment treatment --random-state 42
python scripts/01_run_minimal_pipeline.py --mode dev --outcome visit --treatment treatment --random-state 42 --bootstrap-iterations 100 --selection-metric qini_auc --selection-k 0.20
python scripts/01_run_minimal_pipeline.py --mode dev --outcome conversion --treatment treatment --random-state 42 --bootstrap-iterations 100 --selection-metric qini_auc --selection-k 0.20
python scripts/07_build_sensitivity_analysis.py --mode dev --outcomes visit conversion --selection-k 0.20
python scripts/04_build_final_report.py --mode dev --primary-outcome visit --secondary-outcome conversion --selection-k 0.20
python scripts/05_build_experiment_results.py --mode dev --outcomes visit conversion --audit-outcome visit
python scripts/06_refresh_figures.pypropensity-not-uplift/
├── configs/ # Configuration projet et matrice d'expériences
├── data/ # Données non versionnées
├── docs/ # Protocole, roadmap, métriques, limites
├── notebooks/ # Notebooks narratifs
├── reports/ # Rapports Markdown + figures + table consolidée
├── scripts/ # Entrées reproductibles audit/EDA/pipeline/report
├── src/uplift_study/ # Code testable réutilisable
└── tests/ # Tests unitaires
- Ajouter éventuellement un learner causal avancé : X-Learner, DRLearner ou CausalForestDML.
- Relancer avec bootstrap final plus robuste (
1000) si le temps de calcul le permet. - Exporter un PDF propre du rapport final si un livrable hors GitHub est requis.
- Construire un dashboard léger si l'objectif devient exploratoire/interactif.
- Optimiser l'accuracy.
- Utiliser
exposurecomme traitement principal sans justification séparée. - Versionner les données brutes ou les prédictions ligne à ligne.
- Présenter une causalité forte sans hypothèses.
- Présenter le smoke run comme résultat final.