Machine Learning project 11
Machine Learning Customer Churn Prediction Project
Build and evaluate a complete customer churn prediction workflow with reproducible Python code, explicit metrics, and honest limitations.
Explore Machine Learning training in VizagView all project ideas
Dataset and objective
A seeded synthetic subscription table with tenure, monthly charge, support calls, contract type, autopay, and churn.
Skills practised
- Synthetic business data
- Mixed-feature pipelines
- Class weighting
- ROC AUC
Requirements
- Python 3.10 or later
- A terminal or command prompt
python -m pip install numpy pandas scikit-learn- About 45-60 minutes to build and review
Machine Learning workflow
- Data: A seeded synthetic subscription table with tenure, monthly charge, support calls, contract type, autopay, and churn.
- Preprocessing: Numeric scaling and categorical one-hot encoding are learned inside a ColumnTransformer pipeline.
- Model: A class-weighted RandomForestClassifier models nonlinear churn relationships.
- Evaluation: ROC AUC and class-level precision, recall, and F1 on a stratified holdout set.
Complete Python code
Save the code as ml_customer_churn_prediction.py. The random state and data handling are included so the result can be reproduced and reviewed.
"""Train a churn classifier on reproducibly generated subscription data."""
from __future__ import annotations
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.metrics import classification_report, roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.ensemble import RandomForestClassifier
def make_demo_data(rows: int = 4000, random_state: int = 42) -> pd.DataFrame:
rng = np.random.default_rng(random_state)
tenure = rng.integers(1, 73, rows)
monthly_charge = rng.uniform(20, 130, rows)
support_calls = rng.poisson(1.5, rows)
contract = rng.choice(["monthly", "annual", "two-year"], rows, p=[0.55, 0.3, 0.15])
autopay = rng.choice(["yes", "no"], rows, p=[0.65, 0.35])
contract_risk = np.select([contract == "monthly", contract == "annual"], [1.0, -0.4], default=-1.0)
logit = -1.2 - 0.035 * tenure + 0.018 * (monthly_charge - 60) + 0.35 * support_calls + contract_risk + 0.45 * (autopay == "no")
probability = 1 / (1 + np.exp(-logit))
churn = rng.binomial(1, probability)
return pd.DataFrame({
"tenure_months": tenure,
"monthly_charge": monthly_charge,
"support_calls": support_calls,
"contract": contract,
"autopay": autopay,
"churn": churn,
})
def train_model(random_state: int = 42):
data = make_demo_data(random_state=random_state)
x, y = data.drop(columns="churn"), data["churn"]
x_train, x_test, y_train, y_test = train_test_split(
x, y, test_size=0.25, random_state=random_state, stratify=y
)
preprocessing = ColumnTransformer([
("numeric", StandardScaler(), ["tenure_months", "monthly_charge", "support_calls"]),
("categorical", OneHotEncoder(handle_unknown="ignore"), ["contract", "autopay"]),
])
model = make_pipeline(
preprocessing,
RandomForestClassifier(n_estimators=250, min_samples_leaf=5, class_weight="balanced", random_state=random_state, n_jobs=-1),
)
model.fit(x_train, y_train)
predictions = model.predict(x_test)
probabilities = model.predict_proba(x_test)[:, 1]
return model, y_test, predictions, probabilities
def main() -> None:
_, y_test, predictions, probabilities = train_model()
print("Synthetic Customer Churn Classification")
print(f"ROC AUC: {roc_auc_score(y_test, probabilities):.3f}")
print(classification_report(y_test, predictions, zero_division=0))
print("Validate labels, intervention effects, fairness, and drift before any real customer use.")
if __name__ == "__main__":
main()
How the pipeline works
Numeric scaling and categorical one-hot encoding are learned inside a ColumnTransformer pipeline.
A class-weighted RandomForestClassifier models nonlinear churn relationships. ROC AUC and class-level precision, recall, and F1 on a stratified holdout set.
Run the project
- Create and activate a virtual environment.
- Install the dependencies with
python -m pip install numpy pandas scikit-learn. - Run
python ml_customer_churn_prediction.py. - Review every printed metric together with the limitation below; a single score never proves deployment readiness.
How to interpret the evaluation
Classification projects report class-aware metrics so majority classes do not hide weak performance. Regression projects report errors in target units and include R-squared or a simple baseline where appropriate. Always verify the split strategy matches how new data will arrive.
Accuracy, ethics, and safety limits
A churn score does not show why someone will leave or prove an intervention will work. Validate label quality, fairness, drift, and treatment effects before customer use.
Ways to extend the project
Add time-based splitting, probability calibration, cost-sensitive thresholds, retention-experiment measurement, drift monitoring, and explainability reviews.
Continue learning Machine Learning
Try the next project, return to the Softenant project library, or explore the Machine Learning course in Vizag for guided data preparation, model evaluation, and portfolio feedback.