Skip to content

About

Customer churn prediction modeling.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Customer Churn Prediction

Author: Patrick Maina

A production ML system that predicts customer churn for a Telecommunication company. The project includes a trained XGBoost model, a REST API backend deployed on Railway, and an interactive Streamlit dashboard deployed on Streamlit Community Cloud.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        GitHub                           β”‚
β”‚  Push to main β†’ CI/CD (GitHub Actions)                  β”‚
β”‚    └── Run tests                                        β”‚
β”‚    └── Report status to Railway                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
                       β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚      Railway             β”‚
        β”‚      FastAPI API         β”‚  ◄── Streamlit Community Cloud
        β”‚  /predict  /predict/batchβ”‚       (streamlit/app.py)
        β”‚  /health                 β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Backend: FastAPI on Railway β€” handles all predictions, preprocessing, and SHAP explanations (Explainable AI)
  • Frontend: Streamlit on Streamlit Community Cloud β€” pure HTTP client, calls the backend API
  • Registry: Railway builds and deploys from this repository's Dockerfile
  • CI/CD: GitHub Actions runs tests, and Railway deploys after checks pass

Features

  • Single Prediction β€” Enter customer details and get an instant churn prediction with probability score, risk level (low/medium/high), and a SHAP feature contribution chart explaining the top 10 drivers
  • Batch Prediction β€” Upload a CSV of customers, get predictions for all of them, and download the results
  • Explainability β€” SHAP values aggregated back to original feature names, showing which factors increase or decrease churn risk
  • REST API β€” POST /predict and POST /predict/batch endpoints for programmatic access

Business Understanding

Introduction

The telecommunications industry has become very competitive over the years, with customer retention emerging as a critical challenge. One of the major issues facing telecom providers is customer churn; a scenario where users discontinue their service, either due to dissatisfaction from the provider, or due to the availability of better alternatives. High churn rates can significantly impact a company's overall revenue and scaling potential.

Problem Statement

SyriaTel, a leading telecom provider, is experiencing a significant loss of customers who are choosing to leave its services for competitors. To address this challenge, the company seeks to build a robust predictive model capable of identifying customers who are at risk of churning. By leveraging data-driven insights and predictive modeling, SyriaTel aims to understand the key drivers of customer attrition, determine methods of improving long-term retention, and enhance long-term customer loyalty and profitability.

Objectives

  • Determine the key characteristics and behavior patterns that likely contribute to customer churn
  • Build a robust predictive model that identifies customers with a high likelihood of discontinuing their service
  • Provide data-driven insights and recommendations that will proactively engage and retain high-risk customers

Dataset

This project uses the Telecom Churn Dataset from Kaggle (3,333 customers). Key attributes include:

  • State and Area Code β€” geographic identifiers
  • International and Voice Mail Plans β€” subscription plan flags
  • Call rates β€” day, night, evening, and international charge rates
  • Customer Service Calls β€” number of support interactions

Methodology

1. Data Exploration

Loading, inspecting for missing values/duplicates, and computing descriptive statistics.

2. Data Cleaning

Standardizing column names, converting Area_Code to object type, dropping Phone_Number, and removing highly correlated features (threshold: 0.9).

3. Exploratory Data Analysis

Univariate and bivariate analysis using distribution plots, correlation heatmaps, box plots, and bar charts.

4. Data Preprocessing

One-hot encoding for categorical features, MinMaxScaler for numeric features, and SMOTENC for class imbalance.

5. Predictive Modeling

Trained six models (Logistic Regression as baseline, Decision Tree, Random Forest, Gradient Boosting, XGBoost, and others) evaluated on recall and AUC-ROC.

6. Model Evaluation & Hyperparameter Tuning

ROC curves, AUC scores, confusion matrices, and RandomizedSearchCV for the top two models.


πŸ“ˆ Crucial Visualizations

Analyzing Customer Service Calls by Rate of Churn

customer_service_churn

Distribution of Numerical Features

numerical_dist

Feature Correlation Heatmap

feature_heatmap


Conclusion

