Skip to content

satyamshivam13/Customer_Churn_Prediction

Repository files navigation

Customer Churn Prediction — MLOps Pipeline

Tests Python License: MIT

End-to-end customer churn prediction pipeline with XGBoost (0.868 accuracy, 0.855 ROC-AUC), FastAPI REST API, Docker deployment, batch inference, and model drift monitoring.


Table of Contents


🎯 Project Overview

End-to-end ML pipeline for predicting customer churn in banking, covering data preprocessing, feature engineering, model benchmarking, REST API deployment, Dockerised inference, and data drift monitoring.

What Detail
Dataset Bank Customer Churn — 10,000 customers
Models Logistic Regression · Random Forest · XGBoost
Serving FastAPI REST API (single + batch endpoints)
Deployment Docker / Docker Compose
Monitoring Custom drift detection + prediction logging

🏗️ Architecture

Project Structure

Customer_Churn_Prediction/
├── .github/
│   └── workflows/
│       └── tests.yml          # CI — runs pytest on every push / PR
├── data/
│   ├── raw/                   # Raw Kaggle CSV (Churn_Modelling.csv)
│   ├── processed/             # Train/test splits (git-ignored)
│   ├── sample/
│   │   └── churn_sample_100rows.csv  # Synthetic 100-row sample
│   └── download_data.py       # Automated Kaggle download utility
├── notebooks/
│   └── 01_eda.ipynb           # Exploratory Data Analysis
├── src/
│   ├── data_preprocessing.py  # Cleaning · feature engineering · scaling
│   ├── train_model.py         # LR · RF · XGBoost training + evaluation
│   └── model_monitoring.py    # Drift detection + prediction logging
├── api/
│   └── main.py                # FastAPI application (single + batch predict)
├── models/                    # Serialised models + evaluation artefacts
│   ├── logistic_regression.joblib
│   ├── random_forest.joblib
│   ├── xgboost.joblib
│   ├── preprocessor.joblib
│   ├── model_comparison.csv
│   ├── roc_curves.png
│   ├── confusion_matrices.png
│   ├── feature_importance.png
│   └── monitoring/            # Prediction logs (git-ignored)
├── tests/
│   ├── test_api.py            # FastAPI endpoint tests
│   └── test_preprocessing.py  # Preprocessing unit tests
├── demo_predict.py            # Live API demo script
├── requirements.txt
├── Dockerfile
└── docker-compose.yml

Data Flow

data/raw/Churn_Modelling.csv
        │
        ▼  src/data_preprocessing.py
  Clean → Feature Engineering → Encode → Scale
        │
        ├─► data/processed/  (X_train, X_test, y_train, y_test)
        └─► models/preprocessor.joblib

Training Flow

data/processed/  ─► src/train_model.py
                       │
                       ├─► LogisticRegression   ─► models/logistic_regression.joblib
                       ├─► RandomForestClassifier ► models/random_forest.joblib
                       └─► XGBClassifier         ─► models/xgboost.joblib
                                │
                       models/model_comparison.csv
                       models/roc_curves.png
                       models/feature_importance.png

Inference Flow

POST /predict  ──► preprocess_input()
                        │
                        ▼  models/preprocessor.joblib
               Feature Engineering → Encode → Scale
                        │
                        ▼  models/{model}.joblib
                   predict_proba()
                        │
                        ▼
              { churn_prediction, churn_probability,
                model_used, confidence, timestamp }

Monitoring Flow

Every prediction ─► src/model_monitoring.py
                         │
                ┌────────┴────────┐
                ▼                 ▼
   models/monitoring/        Drift Detection
   predictions_log.jsonl     (vs training dist.)
   metrics_log.jsonl

📊 Model Performance

Trained on 8,000 customers · evaluated on 2,000 held-out customers · random_state=42

Model Accuracy Precision Recall F1 Score ROC-AUC
Logistic Regression 0.849 0.764 0.374 0.502 0.832
Random Forest 0.861 0.806 0.419 0.550 0.858
XGBoost 0.868 0.786 0.479 0.595 0.855

Best ROC-AUC: Random Forest (0.858) — preferred for ranking tasks
Best Accuracy: XGBoost (0.868) — preferred for threshold-based decisions

Full metrics saved to models/model_comparison.csv.


🚀 Quick Start

