Mathew K Analytics

Lesson 73 · Data Science Projects

Customer Churn Prediction: Step-by-Step Classification Models in Python

Welcome to this hands-on notebook focused on predicting customer churn. You will learn how to use Python and machine learning to find out which customers…

⬇ Download notebookOpen in Colab ↗

What you'll learn

Data

No separate download needed — the notebook creates or downloads everything it uses.

📓 Full notebook

Download .ipynb

Week 45: Customer Churn Prediction with Classification Models#

Welcome to this hands-on notebook focused on predicting customer churn.

You will learn how to use Python and machine learning to find out which customers are likely to leave a company.

We will use the Telco Customer Churn Dataset, explore the data, clean it, build classification models, and interpret results.

Customer churn prediction helps businesses keep their customers by taking action before someone leaves.

Let us get started!

# Suppress warnings for a clean notebook
import warnings; warnings.filterwarnings("ignore")
import numpy as np
np.random.seed(42)
# Data setup (Telco Customer Churn Dataset)
import pandas as pd
url = 'https://raw.githubusercontent.com/IBM/telco-customer-churn-on-icp4d/master/data/Telco-Customer-Churn.csv'
df = pd.read_csv(url)
print(df.shape)
print(df.head(3))
(7043, 21)
   customerID  gender  SeniorCitizen Partner Dependents  tenure PhoneService  \
0  7590-VHVEG  Female              0     Yes         No       1           No   
1  5575-GNVDE    Male              0      No         No      34          Yes   
2  3668-QPYBK    Male              0      No         No       2          Yes   

      MultipleLines InternetService OnlineSecurity  ... DeviceProtection  \
0  No phone service             DSL             No  ...               No   
1                No             DSL            Yes  ...              Yes   
2                No             DSL            Yes  ...               No   

  TechSupport StreamingTV StreamingMovies        Contract PaperlessBilling  \
0          No          No              No  Month-to-month              Yes   
1          No          No              No        One year               No   
2          No          No              No  Month-to-month              Yes   

      PaymentMethod MonthlyCharges  TotalCharges Churn  
0  Electronic check          29.85         29.85    No  
1      Mailed check          56.95        1889.5    No  
2      Mailed check          53.85        108.15   Yes  

[3 rows x 21 columns]

Step 1: Understanding the Data#

Let us take a closer look at the churn data.

  • Each row represents a customer.
  • Columns describe customer demographics, contract information, services used, and whether they have churned.

The 'Churn' column says if a customer has left or stayed.

# Check if there are missing values
missing = df.isnull().sum()
print(missing[missing > 0])
Series([], dtype: int64)
# View summary statistics for numerical columns
print(df.describe())
       SeniorCitizen       tenure  MonthlyCharges
count    7043.000000  7043.000000     7043.000000
mean        0.162147    32.371149       64.761692
std         0.368612    24.559481       30.090047
min         0.000000     0.000000       18.250000
25%         0.000000     9.000000       35.500000
50%         0.000000    29.000000       70.350000
75%         0.000000    55.000000       89.850000
max         1.000000    72.000000      118.750000
# View column types and unique values for 'Churn'
print(df.dtypes)
print(df['Churn'].unique())
customerID           object
gender               object
SeniorCitizen         int64
Partner              object
Dependents           object
tenure                int64
PhoneService         object
MultipleLines        object
InternetService      object
OnlineSecurity       object
OnlineBackup         object
DeviceProtection     object
TechSupport          object
StreamingTV          object
StreamingMovies      object
Contract             object
PaperlessBilling     object
PaymentMethod        object
MonthlyCharges      float64
TotalCharges         object
Churn                object
dtype: object
['No' 'Yes']
# How many customers have churned?
print(df['Churn'].value_counts())
Churn
No     5174
Yes    1869
Name: count, dtype: int64

Step 2: Data Cleaning and Preprocessing#

The data sometimes needs cleaning before it can be used in machine learning.

  • Fix or remove empty values
  • Convert text data to numbers
  • Pick the columns we need

Let us start the cleaning process.

# Convert 'TotalCharges' to numeric and handle errors
df['TotalCharges'] = pd.to_numeric(df['TotalCharges'], errors='coerce')
# Drop rows with missing 'TotalCharges'
df = df.dropna(subset=['TotalCharges'])
# Encode the 'Churn' column to 1 for 'Yes' and 0 for 'No'
df['Churn'] = df['Churn'].map({'Yes':1, 'No':0})
# Select columns to use for modeling (drop ID columns)
X = df.drop(['customerID', 'Churn'], axis=1)
y = df['Churn']
# Convert all category columns to dummy variables
X = pd.get_dummies(X)

Step 3: Split Data for Training and Testing#

To check if our model really works, we split our data so it learns from some (training) and is tested on the rest (testing).

# Split into 70% train and 30% test, random_state=42 for repeatability
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

Step 4: Train a Logistic Regression Model#

Let us start with a simple and powerful classification method called Logistic Regression.

  • Logistic Regression works well for yes/no problems.
from sklearn.linear_model import LogisticRegression

# Create and train the model
clf = LogisticRegression(max_iter=1000)
clf.fit(X_train, y_train)
LogisticRegression(max_iter=1000)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
# Predict churn using our trained model
y_pred = clf.predict(X_test)
# Evaluate accuracy
from sklearn.metrics import accuracy_score
acc = accuracy_score(y_test, y_pred)
print(f"Accuracy: {acc:.2f}")
Accuracy: 0.80
# Print confusion matrix for deeper insight
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
print(cm)
[[1378  171]
 [ 261  300]]
# Show precision and recall for balanced understanding
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred, target_names=['Stayed','Churned']))
              precision    recall  f1-score   support

      Stayed       0.84      0.89      0.86      1549
     Churned       0.64      0.53      0.58       561

    accuracy                           0.80      2110
   macro avg       0.74      0.71      0.72      2110
weighted avg       0.79      0.80      0.79      2110

# Try a Decision Tree for comparison
from sklearn.tree import DecisionTreeClassifier

tree = DecisionTreeClassifier(random_state=42, max_depth=4)
tree.fit(X_train, y_train)
y_pred_tree = tree.predict(X_test)
print('Decision Tree accuracy:', accuracy_score(y_test, y_pred_tree))
Decision Tree accuracy: 0.7853080568720379

Quick Recap and Your Next Steps#

In this notebook you learned to:

  • Load a real churn dataset
  • Clean and prepare your data
  • Build and test both logistic regression and decision tree models
  • Measure accuracy and see where the models work best

To practice, try changing parameters, use more models, or visualize top features.

If you learned something valuable, subscribe to the channel and keep exploring data mining!

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.