Telco Customer Churn Prediction. Customer churn, also known as customer... | by Ifeoma Ojialor | Towards Data Science

Customer churn, also known as customer attrition, occurs when customers stop doing business with a company or stop using a company’s services. By being aware of and monitoring churn rate, companies are equipped to determine their customer retention success rates and identify strategies for improvement. We will use a machine learning model to understand the precise customer behaviors and attributes which signal the risk and timing of customer churn.
Understanding our dataset:
We will use the Telco Customer Churn dataset from Kaggle. The raw dataset contains 7043 entries. All entries have several features and a column stating if the customer has churned or not.To better understand the data we will first load it into pandas and explore it with the help of some very basic commands.
import numpy as npimport pandas as pdfrom sklearn.preprocessing import MinMaxScalerfrom sklearn.cluster import KMeansimport matplotlib.pyplot as plt import seaborn as sns%matplotlib inlinefrom sklearn.model_selection import train_test_split#Loading the datadf = pd.read_csv(r’...Churn\telco_customer.csv’)df.info() <class ‘pandas.core.frame.DataFrame’> RangeIndex: 7043 entries, 0 to 7042 Data columns (total 21 columns): customerID 7043 non-null object gender 7043 non-null object SeniorCitizen 7043 non-null int64 Partner 7043 non-null objectDependents 7043 non-null objecttenure 7043 non-null int64 PhoneService 7043 non-null object MultipleLines 7043 non-null object InternetService 7043 non-null object OnlineSecurity 7043 non-null object OnlineBackup 7043 non-null object DeviceProtection 7043 non-null object TechSupport 7043 non-null object StreamingTV 7043 non-null object StreamingMovies 7043 non-null object Contract 7043 non-null object PaperlessBilling 7043 non-null object PaymentMethod 7043 non-null object MonthlyCharges 7043 non-null float64 TotalCharges 7043 non-null object Churn 7043 non-null object dtypes: float64(1), int64(2), object(18) memory usage: 1.1+ MB
df.info() gives us detailed information about every column. We can see that our data is divided into three types;
object: Object format means variables are categorical. Categorical variables in our dataset are: customerID, gender, partner, dependents, phone service, multiple lines, internet service, online security, online backup, device protection, tech support, streaming tv, streaming movies, contract, paperless billing, payment method, total charges, and churn.
int64: It represents the integer variables. Senior citizen and tenure are of this format.
float64: It represents the variables which have some decimal values involved. They are also numerical variables. There is only one variable with this format in our dataset which is monthly charges.
Exploratory Data Analysis
The goal of this section is to get comfortable with our data. We will do bivariate analysis. It is the simplest form of analyzing data where we examine how each variable relates to the churn rate. For categorical features, we can use frequency table or bar plots which will calculate the number of each category in a particular variable. For numerical features, probability density plots can be used to look at the distribution of the variable.
All visualizations for categorical variables will be done in tableau public.
The following inferences can be made from the above bar plots;
The churn percent is almost equal in case of Male and Females.
The percent of churn is higher in case of senior citizens.
The churn rate is higher in case of customers who have phone services.
Customers with Partners and Dependents have lower churn rate as compared to those who don’t have partners & Dependents.
Customers with an electronic payment method have a higher churn rate compared to other payment methods.
Customers with no internet service has a lower churn rate.
Churn rate is much higher in case of Fiber Optic InternetServices. Customers who do not have services like OnlineSecurity, OnlineBackup, and TechSupport have left the platform in the past month.
Now let's look at the numerical variables.
plt.figure(1), plt.subplot(121), sns.distplot(df['tenure']);plt.figure(1), plt.subplot(121), sns.distplot(df['MonthlyCharges']);plt.figure(1), plt.subplot(121), sns.distplot(df['TotalCharges']);
Data Preparation & Feature Engineering:
This section is a fundamental part of machine learning. If this section is not done properly, our model will not work. In this section we will clean up our dataset by dropping irrelevant data, treating missing values, and converting our variables to the proper data type.
Treating Irrelevant data & missing values
In our dataset, we can see that customer ID is not needed for our model so we drop the variable. We do not need to treat missing values as there are none in this dataset.
df.drop([‘customerID’], axis=1, inplace=True)
Converting Categorical to numerical data
Machine learning works with only numerical values. Therefore, we need to convert our categorical values to numerical values. By using the Pandas function “get_dummies()”, we can replace the gender column with “gender_Female” and “gender_Male”. We will use df.info() to show us which ones are categorical and numerical.
df.info()<class ‘pandas.core.frame.DataFrame’> RangeIndex: 7043 entries, 0 to 7042Data columns (total 21 columns): customerID 7043 non-null object gender 7043 non-null object SeniorCitizen 7043 non-null int64 Partner 7043 non-null object Dependents 7043 non-null object tenure 7043 non-null int64 PhoneService 7043 non-null objectMultipleLines 7043 non-null objectInternetService 7043 non-null object OnlineSecurity 7043 non-null object OnlineBackup 7043 non-null object DeviceProtection 7043 non-null object TechSupport 7043 non-null object StreamingTV 7043 non-null object StreamingMovies 7043 non-null object Contract 7043 non-null object PaperlessBilling 7043 non-null object PaymentMethod 7043 non-null object MonthlyCharges 7043 non-null float64 TotalCharges 7043 non-null object Churn 7043 non-null object dtypes: float64(1), int64(2), object(18) memory usage: 1.1+ MB
From the results above, we can see that the variables with the object datatype need to be converted to numerical.
df = pd.get_dummies(df, columns = [‘gender’, ‘Partner’,   ‘Dependents’,’PhoneService’,’MultipleLines’,’InternetService’,‘OnlineSecurity’,’OnlineBackup’,’DeviceProtection’,’TechSupport’,’StreamingTV’,‘StreamingMovies’,’Contract’,’PaperlessBilling’,’PaymentMethod’,’Churn’], drop_first = True)
It is always advisable to use df.info() to check that all our variables were converted to the appropriate data type. After this step, I noticed that total charges still had an object data type. Hence, I will use pd.numeric() function to convert it to a float.
df[‘TotalCharges’] = pd.to_numeric(df.TotalCharges, errors = ‘coerce’)df.drop([‘TotalCharges’], axis = 1, inplace = True)
Splitting the dataset.
First our model needs to be trained, second our model needs to be tested. Therefore it is best to have two different datasets. As for now we only have one, it is very common to split the data accordingly. X is the data with the independent variables, Y is the data with the dependent variable. The test size variable determines in which ratio the data will be split. It is quite common to do this in an 80 Training / 20 Test ratio.
df[‘Churn_Yes’] = df[‘Churn_Yes’].astype(int)Y = df[“Churn_Yes”].valuesX = df.drop(labels = [“Churn_Yes”],axis = 1)# Create Train & Test Datafrom sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=101)
Let us make our first model to predict the target variable. We will start with Logistic Regression which is used for predicting binary outcome.
We will use scikit-learn (sklearn) for making different models which is an open source library for Python. It is one of the most efficient tools which contains many inbuilt functions that can be used for modeling in Python.
from sklearn.linear_model import LogisticRegressionmodel = LogisticRegression()result = model.fit(X_train, y_train)
The dataset has been divided into training and validation part. Let us import LogisticRegression and accuracy_score from sklearn and fit the logistic regression model.
from sklearn import metricsprediction_test = model.predict(X_test)# Print the prediction accuracyprint (metrics.accuracy_score(y_test, prediction_test))
0.800567778566
So our predictions are almost 81% accurate, i.e. we have identified 80% of the churn rate correctly. So with the final objective to reduce churn and take the right preventing actions in time, we want to know which independent variables have the most influence on our predicted outcome. Therefore we set the coefficients in our model to zero and look at the weights of each variable.
weights = pd.Series(model.coef_[0], index=X.columns.values)weights.sort_values(ascending = False)
Here are the results;
InternetService_Fiber optic 0.800533 PaperlessBilling_Yes 0.417392 PaymentMethod_Electronic check 0.293135 StreamingTV_Yes 0.267554 MultipleLines_Yes 0.253773 SeniorCitizen 0.247112 StreamingMovies_Yes 0.197304 MultipleLines_No phone service 0.120019 PaymentMethod_Mailed check 0.019744 gender_Male 0.018991 MonthlyCharges 0.004611 Partner_Yes 0.000535 DeviceProtection_Yes -0.021993 tenure -0.035615 StreamingTV_No internet service -0.095143 TechSupport_No internet service -0.095143 DeviceProtection_No internet service -0.095143 StreamingMovies_No internet service -0.095143 OnlineBackup_No internet service -0.095143 OnlineSecurity_No internet service -0.095143 InternetService_No -0.095143 PaymentMethod_Credit card (automatic) -0.156123 Dependents_Yes -0.182597 OnlineBackup_Yes -0.190353 OnlineSecurity_Yes -0.335387 TechSupport_Yes -0.337772 PhoneService_Yes -0.551735 Contract_One year -0.591394 Contract_Two year -1.257341 dtype: float64
It can be observed that some variables have a positive relation to our predicted variable and some have a negative relation. Customers with negative values show that they are unlikely to churn while those with positive values shows they are likely to churn. These
Most of what I write about keeps me busy in my own Startup analyx. Looking forward to hearing your experience :)