如何利用Python和深度神经网络锁定即将流失的客户?业绩过十万!

 

 

烦恼

作为一名数据分析师,你来到这家跨国银行工作已经半年了。

今天上午,老板把你叫到办公室,面色凝重。

你心里直打鼓,以为自己捅了什么篓子。幸好老板的话让你很快打消了顾虑。

 

 

客户主要分布在法国、德国和西班牙。

你手里掌握的信息,包括他们的年龄、性别、信用、办卡信息等。客户是否已流失的信息在最后一列(Exited)。

 

 

请选择左侧的Python 3.6版本下载安装。

其次是新建文件夹,起名为demo-customer-churn-ann,并且从这个链接下载数据,放到该文件夹下。

 

点击界面右上方的New按钮,新建一个Python 3 Notebook,起名为customer-churn-ann。

 

准备工作结束,下面我们开始清理数据。

清理

首先,读入数据清理最常用的pandas和numpy包。

 

可以看到,数据完整无误读入。但是并非所有的列都对我们预测用户流失有作用。我们一一甄别一下:

  • RowNumber:行号,这个肯定没用,删除
  • CustomerID:用户编号,这个是顺序发放的,删除
  • Surname:用户姓名,对流失没有影响,删除
  • CreditScore:信用分数,这个很重要,保留
  • Geography:用户所在国家/地区,这个有影响,保留
  • Gender:用户性别,可能有影响,保留
  • Age:年龄,影响很大,年轻人更容易切换银行,保留
  • Tenure:当了本银行多少年用户,很重要,保留
  • Balance:存贷款情况,很重要,保留
  • NumOfProducts:使用产品数量,很重要,保留
  • HasCrCard:是否有本行信用卡,很重要,保留
  • IsActiveMember:是否活跃用户,很重要,保留
  • EstimatedSalary:估计收入,很重要,保留
  • Exited:是否已流失,这将作为我们的标签数据

 

 

在Scikit-learn工具包里面,专门提供了方便的工具 LabelEncoder ,让我们可以方便地将类别信息变成数值。

 

这样是不是就完事大吉了呢?

不对,Gender还好说,只有两种取值方式,要么是男,要么是女。我们可以把“是男性”定义为1,那么女性就取值为0。两种取值只是描述类别不同,没有歧义。

而Geography就不同了。因为数据集里面可能的国家地区取值有3种,所以就转换成了0(法国)、1(德国)、2(西班牙)。问题是,这三者之间真的有序列(大小)关系吗?

答案自然是否定的。我们其实还是打算用数值描述分类而已。但是取值有数量的序列差异,就会给机器带来歧义。它并不清楚不同的取值只是某个国家的代码,可能会把这种大小关系带入模型计算,从而产生错误的结果。

 

没有。

因为本例中,OneHotEncoder转换出来的3列数字,实际上是不独立的。给定其中两列的信息,你自己都可以计算出其中的第3列取值。

好比说,某一行的前两列数字是 (0, 0) ,那么第三列肯定是1。因为这是转换规则决定的。3列里只能有1个是1,其余都是0。

如果你做过多元线性回归,应该知道这种情况下,我们是需要去掉其中一列,才能继续分析的。不然会落入“虚拟变量陷阱”(dummy variable trap)。

我们删掉第0列,避免掉进坑里。

X = np.delete(X, [0], 1)

再次打印第一行:

 

这样在后面训练的时候,他就可以和前面的特征矩阵一一对应来操作计算了。

既然标签代表了类别,我们也把它用OneHotEncoder转换,这样方便我们后面做分类学习。

onehotencoder = OneHotEncoder()

y = onehotencoder.fit_transform(y).toarray()

此时的标签变成两列数据,一列代表顾客存留,一列代表顾客流失。

y

array([[ 0., 1.],

[ 1., 0.],

[ 0., 1.],

...,

[ 0., 1.],

[ 0., 1.],

[ 1., 0.]])

总体的数据已经齐全了。但是我们 不能 把它们 都用来 训练。

 

 

你会发现,许多列的方差比原先小得多。机器学习起来,会更加方便。

数据清理和转换工作至此完成。

决策树

如果读过我的《 贷还是不贷:如何用Python和机器学习帮你决策? 》一文,你应该有一种感觉——这个问题和贷款审批决策很像啊!既然在该文中,决策树很好使,我们继续用决策树不就好了?

 

经检测,决策树在咱们的数据集上,表现得还是不错的。总体的准确率为0.81,召回率为0.80,f1分数为0.81,已经很高了。对10个客户做流失可能性判断,它有8次都能判断正确。

但是,这样是否足够?

我们或许可以调整决策树的参数做优化,尝试改进预测结果。

或者我们可以采用 深度学习 。

深度

深度学习的使用场景,往往是因为原有的模型经典机器学习模型过于简单,无法把握复杂数据特性。

我不准备给你讲一堆数学公式,咱们动手做个实验。

请你打开这个网址。

你会看到如下图所示的深度学习游乐场:

 

右侧的图形,里面是蓝色数据,外圈是黄色数据。你的任务就是要用模型分类两种不同数据。

你说那还不容易?我一眼就看出来了。

你看出来没有用。通过你的设置,让机器也能正确区分,才算数。

图中你看到许多加减号。咱们就通过操纵它们来玩儿一玩儿模型。

首先,点图中部上方的"2 HIDDEN LAYERS"左侧减号,把中间隐藏层数降低为1。

 

然后,点击"2 neurons"上面的减号,把神经元数量减少为1。

把页面上方的Activation函数下拉框打开,选择“Sigmoid”。

现在的模型,其实就是经典的逻辑回归(Logistic Regression)。

 

点击左上方的运行按钮,我们看看执行效果。

 

由于模型过于简单,所以机器绞尽脑汁,试图用一条直线切分二维平面上的两类节点。

损失(loss)居高不下。训练集和测试集损失都在0.4左右,显然不符合我们的分类需求。

下面我们试试增加层数和神经元数量。这次点击加号,把隐藏层数加回到2,两层神经元数量都取2。

 

再次点击运行。

经过一段时间,结果稳定了下来,你发现这次电脑用了两条线,把平面切分成了3部分。

 

测试集损失下降到了0.25左右,而训练集损失更是降低到了0.2以下。

模型复杂了,效果似乎更好一些。

再接再厉,我们把第一个隐藏层的神经元数量增加为4看看。

 

点击运行,不一会儿有趣的事情就发生了。

 

机器用一条近乎完美的曲线把平面分成了内外两个部分。测试集和训练集损失都极速下降,训练集损失甚至接近于0。

这告诉我们,许多时候模型过于简单带来的问题,可以通过加深隐藏层次、增加神经元的方法提升模型复杂度,加以改进。

目前流行的划分方法,是用隐藏层的数量多少来区分是否“深度”。当神经网络中隐藏层数量达到3层以上时,就被称为“深度神经网络”,或者“深度学习”。

久闻大名的深度学习,原来就是这么简单。

如果有时间的话,建议你自己在这个游乐场里多动手玩儿一玩儿。你会很快对神经网络和深度学习有个感性认识。

框架

游乐场背后使用的引擎,就是Google的深度学习框架Tensorflow。

所谓框架,就是别人帮你构造好的基础软件应用。你可以通过调用它们,避免自己重复发明轮子,大幅度节省时间,提升效率。

支持Python语言的深度学习的框架有很多,除了Tensorflow外,还有PyTorch, Theano和MXNet等。

我给你的建议是,找到一个你喜欢的软件包,深入学习使用,不断实践来提升自己的技能。 千万不要 跟别人争论哪个深度学习框架更好。一来萝卜白菜各有所爱,每个人都有自己的偏好;二来深度学习的江湖水很深,言多有失。说错了话,别的门派可能会不高兴哟。

我比较喜欢Tensorflow。但是Tensorflow本身是个底层库。虽然随着版本的更迭,界面越来越易用。但是对初学者来说,许多细节依然有些过于琐碎,不容易掌握。

初学者的耐心有限,挫折过多容易放弃。

幸好,还有几个高度抽象框架,是建立在Tensorflow之上的。如果你的任务是 应用 现成的深度学习模型,那么这些框架会给你带来非常大的便利。

这些框架包括Keras, TensorLayer等。咱们今天将要使用的,叫做TFlearn。

它的特点,就是长得很像Scikit-learn。这样如果你熟悉经典机器学习模型,学起来会特别轻松省力。

实战

闲话就说这么多,下面咱们继续写代码吧。

写代码之前,请回到终端下,运行以下命令,安装几个软件包:

pip install tensorflow

pip install tflearn

执行完毕后,回到Notebook里。

我们呼叫tflearn框架。

import tflearn

然后,我们开始搭积木一样,搭神经网络层。

首先是输入层。

net = tflearn.input_data(shape=[None, 11])

注意这里的写法,因为我们输入的数据,是特征矩阵。而经过我们处理后,特征矩阵现在有11列,因此shape的第二项写11。

shape的第一项,None,指的是我们要输入的特征矩阵行数。因为我们现在是搭建模型,后面特征矩阵有可能一次输入,有可能分成组块输入,长度可大可小,无法事先确定。所以这里填None。tflearn会在我们实际执行训练的时候,自己读入特征矩阵的尺寸,来处理这个数值。

下面我们搭建隐藏层。这里我们要使用深度学习,搭建3层。

net = tflearn.fully_connected(net, 6, activation='relu')

net = tflearn.fully_connected(net, 6, activation='relu')

