python 数据分析 电信_实例 | 教你用Python写一个电信客户流失预测模型

原标题:实例 | 教你用Python写一个电信客户流失预测模型

8de7e531747745fdbda002e1bc49413d.jpeg

CDA数据分析师 出品

作者:真达、Mika

数据:真达

【导读】

今天教大家如何用Python写一个电信用户流失预测模型。公众号后台,回复关键字“电信”获取完整数据。

之前我们用Python写了员工流失预测模型,这次我们试试Python预测电信用户的流失。

👇👇👇员工一言不合就离职怎么办?我用Python写了个员工流失预测模型

01

532c3ce3c1c34d148700f54727fe59ac.gif

商业理解

流失客户是指那些曾经使用过产品或服务,由于对产品失去兴趣等种种原因,不再使用产品或服务的顾客。

电信服务公司、互联网服务提供商、保险公司等经常使用客户流失分析和客户流失率作为他们的关键业务指标之一,因为留住一个老客户的成本远远低于获得一个新客户。

预测分析使用客户流失预测模型,通过评估客户流失的风险倾向来预测客户流失。由于这些模型生成了一个流失概率排序名单,对于潜在的高概率流失客户,他们可以有效地实施客户保留营销计划。

下面我们就教你如何用Python写一个电信用户流失预测模型,以下是具体步骤和关键代码。

02

9e949ad3a64c4153ac26d2c8325a75e6.gif

数据理解

此次分析数据来自于IBM Sample Data Sets,统计自某电信公司一段时间内的消费数据。共有7043笔客户资料,每笔客户资料包含21个字段,其中1个客户ID字段,19个输入字段及1个目标字段-Churn(Yes代表流失,No代表未流失),输入字段主要包含以下三个维度指标:用户画像指标、消费产品指标、消费信息指标。字段的具体说明如下:

42fc94c6126f47cf8ab3be3a8d6798a5.png

回复关键字“电信”

获取本期详细数据和代码

03

数据读入和概览

首先导入所需包。

# 数据处理

importnumpy asnp

importpandas aspd

# 可视化

importmatplotlib.pyplot asplt

importseaborn assns

importplotly aspy

importplotly.graph_objs asgo

importplotly.figure_factory asff

# 前处理

fromsklearn.preprocessing importLabelEncoder

fromsklearn.preprocessing importStandardScaler

# 建模

fromsklearn.linear_model importLogisticRegression

fromsklearn.neighbors importKNeighborsClassifier

fromsklearn.tree importDecisionTreeClassifier

fromsklearn importtree

fromsklearn.ensemble importRandomForestClassifier

fromsklearn.naive_bayes importGaussianNB

fromsklearn.neural_network importMLPClassifier

fromsklearn.svm importSVC

fromlightgbm importLGBMClassifier

fromxgboost importXGBClassifier

# 模型评估

fromsklearn.model_selection importtrain_test_split, GridSearchCV

fromsklearn.metrics importconfusion_matrix, accuracy_score, classification_report

fromsklearn.metrics importroc_auc_score, roc_curve, scorer

fromsklearn.metrics importrecall_score, precision_score, f1_score, cohen_kappa_score

pd.set_option( 'display.max_columns', None)

读入数据集

df = pd.read_csv('./Telco-Customer-Churn.csv')

df.head

f73072898197490586b8d31a56727210.png

04

数据初步清洗

首先进行初步的数据清洗工作,包含错误值和异常值处理,并划分类别型和数值型字段类型,其中清洗部分包含:

OnlineSecurity、OnlineBackup、DeviceProtection、TechSupport、StreamingTV、StreamingMovies:错误值处理

TotalCharges:异常值处理

tenure:自定义分箱

定义类别型和数值型字段

# 错误值处理

repl_columns = [ 'OnlineSecurity', 'OnlineBackup', 'DeviceProtection',

'TechSupport', 'StreamingTV', 'StreamingMovies']

fori inrepl_columns:

df[i] = df[i].replace({ 'No internet service': 'No'})

# 替换值SeniorCitizen

df[ "SeniorCitizen"] = df[ "SeniorCitizen"].replace({ 1: "Yes", 0: "No"})

# 替换值TotalCharges

df[ 'TotalCharges'] = df[ 'TotalCharges'].replace( ' ', np.nan)

# TotalCharges空值:数据量小,直接删除

df = df.dropna(subset=[ 'TotalCharges'])

df.reset_index(drop= True, inplace= True) # 重置索引

# 转换数据类型

df[ 'TotalCharges'] = df[ 'TotalCharges'].astype( 'float')

# 转换tenure

