机器学习:用Keras和Pandas进行客户流失预测
客户流失或客户流失是指服务或公司中现有客户的流失,这是许多企业了解的重要组成部分,以便提供更相关和更优质的服务,并留住有价值的客户以提高其盈利能力。在这篇文章中,我们将尝试预测电信运营商的客户流失。我们将使用IBM Watson分析社区的数据集(https://community.watsonanalytics.com/wp-content/uploads/2015/03/WA_Fn-UseC_-Telco-Customer-Churn.csv)。
我们来看看数据集(Python实现):
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import load_model
首先,导入必要的库并确保已将csv文件下载到工作目录中。
data = pd.read_csv('WA_Fn-UseC_-Telco-Customer-Churn.csv')
然后我们将csv文件读入pandas数据帧。在这篇文章中,我们使用了一个相对较小的数据集,可以很容易地存储在内存中,但如果您使用的是更大的文件,强烈建议您查看Tensorflow Dataset API,这超出了本文的范围。
在继续构建机器学习模型之前,我们必须做一些重要的事情,即了解我们的数据集,必要时应用数据争论,并确定机器学习模型的特征。
您可以运行,data.head()并data.columns 查看数据集的要点。
列名
我们来看看这些列到底是什么: data.dtypes
列的数据类型
很明显,我们在此数据集中有一些问题需要解决。
Senior Citizen列有两个值,Yes和No,但这里是1和0,column是int64类型。我们来解决这个问题。首先我们需要用Yes和No替换1和0:
data.SeniorCitizen.replace([0, 1], ["No", "Yes"], inplace= True)
TotalCharges列应为数字。
data.TotalCharges = data.TotalCharges.astype(float)
但是当我们尝试将此列转换为float数据类型时,会引发错误。那是因为这个列有一些空白单元格。让我们深入了解
for charge in data.TotalCharges:
try:
charge = float(charge)
except:
print("charge is: %s" % charge)
以这种方式检查它显示11行有一个空格作为TotalCharge。我们该怎么做?当TotalCharge是空格/空白值时,让我们检查一下MonthlyCharge和Tenure是什么
for i in range(len(data)):
if data.TotalCharges[i] == " ":
print("Tenure is %s and Monthly charges are %s" % (data.tenure[i], data.MonthlyCharges[i]))
当TotalCharge为空时,tenure和Monthly Charges
因此,很明显,当tenure为0时,TotalCharge是空白的,换句话说,他们是相当新的短时间客户。由于他们的tenure为零,因此认为他们的TotalCharge为零是合乎逻辑的。让我们将TotalCharges中的空格替换为0并将列转换为浮点数据类型。
data.TotalCharges.replace([" "], ["0"], inplace= True)
data.TotalCharges = data.TotalCharges.astype(float)
我们做一些归一化
CustomerID,不会对客户流失产生任何影响,所以,让我们首先删除该列。
data.drop("customerID", axis= 1, inplace= True)
for col in data.dtypes[data.dtypes == object].index:
print(col, data[col].unique())
特征和标签列
现在我们有了3个数字列,rest是分类的。为了归一化数值列,让我们将每个列的值除以相关列的最大值。这将确保所有的值都在0-1之间,从而帮助减少那些对最终模型产生不必要影响的值。
因为我们的标签会出现混乱,让我们用1替换Yes,用0替换No,所以我们的模型将是一个二元分类模型。
data.Churn.replace(["Yes", "No"], [1, 0], inplace= True)
接下来,我们应该将所有分类数据编码为one-hot编码。Pandas有一个非常简单的方法:
data = pd.get_dummies(data)
准备训练数据
X = data.drop("Churn", axis= 1)
y = data.Churn
机器学习模型的输入将是X,它具有除Churn之外的所有列,这是我们的标签,因此将其分配给y。为了训练和测试我们的模型,我们应该分割我们的数据集。这种拆分将产生20%的测试数据和80%的训练数据。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.2, random_state= 1234)
训练
创建模型:
model = Sequential()
model.add(Dense(16, input_dim=X_train.shape[1], activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
编译模型:
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fitting the model for 150 epochs with 10 as batch size
model.fit(X_train, y_train, epochs=150, batch_size=10)
这将开始在我们之前创建的训练数据分割上训练您的模型。这需要一段时间才能完成。我训练的模型在训练集上的准确度为84%。
评估和保存模型
_, accuracy = model.evaluate(X_test, y_test)
对于我训练过的模型,我在测试集上获得了77%的准确率。你会得到不同的值。但是,我们在训练集和测试集上的准确度差异约为8%,这可能是由于过度拟合造成的。
model.save('my_model.h5')
您可以保存模型以供将来推断,但请记住,在对此机器学习模型进行推断之前,您必须对我们为上述数据集执行的数据进行相同的转换,归一化。
在这个模型中有很多东西要改进,以及诊断一些问题。您仍然可以使用不同的超参数,当然还有不同的其他模型,如增强,决策树,SVM和其他经典算法,并比较结果。