net = tflearn.fully_connected(net, 6, activation='relu')

activation刚才在深度学习游乐场里面我们遇到过,代表激活函数。如果没有它,所有的输入输出都是线性关系。

Relu函数是激活函数的一种。它大概长这个样子。

 

如果你想了解激活函数的更多知识,请参考后文的学习资源部分。

隐藏层里,每一层我们都设置了6个神经元。其实至今为之,也不存在最优神经元数量的计算公式。工程界的一种做法,是把输入层的神经元数量,加上输出层神经元数量,除以2取整。咱们这里就是用的这种方法,得出6个。

搭好了3个中间隐藏层,下面我们来搭建输出层。

net = tflearn.fully_connected(net, 2, activation='softmax')

net = tflearn.regression(net)

这里我们用两个神经元做输出,并且说明使用回归方法。输出层选用的激活函数为softmax。处理分类任务的时候,softmax比较合适。它会告诉我们每一类的可能性,其中数值最高的,可以作为我们的分类结果。

积木搭完了,下面我们告诉TFlearn,以刚刚搭建的结构,生成模型。

model = tflearn.DNN(net)

有了模型,我们就可以使用拟合功能了。你看是不是跟Scikit-learn的使用方法很相似呢?

model.fit(X_train, y_train, n_epoch=30, batch_size=32, show_metric=True)

注意这里多了几个参数,我们来解释一下。

n_epoch

batch_size

show_metric

以下就是电脑输出的最终训练结果。其实中间运行过程看着更激动人心,你自己试一下就知道了。

Training Step: 7499 | total loss: [1m[32m0.39757[0m[0m | time: 0.656s

| Adam | epoch: 030 | loss: 0.39757 - acc: 0.8493 -- iter: 7968/8000

Training Step: 7500 | total loss: [1m[32m0.40385[0m[0m | time: 0.659s

| Adam | epoch: 030 | loss: 0.40385 - acc: 0.8487 -- iter: 8000/8000

--

我们看到训练集的损失(loss)大概为0.4左右。

打开终端,我们输入

tensorboard --logdir=/tmp/tflearn_logs/

然后在浏览器里输入 http://localhost:6006/

可以看到如下界面:

 

这是模型训练过程的可视化图形,可以看到准确度的攀升和损失降低的曲线。

打开GRAPHS标签页,我们可以查看神经网络的结构图形。

 

我们搭积木的过程,在此处一目了然。

评估

训练好了模型,我们来尝试做个预测吧。

看看测试集的特征矩阵第一行。

X_test[0]

array([ 1.75486502, -0.57369368, -0.55204276, -1.09168714, -0.36890377,

1.04473698, 0.8793029 , -0.92159124, 0.64259497, 0.9687384 ,

1.61085707])

我们就用它来预测一下分类结果。

y_pred = model.predict(X_test)

打印出来看看:

y_pred[0]

array([ 0.70956731, 0.29043278], dtype=float32)

模型判断该客户不流失的可能性为0.70956731。

我们看看实际标签数据:

y_test[0]

array([ 1., 0.])

客户果然没有流失。这个预测是对的。

但是一个数据的预测正确与否,是无法说明问题的。我们下面跑整个测试集,并且使用evaluate函数评价模型。

score = model.evaluate(X_test, y_test)

print('Test accuarcy: %0.4f%%' % (score[0] * 100))

Test accuarcy: 84.1500%

在测试集上,准确性达到84.15%,好样的!

希望在你的努力下,机器做出的准确判断可以帮助银行有效锁定可能流失的客户,降低客户的流失率,继续日进斗金。

说明

你可能觉得,深度学习也没有什么厉害的嘛。原先的决策树算法,那么简单就能实现,也可以达到80%以上的准确度。写了这么多语句,深度学习结果也无非只提升了几个百分点而已。

首先,准确度达到某种高度后,提升是不容易的。这就好像学生考试,从不及格到及格,付出的努力并不需要很高;从95分提升到100,却是许多人一辈子也没有完成的目标。

其次,在某些领域里,1%的提升意味着以百万美元计的利润,或者几千个人的生命因此得到拯救。

第三,深度学习的崛起,是因为大数据的环境。在许多情况下,数据越多,深度学习的优势就越明显。本例中只有10000条记录,与“大数据”的规模还相去甚远。

学习资源

如果你对深度学习感兴趣,推荐以下学习资源。

首先是教材。

第一本是Deep Learning,绝对的经典。

 

第二本是 Hands-On Machine Learning with Scikit-Learn and TensorFlow: Concepts, Tools, and Techniques to Build Intelligent Systems ,深入浅出,通俗易懂。

 

进群:125240963  即可获取数十套PDF哦!

猜你喜欢

转载自www.cnblogs.com/PY1780/p/9277249.html