Prerequisites

  • Python 3.11+
  • Docker (optional, for containerised deployment)

1. Clone and Setup

git clone https://github.com/satyamshivam13/Customer_Churn_Prediction.git
cd Customer_Churn_Prediction

python -m venv venv
# Windows:
venv\Scripts\activate
# Linux / Mac:
source venv/bin/activate

pip install -r requirements.txt

2. Get the Dataset

See Data Setup below.

3. Preprocess Data

python src/data_preprocessing.py

Outputs:

  • data/processed/X_train.csv, X_test.csv, y_train.csv, y_test.csv
  • models/preprocessor.joblib

4. Train Models

python src/train_model.py

Outputs: serialised models, ROC curves, confusion matrices, feature importance plots, model_comparison.csv.

5. Start the API

uvicorn api.main:app --reload --host 0.0.0.0 --port 8000

6. Run the Demo

python demo_predict.py

📂 Data Setup

The full 10,000-row dataset (Churn_Modelling.csv) is included in data/raw/ for reproducibility.

Option A — Automated Kaggle Download (fresh clone)

# Install Kaggle API client
pip install kaggle

# Configure credentials once:
#   1. Visit https://www.kaggle.com/settings/account → API → Create New API Token
#   2. Save kaggle.json to ~/.kaggle/kaggle.json
#   3. Linux/Mac: chmod 600 ~/.kaggle/kaggle.json

python data/download_data.py

Option B — Manual Download

python data/download_data.py --manual

Follow the printed instructions.

Option C — Synthetic Sample (no account needed)

A 100-row synthetic dataset with the same schema is available for pipeline testing without requiring a Kaggle account:

# Run preprocessing on the sample dataset
python - <<'EOF'
from src.data_preprocessing import ChurnDataPreprocessor
p = ChurnDataPreprocessor()
X_train, X_test, y_train, y_test = p.preprocess_pipeline(
    "data/sample/churn_sample_100rows.csv"
)
EOF

The sample file data/sample/churn_sample_100rows.csv contains:

  • 100 synthetic rows (no real customer data)
  • Same 14-column schema as the Kaggle dataset
  • ~33% churn rate (inflated for test coverage of both classes)

🔌 API Usage

Single Prediction

curl -X POST "http://localhost:8000/predict?model_name=xgboost" \
  -H "Content-Type: application/json" \
  -d '{
    "CreditScore": 650,
    "Geography": "France",
    "Gender": "Female",
    "Age": 42,
    "Tenure": 5,
    "Balance": 100000.0,
    "NumOfProducts": 2,
    "HasCrCard": 1,
    "IsActiveMember": 1,
    "EstimatedSalary": 50000.0
  }'

Response:

{
  "churn_prediction": "Yes",
  "churn_probability": 0.7234,
  "model_used": "xgboost",
  "confidence": "High",
  "timestamp": "2026-01-28T10:30:00.123456"
}

Available model names: logistic_regression, random_forest, xgboost (default).

Batch Prediction

curl -X POST "http://localhost:8000/predict/batch?model_name=xgboost" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "CreditScore": 750, "Geography": "France", "Gender": "Male",
      "Age": 35, "Tenure": 8, "Balance": 0.0, "NumOfProducts": 1,
      "HasCrCard": 1, "IsActiveMember": 1, "EstimatedSalary": 80000.0
    },
    {
      "CreditScore": 400, "Geography": "Germany", "Gender": "Female",
      "Age": 58, "Tenure": 2, "Balance": 145000.0, "NumOfProducts": 3,
      "HasCrCard": 0, "IsActiveMember": 0, "EstimatedSalary": 45000.0
    }
  ]'

Response:

{
  "total_customers": 2,
  "successful_predictions": 2,
  "results": [
    { "customer_index": 0, "success": true, "churn_prediction": "No",  "churn_probability": 0.08 },
    { "customer_index": 1, "success": true, "churn_prediction": "Yes", "churn_probability": 0.89 }
  ]
}

Python Client

import requests

response = requests.post(
    "http://localhost:8000/predict",
    params={"model_name": "xgboost"},
    json={
        "CreditScore": 650, "Geography": "France", "Gender": "Female",
        "Age": 42, "Tenure": 5, "Balance": 100000.0, "NumOfProducts": 2,
        "HasCrCard": 1, "IsActiveMember": 1, "EstimatedSalary": 50000.0,
    },
)
print(response.json())

🐳 Docker Deployment

Build and Run

docker build -t churn-prediction-api .
docker run -p 8000:8000 -v $(pwd)/models:/app/models churn-prediction-api

Docker Compose (Recommended)

docker-compose up -d       # start
docker-compose logs -f     # stream logs
docker-compose down        # stop

The Compose file mounts ./models and ./data as volumes, so trained models are available without rebuilding the image.


🔍 Model Monitoring

src/model_monitoring.py provides:

Feature Detail
Prediction logging Every inference written to models/monitoring/predictions_log.jsonl
Data drift detection Mean-shift comparison against training distribution
Performance tracking Log accuracy / precision / recall / F1 / ROC-AUC over time
Health checks Automated model-file and activity checks
Reporting On-demand monitoring report
python src/model_monitoring.py
from src.model_monitoring import ModelMonitor

monitor = ModelMonitor()

# Log a prediction
monitor.log_prediction(
    customer_data=data_dict,
    prediction="Yes",
    probability=0.75,
    model_name="xgboost",
)

# Detect data drift
drift = monitor.detect_data_drift(new_data_df)

# Generate report
print(monitor.generate_monitoring_report())

🧪 Testing

pytest tests/ -v
Test file Coverage
tests/test_preprocessing.py Initialisation · cleaning · feature engineering
tests/test_api.py Root · health · models · predict endpoints

CI runs pytest automatically on every push and pull request via GitHub Actions.


🛠️ Tech Stack

Layer Tools
Language Python 3.11
ML scikit-learn · XGBoost
Data pandas · numpy
Visualisation matplotlib · seaborn · plotly
API FastAPI · Uvicorn · Pydantic
Monitoring Custom (JSONL logs + drift detection)
Testing pytest · httpx
Deployment Docker · Docker Compose
CI/CD GitHub Actions
Development Jupyter · VS Code

📈 Key Insights from EDA

  1. Class imbalance — 20.4% churn rate (2,037 / 10,000 customers)
  2. Age — strong positive correlation (0.29); older customers churn more
  3. Geography — Germany has the highest churn rate of the three countries
  4. Active membership — inactive members churn significantly more (−0.16 correlation)
  5. Product count — customers with 3–4 products have 83–100% churn rate
  6. Balance — slight positive correlation (0.12)
  7. Gender — female customers show higher churn tendency
  8. Tenure — relatively stable across all tenure groups (0–10 years)

📝 Model Training Details

Feature Engineering

Feature Description
TenureGroup Bucketed tenure: 0–3 / 3–6 / 6–9 / 9+ years
BalanceToSalaryRatio Balance / (EstimatedSalary + 1)
AgeGroup Young / Middle / Senior / Elderly
HighProductRisk Flag: NumOfProducts >= 3
EngagementScore Composite of active membership, credit card, products

Hyperparameters

Logistic Regressionmax_iter=1000, solver lbfgs

Random Forestn_estimators=100, max_depth=10, min_samples_split=20

XGBoostn_estimators=100, max_depth=6, learning_rate=0.1, subsample=0.8, colsample_bytree=0.8


🐛 Troubleshooting

Issue Fix
Models not loading in API Run python src/train_model.py first
Dataset not found Run python data/download_data.py or place Churn_Modelling.csv in data/raw/
Import errors Activate the virtual environment; run pip install -r requirements.txt
Docker container fails Ensure models/ contains trained .joblib files

📄 License

MIT — see LICENSE.

👤 Author

Satyam Shivam — Data Science & MLOps Portfolio
GitHub: satyamshivam13

🙏 Acknowledgments

📚 Future Enhancements

  • SMOTE for class imbalance
  • Hyperparameter tuning (Optuna / GridSearchCV)
  • Precision-Recall curves
  • MLflow model versioning & experiment tracking
  • API authentication
  • Frontend dashboard (Streamlit / Gradio)
  • A/B testing framework
  • Real-time predictions with Kafka

Built with Python, FastAPI, and Docker.

About

End-to-end ML pipeline for customer churn prediction. XGBoost (0.868 ROC AUC) + FastAPI REST API + Docker + model drift monitoring. Production-ready

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors