python数据分析实战:生存分析与电信用户流失预测
文章目录
- 1.背景
- 1.1 生存分析、KM曲线及Cox回归
- 1.2 案例背景
- 2.AIC向前逐步回归法进行特征选择
- 3.Cox模型搭建
- 3.1 特征重要性分析
- 3.2 模型校准
- 3.3 对个体进行预测
- 3.3 用户流失预测
- 4.总结
1.背景
1.1 生存分析、KM曲线及Cox回归
常见的回归模型聚焦在事件结果与影响因素上,生存分析既关注结果又关注发生事件。既研究结果影响因素,又研究影响因素与结果出现事件长短的关系,是研究生存现象和发生事件关系及统计规律的一门学科。
什么是生存分析?这篇文章介绍了生存分析中的一些基本概念。风险函数h(t)h(t)h(t)指在ttt事件之前未发生任何事件而在ttt发生事件的概率,累积风险函数H(t)=∫0th(u)du=−ln[S(t)]H(t)=\int_{0}^{t}h(u)du=-ln[S(t)]H(t)=∫0th(u)du=−ln[S(t)],生存函数S(t)=e−H(t)=e−∫0th(u)duS(t)=e^{-H(t)}=e^{-\int_{0}^{t}h(u)du}S(t)=e−H(t)=e−∫0th(u)du表示研究对象到该时刻仍未发生事件的概率。
目前,对生存函数及风险函数的刻画方法分为非参数和参数两类。其中,最常用的是非参数方法中对生存函数进行刻画的Kaplan-Meier曲线法和对累积风险函数进行刻画的Nelson-Aalen曲线法。KM是一类非参数估计方法,不对数据分布做任何假设,而是直接用概率乘法定理估计生存率。
KM方法的优势在于能直观地观察生存曲线,便于不同生存曲线之间进行简单比较,但无法建立数学模型对多个影响因素进行分析。为了解决这个问题,Cox比例风险回归模型诞生了,实现了对包含分类变量及连续变量的多变量回归。
1.2 案例背景
数据来源于kaggle,中文名称为电信用户流失情况表,也被网上很多文章当作案例使用。下面为字段说明,事件为Churn流失,生存时间为tenure使用月数。
接下来我们对这个数据利用Cox比例风险回归模型进行分析。Cox模型使用需要满足比例风险假定Hazard Ratio(HR):各危险因素的作用不随时间的变化而变化,即不随时间的变化而变化。但一般情况下是不用考虑的,官网文档给出了解释我们需不需要考虑PH假定?。
python中支持生存分析的包为lifelines
,可以支持生存函数的绘制、对数秩检测以及Cox模型拟合。此外还要介绍一个包pandas_profiling
,这个包能快速对数据进行描述性统计,包含了数据的分布、均值最大值最小值、缺失值以及相关度。
2.AIC向前逐步回归法进行特征选择
在进行后续操作之前,依然要进行数据清洗及哑变量处理,在此不赘述了。这里介绍一种新的特征选择方式:AIC向前逐步回归法。
逐步回归分为三种,分别是向前逐步回归,向后逐步回归,逐步回归。向前逐步回归的特点是将自变量一个一个当如模型中,每当放入一个变量时,都利用相应的检验准则检验,当加入的变量不能使得模型变得更优良时,变量将会被剔除,如此不断迭代,直到没有适合的新变量加入为止。向后逐步回归的特点是,将所有变量都放入模型之后,一个一个的剔除变量,将某一变量拿出模型而使得模型更优良时,将会剔除此变量。如此反复迭代,直到没有合适的变量剔除为止。逐步回归则是结合了以上的向前和向后逐步回归的特点。
AIC即赤池值,是衡量模型拟合优良性和模型复杂性的一种标准,在建立多元线性回归模型时,变量过多,且有不显著的变量时,可以使用AIC准则结合逐步回归进行变量筛选。AIC数学表达式如下:
AIC=2p+n(log(SSE/n))AIC=2p+n(log(SSE/n))A I C = 2 p + n ( l o g ( S S E / n ) ) AIC=2p+n(log(SSE/n))AIC=2p+n(log(SSE/n))AIC=2p+n(log(SSE/n))
AIC越小我们认为模型更优良,下面以AIC作为判定标准进行向前逐步回归,对特征进行筛选。但是向前逐步回归函数与每次选择的模型有关,并没有现成的包使用。上面的文章是以线性回归为例写的代码,所以我们要先依据Cox模型对其进行改写。
import pandas as pd
import pandas_profiling
import numpy as np
from sklearn import metrics
from sklearn.model_selection import train_test_split
from lifelines import CoxPHFitter
import matplotlib.pyplot as plt
#定义向前逐步回归函数
def forward_select(data):variate=set(data.columns) #将字段名转换成字典类型variate.remove('tenure') #去掉因变量的字段名variate.remove('Churn')selected=[]current_score,best_new_score=float('inf'),float('inf') #目前的分数和最好分数初始值都为无穷大(因为AIC越小越好)#循环筛选变量while variate:aic_with_variate=[]for candidate in variate: #逐个遍历自变量df=data[[candidate]+list(selected)+['tenure','Churn']]cph=CoxPHFitter(penalizer=0.01)cph.fit(df,duration_col='tenure',event_col='Churn',step_size=0.01)aic=cph.AIC_partial_aic_with_variate.append((aic,candidate)) #将第每一次的aic值放进空列表aic_with_variate.sort(reverse=True) #降序排序aic值best_new_score,best_candidate=aic_with_variate.pop() #最好的aic值等于删除列表的最后一个值,以及最好的自变量等于列表最后一个自变量if current_score>best_new_score: #如果目前的aic值大于最好的aic值variate.remove(best_candidate) #移除加进来的变量名,即第二次循环时,不考虑此自变量了selected.append(best_candidate) #将此自变量作为加进模型中的自变量current_score=best_new_score #最新的分数等于最好的分数print("aic is {},continuing!".format(current_score)) #输出最小的aic值else:print("for selection over!")breakreturn(selected)
#拆分训练集和测试集
train, test = train_test_split(df,test_size=0.2)
#进行特征筛选
selected=forward_select(train)
筛选出的特征:
['Contract_Month-to-month','TotalCharges','MonthlyCharges','Contract_Two year','OnlineSecurity_No','InternetService_Fiber optic','DeviceProtection_No internet service','PaymentMethod_Bank transfer (automatic)','PaymentMethod_Credit card (automatic)','Partner_No','OnlineBackup_No','TechSupport_No','PaperlessBilling_No','Dependents_No','MultipleLines_No','StreamingMovies_Yes','MultipleLines_No phone service','StreamingTV_Yes','InternetService_No']
3.Cox模型搭建
3.1 特征重要性分析
data=train[selected+['tenure','Churn']]
#实例化模型
cph=CoxPHFitter(penalizer=0.01)
#数据拟合
cph.fit(data,duration_col='tenure',event_col='Churn',step_size=0.5)
#打印结果
cph.print_summary()
#绘图
fig,ax = plt.subplots(figsize=(12,9))
cph.plot(ax=ax)
plt.show()
拟合结果
Cox数学表达式:
h(t;x1,x2,...,xp)=h0(t)exp(β1x1+β2x2+...+βpxp)h(t;x_1,x_2,...,x_p)=h_0(t)exp(\beta_1 x_1+\beta_2 x_2+...+\beta_p x_p) h(t;x1,x2,...,xp)=h0(t)exp(β1x1+β2x2+...+βpxp)
即准风险率h0(t)h_0(t)h0(t)为所有自变量取值均为0的风险率,(β1,β2,...,βp)(\beta_1,\beta_2,...,\beta_p)(β1,β2,...,βp)是模型的偏自回归系数,反应了自变量对风险率的影响。与一般的回归分析不同,Cox模型不是直接用生存时间作为回归方程的因变量,自变量对生存时间的影响通过风险函数与基准函数的比值来表示。
我们对模型的解读为:
- 当自变量xpx_pxp为连续型变量时,βp\beta_pβp为在除xpx_pxp之外的其他变量均不变的情况下,xpx_pxp每增加一个单位,风险率变化exp(βp)exp(\beta_p)exp(βp)倍。
- 当自变量xpx_pxp为离散型变量时,如有0和1两个分类,βp\beta_pβp为在除xpx_pxp之外的其他变量均不变的情况下,类别1相对类别0风险率是exp(βp)exp(\beta_p)exp(βp)倍。
总体来说,对于影响因子的解读可以分为以下三类:
- β>0\beta>0β>0,风险率随xxx增大而增大,为危险因素。
- β<0\beta<0β<0,风险率随xxx增大而减小,为保护因素。
- β=0\beta=0β=0,风险率不随xxx变化,为无关因素。
这样一来我们便得到了因子的分类,危险因素会加速客户流失,保护因素会减缓客户流失:
3.2 模型校准
校准?总结起来就是模型结果预测概率和真实的经验概率保持一致。
模型校准就是要让模型结果预测概率和真实的经验概率保持一致。说人话也就是,在一个二分类任务中取出大量(M个)模型预测概率为0.6的样本,其中有0.6M个样本真实的标签是1。总结一下,就是模型在预测的时候说某一个样本的概率为0.6,这个样本就真的有0.6的概率是标签为1。
上面是一个正面的例子,下面我再来举一个反面的例子说明模型校准的重要性。还是在一个二分类任务中取出大量(M个)模型预测概率为0.6的样本,而这些样本的真实标签全部都是1。虽然从accuracy的角度来考察,模型预测样本概率为0.6最后输出时会被赋予的标签就是1,即accuracy是100%。但是从置信度的角度来考察,这个模型明显不够自信,本来这些全部都是标签为1的样本,我们肯定希望这个模型自信一点,输出预测概率的时候也是1。
下面我们以训练的模型与之前分割出的测试集做校准分析:
from lifelines.calibration import survival_probability_calibration
fig,ax = plt.subplots(figsize=(12,9))
survival_probability_calibration(cph, test[selected+['tenure','Churn']], t0=40, ax=ax)
ax.grid()
横坐标为预测的事件发生率(Predicted risk),纵坐标是观察到的实际事件发生率(Observed
risk),范围均为0到1,可以理解为事件发生率(百分比)。对角线的虚线是参考线,即预测值=实际值的情况,红线是曲线拟合线。
- 如果预测值=观察值,则红线与参考线完全重合。
- 如果预测值>观察值,即高估了风险,则红线在参考线下面。
- 如果预测值<观察值,即低估了风险,则红线在参考线上面。
以时长<=40为例,我们的图形十分接近对角线,整体来说是一个不错的校准。前8个月风险估计比较准确,8个月后风险被低估。
3.3 对个体进行预测
对测试集的一些个体进行预测,并绘制生存线,数字代表样本序号。
surv_hat=cph.predict_survival_function(test[selected].reset_index())
fig,ax=plt.subplots(figsize=(12,9))
for i in (5,10,50,100,150,200,500,1000):surv_hat[i].plot(label=str(i))
plt.legend()
plt.show()
3.3 用户流失预测
半衰期也可以称为中位生存时间。由于删失的存在,无法以平均时间反应时间发生的时间水平,因此生存分析在描述生存时一般以半衰期,也就是存活概率50%时对应消耗的时间来表述。
下面以个体半衰期作为预测生存时间,得到各个时间结点流失的用户占比。
def count_existing_users(df,timecut):s=[]for i in timecut:l=df.iloc[i,:]s.append(len(l[l<0.5])/len(l))result=pd.DataFrame({'Month':timecut,'Lost Users Ratio':s})return result
count_existing_users(surv_hat,[10*i for i in range(8)])
4.总结
我们分别利用Cox比例风险回归模型比较了不同特征对于客户流失的影响,并且预测了个体客户的生存时长,计算了各时间点用户流失的比例,结果具有一定的参考性。
python数据分析实战:生存分析与电信用户流失预测相关推荐
- 基于python的电信用户流失预测
题目: 电信用户流失预测 <大数据分析与应用> 一.介绍项目背景与分析目标 电信用户流失预测是一种针对电信运营商的数据挖掘应用,目的是通过分析历史的客户使用数据,预测未来的客户流失情况.其 ...
- 电信用户流失预测案例(1)
[Kaggle]Telco Customer Churn 电信用户流失预测案例 前言:案例学习说明与案例建模流程 在学习了经典机器学习算法和Scikit-Learn的调参策略之后,接下来,我们将把 ...
- 电信用户流失预测案例(2)(特征工程)
[Kaggle]Telco Customer Churn 电信用户流失预测案例 第二部分导读 在上一部分中,我们已经完成了对数据集背景解读.数据预处理与探索性分析.在数据背景解读中,我们介绍了数据 ...
- Python数据分析高薪实战第十二天 网络服务用户流失预测分析和国产电视剧评分预测分析
29 综合实战:网络服务用户流失预测与分析 绝大多数互联网公司都面临一个非常重要的问题:用户流失问题.随着互联网和移动互联网的充分发展,发展新用户(也就是一般所说的拉新)的成本越来越高,往往要几块或者 ...
- 电信用户流失预测案例(3)
三.逻辑回归模型训练与结果解释 在完成数据重编码后,接下来即可进行模型训练了,此处我们首先考虑构建可解释性较强的逻辑回归与决策树模型,并围绕最终模型输出结果进行结果解读,而在下一节,我们将继续介绍 ...
- 电信行业用户流失预测——你的用户会流失吗?
博客目的 随着通信技术的飞速发展,通信用户数量的急剧增加,通信市场趋于饱和,运营商之间的竞争愈演愈烈,使得运营商更加关注用户资源流失的问题.通过使用用户产生的数据预测潜在的流失用户,并对这些潜在的流失 ...
- 【数据分析与挖掘实战】电信用户流失分析与预测
背景 关于用户留存有这样一个观点,如果将用户流失率降低5%,公司利润将提升25%-85%.如今高居不下的获客成本让电信运营商遭遇"天花板",甚至陷入获客难的窘境.随着市场饱和度上升 ...
- Python数据分析实战:上海二手房价分析
1 数据搜集 使用 urllib 库中的request 模块爬取赶集网发布的上海二手房信息,包括包括户型.面积.单价等,再使用BeautifulSoup 库解析爬取的HTML数据,最终将数据保存到CS ...
- 【Python机器学习】决策树、逻辑回归、神经网络等模型对电信用户流失分类实战(附源码和数据集)
需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 电信用户流失分类 该实例数据来自kaggle,它的每一条数据为一个用户的信息,共有21个有效字段,其中最后一个字段Churn标志该用户是否流失 1 ...
最新文章
- Grafana常用的监控
- java string 反序列化_如何将java.lang.String的空白JSON字符串值反序列化为null?
- kuka机器人if逻辑编程_【视频】说说工业机器人控制与PLC通讯
- CISCO ACL配置全解
- 《王者荣耀》回应故障:3个工作日内补发排位赛星积分丢失
- Java 压缩解压缩 第三方组件,推荐一个强大的Java开发工具类库!
- 国家开放大学英语和计算机考试答案,最新电大国家开放大学《人文英语》网络核心课形考网考作业试题及答案...
- java 分词搜索_基于JAVA的小型中文分词系统
- sql盲注 解决_sql盲注解决方案.docx
- k2pbreed刷高恪教程_从breed一键刷机工作
- php令牌桶,令牌桶限频(TokenBucket)
- 面试技巧-面试官的考题
- 企业财务管理中的数据分析应用
- 2022年天猫女王节的优惠力度比肩618年中大促购物节
- 什么是人工智能,它是如何使用的?
- 【阿朱洞察】中国大数据行业的下一步走向
- 苹果套路直播计算机隐藏版,套路计算器app,套路计算器隐藏官网版app预约 v1.0 - 浏览器家园...
- GameframeWork框架—学习笔记
- 函数中参数的调用*args **kwargs
- 综述论文要写英文摘要吗_英文论文的写作讲解 写好英文论文要注意这三点