The XGBoost Classifier achieved a recall score of 0.82 and AUC of 0.911. The Gradient Boosting model achieved a slightly higher AUC of 0.921 but lower recall of 0.81. Given the nature of churn prediction where missing a churner is more costly than a false alarm, the XGBoost model is recommended. Key churn drivers identified: Customer_Service_Calls, Total_Day_Charge, and International_Plan.

Business Recommendations

  1. Targeted Incentives for High-Churn Area Codes β€” Customers in area codes 415 and 510 exhibit higher churn tendencies. Offering specialized discounts, loyalty rewards, or exclusive promotions in these regions can serve as an effective retention incentive.

  2. Enhance Customer Service Efficiency β€” A high number of customer service interactions is correlated with increased churn. Investing in staff training and better conflict resolution frameworks can significantly boost customer satisfaction.

  3. State-Specific Retention Strategies β€” States such as Texas, New Jersey, Maryland, Miami, and New York report above-average churn. Developing localized marketing and enhanced customer support in these regions would strengthen retention.

  4. Review and Optimize Call Rate Plans β€” Customers who churn often experience high day, evening, night, and international call rates. Introducing more competitive or bundled plans could make services more attractive.


Local Development

Prerequisites

  • Docker and Docker Compose
  • uv (Python package manager)

Setup

git clone https://github.com/Patricknmaina/customer_churn_prediction.git
cd customer_churn_prediction
uv sync

Run locally with Docker Compose

docker compose up

This starts both services:

  • FastAPI backend at http://localhost:8000
  • Streamlit dashboard at http://localhost:8501

Run tests

uv run pytest tests/ -v --tb=short

Retrain the model

uv run train

This runs the full training pipeline and saves updated artifacts to artifacts/.

Deployment

Backend β€” DigitalOcean App Platform (Legacy)

The backend is deployed as a Docker container via DigitalOcean App Platform. The CI/CD pipeline handles all deployments automatically on push to main.

One-time bootstrap (first deploy)

1. Authenticate with DigitalOcean:

doctl auth init

2. Create the container registry:

doctl registry create customer-churn-registry --subscription-tier basic

3. Build and push the image manually:

doctl registry login --expiry-seconds 1200
docker build --target api -t registry.digitalocean.com/customer-churn-registry/churn-api:latest .
docker push registry.digitalocean.com/customer-churn-registry/churn-api:latest

4. Create the App Platform app:

doctl apps create --spec .do/app.yaml

5. Get the App ID and live URL:

doctl apps list
doctl apps get <APP_ID> --format DefaultIngress

CI/CD (automatic after bootstrap)

Every push to main automatically:

  1. Runs tests (uv run pytest)
  2. Builds a new Docker image tagged with the commit SHA and latest
  3. Pushes the image to DOCR
  4. Triggers a new App Platform deployment

Required GitHub repository secrets:

Secret Value
DIGITALOCEAN_ACCESS_TOKEN Your DigitalOcean API token
DOCR_REGISTRY customer-churn-registry
DIGITALOCEAN_APP_ID App ID from doctl apps list

Add these at: GitHub repo β†’ Settings β†’ Secrets and variables β†’ Actions


Backend β€” Railway (Migration Path)

This repo now includes railway.toml for Railway config-as-code.

Current Railway configuration:

  • Builder: DOCKERFILE
  • Dockerfile path: Dockerfile.api
  • Healthcheck path: /health
  • Healthcheck timeout: 300 seconds
  • Restart policy: ON_FAILURE (max retries: 10)
  • Replicas: 1

One-time setup on Railway

  1. Create a new Railway project and service from this GitHub repository.
  2. Confirm the service is using the repo Dockerfile (or leave default detection).
  3. In service variables, set:
    • PYTHONUNBUFFERED=1
  4. Deploy once and verify GET /health returns:
    • status: "healthy"
    • model_loaded: true
  5. Copy the public Railway backend URL for frontend configuration.

Notes

  • The API container now binds to Railway's dynamic port using ${PORT:-8000}.
  • Model artifacts are baked into the image (artifacts/), so inference works on Railway without external storage.
  • If you retrain locally, commit updated artifacts/ and redeploy.

CI/CD on Railway

