Churn Project
Daniele Vecchiarelli - Júlia Révai - Antonio Gerardo Lapenna
import pandas as pd
import numpy as np
dataset = pd.read_csv('./churn.csv') # Local File
dataset = dataset[dataset.iloc[:,0:18]!= 'Unknown'] #drop all rows where status is unknown
dataset = dataset.dropna(axis=0, how='any') #drop na rows
# set x and y values
X = dataset.iloc[:, 3:18].values
y = dataset.iloc[:, 2].values
Data Processing
# Encoding categorical data
from sklearn import *
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.metrics import ConfusionMatrixDisplay
labelencoder = LabelEncoder()
for i in range(1,7):
if i != 2:
X[:, i] = labelencoder.fit_transform(X[:, i])
# Y encoding 1 = Existing Customer / 0 = Attrited Customer
y[:] = labelencoder.fit_transform(y[:])
from sklearn.compose import ColumnTransformer
ct = ColumnTransformer([("X", OneHotEncoder(dtype = int), [1])], remainder = 'passthrough')
X = ct.fit_transform(X)
X = X[:, 1:]
print(X)
# Splitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
# Feature Scaling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
[[1 45 3 ... 1144 42 1.01]
[0 49 5 ... 1291 33 1.45]
[1 51 3 ... 1887 20 0.0]
...
[1 50 2 ... 15476 117 7.42]
[0 44 1 ... 10291 60 0.0]
[0 43 2 ... 10294 61 3.09]]
ANN Creation / Training
# Importing the Keras libraries and packages
from tensorflow.keras import *
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras import layers
from tensorflow.keras.callbacks import Callback
import tensorflow as tf
# Initialising the ANN
classifier = Sequential(
[
layers.Dense(24, kernel_initializer = 'uniform', activation = 'relu'),
layers.Dense(24, kernel_initializer = 'uniform', activation = 'relu'),
layers.Dense(24, kernel_initializer = 'uniform', activation = 'relu'),
layers.Dense(12, kernel_initializer = 'uniform', activation = 'relu'),
layers.Dense(1, kernel_initializer = 'uniform', activation = 'sigmoid')
]
)
# Compiling the ANN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
# Testing
X_t = np.asarray(X_train).astype('float32').reshape(-1,15)
Y_t = np.asarray(y_train).astype('float32').reshape(-1,1)
class Callback(tf.keras.callbacks.Callback):
def __init__(self):
self.data = []
def on_epoch_end(self,epoch,logs):
self.data.append(logs)
def data(self):
return self.data
batch_size = 32
callback = Callback()
data = classifier.fit(
X_t,
Y_t,
batch_size = batch_size, # Default
epochs = int(len(X_t) / batch_size),
callbacks=[callback],
verbose=1
)
#print(data.params)
Epoch 1/88
89/89 [==============================] - 1s 1ms/step - loss: 0.6567 - accuracy: 0.8443
Epoch 2/88
89/89 [==============================] - 0s 1ms/step - loss: 0.3445 - accuracy: 0.8394
Epoch 3/88
89/89 [==============================] - 0s 2ms/step - loss: 0.2948 - accuracy: 0.8477
Epoch 4/88
89/89 [==============================] - 0s 2ms/step - loss: 0.2848 - accuracy: 0.8350
Epoch 5/88
89/89 [==============================] - 0s 2ms/step - loss: 0.2595 - accuracy: 0.8426
Epoch 6/88
89/89 [==============================] - 0s 2ms/step - loss: 0.2562 - accuracy: 0.8948
Epoch 7/88
89/89 [==============================] - 0s 2ms/step - loss: 0.2528 - accuracy: 0.8999
Epoch 8/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2441 - accuracy: 0.9082
Epoch 9/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2419 - accuracy: 0.9080
Epoch 10/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2345 - accuracy: 0.9143
Epoch 11/88
89/89 [==============================] - 0s 2ms/step - loss: 0.2400 - accuracy: 0.9052
Epoch 12/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2256 - accuracy: 0.9109
Epoch 13/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2163 - accuracy: 0.9155
Epoch 14/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2070 - accuracy: 0.9142
Epoch 15/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2149 - accuracy: 0.9156
Epoch 16/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2015 - accuracy: 0.9216
Epoch 17/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2103 - accuracy: 0.9124
Epoch 18/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1980 - accuracy: 0.9210
Epoch 19/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2029 - accuracy: 0.9176
Epoch 20/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1885 - accuracy: 0.9256
Epoch 21/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1973 - accuracy: 0.9201
Epoch 22/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2038 - accuracy: 0.9213
Epoch 23/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2045 - accuracy: 0.9196
Epoch 24/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1951 - accuracy: 0.9223
Epoch 25/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2001 - accuracy: 0.9193
Epoch 26/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1924 - accuracy: 0.9260
Epoch 27/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2074 - accuracy: 0.9148
Epoch 28/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1909 - accuracy: 0.9232
Epoch 29/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1943 - accuracy: 0.9197
Epoch 30/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1977 - accuracy: 0.9207
Epoch 31/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1885 - accuracy: 0.9265
Epoch 32/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1906 - accuracy: 0.9212
Epoch 33/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1814 - accuracy: 0.9317
Epoch 34/88
89/89 [==============================] - 0s 1ms/step - loss: 0.2042 - accuracy: 0.9169
Epoch 35/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1885 - accuracy: 0.9252
Epoch 36/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1959 - accuracy: 0.9259
Epoch 37/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1873 - accuracy: 0.9263
Epoch 38/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1932 - accuracy: 0.9226
Epoch 39/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1969 - accuracy: 0.9224
Epoch 40/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1866 - accuracy: 0.9279
Epoch 41/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1913 - accuracy: 0.9256
Epoch 42/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1806 - accuracy: 0.9308
Epoch 43/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1849 - accuracy: 0.9246
Epoch 44/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1816 - accuracy: 0.9287
Epoch 45/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1835 - accuracy: 0.9282
Epoch 46/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1867 - accuracy: 0.9271
Epoch 47/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1802 - accuracy: 0.9308
Epoch 48/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1726 - accuracy: 0.9355
Epoch 49/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1763 - accuracy: 0.9356
Epoch 50/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1739 - accuracy: 0.9328
Epoch 51/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1763 - accuracy: 0.9349
Epoch 52/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1791 - accuracy: 0.9288
Epoch 53/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1753 - accuracy: 0.9311
Epoch 54/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1659 - accuracy: 0.9351
Epoch 55/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1735 - accuracy: 0.9316
Epoch 56/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1628 - accuracy: 0.9361
Epoch 57/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1672 - accuracy: 0.9409
Epoch 58/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1690 - accuracy: 0.9321
Epoch 59/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1692 - accuracy: 0.9354
Epoch 60/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1660 - accuracy: 0.9363
Epoch 61/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1719 - accuracy: 0.9324
Epoch 62/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1670 - accuracy: 0.9327
Epoch 63/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1801 - accuracy: 0.9290
Epoch 64/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1612 - accuracy: 0.9360
Epoch 65/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1671 - accuracy: 0.9336
Epoch 66/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1607 - accuracy: 0.9423
Epoch 67/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1602 - accuracy: 0.9361
Epoch 68/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1647 - accuracy: 0.9359
Epoch 69/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1648 - accuracy: 0.9368
Epoch 70/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1517 - accuracy: 0.9415
Epoch 71/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1553 - accuracy: 0.9365
Epoch 72/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1586 - accuracy: 0.9369
Epoch 73/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1520 - accuracy: 0.9405
Epoch 74/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1552 - accuracy: 0.9349
Epoch 75/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1486 - accuracy: 0.9389
Epoch 76/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1571 - accuracy: 0.9353
Epoch 77/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1467 - accuracy: 0.9390
Epoch 78/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1510 - accuracy: 0.9423
Epoch 79/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1390 - accuracy: 0.9437
Epoch 80/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1483 - accuracy: 0.9404
Epoch 81/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1473 - accuracy: 0.9414
Epoch 82/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1465 - accuracy: 0.9415
Epoch 83/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1504 - accuracy: 0.9384
Epoch 84/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1502 - accuracy: 0.9385
Epoch 85/88
89/89 [==============================] - 0s 2ms/step - loss: 0.1338 - accuracy: 0.9456
Epoch 86/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1539 - accuracy: 0.9387
Epoch 87/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1381 - accuracy: 0.9473
Epoch 88/88
89/89 [==============================] - 0s 1ms/step - loss: 0.1377 - accuracy: 0.9413
Results
# Part 3 - Making the predictions and evaluating the model
# Predicting the Test set results
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.5)
# Making the Confusion Matrix
from sklearn.metrics import confusion_matrix
y_pred2 = [int(i) for i in y_pred]
y_test2 = list(y_test)
# Confusion Matrix Plot
ConfusionMatrixDisplay.from_predictions(y_test2, y_pred2)
# Computing Accuracy, Precision and Recall
from sklearn.metrics import accuracy_score, precision_score, recall_score
print("Accuracy :",accuracy_score(y_test2,y_pred2))
print("Precision :",precision_score(y_test2,y_pred2))
print("Recall :",recall_score(y_test2,y_pred2))
0.9103740296400847
0.9329073482428115
0.9644921552436003
Graph Results
import matplotlib.pyplot as plt
x = []
y = []
for i in callback.data:
x.append(i["loss"])
y.append(i["accuracy"])
fig, ax = plt.subplots(constrained_layout=True)
pl1 = ax.plot(range(0,len(y)) , y,label='Accuracy')
ax.set_xlabel('Epoch')
ax2 = ax.twinx()
pl2 = ax2.plot(range(0,len(x)) , x , color='#ff6f00',label='Loss Function')
lns = pl1+pl2
labs = [l.get_label() for l in lns]
ax.legend(lns, labs, loc='center right')
fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.show()
/shared-libs/python3.7/py-core/lib/python3.7/site-packages/ipykernel_launcher.py:16: UserWarning: This figure was using constrained_layout, but that is incompatible with subplots_adjust and/or tight_layout; disabling constrained_layout.
app.launch_new_instance()