Customer Churn Prediction using Machine Learning
Pada project part 1 kemarin kita telah melakukan Cleansing Data. Sekarang, sebagai data scientist kamu diminta untuk membuat model yang tepat.
Pada tugas kali ini, kamu akan melakukan Pemodelan Machine Learning dengan menggunakan data bulan lalu, yakni Juni 2020.
Langkah yang akan dilakukan adalah,
- Melakukan Exploratory Data Analysis
- Melakukan Data Pre-Processing
- Melakukan Pemodelan Machine Learning
- Menentukan Model Terbaik
Library yang Digunakan
Pada analisis kali ini, akan digunakan beberapa package yang membantu kita dalam melakukan analisis data,
- Pandas (Python for Data Analysis) adalah library Python yang fokus
untuk proses analisis data seperti manipulasi data, persiapan data, dan
pembersihan data.
read_csv()
digunakan untuk membaca file csvreplace()
digunakan untuk mengganti nilaivalue_counts()
digunakan untuk mengitung unik dari kolomdrop()
digunakan untuk menghapusdescribe()
digunakan untuk melihat deskripsi datanyavalue_counts()
digunakan untuk mengitung unik dari kolom
- Matplotlib adalah library Python yang fokus pada visualisasi data
seperti membuat plot grafik. Matplotlib dapat digunakan dalam skrip
Python, Python dan IPython shell, server aplikasi web, dan beberapa
toolkit graphical user interface (GUI) lainnya.
figure()
digunakan untuk membuat figure gambar barusubplots()
digunakan untuk membuat gambar dan satu set subplottitle()
digunakan untuk memberi judul pada gambarylabel()
digunakan untuk memberi label sumbu Y pada gambarxlabel()
digunakan untuk memberi label sumbu Y pada gambarpie()
digunakan untuk membuat pie chart
-
Seaborn membangun plot di atas Matplotlib dan memperkenalkan tipe plot tambahan. Ini juga membuat plot Matplotlib tradisional Anda terlihat lebih cantik.
countplot()
digunakan untuk membuat plot dengan jumlah pengamatan di setiap bin kategorik variableheatmap()
Plot rectangular data as a color-encoded matrix
-
Scikit-learn adalah library dalam Python yang menyediakan banyak algoritma Machine Learning baik untuk Supervised, Unsupervised Learning, maupun digunakan untuk mempreparasi data.
LabelEncoder()
digunakan untuk merubah nilai dari suatu variable menjadi 0 atau 1train_test_split()
digunakan untuk membagi data menjadi 2 row bagian (Training & Testing)LogisticRegression()
digunakan untuk memanggil algoritma Logistic RegressionRandomForestClassifier()
digunakan untuk memanggil algoritma Random Forest Classifierconfusion_matrix()
digunakan untuk membuat confusion matrixclassification_report()
digunakan untuk membuat classification report, yang dianataranya berisi akurasi model
-
Xgboost adalah library dalam Python untuk algoritma extreme gradient boosting (xgboost)
XGBClassifier()
digunakan untuk memanggil algoritma XG Boost Classifier
-
Pickle mengimplementasikan protokol biner untuk serializing dan de-serializing dari struktur objek Python.
dump()
digunakan untuk menyimpan
#Import library yang dibutuhkan
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import confusion_matrix, classification_report
import pickle
from pathlib import Path
Data yang Digunakan
Untuk Dataset yang digunakan sudah disediakan dalam format csv, silahkan baca melalui fungsi pandas di python df_load = pd.read_csv('https://dqlab-dataset.s3-ap-southeast-1.amazonaws.com/dqlab_telco_final.csv')
Untuk detil datanya adalah sebagai berikut:
UpdatedAt
Periode of Data takencustomerID
Customer IDgender
Whether the customer is a male or a female (Male, Female)SeniorCitizen
Whether the customer is a senior citizen or not (Yes, No)Partner
Whether the customer has a partner or not (Yes, No)tenure
Number of months the customer has stayed with the companyPhoneService
Whether the customer has a phone service or not (Yes, No)InternetService
Customer’s internet service provider (Yes, No)StreamingTV
Whether the customer has streaming TV or not (Yes, No)PaperlessBilling
Whether the customer has paperless billing or not (Yes, No)MonthlyCharges
The amount charged to the customer monthlyTotalCharges
The total amount charged to the customerChurn
Whether the customer churned or not (Yes, No)
File Unloading
Lakukan import dataset ke dalam workspace dengan menggunakan read_csv dan tampilkan juga bentuk atau shape dari dataset tersebut beserta 5 data teratas.
sumber dataset : https://dqlab-dataset.s3-ap-southeast-1.amazonaws.com/dqlab_telco_final.csv
#import dataset
df_load = pd.read_csv("https://dqlab-dataset.s3-ap-southeast-1.amazonaws.com/dqlab_telco_final.csv")
#Tampilkan bentuk dari dataset
print(df_load.shape)
#Tampilkan 5 data teratas
print(df_load.head())
#Tampilkan jumlah ID yang unik
print(df_load.customerID.nunique())
""" Output
(6950, 13)
UpdatedAt customerID gender SeniorCitizen Partner tenure PhoneService \
0 202006 45759018157 Female No Yes 1 No
1 202006 45315483266 Male No Yes 60 Yes
2 202006 45236961615 Male No No 5 Yes
3 202006 45929827382 Female No Yes 72 Yes
4 202006 45305082233 Female No Yes 56 Yes
StreamingTV InternetService PaperlessBilling MonthlyCharges TotalCharges \
0 No Yes Yes 29.85 29.85
1 No No Yes 20.50 1198.80
2 Yes Yes No 104.10 541.90
3 Yes Yes Yes 115.50 8312.75
4 Yes Yes No 81.25 4620.40
Churn
0 No
1 No
2 Yes
3 No
4 No
6950
"""
Exploratory Data Analysis
Exploratory Data Analysis memungkinkan analyst memahami isi data yang digunakan, mulai dari distribusi, frekuensi, korelasi dan lainnya. Pada umumnya EDA dilakukan dengan beberapa cara:
- Univariat Analysis — analisis deskriptif dengan satu variabel.
- Bivariat Analysis — analisis relasi dengan dua variabel yang biasanya dengan target variabel.
- Multivariat Analysis — analisis yang menggunakan lebih dari atau sama dengan tiga variabel.
Dalam kasus ini, kamu diminta untuk melihat persebaran dari:
- Prosentase persebaran data Churn dan tidaknya dari seluruh data
- Persebarang data dari variable predictor terhadap label (Churn)
Lakukan import matplotlib dan seaborn
#import matplotlib dan seaborn
import matplotlib.pyplot as plt
import seaborn as sns
Memvisualisasikan Prosentase Churn
Kita ingin melihat visualisasi data secara univariat terkait prosentase data churn dari pelanggan. Gunakan fungsi value_counts()
untuk menghitung banyaknya unik dari sebuah kolom, pie()
untuk membuat pie chart
from matplotlib import pyplot as plt
import numpy as np
#Your codes here
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.axis('equal')
labels = ['Yes','No']
churn = df_load.Churn.value_counts()
ax.pie(churn, labels=labels, autopct='%.0f%%')
plt.show()
Exploratory Data Analysis (EDA) Variabel Numerik
Hal yang akan kita lakukan selanjutnya adalah memilih variable predictor yang bersifat numerik dan membuat plot secara bivariat, kemudian menginterpretasikannya
Gunakan data `df_load` untuk di olah di tahap ini dan gunakan fungsi `subplots()` untuk membuat gambar dan satu set subplot.
Codingan yang tepat akan menghasilkan output sebagai berikut.
from matplotlib import pyplot as plt
import numpy as np
#creating bin in chart
numerical_features = ['MonthlyCharges','TotalCharges','tenure']
fig, ax = plt.subplots(1, 3, figsize=(15, 6))
# Use the following code to plot two overlays of histogram per each numerical_features, use a color of blue and orange, respectively
df_load[df_load.Churn == 'No'][numerical_features].hist(bins=20, color='blue', alpha=0.5, ax=ax)
df_load[df_load.Churn == 'Yes'][numerical_features].hist(bins=20, color='orange', alpha=0.5, ax=ax)
plt.show()
Exploratory Data Analysis (EDA) Variabel Kategorik
Setelah itu, kita akan melakukan pemilihan variable predictor yang bersifat kategorik dan membuat plot secara bivariat, kemudian menginterpretasikannya
Gunakan data `df_load` untuk di olah di tahap ini. Gunakan fungsi `countplot()` untuk membuat plot dengan jumlah pengamatan di setiap bin kategorik variable
Hasil yang diharapkan adalah sebagai berikut.
from matplotlib import pyplot as plt
import numpy as np
import seaborn as sns
sns.set(style='darkgrid')
# Your code goes here
fig, ax = plt.subplots(3, 3, figsize=(14, 12))
sns.countplot(data=df_load, x='gender', hue='Churn', ax=ax[0][0])
sns.countplot(data=df_load, x='Partner', hue='Churn', ax=ax[0][1])
sns.countplot(data=df_load, x='SeniorCitizen', hue='Churn', ax=ax[0][2])
sns.countplot(data=df_load, x='PhoneService', hue='Churn', ax=ax[1][0])
sns.countplot(data=df_load, x='StreamingTV', hue='Churn', ax=ax[1][1])
sns.countplot(data=df_load, x='InternetService', hue='Churn', ax=ax[1][2])
sns.countplot(data=df_load, x='PaperlessBilling', hue='Churn', ax=ax[2][1])
plt.tight_layout()
plt.show()
Kesimpulan
Berdasarkan hasil dan analisa di atas dapat disimpulkan:
- pada tahap
C.1
dapat kita ketahui bahwa sebaran data secara kesuluruhan customer tidak melakukan churn, dengan detilChurn
sebanyak 26% danNo Churn
sebanyak 74%. - pada tahap
C.2
dapat kita ketahui bahwa untukMonthlyCharges
ada kecenderungan semakin kecil nilai biaya bulanan yang dikenakan, semakin kecil juga kecenderungan untuk melakukanChurn
. UntukTotalCharges
terlihat tidak ada kecenderungan apapun terhadapChurn
customers. Untuktenure
ada kecenderungan semakin lama berlangganan customer, semakin kecil kecenderungan untuk melakukanChurn
. - pada tahap
C.3
dapat kita ketahui bahwa tidak ada perbedaan yang signifikan untuk orang melakukanchurn
dilihat dari faktor jenis kelamin (gender
) dan layanan telfonnya (PhoneService
). Akan tetapi ada kecenderungan bahwa orang yang melakukanchurn
adalah orang-orang yang tidak memiliki partner(partner: No)
, orang-orang yang statusnya adalah senior citizen(SeniorCitizen: Yes)
, orang-orang yang mempunyai layanan streaming TV(StreamingTV: Yes)
, orang-orang yang mempunyai layanan Internet(internetService: Yes)
dan orang-orang yang tagihannya paperless(PaperlessBilling: Yes)
.
Menghapus Unnecessary Columns dari data
Selanjutnya kita akan mengapus kolom yang tidak akan diikutsertakan dalam pemodelan, kemudian simpan dengan nama cleaned_df
. Tampilkan 5 rows teratas nya.
drop()
untuk menghapus kolom dari suatu data
#Remove the unnecessary columns customerID & UpdatedAt
cleaned_df = df_load.drop(['customerID','UpdatedAt'], axis=1)
print(cleaned_df.head())
Encoding Data
Gunakan data dari hasil dan analisa sebelumnya cleaned_df
, untuk merubah value dari data yang masih berbentuk string untuk diubah ke dalam bentuk numeric menggunakan LabelEncoder()
. Gunakan describe()
untuk melihat deskripsi datanya.
from sklearn.preprocessing import LabelEncoder
#Convert all the non-numeric columns to numerical data types
for column in cleaned_df.columns:
if cleaned_df[column].dtype == np.number: continue
# Perform encoding for each non-numeric column
cleaned_df[column] = LabelEncoder().fit_transform(cleaned_df[column])
print(cleaned_df.describe())
""" Output
gender SeniorCitizen ... TotalCharges Churn
count 6950.000000 6950.000000 ... 6950.000000 6950.000000
mean 0.504317 0.162302 ... 2286.058750 0.264173
std 0.500017 0.368754 ... 2265.702553 0.440923
min 0.000000 0.000000 ... 19.000000 0.000000
25% 0.000000 0.000000 ... 406.975000 0.000000
50% 1.000000 0.000000 ... 1400.850000 0.000000
75% 1.000000 0.000000 ... 3799.837500 1.000000
max 1.000000 1.000000 ... 8889.131250 1.000000
[8 rows x 11 columns]
"""
Splitting Dataset
Gunakan data dari hasil dan analisa sebelumnya cleaned_df
,
untuk dibagi datasetnya menjadi 2 bagian (70% training & 30%
testing) berdasarkan variable predictor (X) dan targetnya (Y). Gunakan
train_test_split() untuk membagi data tersebut. Sertakan value_counts
untuk mengecek apakah pembagian sudah sama proporsinya. Simpan hasil spliting data menjadi x_train
, y_train
, x_test
& y_test
from sklearn.model_selection import train_test_split
# Predictor dan target
X = cleaned_df.drop('Churn', axis = 1)
y = cleaned_df['Churn']
# Splitting train and test
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Print according to the expected result
print('Jumlah baris dan kolom dari x_train adalah:', x_train.shape,', sedangkan Jumlah baris dan kolom dari y_train adalah:', y_train.shape)
print('Prosentase Churn di data Training adalah:')
print(y_train.value_counts(normalize=True))
print('Jumlah baris dan kolom dari x_test adalah:', x_test.shape,', sedangkan Jumlah baris dan kolom dari y_test adalah:', y_test.shape)
print('Prosentase Churn di data Testing adalah:')
print(y_test.value_counts(normalize=True))
""" Output
Jumlah baris dan kolom dari x_train adalah: (4865, 10) , sedangkan Jumlah baris dan kolom dari y_train adalah: (4865,)
Prosentase Churn di data Training adalah:
0 0.734841
1 0.265159
Name: Churn, dtype: float64
Jumlah baris dan kolom dari x_test adalah: (2085, 10) , sedangkan Jumlah baris dan kolom dari y_test adalah: (2085,)
Prosentase Churn di data Testing adalah:
0 0.738129
1 0.261871
Name: Churn, dtype: float64
"""
Kesimpulan
Setelah kita analisis lebih lanjut, ternyata ada kolom yang tidak dibutuhkuan dalam model, yaitu Id Number pelanggannya (customerID
) & periode pengambilan datanya (UpdatedAt
),
maka hal ini perlu dihapus. Kemudian kita lanjut mengubah value dari
data yang masih berbentuk string menjadi numeric melalui encoding,
setelah dilakukan terlihat di persebaran datanya khususnya kolom min dan
max dari masing masing variable sudah berubah menjadi 0 & 1. Tahap
terakhir adalah membagi data menjadi 2 bagian untuk keperluan modelling,
setelah dilakukan terlihat dari jumlah baris dan kolom masing-masing
data sudah sesuai & prosentase kolom churn juga sama dengan data di
awal, hal ini mengindikasikan bahwasannya data terpisah dengan baik dan
benar.
Pembuatan Model
Selanjutnya kita akan membuat model dengan menggunakan Algoritma Logistic Regression.
LogisticRegression()
memanggil algoritma tersebut, fit ke data train dan simpan sebagai log_model
from sklearn.linear_model import LogisticRegression
log_model = LogisticRegression().fit(X_train,y_train)
print('Model Logistic Regression yang terbentuk adalah: \n', log_model)
""" Output
Model Logistic Regression yang terbentuk adalah:
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
verbose=0, warm_start=False)
"""
Performansi Model Training - Menampilkan Metrics
Setelah
kita membuat modelnya, maka lakukan perhitungan untuk memperoleh
classification reportnya dan confusion matrixnya di data training
seperti hasil di bawah ini. Gunakan classification_report()
& confusion_matrix()
.
from sklearn.metrics import classification_report
# Predict
y_train_pred = log_model.predict(x_train)
# Print classification report
print('Classification Report Training Model (Logistic Regression) :')
print(classification_report(y_train, y_train_pred))
""" Output
"""
anthony December 8, 2021 at 6:35 PM
mantab :)