DEV Community

Cover image for Churn prediction where the simple model wins: logistic regression against five rivals
Omar Essam El Sherbiny
Omar Essam El Sherbiny

Posted on

Churn prediction where the simple model wins: logistic regression against five rivals

This was my final project for IBM's Supervised Machine Learning: Classification course: predict which telecom customers will leave, using the IBM Telco Customer Churn dataset (7,043 customers, 26.5% of whom churned). The modelling was the easy part. The interesting decision came at the end, when the best three models turned out to be indistinguishable.

A fair comparison first

Every model family was grid-searched on the same five stratified folds of the same 80/20 split, scored by ROC AUC, and then evaluated once on the held-out test set with a 95% confidence interval.

Model CV AUC Test AUC 95% CI
Gradient boosting 0.849 0.846 0.825–0.868
Random forest 0.849 0.843 0.821–0.865
Logistic regression (L2, C = 0.1) 0.844 0.843 0.821–0.865
SVM, RBF kernel 0.844 0.843 0.819–0.865
k-nearest neighbours 0.838 0.832 0.808–0.854
Decision tree (pruned) 0.839 0.831 0.807–0.854

Model comparison

Gradient boosting has the highest number, but its lead over logistic regression is 0.003 AUC, well inside overlapping confidence intervals. When the accuracy is a tie, I pick on the things that matter after deployment: can the business read the model, and is its ranking stable?

Why logistic regression got the job

Logistic regression gives odds ratios that a retention team can act on directly:

Feature Odds ratio What it means
Two-year contract 0.33 a third of the churn odds of month-to-month
Fibre-optic internet 2.43 2.4 times the odds of DSL
Tenure (per ~24 months) 0.45 churn risk halves with every two years
Tech support add-on 0.68 support customers stay more often

Odds ratios

I checked whether the simple model was leaving signal on the table: permutation importance on the gradient-boosting model ranks the same drivers (tenure, contract, fibre) at the top. The model is also stable: eight variations (L1 or L2, C from 0.1 to 10, with and without class weights) all land within 0.001 AUC of each other.

Two details that are easy to miss

Collinearity. MonthlyCharges is almost entirely determined by the service flags (R² = 0.999), and TotalCharges is essentially tenure times monthly charges (r = 0.9996). Keeping them makes coefficients unreadable without adding information, so both were dropped, leaving 22 model features.

The threshold. The default 0.5 threshold is rarely the right one for an imbalanced problem. I set it at the point on the precision–recall curve that maximises F1 (0.35 for logistic regression), which gives precision 0.58 and recall 0.70. Class weighting does something similar: class_weight="balanced" lifts recall from 0.52 to 0.79 at the default threshold, at a cost in precision.

What it means for a retention campaign

A churn model is only useful if it changes who gets a call. Ranking customers by predicted probability:

  • contacting the top 20% reaches 50% of the churners and 56% of the revenue at risk;
  • the top 30% reaches 66% of the churners and 71% of that revenue.

Gains chart

Limits

The dataset is a single snapshot with no time dimension, so the model predicts who has churned rather than who will churn next quarter. The threshold ignores the cost of contacting a customer, which a real campaign would put in.


Omar Essam El Sherbiny. Head of Data at WalaPlus. Data platforms on Google Cloud, data governance, applied ML. More at omaressam.web.app.

Top comments (0)