← Back to selected projects

Independent learning project · 2023

Predicting churn.
Interrogating the result.

An exploratory logistic-regression project examining class imbalance, threshold choices, and what makes an evaluation trustworthy.

ProblemIdentify customers likely to leave
ToolsPython · scikit-learn · SMOTE
MethodLogistic regression
StatusHistorical learning project

01The modeling question

Can customer characteristics help identify customers who may leave a bank? The project approaches churn as a binary classification problem and explores the challenge of finding a smaller churn class within a larger retained-customer population.

For a retention team, missing a likely churner and contacting a customer who would have stayed have different costs. That makes precision and recall more informative than accuracy alone.

02Data & modeling approach

The baseline notebook splits the customer data into training and test sets, holding out 20% of observations with a fixed random seed. It fits a logistic-regression classifier and evaluates predictions with a classification report and confusion matrix.

The baseline test set contains 2,000 customers, including 393 churn cases. The notebook then explores SMOTE oversampling and a lower decision threshold of 0.4 to increase sensitivity to churn.

  1. Prepare customer features and the binary churn target.
  2. Fit and evaluate a baseline logistic-regression model.
  3. Explore class balancing with synthetic minority observations.
  4. Adjust the decision threshold and review the precision–recall tradeoff.

03What the notebook reports

Historical notebook evaluation metrics for churn class
Notebook runChurn precisionChurn recallAccuracy
Baseline45%7%80%
SMOTE + 0.4 threshold*60%86%65%

The baseline misses most churn cases. Its confusion matrix identifies 28 churners and misses 365. An overall accuracy near 80% hides that weakness because most customers in the test set are non-churners.

The adjusted run reports higher recall alongside more false positives. However, its evaluation setup prevents treating those numbers as reliable performance on unseen customers.

*An important evaluation limitation

The historical notebook applies SMOTE to the full dataset before the train/test split. This can leak information across the split and inflate performance. The adjusted test set also has a different class balance, so the two rows are not a clean like-for-like comparison. The reported 86% recall is a learning result, not a validated deployment metric.

04A stronger evaluation design

Reviewing this project makes the next steps clear. A sound re-evaluation would:

  1. Split the original data first. Keep an untouched test set with the original customer distribution.
  2. Resample only training data. Place SMOTE inside the training workflow and within each cross-validation fold.
  3. Choose the threshold on validation data. Use the cost of missed churn and unnecessary outreach to guide the tradeoff.
  4. Evaluate once on the test set. Report confusion counts, precision, recall, and precision–recall performance without tuning against that set.

This is a proposed improvement to the historical work; the portfolio does not claim that this corrected experiment has already been run.

05Deliverable & practical value

The deliverable is an exploratory notebook documenting a baseline and an attempted class-imbalance adjustment. Its value is in exposing the limits of accuracy, showing how a threshold changes errors, and identifying the need for a leakage-free evaluation before using predictions operationally.

Read the original notebook on GitHub

Keep exploring

A personal SQL practice tool

Next project