deftransform_tenure(x):

ifx <= 12:

return'Tenure_1'

elifx <= 24:

return'Tenure_2'

elifx <= 36:

return'Tenure_3'

elifx <= 48:

return'Tenure_4'

elifx <= 60:

return'Tenure_5'

else:

return'Tenure_over_5'

df[ 'tenure_group'] = df.tenure.apply(transform_tenure)

# 数值型和类别型字段

Id_col = [ 'customerID']

target_col = [ 'Churn']

cat_cols = df.nunique[df.nunique < 10].index.tolist

num_cols = [i fori indf.columns ifi notincat_cols + Id_col]

print( '类别型字段:n', cat_cols)

print( '-'* 30)

print( '数值型字段:n', num_cols)

类别型字段:

[ 'gender', 'SeniorCitizen', 'Partner', 'Dependents', 'PhoneService', 'MultipleLines', 'InternetService', 'OnlineSecurity', 'OnlineBackup', 'DeviceProtection', 'TechSupport', 'StreamingTV', 'StreamingMovies', 'Contract', 'PaperlessBilling', 'PaymentMethod', 'Churn', 'tenure_group']

------------------------------

数值型字段:

[ 'tenure', 'MonthlyCharges', 'TotalCharges']

05

探索性分析

对指标进行归纳梳理,分用户画像指标,消费产品指标,消费信息指标。探索影响用户流失的关键因素。

1. 目标变量Churn分布

d88aff82b70942c193c475749a83f6ed.png

经过初步清洗之后的数据集大小为7032条记录,其中流失客户为1869条,占比26.6%,未流失客户占比73.4%。

df['Churn'].value_counts

No5163

Yes1869

Name: Churn, dtype: int64

trace0 = go.Pie(labels=df[ 'Churn'].value_counts.index,

values=df[ 'Churn'].value_counts.values,

hole= .5,

rotation= 90,

marker=dict(colors=[ 'rgb(154,203,228)', 'rgb(191,76,81)'],

line=dict(color= 'white', width= 1.3))

)

data = [trace0]

layout = go.Layout(title= '目标变量Churn分布')

fig = go.Figure(data=data, layout=layout)

py.offline.plot(fig, filename= './html/整体流失情况分布.html')

2.性别

392e4f85dc7d4c82bc94f4631e9e03a2.png

分析可见,男性和女性在客户流失比例上没有显著差异。

plot_bar(input_col= 'gender', target_col= 'Churn', title_name= '性别与是否流失的关系')

3. 老年用户

3d08674de9824113b79c0a6bfb34698a.png

老年用户流失比例更高,为41.68%,比非老年用户高近两倍,此部分原因有待进一步探讨。

plot_bar(input_col= 'SeniorCitizen', target_col= 'Churn', title_name= '老年用户与是否流失的关系')

4. 是否有配偶

2635715d9d5c49c4b9758d24f55f9ca0.png

从婚姻情况来看,数据显示,未婚人群中流失的比例比已婚人数高出13%。

plot_bar(input_col= 'Partner', target_col= 'Churn', title_name= '是否有配偶与是否流失的关系')

5. 上网时长

5c97208fabef44ec8313dde594deb068.png

经过分析,这方面可以得出两个结论:

用户的在网时长越长,表示用户的忠诚度越高,其流失的概率越低;

新用户在1年内的流失率显著高于整体流失率,为47.68%。

plot_bar(input_col= 'tenure_group', target_col= 'Churn', title_name= '在网时长与是否流失的关系')

6. 付款方式

867d66443d4b4f2ea7f06074f2d988e2.png

支付方式上,支付上,选择电子支票支付方式的用户流失最高,达到45.29%,其他三种支付方式的流失率相差不大。

pd.crosstab( df['PaymentMethod'], df['Churn'])

8cc402d48bbb415b9a020424cc61900d.png

plot_bar(input_col= 'PaymentMethod', target_col= 'Churn', title_name= '付款方式与是否流失关系')

7. 月费用

437a58bdf6ab4befbadd93449b8fed2f.png

整体来看,随着月费用的增加,流失用户的比例呈现高高低低的变化,月消费80-100元的用户相对较高。

plot_histogram(input_col= 'MonthlyCharges', title_name= '月费用与是否流失关系')

8. 数值型属性相关性

ef1bc812c41a49869cdc9bce7f4de135.png

从相关性矩阵图可以看出,用户的往来期间和总费用呈现高度相关,往来期间越长,则总费用越高。月消费和总消费呈现显著相关。

plt.figure(figsize=( 15, 10))

sns.heatmap(df.corr, linewidths= 0.1, cmap= 'tab20c_r', annot= True)

plt.title( '数值型属性的相关性', fontdict={ 'fontsize': 'xx-large', 'fontweight': 'heavy'})

plt.xticks(fontsize= 12)

plt.yticks(fontsize= 12)

plt.show

06

特征选择

使用统计检定方式进行特征筛选。

# 删除tenure

df = df.drop('tenure', axis=1)

from feature_selection import Feature_select

# 划分X和y

X = df.drop(['customerID', 'Churn'], axis=1)

y = df['Churn']

fs = Feature_select(num_method='anova', cate_method='kf', pos_label='Yes')

x_sel = fs.fit_transform(X, y)

2020 09:30:02 INFO attr selectsuccess!

Afterselectattr: [ 'DeviceProtection', 'MultipleLines', 'OnlineSecurity', 'TechSupport', 'tenure_group', 'PaperlessBilling', 'InternetService', 'PaymentMethod', 'SeniorCitizen', 'MonthlyCharges', 'Dependents', 'Partner', 'Contract', 'StreamingTV', 'TotalCharges', 'StreamingMovies', 'OnlineBackup']

经过特征筛选,gender和PhoneService字段被去掉。

07

建模前处理

在python中,为满足建模需要,一般需要对数据做以下处理:

对于二分类变量,编码为0和1;

对于多分类变量,进行one_hot编码;

对于数值型变量,部分模型如KNN、神经网络、Logistic需要进行标准化处理。

# 筛选变量

select_features = x_sel.columns

# 建模数据

df_model = pd.concat([df['customerID'], df[select_features], df['Churn']], axis=1)

Id_col = ['customerID']

target_col = ['Churn']

# 分类型

cat_cols = df_model.nunique[df_model.nunique < 10].index.tolist

# 二分类属性

binary_cols = df_model.nunique[df_model.nunique == 2].index.tolist

# 多分类属性

multi_cols = [i for i in cat_cols if i not in binary_cols]

# 数值型

num_cols = [i for i in df_model.columns if i not in cat_cols + Id_col]

# 二分类-标签编码

le = LabelEncoder

for i in binary_cols:

df_model[i] = le.fit_transform(df_model[i])

# 多分类-哑变量转换

df_model = pd.get_dummies(data=df_model, columns=multi_cols)

df_model.head

aab68371210249d7b783bb2ea41745a8.png

08

模型建立和评估

首先使用分层抽样的方式将数据划分训练集和测试集。

# 重新划分

X = df_model.drop([ 'customerID', 'Churn'], axis=1)

y = df_model[ 'Churn']

# 分层抽样

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0, stratify=y)

print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

#修正索引

fori in[X_train, X_test, y_train, y_test]:

i.index = range(i.shape[0])

(5625, 31) (1407, 31) (5625,) (1407,)

# 保存标准化训练和测试数据

st= StandardScaler

num_scaled_train= pd.DataFrame(st.fit_transform(X_train[num_cols]), columns=num_cols)

num_scaled_test= pd.DataFrame(st.transform(X_test[num_cols]), columns=num_cols)

X_train_sclaed= pd.concat([X_train.drop(num_cols, axis= 1), num_scaled_train], axis= 1)

X_test_sclaed= pd.concat([X_test.drop(num_cols, axis= 1), num_scaled_test], axis= 1)

然后建立一系列基准模型并比较效果。

c7ba51c831c6451e9c2c69ffb0c6d873.png

假如我们关注roc指标,从模型表现效果来看,Naive Bayes效果最好。

我们也可以对模型进行进一步优化,比如对决策树参数进行调优。

parameters = { 'splitter': ( 'best', 'random'),

'criterion': ( "gini", "entropy"),

"max_depth": [* range( 3, 20)],

}

clf = DecisionTreeClassifier(random_state= 25)

GS = GridSearchCV(clf, parameters, scoring= 'f1', cv= 10)

GS.fit(X_train, y_train)

print(GS.best_params_)

print(GS.best_score_)

{ 'criterion': 'entropy', 'max_depth': 5, 'splitter': 'best'}

0.585900839405024

clf = GS.best_estimator_

test_pred = clf.predict(X_test)

print('测试集:n', classification_report(y_test, test_pred))

测试集:

precisionrecallf1-scoresupport

0 0 .860 .860 .861033

1 0 .610 .610 .61374

accuracy0 .791407

macroavg0 .730 .730 .731407

weightedavg0 .790 .790 .791407

将这颗树绘制出来。

importgraphviz

dot_data = tree.export_graphviz(decision_tree=clf, max_depth= 3,

out_file= None,

feature_names=X_train.columns,

class_names=[ 'not_churn', 'churn'],

filled= True,

rounded= True

)

graph = graphviz.Source(dot_data)

c684549a0435463dad31b5fb31d417ce.png

输出决策树属性重要性排序:

imp = pd.DataFrame(zip(X_train.columns, clf.feature_importances_))

imp.columns = ['feature', 'importances']

imp = imp.sort_values('importances', ascending=False)

imp = imp[imp['importances'] != 0]

table = ff.create_table(np.round(imp, 4))

py.offline.iplot(table)

a2509a4563df438782a864d715323cba.png

后续优化方向:

数据:分类技术应用在目标类别分布越均匀的数据集时,其所建立之分类器通常会有比较好的分类效能。针对数据在目标字段上分布不平衡,可采用过采样和欠采样来处理类别不平衡问题;

属性:进一步属性筛选方法和属性组合;

算法:参数调优;调整预测门槛值来增加预测效能。

关注CDA数据分析师公众号

回复关键字“电信”

获取详细数据代码

CDA数据分析师

本文出品:CDA数据分析师(ID: cdacdacda)返回搜狐,查看更多

责任编辑:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/488537.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人机融合智能与深度态势感知

来源&#xff1a;人机与认知实验室【“常无欲以观其妙&#xff0c;常有欲以观其徼。”&#xff0c;意思是身处物外可以以旁观者的身份来看待事物&#xff0c;身处事内则要考虑各种极限。】0 引言伴随着深度学习[1]、强化学习[2]等新一代人工智能技术的发展&#xff0c;智能化已…

java大数模板_java大数模板

这几天做了几道用大数的题&#xff0c;发现java来做大数运算十分方便。对acmer来说是十分实用的1.valueOf(parament); 将参数转换为制定的类型比如 int a3;BigInteger bBigInteger.valueOf(a);则b3;String s”12345”;BigInteger cBigInteger.valueOf(s);则c12345&#xff1b;2…

20162317 2016-2017-2 《程序设计与数据结构》第8周学习总结

20162317 2016-2017-2 《程序设计与数据结构》第8周学习总结 教材学习内容总结 1.异常的定义&#xff08;中断正常指令的事件&#xff09; 2.异常的特点&#xff08;异常是对象&#xff09; 3.异常的分类&#xff08;CheckedExcception 和 UncheckedException&#xff09; 4.异…

sql return的用法_【实用技能】Seacms 8.7版本SQL注入分析

有些小伙伴刚刚接触SQL编程&#xff0c;对SQL注入表示不太了解。其实在Web攻防中&#xff0c;SQL注入就是一个技能繁杂项&#xff0c;为了帮助大家能更好的理解和掌握&#xff0c;今天小编将要跟大家分享一下关于Seacms 8.7版本SQL注入分析的内容&#xff0c;一定要认真学习哦。…

国科大UCAS胡包钢教授《信息论与机器学习》课程第二讲:信息论基础一

来源&#xff1a;专知信息论中最为基本的概念就是香农熵&#xff08;第8页&#xff09;&#xff0c;由此可以导出信息论中其它各种定义&#xff0c;以至我们常规应用的其它经验式定义&#xff08;以后会提到&#xff09;。学习信息论基础知识时要避免仅是概念与定义的简单记忆&…

通讯录分组名称大全简单_公司起名取名:建筑公司名称大全简单大气

阅读本文前&#xff0c;请您先点击上面的“蓝色字体”再点击关注&#xff0c;这样您就可以继续免费收取到文章了&#xff0c;每天都有分享&#xff0c;完全是免费订阅&#xff0c;请放心关注。时代在变迁&#xff0c;人们的生活节奏在加快&#xff0c;各类楼盘高低错落&#xf…

美国发布《量子网络战略愿景》

来源&#xff1a;国防科技要闻背景探索如何建立量子网络将促进新兴技术的发展&#xff0c;从而加速当前互联网的发展&#xff0c;提高通信的安全性&#xff0c;并大幅推动计算技术的进步。美国将利用其在量子网络领域的领先地位&#xff0c;加速在国家和金融安全、病人隐私、药…

Jürgen Schmidhuber眼中的深度学习十年,以及下一个十年展望

大数据文摘出品来源&#xff1a;Medium作者&#xff1a;Jrgen Schmidhuber编译&#xff1a;张秋玥、马莉2020年是充满科幻的一年&#xff0c;曾经我们畅想飞行汽车、智能洗碗机器人以及能自动写代码的程序&#xff0c;然而这一切都没有发生。2020迎接我们的是澳洲大火、新冠病毒…

docker pidfile_Zabbix5监控Docker

zabbix_agent配置Zabbix 监控Docker 时 agent 需要使用 zabbix_agent2&#xff0c;而不是zabbix_agent主要模式时配置如下&#xff1a;[rootlocalhost#] cat /etc/zabbix/zabbix_agent2.conf |grep -v ^#|grep -v ^$ PidFile/var/run/zabbix/zabbix_agent2.pidLogFile/var/log…

Gartner:2020 年 AI 平台魔力象限:意外多多

来源&#xff1a;云头条众多企业决策者向市场研究公司Gartner寻求企业软件堆栈方面的建议。魔力象限报告是Gartner发布的最可信、最真实、最权威的研究报告之一。由于它影响企业的采购决策&#xff0c;因此诸多供应商竭力想在报告中占有一席之地。Gartner最近发布了数据科学和机…

CentOS6.9编译安装LNMP环境

CentOS6.9编译安装LNMP环境 今天尝试一下用编译的方式来搭建lnmp运行环境。所有软件都采用当前最新版本&#xff0c;除了CentOS。这是由于目前企业大多数应该都还在使用CentOS6的缘故&#xff0c;并且CentOS7目前还在迭代中。虽说不会有大的改动&#xff0c;但也算不上完全稳定…

生物,AI,心理:目前的大脑/认知/意识/AGI/DRL模型

来源&#xff1a;人工智能前沿讲习一 基于生物和经验的模型首先是 2012 年的 Spaun&#xff0c;基于生物基础&#xff08;脑图谱&#xff09;&#xff0c;类生物神经元&#xff08;尖峰放电 SNN&#xff09;。在训练后可完成多种识别和生成和反应任务。map the visual hierar…

java 使用nullable_Java Stream ofNullable(T)用法及代码示例

如果此流不为null&#xff0c;则ofNullable(T)方法将返回包含单个元素的顺序Stream&#xff0c;否则该方法将返回空Stream。它有助于处理空流和NullPointerException。用法:static Stream ofNullable(T t)参数&#xff1a;此方法接受单个参数t&#xff0c;该参数t是要返回其Str…

python数据标注工具_数据标注工具大全汇总,有了这些工具再也不用自己开发了...

数据标注工具大全汇总&#xff0c;有了这些工具再也不用自己开发了。 做数据标注三年了&#xff0c;总是遇到各种各样的需求&#xff0c;总是想找一款最高效&#xff0c;最快速&#xff0c;最好用的标注工具&#xff0c;最重要的是免费&#xff0c;经过三年的收集&#xff0c;大…

决策智能(Decision Intelligence)二三事

来源&#xff1a;https://www.zhihu.com/people/wang-jing-28-89-94什么是决策智能&#xff1f;大家看到这四个字&#xff0c;大多数人心里的发问会是”什么是决策智能“呢&#xff1f;别说你没想&#xff0c;别骗我了。那么什么是决策智能呢&#xff1f;以下是维基的定义&…

python基础——面向对象的程序设计

python基础——面向对象的程序设计 1 什么是面向对象的程序设计 面向过程的程序设计的核心是过程&#xff0c;过程即解决问题的步骤&#xff0c;面向过程的设计就好比精心设计好一条流水线&#xff0c;考虑周全什么时候处理什么东西。 优点是&#xff1a;极大的降低了程序的复杂…

移动端 h5如何生成快捷方式_削微整理了几个经常在H5移动端开发遇到的东西

不用说我也知道&#xff0c;此类文章太多太多了&#xff0c;常见的譬如&#xff1a;viewport、强制浏览器全屏、IOS的Web APP模式、可点击元素出现阴影&#xff08;这个我觉得真没必要去掉&#xff0c;用户点击是需要反馈的&#xff0c;而这个背景色刚刚好提供了一种反馈&#…

SCI至上只是结果,而不是原因

来源&#xff1a;赵斌科学网博客我从来不认为SCI一无是处&#xff0c;相反&#xff0c;我们大多数科研人员应该感谢它。中国科研评价体系中的的问题&#xff0c;不是破四唯&#xff0c;破SCI至上&#xff0c;而是打破特权、消除歧视。近日&#xff0c;教育部和科技部联合发文&a…

spark mysql 交互_Spark - 直接操作数据源 MySQL

如果我们的Mysql服务器性能不咋滴&#xff0c;但是硬盘很够&#xff0c;如何才能做各种复杂的聚合操作&#xff1f;答案就是使用spark的计算能力的&#xff0c;我们可以将mysql数据源接入到spark中。读取val mysqlDF spark.read.format("jdbc").option("driver…