YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
๐ Customer Churn & Lifetime Value Prediction
A machine learning project that predicts customer churn (classification) and customer lifetime value (regression) using a telecom/subscription dataset from Egyptian cities.
๐๏ธ Project Structure
CustomerChurn/
โโโ customer_churn_clv.csv # Dataset (5 000 customers, 16 columns)
โโโ ml_model.ipynb # Main Jupyter notebook (EDA + modelling)
โโโ linear_model.joblib # Serialised Linear Regression pipeline (CLV)
โโโ logistic_model.joblib # Serialised Logistic Regression pipeline (Churn)
โโโ README.md
๐ Dataset
| Column | Type | Description |
|---|---|---|
customer_id |
object | Unique customer identifier |
age |
float64 | Customer age (95 missing values) |
city |
object | City (Cairo, Giza, Alexandria, Mansoura, Other) |
tenure_months |
int64 | Months as a customer |
contract |
object | Contract type: monthly, yearly, two_year |
plan |
object | Service plan: basic, standard, premium |
payment_method |
object | card, cash_on_delivery, bank_transfer, wallet |
monthly_charge |
float64 | Monthly bill (EGP) |
logins_per_month |
int64 | Login frequency |
avg_session_min |
float64 | Average session duration in minutes (147 missing) |
support_tickets |
int64 | Support tickets raised |
late_payments |
int64 | Number of late payments |
referrals |
int64 | Referrals made |
discount_used |
int64 | Whether a discount was used (0/1) |
lifetime_value |
float64 | Regression target โ Customer Lifetime Value |
churned |
int64 | Classification target โ 1 = churned, 0 = retained |
Dataset size: 5 000 rows ร 16 columns
Class balance: 67.28% retained ยท 32.72% churned
๐ Exploratory Data Analysis
- Missing values:
age(95),avg_session_min(147) โ imputed with median. - Churn by contract type: Bar chart showing monthly contracts have significantly higher churn.
- Tenure vs. Lifetime Value: Scatter plot confirming strong positive relationship.
- Correlation analysis:
tenure_months(0.744) andmonthly_charge(0.552) are the strongest numeric predictors of CLV.
โ๏ธ Preprocessing Pipeline
A shared ColumnTransformer is reused across all models:
num_cols = ["age", "tenure_months", "monthly_charge", "logins_per_month",
"avg_session_min", "support_tickets", "late_payments",
"referrals", "discount_used"]
cat_cols = ["city", "contract", "plan", "payment_method"]
prep = ColumnTransformer([
("num", Pipeline([
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler())
]), num_cols),
("cat", OneHotEncoder(handle_unknown="ignore"), cat_cols),
])
Train / test split: 80 % / 20 %, stratified by churned.
๐ค Models & Results
Regression โ Customer Lifetime Value (CLV)
| Model | Rยฒ | RMSE |
|---|---|---|
| Linear Regression | 0.880 | 1 801 |
| SVR (RBF, C=10) | 0.985 | โ |
Top CLV predictors (Linear Regression coefficients):
tenure_months(+3 843) โ strongest positive drivermonthly_charge(+2 485)contract_two_year(+343),plan_premium(+338)support_tickets(โ129) โ negative impact
Classification โ Churn
| Model | Accuracy | ROC-AUC | Notes |
|---|---|---|---|
| Logistic Regression | 0.67 | 0.746 | class_weight="balanced", max_iter=1000 |
| SGD Classifier | 0.67 | 0.731 | loss="log_loss", class_weight="balanced" |
| SVC (RBF, C=1) | โ | 0.731 | class_weight="balanced" |
Logistic Regression โ Churn class report:
precision recall f1-score support
0 0.80 0.67 0.73 673
1 0.50 0.66 0.57 327
accuracy 0.67 1000
Top churn risk factors (odds ratios > 1 = higher churn risk):
contract_monthly(2.32ร) โ biggest churn driversupport_tickets(1.50ร)monthly_charge(1.97ร)late_payments(1.36ร)
๐ฎ Inference Example
import joblib, pandas as pd
log = joblib.load("logistic_model.joblib")
lin = joblib.load("linear_model.joblib")
new_customer = pd.DataFrame([{
"age": 29, "city": "Cairo", "tenure_months": 4, "contract": "monthly",
"plan": "standard", "payment_method": "cash_on_delivery",
"monthly_charge": 300.0, "logins_per_month": 6, "avg_session_min": 9.0,
"support_tickets": 3, "late_payments": 2, "referrals": 0, "discount_used": 1,
}])
print("Churn probability :", log.predict_proba(new_customer)[0, 1]) # โ 0.964
print("Predicted lifetime value:", lin.predict(new_customer)[0]) # โ 930 EGP
๐ ๏ธ Installation & Usage
# Clone repository
git clone https://github.com/<your-username>/CustomerChurn.git
cd CustomerChurn
# Install dependencies
pip install pandas scikit-learn matplotlib numpy joblib jupyter
# Launch notebook
jupyter notebook ml_model.ipynb
๐ฆ Saved Models
The two production pipelines (preprocessing + model) are serialised with joblib:
| File | Task | Algorithm |
|---|---|---|
logistic_model.joblib |
Churn classification | Logistic Regression |
linear_model.joblib |
CLV regression | Linear Regression |
Both pipelines include the full preprocessing steps (imputation, scaling, one-hot encoding) and can be used out-of-the-box on raw customer records.
๐ Key Business Insights
- Monthly contract customers are 2.3ร more likely to churn โ prioritise converting them to annual plans.
- Tenure and monthly charge together explain ~88% of CLV variance โ long-term, high-spend customers are the most valuable.
- Support tickets and late payments are strong churn signals โ early intervention workflows could reduce churn risk.
- A new customer (29 y/o, short tenure, monthly plan, 3 tickets, 2 late payments) shows a 96.4% churn probability and only ~930 EGP predicted CLV.
๐งฐ Tech Stack
- Python 3.10+
- scikit-learn 1.x
- Pandas 2.x
- Matplotlib
- Joblib
- Jupyter Notebook
๐ License
This project is released under the MIT License.