Pokemogo 2018-11-21
点击上方关注,All in AI中国
得到一份工作并不容易,你需要让自己与众不同。仅仅证明你知道如何使用像scikit-learn或ggplot2这样的工具是不够的。所以问题是,你能做什么?我最喜欢的策略之一是展示商业影响力。"商业影响是什么意思?"
在一天结束时,你将直接或间接地处理一些面向商业方面的事情。这可能会降低成本,增加收入,改善客户体验等等。在这篇文章中,我将逐步向你展示如何构建一个客户流失预测模型来演示种种因素对商业的影响。(https://www.dataoptimal.com/churn-prediction-with-r/)
这是一个简短的概述:
商业背景
在任何现实世界的数据科学项目开始时,你需要首先提出一系列问题。(https://towardsdatascience.com/how-to-construct-valuable-data-science-projects-in-the-real-world-203a4f520d54)
以下是一些好的建议:
继续之前的客户流失理念,让我们假设你在电信行业工作。
有一天,你的老板来找你并问:"我们如何利用现有数据改善业务?"
让我们来看看详细回答每个问题,以便提出解决老板问题的战略方法。
你想解决的问题是什么?
在查看现有数据后,你发现获得新客户的成本比保留现有客户高出五倍。
现在,更集中的问题变成了"我们如何提高客户保留率以降低成本?"
你的潜在解决方案是什么?
由于我们可以访问现有客户数据,因此我们可以尝试构建机器学习模型来预测客户流失。
为了避免过于复杂化和过于抽象的东西,无法向管理层解释,我们将使用逻辑回归模型。(https://en.wikipedia.org/wiki/Logistic_regression)
你将如何评估你的模型?
我们将使用一系列机器学习评估指标(ROC,AUC,灵敏度,特异性)以及面向商业的指标(成本节约)。
逻辑回归
现在我们已经熟悉了商业背景,并且我们已经确定了问题的范围,让我们来看看我们的潜在解决方案。
我们可以尝试使用众多机器学习模型。一切都有利有弊。
为了简单起见,让我们坚持只讨论逻辑回归。
逻辑回归是一种线性分类器。(https://en.wikipedia.org/wiki/Linear_classifier)由于我们试图预测"流失"或"没有流失",因此分类模型正是我们所需要的。
这是一个很好的模型,因为它比许多其他模型更容易解释,比如随机森林。(https://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm)我所说的"解释"是指我们可以更容易地看到特征与输出之间的关系。
逻辑回归的缺点是它倾向于线性拟合。如果决策边界不是线性的,它可能不如像随机森林那样的模型。
基本上我们正在考虑灵敏度的可解释性。(https://towardsdatascience.com/understanding-the-bias-variance-tradeoff-165e6942b229)在实现机器学习模型时,这始终是一个考虑因素。
准备数据
下一步是准备数据。
此工作流程因项目而异,但在我们的示例中,我将使用以下工作流程:
我在工作流程中遗漏了一个完整的探索阶段(https://towardsdatascience.com/exploratory-data-analysis-8fc1cb20fd15)。在以后的文章中,我将讨论这个方面,因为我认为它与建模阶段同样重要,甚至更重要。
1) 导入数据
让我们从导入数据开始(https://github.com/dataoptimal/posts/tree/master/business%20impact%20project)。你可以前往我们的github页面拷贝一份。(https://github.com/dataoptimal/posts/tree/master/business%20impact%20project)
我们将利用Tidyverse库(https://www.tidyverse.org/)。对于使用R的数据科学家来说,这是一个必备的库。请务必查看他们的文档。
我喜欢在开始时设置我的工作目录的路径。请务必将path_loc变量修改为代码和数据集所在的工作目录。
由于这是一个csv文件,我使用read_csv函数将数据读入数据帧df。
2) 快速浏览
导入数据后,你需要快速查看它。
我想首先查看特性列的尺寸和名称。
我们可以看到有21个特性和7,043行。有各种特性,如TotalCharges和保留率。我们要尝试和预测的输出是"流失"。
另一个很棒的特性是glimpse。这使我们可以更详细地快速查看我们的特性。
3) 清理数据
在我们开始使用逻辑回归模型之前,我们需要做一些小的清理。
让我们首先将字符变量变为因子。
在这段代码中,我们使用dplyr(https://dplyr.tidyverse.org/)的mutate_if函数将字符变量更改为因子类型。
%>%被称为管道运算符。它来自magrittr图书馆,也是Tidyverse的一部分。(https://magrittr.tidyverse.org/index.html)
该运算符的基本思想是使代码更具可读性。你可以在此处了解更多信息。(https://r4ds.had.co.nz/pipes.html)
让我们也将SeniorCitizen变量从整数更改为一个因子。
接下来,我们将检查缺失值。我们可以使用purrr库(https://purrr.tidyverse.org/)中的map函数执行此操作。如果你还没有猜到,这个图书馆也是Tidyverse的一部分。
我们可以看到TotalCharges有11个缺失值。要替换这些缺失值,我们只需用中位数进行简单替换即可。
有关更换缺失值的技术更严格的方法,请查看此来源。(https://github.com/matthewbrems/ODSC-missing-data-may-18/blob/master/Analysis%20with%20Missing%20Data.pdf)
我们要做的最后一件事是删除CustomerID特性。这是每个客户的唯一标识符,因此它可能不会向我们的模型添加任何有用的信息。
如果你想对它进行测试,你可以随时保留此特性并查看结果的比较结果。
4) 分割数据
为了确保我们不会过度拟合我们的模型,我们会将数据分成训练集和测试集。这称为交叉验证。(https://en.wikipedia.org/wiki/Cross-validation_%28statistics%29)
我们将在训练集上训练模型,然后在测试集上测试其性能。我们将随机选择75%的数据作为我们的训练集,25%作为我们的测试集。我鼓励你尝试不同的分组来查看你的结果如何比较(可能是你的训练/测试组的80%/ 20%和60%/ 40%)。
要创建分割,我们将使用Caret包。(http://topepo.github.io/caret/index.html)让我们首先导入Caret并设置种子,以便我们的结果可以复制。
接下来,我们将使用createDataPartition函数选择75%的数据用于训练集。这将选择75%行的随机样本。
最后,我们将使用上面的行样本创建我们的训练和测试数据帧。
还有其他方法,如k-fold交叉验证,所以一定要仔细阅读。
有关如何在Caret中实现k-fold交叉验证的信息,请在R控制台中输入help("createFolds")。
拟合模型
现在我们已经将数据分割为训练和测试集,现在是拟合模型的时候了。
为了实现逻辑回归模型,我们将使用广义线性模型(GLM)函数glm。(https://www.statmethods.net/advstats/glm.html)
有不同类型的GLM,其中包括逻辑回归。要指定我们要执行二元逻辑回归,我们将使用参数family = binomial。
以下是适合逻辑回归模型的完整代码:
在下一节中,我们将进行预测并评估我们的模型。
做出预测
现在我们已经适应了我们的模型,是时候看看它的表现了。
为此,我们将使用测试数据集进行预测。我们将传入上一节中的fitmodel。为了预测概率,我们将指定type ="response"。
我们要将这些概率转换为二元响应,因为我们预测的流失变量是"是"或"否"。
我不确定R是如何编写响应的,但我可以使用对比函数快速检查。
查看结果,我们可以看到Yes使用1进行编码。
现在我们知道了响应编码,我们可以将预测结果转换为是和否响应。
我们将响应阈值设置为0.5,因此如果预测概率高于0.5,我们会将此响应转换为是。
最后一步是将字符响应转换为因子类型。这使得编码对于逻辑回归模型是正确的。
我们稍后会仔细研究这个阈值,所以不要担心为什么我们将它设置为0.5。目前,我们只是将此值用于此示例。
进行预测的一个重要部分是评估和验证模型。
让我们详细了解一些评估指标,最后采用更严格的模型验证方法,即k-fold交叉验证(https://machinelearningmastery.com/k-fold-cross-validation/)。
评估模型
在我们做出预测之后,是时候评估我们的模型了。
快速执行此操作的一个很好的工具是使用Caret的混淆矩阵函数。
我们将提供我们的glm.pred预测数组,以及测试$ Churn的实际结果。
最后,我们将使用positive ="Yes"将正数类指定为"是"。
该函数既产生混淆矩阵,也产生其他感兴趣的统计数据。
混淆矩阵显示为每个类进行了多少正确和不正确的预测。
以下是我们模型中的混淆矩阵:
我们可以看到模型正确地预测了"No"1165次,并且当实际响应为"是"205次时错误地预测"否"。
同样,当实际答案是"是"262次时,模型正确预测"是"。同时,当实际响应为"否"128次时,它错误地预测"是"。
我们的整体准确率为81%。一个简单的基线模型是预测大多数类,在我们的例子中是"否"。
如果我们只是预测了大多数类,我们的准确率将达到73%。测试集中有1760个观测值,1293个是"否"。如果你将1293除以1760就可以得到73%的准确率。
其他一些有用的指标是灵敏度和特异性。由于我们的类略有不平衡(~73%="否",~27%="是"),因此这些指标可能更有用。
灵敏度表示"真阳性"率。这是衡量我们预测积极类的准确程度的方法,在我们的例子中是"是"。
混乱矩阵函数直接报告此情况,但如果你想自己计算,则将"True Positives"除以"True Positives"和"False Negatives"之和。这是一个使视觉更清晰的视觉效果:
另一个有用的指标是特异性,它表示"真阴性"率。这是衡量我们预测负面类的准确程度的指标。这里是一个直观的解释细节:
另一个有用的指标是接收器工作特性(ROC)曲线下的面积,也称为AUC。(https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc)
最初在第二次世界大战期间实施的用于分析雷达信号的ROC是真阳性率与假阳性率的关系图。
回到我们原来的模型,我将会用0.5作为做出"是"(或肯定)预测的阈值。虽然我没有充分的理由选择0.5。
ROC是一个很好的工具,因为它可以根据阈值的不同绘制TPR与FPR的对比图。我们可以使用ROCR库(https://cran.r-project.org/web/packages/ROCR/ROCR.pdf)绘制ROC曲线图。这是完整的R代码:
如前所述,另一个有用的衡量指标是ROC曲线下的面积,称为AUC。(https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc)
AUC可以取0到1之间的任何值,其中1是最好的。这是将ROC简化为单个数字以评估模型的便捷方式。
这是用于评估我们模型的R代码:
我们的模型的AUC为0.85,非常好。如果我们只是随机猜测,我们的ROC将是45度线。这相当于AUC为0.5。
我们的表现优于随机猜测,所以我们知道我们的模型至少增加了一些价值!
K-fold交叉验证
现在我们已经对我们的模型进行了训练,测试和评估,让我们更严格地评估模型。
我们将数据集分割为训练和测试数据集,这是尝试和防止过度拟合的好方法。
更好的方法是使用K-fold交叉验证。(http://statweb.stanford.edu/~tibs/sta306bfiles/cvwrong.pdf)
在这种模型验证技术中,我们通过指定一定数量的"折叠"将数据随机分配到测试和训练集。在上面的示例中,折叠的数量是k = 4。
在每个折叠上运行模型后,我们对每个折叠的评估指标进行平均。因此,如果我们使用ROC运行模型四次,我们会将四个ROC值平均起来。这是尝试和防止过度拟合模型的好方法。
常用的折叠数是10,这是我们将使用的数据。我们还将重复这个过程3次,只是为我们的方法增加一点技术严谨性。这是完整的R代码:
我们首先使用trainControl特性设置k-fold CV设置。所有输入都非常简单。正如我之前提到的,我们使用10次,重复3次。
接下来我们训练模型。正如我们之前所做的那样,我们正在使用"glm"方法中的"二项式"族(https://cran.r-project.org/web/packages/rstanarm/vignettes/binomial.html)。为了评估我们的模型,我们将使用"ROC"。该模型实际上是在报告AUC,但我们在训练函数中指定的方式是公制="ROC"。
你还会注意到我在trainControl函数的代码之前将正数类改为"是"。我这样做是为了能够将灵敏度和特异性与之前的结果进行比较。
结果与我们之前的结果相似。
和以前一样,我们的AUC是0.85。这在输出中报告为ROC,但它实际上是AUC。
真阳性率(敏感度)为0.55,真阴性率(特异性)为0.90。
商业影响
到目前为止,我们已经使用k-fold交叉验证和逻辑回归来预测客户流失。
我们研究了有用的评估指标,如AUC,敏感性和特异性。
这一切都很好,但现在呢?
如果我们去找首席执行官并单独介绍这些结果,他或她会说"那又怎么样?"
我们开发此模型的实际目标是显示商业影响。在我们的例子中,这将节省成本。
让我逐步介绍如何节省成本。
首先,让我们对一些不同的成本做一些假设。
我们假设电信行业的客户购置成本约为300美元。如果我们预测客户不会流失,但他们确实会流失(假阴性,FN),那么我们将不得不花费300美元购买该客户的替代品。
现在让我们假设获得新客户而不是保留现有客户的成本要贵5倍。如果我们预测客户会流失,我们需要花费60美元来保留该客户。
有时我们会正确地预测客户会流失(真阳性,TP),有时我们会错误地预测客户会流失(假阳性,FP)。在这两种情况下,我们将花费60美元来保留客户。
最后,我们正确地预测客户不会流失(真阴性,TN)。在这种情况下,我们不会花任何钱。
以下是成本的总结:
如果我们将每个预测类型(FN,TP,FP和TN)的数量乘以与每个预测类型相关联的成本并将它们相加,那么我们就可以计算出与模型相关的总成本。这是这个等式的样子:
成本= FN($ 300)+ TP($ 60)+ FP($ 60)+ TN($ 0)
作为一个例子,我们假设我们对每个预测做出如下预测:
然后我们的总成本是3600美元。
10 *($ 300)+ 5 *($ 60)+ 5 *($ 60)+ 5 *($ 0)= $ 3600
现在让我们将此成本评估应用于我们的模型。
我们首先拟合模型,然后以概率的形式进行预测。
接下来,让我们创建一个阈值向量和一个成本向量。
阈值向量将包含每个模型的阈值。在我们仅使用0.5作为阈值之前,让我们看一下在0和1之间以0.1为增量的阈值(例如,0.1,0.2,0.3 ...... 0.9,1.0)。
成本向量将只是一个长度为10的向量,从零开始。当我们遍历函数时,我们将填充此函数,在我们运行的时候评估每个阈值。为了评估成本,我们将使用与之相同的成本等式。
现在我们将创建一个for循环来使用各种阈值进行预测,并评估每个阈值的成本。
我没有使用TN,FP,FN和TP的每个结果的总数,而是使用百分比代替。这就是为什么我使用混淆矩阵将每个值提取出来并除以1760。
在我们的测试集中有1760个观测值,因此这个数字来自于此。通过这种方式,我计算了每个客户的成本。
现在让我们假设我们公司目前正在使用我们称之为"简单模型"的东西,其默认值为0.5。我们可以继续适应该模型,进行预测并计算成本。我们称这个模型为cost_simple。
最后,我们可以将所有结果放在数据框中并绘制它们。
查看结果,我们可以看到,在0.2的阈值下,每个客户的最低成本约为40美元。
我们公司目前实施的"简单"模型每个客户的成本约为48美元,阈值为0.50。
如果我们假设我们拥有大约500,000的客户群,那么从简单模型到优化模型的转换可以节省400万美元的成本。
这种类型的成本节约可能会对商业产生重大影响,具体取决于商业规模。
结论
在这篇文章中,我们开发了一种机器学习模型来预测客户流失。
具体来说,我们完成了以下每个步骤:
最后,我们为客户流失问题开发了一个优化的逻辑回归模型。
假设公司使用的逻辑回归模型的默认阈值为0.5,我们就能够确定最佳阈值实际为0.2。
这将使每位客户的成本从48.00美元降至40.00美元。客户群约为500,000,每年可节省400万美元的成本。这无疑具有重大意义!
虽然这是一个假例,但它与你在现实世界中遇到的问题可能非常相似。
能够有效地识别问题并显示真正的商业影响将使你与就业市场中的其他数据科学家区分开来。
我们应重点掌握如何实现机器学习模型并对其进行评估。如果你能够像我们在这篇文章中所做的那样,进行预测并显示你所得出的结果,那么你将很快就能找到工作!
作者——John Sullivan
来源:https://towardsdatascience.com/create-better-data-science-projects-with-business-impact-churn-prediction-with-r-f609c23a6287