4 – 电信客户流失预测

1. 数据集介绍

  • 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

2. 处理流程

分析流程:数据概况分析->单变量分析->可视化->逻辑回归模型

数据概况分析

  • 数据行/列数量
  • 缺失值分布

单变量分析

  • 数字型变量的描述指标(平均值,最大最小值,标准差)
  • 类别型变量(多少个分类,各自占比)
  • 正负样本占比

相关性分析与可视化

  • 按类别交叉对比
  • 变量之间的相关性分析
  • 散点图/热力图

逻辑回归分析

  • 模型建立
  • 模型评估与优化

3. 案例实现

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline 
churn=pd.read_csv('data/churn.csv')
churn.info()
  输出结果:
  RangeIndex: 7043 entries, 0 to 7042
  Data columns (total 16 columns):
  Churn                7043 non-null object
  gender               7043 non-null object
  Partner_att          7043 non-null int64
  Dependents_att       7043 non-null int64
  landline             7043 non-null int64
  internet_att         7043 non-null int64
  internet_other       7043 non-null int64
  StreamingTV          7043 non-null int64
  StreamingMovies      7043 non-null int64
  Contract_Month       7043 non-null int64
  Contract_1YR         7043 non-null int64
  PaymentBank          7043 non-null int64
  PaymentCreditcard    7043 non-null int64
  PaymentElectronic    7043 non-null int64
  MonthlyCharges       7043 non-null float64
  TotalCharges         7043 non-null float64
  dtypes: float64(2), int64(12), object(2)
  memory usage: 880.5+ KB
#预测目标是churn,是类别型变量  gender也是类别型变量 需要对类别型变量进行处理
churn.head()
  输出结果:
  Churn  gender  Partner_att  Dependents_att  landline  internet_att  
  0    No  Female            1               0         0             1   
  1    No    Male            0               0         1             1   
  2   Yes    Male            0               0         1             1   
  3    No    Male            0               0         0             1   
  4   Yes  Female            0               0         1             0   

     internet_other  StreamingTV  StreamingMovies  Contract_Month  Contract_1YR  
  0               0            0                0               1             0   
  1               0            0                0               0             1   
  2               0            0                0               1             0   
  3               0            0                0               0             1   
  4               1            0                0               1             0   

     PaymentBank  PaymentCreditcard  PaymentElectronic  MonthlyCharges  
  0            0                  0                  1           29.85   
  1            0                  0                  0           56.95   
  2            0                  0                  0           53.85   
  3            1                  0                  0           42.30   
  4            0                  0                  1           70.70   

     TotalCharges  
  0         29.85  
  1       1889.50  
  2        108.15  
  3       1840.75  
  4        151.65  

需要把churn和gender转变为数字型变量,使用get_dummies

churn=pd.get_dummies(churn)
churn.head()
输出结果:
      Churn_No  Churn_Yes  gender_Female  gender_Male  
  0         1          0              1            0  
  1         1          0              0            1  
  2         0          1              0            1  
  3         1          0              0            1  
  4         0          1              1            0  

数据整理,将churn_yes保留,将female保留,drop不需要的数据

churn.drop(['Churn_No','gender_Male'],axis=1,inplace=True)
#变量大小写不规则,统一变成小写
churn.columns=churn.columns.str.lower()
churn.head()
 输出结果
        churn_yes  gender_female  
  0          0              1  
  1          0              0  
  2          1              0  
  3          0              0  
  4          1              1  

将churn_yes重命名

churn=churn.rename(columns={'churn_yes':'flag'})
#二分类模型,分析flag 1和0的占比
churn.flag.value_counts()

输出结果:

  0    5174
  1    1869
  Name: flag, dtype: int64
churn.flag.value_counts(1)

输出结果:

  0    0.73463
  1    0.26537
  Name: flag, dtype: float64

按照标签进行分组,查看不同标签分组的平均值

summary=churn.groupby('flag')
summary.mean()

输出结果:

        partner_att  dependents_att  landline  internet_att  internet_other  
  flag                                                                        
  0        0.528218        0.344801  0.901044      0.379204        0.347700   
  1        0.357945        0.174425  0.909042      0.245586        0.693954   

        streamingtv  streamingmovies  contract_month  contract_1yr  paymentbank  
  flag                                                                            
  0        0.365868         0.369927        0.429068      0.252609     0.248550   
  1        0.435527         0.437667        0.885500      0.088818     0.138042   

        paymentcreditcard  paymentelectronic  monthlycharges  totalcharges  
  flag                                                                       
  0              0.249324           0.250097       61.265124   2545.918081   
  1              0.124131           0.573034       74.441332   1528.514714   

        gender_female  
  flag                 
  0          0.492656  
  1          0.502408  

观察flag在0和1的情况下,所有自变量的差别 internet_other变量,在0的分组中,均值是0.35,在1的分组中,均值是0.69。数据显示如果使用别的公司的互联网,用户流失的概率就越高

sns.countplot(y='contract_month',hue='flag',data=churn)

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

逻辑回归模型

自变量可以分为几类,partner/dependents,internet,streaming,contract,payment,charges,后续大家可以自己挑选进行建模

这里先选取几个contract_month,internet_other与streamingtv

# 确定目标值和特征值
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)
#使用sklearn
from sklearn import linear_model
lr=linear_model.LogisticRegression()
lr.fit(x_train,y_train)

模型的评估

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)
from sklearn.metrics import roc_auc_score
roc_auc_score(y_test, y_pred_test)

参数调整

从Y标签的类别分布上看,未流失用户为:5174 流失用户为:1869,属于样本分布不均衡问题,我们可以通过调整逻辑回归的模型参数来为占比较低的类别增加权重

LogisticRegression(class_weight='balanced')

除此之外我们可以进一步通过网格搜索来调整其它参数

from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import GridSearchCV
kfold = StratifiedKFold(n_splits=5, shuffle=True)
lr = linear_model.LogisticRegression()
param_grid = {'solver': ['newton-cg', 'lbfgs', 'liblinear'],
              'C': [0.001, 0.01, 1, 10, 100],'class_weight':['balanced']}
search = GridSearchCV(lr, param_grid, cv=kfold)
lr = search.fit(x_train, y_train)

我们打印获取到的最优参数组合

lr.best_params_

{‘C’: 1, ‘class_weight’: ‘balanced’, ‘solver’: ‘newton-cg’}

查看模型的回归系数

# x=churn[['contract_month','internet_other','streamingtv']]
lr.coef_

[[2.25630305 1.12102112 0.28519637]]

从结果中反应了特征重要性, contract_month 重要性最高,internet_other 其次,为了降低流失率,可以考虑针对月付费用户以及使用它网宽带的用户做针对性的营销

4. 小结

本小节,我们使用了逻辑回归算法做了用户流失分析的案例

  • 除了直接预测用户是否会流失之外, 还可以利用模型中的回归系数得出对业务有帮助的建议
  • 当样本类别分布不均衡时(如本例中,0样本是数量是5174,1样本数量是1869),可以通过添加参数class_weight=’balanced’来增加样本占比较低类别的权重
逻辑回归

3 - 分类评估指标

2023-5-19 16:35:11

数学基础

数学常用概念

2023-5-17 19:22:25