GitHub Actions now runs tests only. Deployment is handled by Railway GitHub Autodeploy.

  1. Open your Railway service.
  2. Enable GitHub Autodeploy for main.
  3. Enable Wait for CI in Railway deployment settings.
  4. Select this workflow as the required check: CI β€” Backend Tests.

With this setup:

  1. A push to main triggers GitHub tests.
  2. Railway deploys only after CI succeeds.
  3. Failed CI blocks deployment.

Frontend β€” Streamlit Community Cloud

1. Go to share.streamlit.io and sign in with GitHub

2. Click Create app β†’ Deploy a public app from GitHub

3. Fill in:

  • Repository: Patricknmaina/customer_churn_prediction
  • Branch: main
  • Main file path: streamlit/app.py

4. Click Advanced settings and add:

API_URL = https://<your-railway-backend>.up.railway.app

5. Click Deploy!

Community Cloud reads streamlit/requirements.txt, installs the four frontend dependencies, and serves the app at https://<your-app-name>.streamlit.app.


Retraining the Model

When new data is available or the model needs updating:

# 1. Retrain locally
uv run train

# 2. Commit the updated artifacts
git add artifacts/
git commit -m "retrain model - <reason>"
git push

GitHub CI validates the push and Railway deploys the updated image after checks pass.

Technologies

Category Tools
ML XGBoost 3.0, scikit-learn 1.6, SHAP 0.42+, imbalanced-learn 0.13
API FastAPI 0.115+, Uvicorn 0.32+, Pydantic 2.10+
Frontend Streamlit 1.40+, Plotly 6.1, pandas 2.2, requests
Packaging uv, joblib
Containerization Docker (multi-stage build), Docker Compose
CI/CD GitHub Actions
Hosting Railway (backend), Streamlit Community Cloud (frontend)
Registry Railway-managed deployment pipeline
Testing pytest 8+, pytest-cov, httpx

Repository Structure

customer_churn_prediction/
β”œβ”€β”€ api/                        # FastAPI backend
β”‚   β”œβ”€β”€ main.py                 # App entrypoint, endpoints (/health, /predict, /predict/batch)
β”‚   └── schemas.py              # Pydantic request/response models
β”œβ”€β”€ streamlit/                  # Streamlit dashboard
β”‚   β”œβ”€β”€ app.py                  # Interactive UI (Home, Single Prediction, Batch Prediction tabs)
β”‚   └── requirements.txt        # Frontend-only dependencies for Streamlit Community Cloud
β”œβ”€β”€ scripts/                    # ML pipeline
β”‚   β”œβ”€β”€ config.py               # Central constants (paths, features, thresholds, model params)
β”‚   β”œβ”€β”€ data_prep/              # Cleaning and preprocessing
β”‚   β”œβ”€β”€ eda/                    # EDA visualization utilities
β”‚   β”œβ”€β”€ modeling/               # Training, evaluation, hyperparameter tuning
β”‚   └── serving/                # ChurnPredictor inference engine (predict.py)
β”œβ”€β”€ tests/                      # Full test suite mirroring scripts/ structure
β”œβ”€β”€ artifacts/                  # Serialized model artifacts (committed for CI/CD builds)
β”‚   β”œβ”€β”€ model.joblib
β”‚   β”œβ”€β”€ scaler.joblib
β”‚   β”œβ”€β”€ encoder.joblib
β”‚   β”œβ”€β”€ label_encoder.joblib
β”‚   β”œβ”€β”€ feature_names.json
β”‚   └── dropped_features.json
β”œβ”€β”€ .do/
β”‚   └── app.yaml                # DigitalOcean App Platform deployment spec
β”œβ”€β”€ .github/workflows/
β”‚   └── deploy-api.yml          # CI pipeline (backend tests)
β”œβ”€β”€ Dockerfile                  # Multi-stage build (api target, streamlit target)
β”œβ”€β”€ docker-compose.yml          # Local development (both services)
β”œβ”€β”€ pyproject.toml              # Project metadata and dependencies
└── data/
    └── churn.csv               # Raw dataset (Kaggle Telecom Churn)

License

MIT License - see LICENSE file for details

About

Customer churn prediction modeling.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages