Skip to content

About

Predicts which dormant B2B clients will reactivate if contacted. End-to-end ML pipeline turns 2M transactions into a campaign-ready priority list via Extra Trees + RFM feature engineering. Delivers 3.4× lift over random outreach. Python, scikit-learn, XGBoost.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VarGroup — Customer Reactivation Propensity Model

A machine learning project that ranks dormant B2B clients by their probability of returning, turning a 2-million-row transaction log into a campaign-ready priority list for marketing.

Python scikit--learn XGBoost Status


Business problem

VarGroup's marketing team needed a way to decide which inactive customers to re-engage first. With tens of thousands of dormant clients and a finite campaign budget, random outreach wastes money on clients who will never come back. The goal of this project was to build a reactivation propensity score that ranks every silent client by how likely they are to make a positive-NET purchase if contacted — so the sales team can focus on the top of the list.


TL;DR results

Metric Value
Inactive clients scored 13,244
Reactivations observed in target window 875 (6.61%)
Best model Extra Trees Classifier
AUC-ROC 0.70
PR-AUC (Average Precision) 0.22
F1-optimal threshold 0.55
Lift over random targeting 3.4×

For every 100 clients contacted using the model, the campaign reaches 3.4× more reactivatable customers than a random outreach of the same size.


Methodology

1. Time-split target definition (no leakage)

  • Observation cutoff: 2019-12-31
  • Feature window: all transactions strictly before the cutoff
  • Target window: January–June 2020 (6 months after cutoff)
  • Target = 1 if the client has at least one positive-NET transaction in the target window; returns and zero-value lines do not count
  • Population filter: only clients with no purchases in the 24 months before the cutoff are included — i.e. the model learns the transition from inactive to active, not the next purchase of an already-engaged customer

2. Feature engineering

Transactions are aggregated from 2M rows to one row per client (an Analytical Base Table), capturing:

  • RFM core — recency, frequency, monetary sum/mean/max/std
  • Inter-purchase gaps — mean, max, and standard deviation of days between purchases
  • Product mix — unique items, unique families, entropy of purchase categories
  • Spend windows — last-12-month and last-36-month spend
  • Tool vs. non-tool split — spend share and transaction share on core tool products
  • Spend momentum — monthly spend trend over the client's history
  • Ratios — average ticket, spend per active month, tool share of transactions
  • Firmographics — region, trade sector, employee count, economic potential, potential gap

3. Class imbalance

Reactivators are ~6.6% of the population. Rather than using SMOTE (which can inject noise into tabular data), random undersampling of the majority class was used. Ratios 1:5, 1:10 and 1:20 were tested; 1:10 gave the best Precision–Recall trade-off.

4. Modeling

Three models trained on the balanced set and evaluated on the original imbalanced test set (so metrics reflect real deployment):

  • Extra Trees Classifier ← selected
  • XGBoost
  • Logistic Regression

Selection criterion: PR-AUC, the most informative metric under heavy class imbalance.

5. Threshold tuning

A threshold sweep from 0.10 to 0.90 was used to map the Precision/Recall trade-off. The F1-maximising threshold of 0.55 is the default operating point, but it is deliberately exposed as a business lever: lower it to cast a wider net, raise it to prioritise conversion rate over reach.

6. Feature importance & leakage audit

  • Both native (impurity-based) and permutation importance were computed — permutation is model-agnostic and more robust against high-cardinality bias
  • A dedicated leakage audit retrained the model without registry snapshot fields (columns ending in _first) and compared AUC delta, to verify that results are not driven by information that leaked from the target window into the static client registry

7. Scoring & delivery

The final model is applied to the full inactive population to produce reactivation_scores.csv — every client ranked by predicted reactivation probability. The subset above threshold is written to campaign_targets.csv, ready for the CRM.


Key business insights

  • High-spend clients have the highest reactivation propensity. The "whales" that have gone quiet are disproportionately worth chasing.
  • Tool-focused buyers (60–80% tool spend share) are the best campaign targets. Pure generalists and pure specialists are harder to bring back.
  • Recency alone does not predict reactivation. Behavioural patterns — product diversity, spend momentum, inter-purchase variability — matter far more than "how long since they last bought".
  • The top-ranked features by permutation importance are TRADE SECTOR, REGION, and MAX_GAP_DAYS — a mix of firmographics and behavioural variability.

Project structure

VarGroup-Reactivation-Model/
├── README.md
├── requirements.txt
├── .gitignore
├── notebooks/
│   └── project_final.ipynb       # Full end-to-end analysis
├── outputs/
│   ├── reactivation_scores.csv   # All 13,244 inactive clients, ranked
│   └── campaign_targets.csv      # Subset above the F1-optimal threshold
└── data/
    └── README.md                 # Data is confidential and not shipped

Data

The raw transactional data (TOOL_CLIENT.csv, TOOL_SALES.csv) is not included in this repository — it contains confidential client information. The notebook assumes both files are placed in data/ before running.

The shipped outputs/ files contain anonymised client IDs and model scores only, no transactional detail.


How to run

# 1. Clone
git clone https://github.com/<your-username>/VarGroup-Reactivation-Model.git
cd VarGroup-Reactivation-Model

# 2. Create a virtual environment (recommended)
python -m venv .venv
source .venv/bin/activate          # macOS / Linux
# .venv\Scripts\activate           # Windows

# 3. Install dependencies
pip install -r requirements.txt

# 4. Place the raw data in data/ (not shipped — see Data section)
#    data/TOOL_CLIENT.csv
#    data/TOOL_SALES.csv

# 5. Open the notebook
jupyter lab notebooks/project_final.ipynb

Tech stack

  • Python 3.10+
  • pandas, numpy — data wrangling
  • scikit-learn — Extra Trees, Logistic Regression, pipelines, metrics, permutation importance
  • xgboost — gradient-boosted trees
  • category_encoders — target encoding for high-cardinality categoricals
  • matplotlib, seaborn — EDA and result visualisation

Future work

  • Calibration — Platt scaling or isotonic regression to make scores directly interpretable as probabilities
  • Uplift modeling — move from "who will reactivate?" to "who will reactivate because we contacted them?", which is the real marketing question
  • Time-aware cross-validation — rolling-origin CV across multiple observation dates for a more robust generalisation estimate
  • Survival analysis framing — model time-to-reactivation rather than a binary 6-month window
  • Cost-sensitive thresholding — replace F1 with a business-loss function that weighs campaign cost against lifetime value

License

This project is released under the MIT License — see LICENSE for details.


Built as an end-to-end case study in customer analytics: from raw transactions to a deployed marketing priority list.

About

Predicts which dormant B2B clients will reactivate if contacted. End-to-end ML pipeline turns 2M transactions into a campaign-ready priority list via Extra Trees + RFM feature engineering. Delivers 3.4× lift over random outreach. Python, scikit-learn, XGBoost.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages