Group 7 - AIYA (NUS) Project¶
In [1]:
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.ticker as mtick
import matplotlib.pyplot as plt
sns.set(style = 'white')
In [2]:
telecom_cust = pd.read_csv(r"C:\Users\dmgte\OneDrive\Documents\NUS course Material\AIYA project data.csv")
print(telecom_cust)
customerID gender SeniorCitizen Partner Dependents tenure \
0 7590-VHVEG Female 0 Yes No 1
1 5575-GNVDE Male 0 No No 34
2 3668-QPYBK Male 0 No No 2
3 7795-CFOCW Male 0 No No 45
4 9237-HQITU Female 0 No No 2
... ... ... ... ... ... ...
7038 6840-RESVB Male 0 Yes Yes 24
7039 2234-XADUH Female 0 Yes Yes 72
7040 4801-JZAZL Female 0 Yes Yes 11
7041 8361-LTMKD Male 1 Yes No 4
7042 3186-AJIEK Male 0 No No 66
PhoneService MultipleLines InternetService OnlineSecurity ... \
0 No No phone service DSL No ...
1 Yes No DSL Yes ...
2 Yes No DSL Yes ...
3 No No phone service DSL Yes ...
4 Yes No Fiber optic No ...
... ... ... ... ... ...
7038 Yes Yes DSL Yes ...
7039 Yes Yes Fiber optic No ...
7040 No No phone service DSL Yes ...
7041 Yes Yes Fiber optic No ...
7042 Yes No Fiber optic Yes ...
DeviceProtection TechSupport StreamingTV StreamingMovies Contract \
0 No No No No Month-to-month
1 Yes No No No One year
2 No No No No Month-to-month
3 Yes Yes No No One year
4 No No No No Month-to-month
... ... ... ... ... ...
7038 Yes Yes Yes Yes One year
7039 Yes No Yes Yes One year
7040 No No No No Month-to-month
7041 No No No No Month-to-month
7042 Yes Yes Yes Yes Two year
PaperlessBilling PaymentMethod MonthlyCharges TotalCharges \
0 Yes Electronic check 29.85 29.85
1 No Mailed check 56.95 1889.5
2 Yes Mailed check 53.85 108.15
3 No Bank transfer (automatic) 42.30 1840.75
4 Yes Electronic check 70.70 151.65
... ... ... ... ...
7038 Yes Mailed check 84.80 1990.5
7039 Yes Credit card (automatic) 103.20 7362.9
7040 Yes Electronic check 29.60 346.45
7041 Yes Mailed check 74.40 306.6
7042 Yes Bank transfer (automatic) 105.65 6844.5
Churn
0 No
1 No
2 Yes
3 No
4 Yes
... ...
7038 No
7039 No
7040 No
7041 Yes
7042 No
[7043 rows x 21 columns]
In [3]:
telecom_cust.head()
Out[3]:
| customerID | gender | SeniorCitizen | Partner | Dependents | tenure | PhoneService | MultipleLines | InternetService | OnlineSecurity | ... | DeviceProtection | TechSupport | StreamingTV | StreamingMovies | Contract | PaperlessBilling | PaymentMethod | MonthlyCharges | TotalCharges | Churn | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 7590-VHVEG | Female | 0 | Yes | No | 1 | No | No phone service | DSL | No | ... | No | No | No | No | Month-to-month | Yes | Electronic check | 29.85 | 29.85 | No |
| 1 | 5575-GNVDE | Male | 0 | No | No | 34 | Yes | No | DSL | Yes | ... | Yes | No | No | No | One year | No | Mailed check | 56.95 | 1889.5 | No |
| 2 | 3668-QPYBK | Male | 0 | No | No | 2 | Yes | No | DSL | Yes | ... | No | No | No | No | Month-to-month | Yes | Mailed check | 53.85 | 108.15 | Yes |
| 3 | 7795-CFOCW | Male | 0 | No | No | 45 | No | No phone service | DSL | Yes | ... | Yes | Yes | No | No | One year | No | Bank transfer (automatic) | 42.30 | 1840.75 | No |
| 4 | 9237-HQITU | Female | 0 | No | No | 2 | Yes | No | Fiber optic | No | ... | No | No | No | No | Month-to-month | Yes | Electronic check | 70.70 | 151.65 | Yes |
5 rows × 21 columns
In [4]:
telecom_cust.columns.values
Out[4]:
array(['customerID', 'gender', 'SeniorCitizen', 'Partner', 'Dependents',
'tenure', 'PhoneService', 'MultipleLines', 'InternetService',
'OnlineSecurity', 'OnlineBackup', 'DeviceProtection',
'TechSupport', 'StreamingTV', 'StreamingMovies', 'Contract',
'PaperlessBilling', 'PaymentMethod', 'MonthlyCharges',
'TotalCharges', 'Churn'], dtype=object)
In [5]:
telecom_cust.dtypes
Out[5]:
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
In [6]:
telecom_cust.TotalCharges = pd.to_numeric(telecom_cust.TotalCharges, errors='coerce')
telecom_cust.isnull().sum()
Out[6]:
customerID 0 gender 0 SeniorCitizen 0 Partner 0 Dependents 0 tenure 0 PhoneService 0 MultipleLines 0 InternetService 0 OnlineSecurity 0 OnlineBackup 0 DeviceProtection 0 TechSupport 0 StreamingTV 0 StreamingMovies 0 Contract 0 PaperlessBilling 0 PaymentMethod 0 MonthlyCharges 0 TotalCharges 11 Churn 0 dtype: int64
After looking at the above output, we can say that there are 11 missing values for Total Charges. Let us replace remove these 11 rows from our data set
In [7]:
telecom_cust.dropna(inplace = True)
df3 = telecom_cust.iloc[:,1:]
df3['Churn'].replace(to_replace='Yes', value=1, inplace=True)
df3['Churn'].replace(to_replace='No', value=0, inplace=True)
print(df3)
df_dummies = pd.get_dummies(df3)
df_dummies.head()
gender SeniorCitizen Partner Dependents tenure PhoneService \
0 Female 0 Yes No 1 No
1 Male 0 No No 34 Yes
2 Male 0 No No 2 Yes
3 Male 0 No No 45 No
4 Female 0 No No 2 Yes
... ... ... ... ... ... ...
7038 Male 0 Yes Yes 24 Yes
7039 Female 0 Yes Yes 72 Yes
7040 Female 0 Yes Yes 11 No
7041 Male 1 Yes No 4 Yes
7042 Male 0 No No 66 Yes
MultipleLines InternetService OnlineSecurity OnlineBackup \
0 No phone service DSL No Yes
1 No DSL Yes No
2 No DSL Yes Yes
3 No phone service DSL Yes No
4 No Fiber optic No No
... ... ... ... ...
7038 Yes DSL Yes No
7039 Yes Fiber optic No Yes
7040 No phone service DSL Yes No
7041 Yes Fiber optic No No
7042 No Fiber optic Yes No
DeviceProtection TechSupport StreamingTV StreamingMovies Contract \
0 No No No No Month-to-month
1 Yes No No No One year
2 No No No No Month-to-month
3 Yes Yes No No One year
4 No No No No Month-to-month
... ... ... ... ... ...
7038 Yes Yes Yes Yes One year
7039 Yes No Yes Yes One year
7040 No No No No Month-to-month
7041 No No No No Month-to-month
7042 Yes Yes Yes Yes Two year
PaperlessBilling PaymentMethod MonthlyCharges \
0 Yes Electronic check 29.85
1 No Mailed check 56.95
2 Yes Mailed check 53.85
3 No Bank transfer (automatic) 42.30
4 Yes Electronic check 70.70
... ... ... ...
7038 Yes Mailed check 84.80
7039 Yes Credit card (automatic) 103.20
7040 Yes Electronic check 29.60
7041 Yes Mailed check 74.40
7042 Yes Bank transfer (automatic) 105.65
TotalCharges Churn
0 29.85 0
1 1889.50 0
2 108.15 1
3 1840.75 0
4 151.65 1
... ... ...
7038 1990.50 0
7039 7362.90 0
7040 346.45 0
7041 306.60 1
7042 6844.50 0
[7032 rows x 20 columns]
Out[7]:
| SeniorCitizen | tenure | MonthlyCharges | TotalCharges | Churn | gender_Female | gender_Male | Partner_No | Partner_Yes | Dependents_No | ... | StreamingMovies_Yes | Contract_Month-to-month | Contract_One year | Contract_Two year | PaperlessBilling_No | PaperlessBilling_Yes | PaymentMethod_Bank transfer (automatic) | PaymentMethod_Credit card (automatic) | PaymentMethod_Electronic check | PaymentMethod_Mailed check | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 1 | 29.85 | 29.85 | 0 | 1 | 0 | 0 | 1 | 1 | ... | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 34 | 56.95 | 1889.50 | 0 | 0 | 1 | 1 | 0 | 1 | ... | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
| 2 | 0 | 2 | 53.85 | 108.15 | 1 | 0 | 1 | 1 | 0 | 1 | ... | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
| 3 | 0 | 45 | 42.30 | 1840.75 | 0 | 0 | 1 | 1 | 0 | 1 | ... | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
| 4 | 0 | 2 | 70.70 | 151.65 | 1 | 1 | 0 | 1 | 0 | 1 | ... | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
5 rows × 46 columns
In [8]:
plt.figure(figsize=(15,8))
df_dummies.corr()['Churn'].sort_values(ascending = False).plot(kind='bar')
Out[8]:
<Axes: >
In [9]:
colors = ['#4D3425','#E4512B']
ax = (telecom_cust['gender'].value_counts()*100.0 /len(telecom_cust)).plot(kind='bar',
stacked = True,
rot = 0,
color = colors)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.set_ylabel('% Customers')
ax.set_xlabel('Gender')
ax.set_ylabel('% Customers')
ax.set_title('Gender Distribution')
totals = []
for i in ax.patches:
totals.append(i.get_width())
total = sum(totals)
for i in ax.patches:
ax.text(i.get_x()+.15, i.get_height()-3.5, \
str(round((i.get_height()/total), 1))+'%',
fontsize=12,
color='white',
weight = 'bold')
- % Senior Citizens - There are only 16% of the customers who are senior citizens. Thus most of our customers in the data are younger people.
In [10]:
ax = (telecom_cust['SeniorCitizen'].value_counts()*100.0 /len(telecom_cust))\
.plot.pie(autopct='%.1f%%', labels = ['No', 'Yes'],figsize =(5,5), fontsize = 12 )
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.set_ylabel('Senior Citizens',fontsize = 12)
ax.set_title('% of Senior Citizens', fontsize = 12)
Out[10]:
Text(0.5, 1.0, '% of Senior Citizens')
- Partner and dependent status - About 50% of the customers have a partner, while only 30% of the total customers have dependents.
In [11]:
df2 = pd.melt(telecom_cust, id_vars=['customerID'], value_vars=['Dependents','Partner'])
df3 = df2.groupby(['variable','value']).count().unstack()
df3 = df3*100/len(telecom_cust)
colors = ['#4D3425','#E4512B']
ax = df3.loc[:,'customerID'].plot.bar(stacked=True, color=colors,
figsize=(8,6),rot = 0,
width = 0.2)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.set_ylabel('% Customers',size = 14)
ax.set_xlabel('')
ax.set_title('% Customers with dependents and partners',size = 14)
ax.legend(loc = 'center',prop={'size':14})
for p in ax.patches:
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate('{:.0f}%'.format(height), (p.get_x()+.25*width, p.get_y()+.4*height),
color = 'white',
weight = 'bold',
size = 14)
In [12]:
colors = ['#4D3425','#E4512B']
partner_dependents = telecom_cust.groupby(['Partner','Dependents']).size().unstack()
ax = (partner_dependents.T*100.0 / partner_dependents.T.sum()).T.plot(kind='bar',
width = 0.2,
stacked = True,
rot = 0,
figsize = (8,6),
color = colors)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.legend(loc='center',prop={'size':14},title = 'Dependents',fontsize =14)
ax.set_ylabel('% Customers',size = 14)
ax.set_title('% Customers with/without dependents based on whether they have a partner',size = 14)
ax.xaxis.label.set_size(14)
for p in ax.patches:
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate('{:.0f}%'.format(height), (p.get_x()+.25*width, p.get_y()+.4*height),
color = 'white',
weight = 'bold',
size = 14)
In [13]:
ax = sns.distplot(telecom_cust['tenure'], hist=True, kde=False,
bins=int(180/5), color = 'darkblue',
hist_kws={'edgecolor':'black'},
kde_kws={'linewidth': 4})
ax.set_ylabel('# of Customers')
ax.set_xlabel('Tenure (months)')
ax.set_title('# of Customers by their tenure')
C:\Users\dmgte\AppData\Local\Temp\ipykernel_4764\2715800857.py:1: UserWarning: `distplot` is a deprecated function and will be removed in seaborn v0.14.0. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms). For a guide to updating your code to use the new functions, please see https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751 ax = sns.distplot(telecom_cust['tenure'], hist=True, kde=False,
Out[13]:
Text(0.5, 1.0, '# of Customers by their tenure')
In [14]:
ax = telecom_cust['Contract'].value_counts().plot(kind = 'bar',rot = 0, width = 0.3)
ax.set_ylabel('# of Customers')
ax.set_title('# of Customers by Contract Type')
Out[14]:
Text(0.5, 1.0, '# of Customers by Contract Type')
In [15]:
fig, (ax1,ax2,ax3) = plt.subplots(nrows=1, ncols=3, sharey = True, figsize = (20,6))
ax = sns.distplot(telecom_cust[telecom_cust['Contract']=='Month-to-month']['tenure'],
hist=True, kde=False,
bins=int(180/5), color = 'turquoise',
hist_kws={'edgecolor':'black'},
kde_kws={'linewidth': 4},
ax=ax1)
ax.set_ylabel('# of Customers')
ax.set_xlabel('Tenure (months)')
ax.set_title('Month to Month Contract')
ax = sns.distplot(telecom_cust[telecom_cust['Contract']=='One year']['tenure'],
hist=True, kde=False,
bins=int(180/5), color = 'steelblue',
hist_kws={'edgecolor':'black'},
kde_kws={'linewidth': 4},
ax=ax2)
ax.set_xlabel('Tenure (months)',size = 14)
ax.set_title('One Year Contract',size = 14)
ax = sns.distplot(telecom_cust[telecom_cust['Contract']=='Two year']['tenure'],
hist=True, kde=False,
bins=int(180/5), color = 'darkblue',
hist_kws={'edgecolor':'black'},
kde_kws={'linewidth': 4},
ax=ax3)
ax.set_xlabel('Tenure (months)')
ax.set_title('Two Year Contract')
C:\Users\dmgte\AppData\Local\Temp\ipykernel_4764\3842341399.py:3: UserWarning: `distplot` is a deprecated function and will be removed in seaborn v0.14.0. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms). For a guide to updating your code to use the new functions, please see https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751 ax = sns.distplot(telecom_cust[telecom_cust['Contract']=='Month-to-month']['tenure'], C:\Users\dmgte\AppData\Local\Temp\ipykernel_4764\3842341399.py:13: UserWarning: `distplot` is a deprecated function and will be removed in seaborn v0.14.0. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms). For a guide to updating your code to use the new functions, please see https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751 ax = sns.distplot(telecom_cust[telecom_cust['Contract']=='One year']['tenure'], C:\Users\dmgte\AppData\Local\Temp\ipykernel_4764\3842341399.py:22: UserWarning: `distplot` is a deprecated function and will be removed in seaborn v0.14.0. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms). For a guide to updating your code to use the new functions, please see https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751 ax = sns.distplot(telecom_cust[telecom_cust['Contract']=='Two year']['tenure'],
Out[15]:
Text(0.5, 1.0, 'Two Year Contract')
In [16]:
telecom_cust.columns.values
Out[16]:
array(['customerID', 'gender', 'SeniorCitizen', 'Partner', 'Dependents',
'tenure', 'PhoneService', 'MultipleLines', 'InternetService',
'OnlineSecurity', 'OnlineBackup', 'DeviceProtection',
'TechSupport', 'StreamingTV', 'StreamingMovies', 'Contract',
'PaperlessBilling', 'PaymentMethod', 'MonthlyCharges',
'TotalCharges', 'Churn'], dtype=object)
In [17]:
services = ['PhoneService','MultipleLines','InternetService','OnlineSecurity',
'OnlineBackup','DeviceProtection','TechSupport','StreamingTV','StreamingMovies']
fig, axes = plt.subplots(nrows = 3,ncols = 3,figsize = (15,12))
for i, item in enumerate(services):
if i < 3:
ax = telecom_cust[item].value_counts().plot(kind = 'bar',ax=axes[i,0],rot = 0)
elif i >=3 and i < 6:
ax = telecom_cust[item].value_counts().plot(kind = 'bar',ax=axes[i-3,1],rot = 0)
elif i < 9:
ax = telecom_cust[item].value_counts().plot(kind = 'bar',ax=axes[i-6,2],rot = 0)
ax.set_title(item)
In [18]:
telecom_cust[['MonthlyCharges', 'TotalCharges']].plot.scatter(x = 'MonthlyCharges',
y='TotalCharges')
Out[18]:
<Axes: xlabel='MonthlyCharges', ylabel='TotalCharges'>
In [19]:
colors = ['#4D3425','#E4512B']
ax = (telecom_cust['Churn'].value_counts()*100.0 /len(telecom_cust)).plot(kind='bar',
stacked = True,
rot = 0,
color = colors,
figsize = (8,6))
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.set_ylabel('% Customers',size = 14)
ax.set_xlabel('Churn',size = 14)
ax.set_title('Churn Rate', size = 14)
totals = []
for i in ax.patches:
totals.append(i.get_width())
total = sum(totals)
for i in ax.patches:
ax.text(i.get_x()+.15, i.get_height()-4.0, \
str(round((i.get_height()/total), 1))+'%',
fontsize=12,
color='white',
weight = 'bold',)
In [20]:
sns.boxplot(x = telecom_cust.Churn, y = telecom_cust.tenure)
Out[20]:
<Axes: xlabel='Churn', ylabel='tenure'>
In [21]:
colors = ['#4D3425','#E4512B']
contract_churn = telecom_cust.groupby(['Contract','Churn']).size().unstack()
ax = (contract_churn.T*100.0 / contract_churn.T.sum()).T.plot(kind='bar',
width = 0.3,
stacked = True,
rot = 0,
figsize = (10,6),
color = colors)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.legend(loc='best',prop={'size':14},title = 'Churn')
ax.set_ylabel('% Customers',size = 14)
ax.set_title('Churn by Contract Type',size = 14)
for p in ax.patches:
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate('{:.0f}%'.format(height), (p.get_x()+.25*width, p.get_y()+.4*height),
color = 'white',
weight = 'bold',
size = 14)
In [22]:
colors = ['#4D3425','#E4512B']
seniority_churn = telecom_cust.groupby(['SeniorCitizen','Churn']).size().unstack()
ax = (seniority_churn.T*100.0 / seniority_churn.T.sum()).T.plot(kind='bar',
width = 0.2,
stacked = True,
rot = 0,
figsize = (8,6),
color = colors)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.legend(loc='center',prop={'size':14},title = 'Churn')
ax.set_ylabel('% Customers')
ax.set_title('Churn by Seniority Level',size = 14)
for p in ax.patches:
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate('{:.0f}%'.format(height), (p.get_x()+.25*width, p.get_y()+.4*height),
color = 'white',
weight = 'bold',size =14)
In [23]:
ax = sns.kdeplot(telecom_cust.MonthlyCharges[(telecom_cust["Churn"] == 'No') ],
color="Red", shade = True)
ax = sns.kdeplot(telecom_cust.MonthlyCharges[(telecom_cust["Churn"] == 'Yes') ],
ax =ax, color="Blue", shade= True)
ax.legend(["Not Churn","Churn"],loc='upper right')
ax.set_ylabel('Density')
ax.set_xlabel('Monthly Charges')
ax.set_title('Distribution of monthly charges by churn')
C:\Users\dmgte\AppData\Local\Temp\ipykernel_4764\2862132292.py:1: FutureWarning: `shade` is now deprecated in favor of `fill`; setting `fill=True`. This will become an error in seaborn v0.14.0; please update your code. ax = sns.kdeplot(telecom_cust.MonthlyCharges[(telecom_cust["Churn"] == 'No') ], C:\Users\dmgte\AppData\Local\Temp\ipykernel_4764\2862132292.py:3: FutureWarning: `shade` is now deprecated in favor of `fill`; setting `fill=True`. This will become an error in seaborn v0.14.0; please update your code. ax = sns.kdeplot(telecom_cust.MonthlyCharges[(telecom_cust["Churn"] == 'Yes') ],
Out[23]:
Text(0.5, 1.0, 'Distribution of monthly charges by churn')
In [24]:
ax = sns.kdeplot(telecom_cust.TotalCharges[(telecom_cust["Churn"] == 'No') ],
color="Red", shade = True)
ax = sns.kdeplot(telecom_cust.TotalCharges[(telecom_cust["Churn"] == 'Yes') ],
ax =ax, color="Blue", shade= True)
ax.legend(["Not Churn","Churn"],loc='upper right')
ax.set_ylabel('Density')
ax.set_xlabel('Total Charges')
ax.set_title('Distribution of total charges by churn')
C:\Users\dmgte\AppData\Local\Temp\ipykernel_4764\3097405637.py:1: FutureWarning: `shade` is now deprecated in favor of `fill`; setting `fill=True`. This will become an error in seaborn v0.14.0; please update your code. ax = sns.kdeplot(telecom_cust.TotalCharges[(telecom_cust["Churn"] == 'No') ], C:\Users\dmgte\AppData\Local\Temp\ipykernel_4764\3097405637.py:3: FutureWarning: `shade` is now deprecated in favor of `fill`; setting `fill=True`. This will become an error in seaborn v0.14.0; please update your code. ax = sns.kdeplot(telecom_cust.TotalCharges[(telecom_cust["Churn"] == 'Yes') ],
Out[24]:
Text(0.5, 1.0, 'Distribution of total charges by churn')
1. Logistic Regression
In [25]:
# We will use the data frame where we had created dummy variables
y = df_dummies['Churn'].values
X = df_dummies.drop(columns = ['Churn'])
# Scaling all the variables to a range of 0 to 1
from sklearn.preprocessing import MinMaxScaler
features = X.columns.values
scaler = MinMaxScaler(feature_range = (0,1))
scaler.fit(X)
X = pd.DataFrame(scaler.transform(X))
X.columns = features
In [26]:
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=101)
In [27]:
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
result = model.fit(X_train, y_train)
In [28]:
from sklearn import metrics
prediction_test = model.predict(X_test)
print (metrics.accuracy_score(y_test, prediction_test))
0.8075829383886256
In [29]:
weights = pd.Series(model.coef_[0],
index=X.columns.values)
print (weights.sort_values(ascending = False)[:10].plot(kind='bar'))
Axes(0.125,0.11;0.775x0.77)
In [30]:
print(weights.sort_values(ascending = False)[-10:].plot(kind='bar'))
Axes(0.125,0.11;0.775x0.77)
2. Random Forest
In [31]:
from sklearn.ensemble import RandomForestClassifier
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=101)
model_rf = RandomForestClassifier(n_estimators=1000 , oob_score = True, n_jobs = -1,
random_state =50, max_features = "auto",
max_leaf_nodes = 30)
model_rf.fit(X_train, y_train)
prediction_test = model_rf.predict(X_test)
print (metrics.accuracy_score(y_test, prediction_test))
print(prediction_test)
C:\Users\dmgte\anaconda32\lib\site-packages\sklearn\ensemble\_forest.py:424: FutureWarning: `max_features='auto'` has been deprecated in 1.1 and will be removed in 1.3. To keep the past behaviour, explicitly set `max_features='sqrt'` or remove this parameter as it is also the default value for RandomForestClassifiers and ExtraTreesClassifiers. warn(
0.8088130774697939 [1 0 0 ... 0 0 0]
In [32]:
importances = model_rf.feature_importances_
weights = pd.Series(importances,
index=X.columns.values)
weights.sort_values()[-10:].plot(kind = 'barh')
Out[32]:
<Axes: >
3. Support Vecor Machine (SVM)
In [33]:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=99)
In [34]:
from sklearn.svm import SVC
model.svm = SVC(kernel='linear')
model.svm.fit(X_train,y_train)
preds = model.svm.predict(X_test)
metrics.accuracy_score(y_test, preds)
Out[34]:
0.820184790334044
In [35]:
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test,preds))
[[953 89] [164 201]]
In [43]:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM
# Load the dataset
data_path = r"C:\Users\dmgte\OneDrive\Documents\NUS course Material\AIYA project data.csv"
df = pd.read_csv(data_path)
# Preprocessing
# Drop irrelevant columns
df = df.drop(['customerID', 'TotalCharges'], axis=1)
# Convert categorical variables to numerical
categorical_columns = df.select_dtypes(include=['object']).columns.tolist()
le = LabelEncoder()
for col in categorical_columns:
df[col] = le.fit_transform(df[col])
# Split the data into features and target variable
X = df.drop('Churn', axis=1)
y = df['Churn']
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Feature scaling
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Reshape X_train and X_test
X_train_reshaped = X_train_scaled.reshape(X_train_scaled.shape[0], X_train_scaled.shape[1], 1)
X_test_reshaped = X_test_scaled.reshape(X_test_scaled.shape[0], X_test_scaled.shape[1], 1)
# Build the LSTM model
model = Sequential()
model.add(LSTM(26, activation='relu', input_shape=(X_train_reshaped.shape[1], X_train_reshaped.shape[2]), return_sequences=True))
model.add(LSTM(14, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# Compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# Train the model
model.fit(X_train_reshaped, y_train, epochs=10, batch_size=32, verbose=1)
# Evaluate the model
loss, accuracy = model.evaluate(X_test_reshaped, y_test, verbose=0)
print("Accuracy:", accuracy)
# Reshape test data for prediction
X_test_for_prediction = X_test_scaled.reshape(X_test_scaled.shape[0], X_test_scaled.shape[1], 1)
# Make predictions
predictions = (model.predict(X_test_for_prediction) > 0.5).astype(int)
# Reshape predictions and y_test arrays
predictions = predictions.flatten()
y_test_flattened = y_test.values.flatten()
# Create a dataframe to display the predicted and real values
results = pd.DataFrame({'Predicted Values': predictions, 'Real Values': y_test_flattened})
print(results)
Epoch 1/10
177/177 [==============================] - 6s 14ms/step - loss: 0.5606 - accuracy: 0.7345
Epoch 2/10
177/177 [==============================] - 2s 13ms/step - loss: 0.5002 - accuracy: 0.7423
Epoch 3/10
177/177 [==============================] - 2s 13ms/step - loss: 0.4767 - accuracy: 0.7583
Epoch 4/10
177/177 [==============================] - 2s 13ms/step - loss: 0.4660 - accuracy: 0.7767
Epoch 5/10
177/177 [==============================] - 2s 14ms/step - loss: 0.4627 - accuracy: 0.7751
Epoch 6/10
177/177 [==============================] - 2s 14ms/step - loss: 0.4590 - accuracy: 0.7744
Epoch 7/10
177/177 [==============================] - 3s 16ms/step - loss: 0.4581 - accuracy: 0.7794
Epoch 8/10
177/177 [==============================] - 3s 19ms/step - loss: 0.4572 - accuracy: 0.7765
Epoch 9/10
177/177 [==============================] - 3s 18ms/step - loss: 0.4512 - accuracy: 0.7849
Epoch 10/10
177/177 [==============================] - 3s 18ms/step - loss: 0.4519 - accuracy: 0.7812
Accuracy: 0.7948899865150452
45/45 [==============================] - 1s 5ms/step
Predicted Values Real Values
0 1 1
1 0 0
2 0 0
3 1 1
4 0 0
... ... ...
1404 0 0
1405 0 0
1406 0 0
1407 0 0
1408 0 1
[1409 rows x 2 columns]
In [44]:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM
# Load the dataset
data_path = r"C:\Users\dmgte\OneDrive\Documents\NUS course Material\AIYA project data.csv"
df = pd.read_csv(data_path)
# Preprocessing
# Drop irrelevant columns
df = df.drop(['customerID', 'TotalCharges'], axis=1)
# Convert categorical variables to numerical
categorical_columns = df.select_dtypes(include=['object']).columns.tolist()
le = LabelEncoder()
for col in categorical_columns:
df[col] = le.fit_transform(df[col])
# Split the data into features and target variable
X = df.drop('Churn', axis=1)
y = df['Churn']
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Feature scaling
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Reshape X_train and X_test
X_train_reshaped = X_train_scaled.reshape(X_train_scaled.shape[0], X_train_scaled.shape[1], 1)
X_test_reshaped = X_test_scaled.reshape(X_test_scaled.shape[0], X_test_scaled.shape[1], 1)
# Build the LSTM model
model = Sequential()
model.add(LSTM(26, activation='relu', input_shape=(X_train_reshaped.shape[1], X_train_reshaped.shape[2]), return_sequences=True))
model.add(LSTM(14, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# Compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# Train the model
model.fit(X_train_reshaped, y_train, epochs=10, batch_size=32, verbose=1)
# Evaluate the model
loss, accuracy = model.evaluate(X_test_reshaped, y_test, verbose=0)
print("Accuracy:", accuracy)
# Reshape test data for prediction
X_test_for_prediction = X_test_scaled.reshape(X_test_scaled.shape[0], X_test_scaled.shape[1], 1)
# Make predictions
predictions = (model.predict(X_test_for_prediction) > 0.5).astype(int)
# Reshape predictions and y_test arrays
predictions = predictions.flatten()
y_test_flattened = y_test.values.flatten()
# Create a dataframe to display the predicted and real values
results = pd.DataFrame({'Predicted Values': predictions, 'Real Values': y_test_flattened})
print(results)
Epoch 1/10
177/177 [==============================] - 6s 14ms/step - loss: 0.5589 - accuracy: 0.7334
Epoch 2/10
177/177 [==============================] - 2s 14ms/step - loss: 0.5154 - accuracy: 0.7387
Epoch 3/10
177/177 [==============================] - 3s 16ms/step - loss: 0.4823 - accuracy: 0.7600
Epoch 4/10
177/177 [==============================] - 3s 15ms/step - loss: 0.4690 - accuracy: 0.7716
Epoch 5/10
177/177 [==============================] - 3s 17ms/step - loss: 0.4579 - accuracy: 0.7787
Epoch 6/10
177/177 [==============================] - 3s 19ms/step - loss: 0.4561 - accuracy: 0.7799
Epoch 7/10
177/177 [==============================] - 3s 19ms/step - loss: 0.4525 - accuracy: 0.7810
Epoch 8/10
177/177 [==============================] - 3s 20ms/step - loss: 0.4473 - accuracy: 0.7810
Epoch 9/10
177/177 [==============================] - 3s 19ms/step - loss: 0.4443 - accuracy: 0.7847
Epoch 10/10
177/177 [==============================] - 4s 20ms/step - loss: 0.4469 - accuracy: 0.7794
Accuracy: 0.7977288961410522
45/45 [==============================] - 1s 6ms/step
Predicted Values Real Values
0 1 1
1 0 0
2 0 0
3 1 1
4 0 0
... ... ...
1404 0 0
1405 0 0
1406 0 0
1407 0 0
1408 0 1
[1409 rows x 2 columns]
In [ ]:
import pandas as pd
import matplotlib.pyplot as plt
# Load the dataset and select the "tenure" and "Churn" columns
tenure = df_dummies['tenure']
churn = df_dummies['Churn']
# Create a scatter plot with colored dots
plt.scatter(range(len(tenure)), tenure, c=churn.map({1: 'yellow', 0: 'blue'}))
# Add labels and title
plt.xlabel('Index')
plt.ylabel('Tenure')
plt.title('Scatter Plot of Tenure')
# Show the plot
plt.show()
In [ ]:
In [ ]:
In [ ]: