我是靠谱客的博主 幸福眼神,最近开发中收集的这篇文章主要介绍电信客户流失预测,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

案例 电信客户流失预测

  • 案例简介

    • AT&T数据,用户个人,通话,上网等信息数据

    • 充分利用数据预测客户的流失情况

    • 帮助挽留用户,保证用户基数和活跃程度

  • 数据说明

    • CustomerID 客户ID

    • Gender 性别

    • partneratt 配偶是否也为att用户

    • dependents_att 家人是否也是att用户

    • landline 是否使用att固话服务

    • internet_att/internet_other 是否使用att的互联网服务

    • Paymentbank/creditcard/electroinc 付款方式

    • MonthlyCharges 每月话费

    • TotalCharges 累计话费

    • Contract_month/1year 用户使用月度/年度合约

    • StreamingTv/streamingMovies 是否使用在线视频或者电影app

    • Churn 客户转化的flag

  • 处理流程

    • 分析流程:数据概况分析->单变量分析->相关性分析与可视化->回归模型

      • 数据概况分析

        • 数据行/列数量

        • 缺失值分布

      • 单变量分析

        • 数字型变量的描述指标(平均值,最大最小值,标准差)

        • 类别型变量(多少个分类,各自占比)

        • 正负样本占比

      • 相关性分析与可视化

        • 按类别交叉对比

        • 变量之间的相关性分析

        • 散点图/热力图

      • 逻辑回归分析

                        》 模型建立

                        》模型评估与优化 

代码

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline 
churn=pd.read_csv('churn.csv')
churn.info()
#显示结果
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7043 entries, 0 to 7042
Data columns (total 16 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   Churn              7043 non-null   object 
 1   gender             7043 non-null   object 
 2   Partner_att        7043 non-null   int64  
 3   Dependents_att     7043 non-null   int64  
 4   landline           7043 non-null   int64  
 5   internet_att       7043 non-null   int64  
 6   internet_other     7043 non-null   int64  
 7   StreamingTV        7043 non-null   int64  
 8   StreamingMovies    7043 non-null   int64  
 9   Contract_Month     7043 non-null   int64  
 10  Contract_1YR       7043 non-null   int64  
 11  PaymentBank        7043 non-null   int64  
 12  PaymentCreditcard  7043 non-null   int64  
 13  PaymentElectronic  7043 non-null   int64  
 14  MonthlyCharges     7043 non-null   float64
 15  TotalCharges       7043 non-null   float64
dtypes: float64(2), int64(12), object(2)
memory usage: 880.5+ KB
#预测目标是churn,是类别型变量  gender也是类别型变量 需要对类别型变量进行处理

churn.head()
#显示结果
 ChurngenderPartner_attDependents_attlandlineinternet_attinternet_otherStreamingTVStreamingMoviesContract_MonthContract_1YRPaymentBankPaymentCreditcardPaymentElectronicMonthlyChargesTotalCharges
0NoFemale10010001000129.8529.85
1NoMale00110000100056.951889.50
2YesMale00110001000053.85108.15
3NoMale00010000110042.301840.75
4YesFemale00101001000170.70151.65
churn.describe()
#显示结果
 Partner_attDependents_attlandlineinternet_attinternet_otherStreamingTVStreamingMoviesContract_MonthContract_1YRPaymentBankPaymentCreditcardPaymentElectronicMonthlyChargesTotalCharges
count7043.0000007043.0000007043.0000007043.0000007043.0000007043.0000007043.0000007043.0000007043.0000007043.0000007043.0000007043.0000007043.0000007043.000000
mean0.4830330.2995880.9031660.3437460.4395850.3843530.3879030.5501920.2091440.2192250.2161010.33579464.7616922275.929881
std0.4997480.4581100.2957520.4749910.4963720.4864770.4873070.4975100.4067260.4137510.4116130.47230130.0900472266.920469
min0.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.00000018.25000018.800000
25%0.0000000.0000001.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.00000035.500000392.575000
50%0.0000000.0000001.0000000.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000000.00000070.3500001389.850000
75%1.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000000.0000000.0000000.0000001.00000089.8500003778.525000
max1.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.000000118.7500008684.800000
#需要把churn和gender转变为数字型变量,使用get_dummies
churn=pd.get_dummies(churn)
 Partner_attDependents_attlandlineinternet_attinternet_otherStreamingTVStreamingMoviesContract_MonthContract_1YRPaymentBankPaymentCreditcardPaymentElectronicMonthlyChargesTotalChargesChurn_NoChurn_Yesgender_Femalegender_Male
010010001000129.8529.851010
100110000100056.951889.501001
200110001000053.85108.150101
300010000110042.301840.751001
400101001000170.70151.650110
.........................................................
703811110110100084.801990.501001
7039111011101010103.207362.901010
704011010001000129.60346.451010
704110101001000074.40306.600101
7042001011100100105.656844.501001

7043 rows × 18 columns

#数据整理,将churn_yes保留,将female保留,drop不需要的数据
churn.drop(['Churn_No','gender_Male'],axis=1,inplace=True)
#churn_No。churn_Yes留一个即可,任何一个都可表达数值,本案例讲的是从训练数据中得出是否流失,churn_Yes中的1代表流失,0代表没有。
#留下gender_female,此时的1为女,0为难。需要在下面修改变量命名

churn
#显示结果
Partner_attDependents_attlandlineinternet_attinternet_otherStreamingTVStreamingMoviesContract_MonthContract_1YRPaymentBankPaymentCreditcardPaymentElectronicMonthlyChargesTotalChargesChurn_Yesgender_Female
010010001000129.8529.8501
100110000100056.951889.5000
200110001000053.85108.1510
300010000110042.301840.7500
400101001000170.70151.6511
...................................................
703811110110100084.801990.5000
7039111011101010103.207362.9001
704011010001000129.60346.4501
704110101001000074.40306.6010
7042001011100100105.656844.5000

7043 rows × 16 columns

#变量大小写不规则,统一变成小写
churn.columns=churn.columns.str.lower()  #把所有的列名改为小写
churn.columns
#显示结果
Index(['partner_att', 'dependents_att', 'landline', 'internet_att',
       'internet_other', 'streamingtv', 'streamingmovies', 'contract_month',
       'contract_1yr', 'paymentbank', 'paymentcreditcard', 'paymentelectronic',
       'monthlycharges', 'totalcharges', 'churn_yes', 'gender_female'],
      dtype='object')
#将churn_yes重命名,方便后续的变量编写,修改列名,传入columns={"要被修改的列名";‘修改后的列名’}
churn=churn.rename(columns={'churn_yes':'flag'})
churn=churn.rename(columns={'gender_female':'gender'})

churn
#显示结果;此时列名已经改变。
 partner_attdependents_attlandlineinternet_attinternet_otherstreamingtvstreamingmoviescontract_monthcontract_1yrpaymentbankpaymentcreditcardpaymentelectronicmonthlychargestotalchargesflaggender
010010001000129.8529.8501
100110000100056.951889.5000
200110001000053.85108.1510
300010000110042.301840.7500
400101001000170.70151.6511
...................................................
703811110110100084.801990.5000
7039111011101010103.207362.9001
704011010001000129.60346.4501
704110101001000074.40306.6010
7042001011100100105.656844.5000

7043 rows × 16 columns

#二分类模型,查看样本分布情况,分析flag 1和0的占比
churn.flag.value_counts() #流失共有1869个,未流失5174个
#显示结果
0    5174
1    1869
Name: flag, dtype: int64

#大多数是未流失用户,流失用户占26.5%
churn.flag.value_counts(normalize=True)
#显示结果
0    0.73463
1    0.26537
Name: flag, dtype: float64

#churn.flag.value_counts(1)  #value_counts(1) 查看比例 
#等同churn.flag.value_counts(normalize=True)
#value_counts()  把每個值分別有多少展示一下.在 python 当中 除了 0 其他數字都是 true。所以在这里,括号里可以用任何数字表示。
summary=churn.groupby('flag') 
summary.mean()           #按流失率求各个部门占比,这几个数据流失比较明显 ~~~ internet_other	contract_month  paymentelectronic
#显示结果
 partner_attdependents_attlandlineinternet_attinternet_otherstreamingtvstreamingmoviescontract_monthcontract_1yrpaymentbankpaymentcreditcardpaymentelectronicmonthlychargestotalchargesgender
flag               
00.5282180.3448010.9010440.3792040.3477000.3658680.3699270.4290680.2526090.2485500.2493240.25009761.2651242545.9180810.492656
10.3579450.1744250.9090420.2455860.6939540.4355270.4376670.8855000.0888180.1380420.1241310.57303474.4413321528.5147140.502408

结论:观察flag在0和1的情况下,所有自变量的差别 internet_other变量,在0的分组中,均值是0.35,在1的分组中,均值是0.69。数据显示如果使用别的公司的互联网,用户流失的概率就越高(拿0.35跟0.69对比,流失的数据占了没流失的近2倍。)

sns.countplot(y='contract_month',hue='flag',data=churn) #hue目标值是什么target
<matplotlib.axes._subplots.AxesSubplot at 0x232eef53fd0>

结论:contract_month为1的客户流失的概率更高,即与非按月付费客户相比,按月付费客户流失比例高

#围绕flag变量,分析其他变量与flag的相关关系;ascending=False降序
churn.corr()[['flag']].sort_values('flag',ascending=False)

#显示结果
 flag
flag1.000000
contract_month0.405103
internet_other0.308020
paymentelectronic0.301919
monthlycharges0.193356
streamingtv0.063228
streamingmovies0.061382
landline0.011942
gender0.008612
paymentbank-0.117937
internet_att-0.124214
paymentcreditcard-0.134302
partner_att-0.150448
dependents_att-0.164221
contract_1yr-0.177820
totalcharges-0.198175

结论:contract_month,internet_other,paymentelectronic与flag相关性高。

逻辑回归模型,

选择不同的数据进行建模,以下是对模型测试,并进行不断优化。

第一次,随机选取可用x数据

#设定因变量与自变量, y是 flag, x根据刚才的相关分析挑选contract_month,internet_other与streamingtv
#自变量可以分为几类,partner/dependents,internet,streaming,contract,payment,charges,后续可以自己挑选进行建模
#确定目标值和特征值
y=churn['flag']
x=churn[['contract_month','internet_other','streamingtv']]

#调用sklearn模块,随机抽取训练集与测试集
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3,random_state=100)

#使用LR预测
from sklearn import linear_model
lr=linear_model.LogisticRegression()
lr.fit(x_train,y_train)
#LogisticRegression()

lr.intercept_
#array([-3.25029156])

lr.coef_
#array([[2.2229613 , 1.15089043, 0.24559832]])

模型的评估
y_pred_train=lr.predict(x_train)
y_pred_test=lr.predict(x_test)
import sklearn.metrics as metrics
metrics.accuracy_score(y_train,y_pred_train)
#0.7697768762677485

metrics.accuracy_score(y_test,y_pred_test)
#0.7453857075248462

from sklearn.metrics import roc_curve,auc
fpr,tpr,threshold=roc_curve(y_train,y_pred_train)
roc_auc=auc(fpr,tpr)
roc_auc
#0.7247770357096229

第二次,将是否使用在线视频 改为电子支付 测试对数据的影响

#设定因变量与自变量, y是 flag, x经过模型优化改变为contract_month,internet_other,将streamingtv调整为paymentelectronic
y=churn['flag']
x=churn[['contract_month','internet_other','paymentelectronic']]

#调用sklearn模块,随机抽取训练集与测试集
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3,random_state=100)

#使用LR预测
from sklearn import linear_model
lr=linear_model.LogisticRegression()
lr.fit(x_train,y_train)
#LogisticRegression()

lr.intercept_
#array([-3.21842661])

lr.coef_
#array([[2.01264249, 1.05076404, 0.64248053]])

#模型的评估
y_pred_train=lr.predict(x_train)
y_pred_test=lr.predict(x_test)
import sklearn.metrics as metrics
metrics.accuracy_score(y_train,y_pred_train)
#0.7776876267748478
metrics.accuracy_score(y_test,y_pred_test)
#0.7624230951254141

from sklearn.metrics import roc_curve,auc
fpr,tpr,threshold=roc_curve(y_train,y_pred_train)
roc_auc=auc(fpr,tpr)
roc_auc
#0.6669635362478181

第三次,改变测试集和训练集的分布

#模型优化,测试集与训练集对半分.
y=churn['flag']
x=churn[['contract_month','internet_other','paymentelectronic']]

#调用sklearn模块,随机抽取训练集与测试集
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.5,random_state=100)

#使用LR预测
from sklearn import linear_model
lr=linear_model.LogisticRegression()
lr.fit(x_train,y_train)
#LogisticRegression()

lr.intercept_
#array([-3.22833942])

lr.coef_
#array([[2.03292538, 1.04095427, 0.62567014]])

#模型的评估
y_pred_train=lr.predict(x_train)
y_pred_test=lr.predict(x_test)
import sklearn.metrics as metrics
metrics.accuracy_score(y_train,y_pred_train)
#0.7779040045441636
metrics.accuracy_score(y_test,y_pred_test)
#0.768313458262351

from sklearn.metrics import roc_curve,auc
fpr,tpr,threshold=roc_curve(y_train,y_pred_train)
roc_auc=auc(fpr,tpr)
roc_auc
#0.666251219518281

结论:auc 的选择如果为0.5-1是推荐的。 风控0.6, 0.7, 0.8,很少有超过0.85的情况.(零点六几基本就可以用了,所以这里的数据为有效数据)

AUC的物理意义为任取一对例和负例,正例得分大于负例得分的概率,AUC越大,表明方法效果越好

电信客户流失预测:系数1*特征1+系数2*特征2+系数3*特征3.。。。=流失概率

 

1,要针对沉默会员做会员重新激活,应该挑选具有什么特征的会员?

     按月付费的流失率比较高,想办法让用户办按年付费的套餐,可以给按月付费的老用户发广告,老用户回馈,充值返现。满减优惠。

2,商品A库存积压严重,现在要通过促销活动清仓,选择哪些类型的促销活动更容易实现该目标?

     根据类别找到更感兴趣的用户。不断换用户特征,测试出一批用户后,找出更可能买的用户特征。哪些用户更可能买。

3,网站需要大流量广告位来满足VIP商家的精准广告投放,具有哪些特征的广告位更符合VIP商家的客户需求?

     测试出的这一批用户,可以反过来看下用户所拥有的特征。

最后

以上就是幸福眼神为你收集整理的电信客户流失预测的全部内容,希望文章能够帮你解决电信客户流失预测所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部