A complete end-to-end machine learning project that predicts whether a telecom customer will churn. This project utilizes the Telco Customer Churn dataset to build a training pipeline, exposes the model via a Flask REST API, and provides a user-friendly web interface.
This repository demonstrates the full MLOps workflow: Data Cleaning → Preprocessing Pipeline → Model Training → Threshold Tuning → Model Persistence → REST API → Web UI.
(Optional: Add a screenshot of your Web UI here)
- Home UI:
GET /(Paste JSON payload and view prediction) - Health Check:
GET /health - Prediction API:
POST /predict(JSON input → JSON output)
The API response includes:
churn_probability: The raw probability score from the model.churn_label:1(Churn) or0(No Churn) based on a custom tuned threshold.threshold: The specific threshold value used for the decision.
- Data Validation: Loaded and validated dataset shape (7,043 rows, 21 columns).
- Data Cleaning: Handled real-world dirty data, specifically converting
TotalChargesfromobjectto numeric and handling resultingNaNvalues. - ** robust Pipeline:**
ColumnTransformerfor handling mixed data types.OneHotEncoder(handle_unknown="ignore")to ensure the API doesn't crash on unseen categories.StandardScalerfor normalizing numeric features.
- Algorithm: Logistic Regression (Baseline).
- Pipeline Integration: Used scikit-learn
Pipelineto bundle preprocessing and modeling, preventing data leakage and ensuring consistency between training and inference. - Threshold Tuning: Instead of the default
0.5, the classification threshold was tuned using the Precision-Recall curve to prioritize specific business metrics (e.g., Target Recall).
- Persistence: Model artifacts saved using
joblib. - API: Flask REST API handling JSON requests.
- Frontend: A clean HTML/JS/CSS dashboard for testing predictions manually.
Customer-Churn-Prediction-System/
├── app/
│ ├── app.py # Main Flask application
│ ├── static/ # CSS/JS files
│ │ └── app.js
│ └── templates/ # HTML templates
│ └── index.html
├── data/
│ ├── processed/ # Cleaned data for training
│ └── raw/ # Original dataset
├── models/
│ ├── churn_pipeline.joblib # Trained model pipeline
│ ├── schema.json # Expected input schema
│ └── threshold.json # Tuned threshold value
├── notebooks/
│ └── Customer Churn EDA.ipynb # Jupyter notebook for analysis
├── src/
│ ├── client_test.py # Script to test the API programmatically
│ └── predict.py # Prediction logic
├── requirements.txt
└── README.md
python -m venv .venv
# Activate in PowerShell:
.venv\Scripts\Activate.ps1
# Or in Command Prompt (cmd):
# .venv\Scripts\activate.bat
pip install -r requirements.txt
*> Note: If requirements.txt is missing, install necessary packages (flask, scikit-learn, pandas, numpy) and generate it: pip freeze > requirements.txt*
From the project root directory:
python -m app.app
Once the server starts, open your browser:
- UI: http://127.0.0.1:5000/
- Health Check: http://127.0.0.1:5000/health
Send a JSON object containing customer data to get a churn prediction.
Headers:
Content-Type: application/json
Example Payload:
{
"gender": "Female",
"SeniorCitizen": 0,
"Partner": "Yes",
"Dependents": "Yes",
"tenure": 24,
"PhoneService": "Yes",
"MultipleLines": "No",
"InternetService": "No",
"OnlineSecurity": "No internet service",
"OnlineBackup": "No internet service",
"DeviceProtection": "No internet service",
"TechSupport": "No internet service",
"StreamingTV": "No internet service",
"StreamingMovies": "No internet service",
"Contract": "One year",
"PaperlessBilling": "No",
"PaymentMethod": "Mailed check",
"MonthlyCharges": 20.0,
"TotalCharges": 480.0
}
Example Response:
{
"churn_probability": 0.0310,
"churn_label": 0,
"threshold": 0.4021
}
Run the included test script to simulate a client request:
python src/client_test.py
curl -X POST [http://127.0.0.1:5000/predict](http://127.0.0.1:5000/predict) ^
-H "Content-Type: application/json" ^
-d "{\"gender\":\"Male\", \"SeniorCitizen\": 0, \"Partner\": \"No\", \"Dependents\": \"No\", \"tenure\": 1, \"PhoneService\": \"No\", \"MultipleLines\": \"No phone service\", \"InternetService\": \"DSL\", \"OnlineSecurity\": \"No\", \"OnlineBackup\": \"Yes\", \"DeviceProtection\": \"No\", \"TechSupport\": \"No\", \"StreamingTV\": \"No\", \"StreamingMovies\": \"No\", \"Contract\": \"Month-to-month\", \"PaperlessBilling\": \"Yes\", \"PaymentMethod\": \"Electronic check\", \"MonthlyCharges\": 29.85, \"TotalCharges\": 29.85}"
models/churn_pipeline.joblib: Contains the full pipeline (Preprocessing + Classifier). This ensures that the exact same transformations applied during training are applied during inference.models/schema.json: Stores the list of expected input columns. This is used to align the JSON input with the model's expected dataframe structure.models/threshold.json: Stores the optimal probability threshold derived during the EDA/Training phase.
- Add
src/train.pyto automate the training and threshold selection process. - Implement Pydantic for stricter input validation and error handling.
- Add a
/predict_batchendpoint for bulk processing. - integrate SHAP values to explain why a customer is at risk of churning.
MIT