文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

教你用Python写一个电信客户流失预测模型

2024-12-03 19:19

关注

今天教大家如何用Python写一个电信用户流失预测模型。之前我们用Python写了员工流失预测模型,这次我们试试Python预测电信用户的流失。

01、商业理解

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

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

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

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

02、数据理解

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

03、数据读入和概览

首先导入所需包。

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

读入数据集

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

04、数据初步清洗

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

  1. # 错误值处理 
  2. repl_columns = ['OnlineSecurity''OnlineBackup''DeviceProtection',  
  3.                 'TechSupport','StreamingTV''StreamingMovies'
  4.  
  5. for i in repl_columns: 
  6.     df[i]  = df[i].replace({'No internet service' : 'No'})  
  7.  
  8. # 替换值SeniorCitizen 
  9. df["SeniorCitizen"] = df["SeniorCitizen"].replace({1"Yes"0"No"})  
  10.  
  11. # 替换值TotalCharges 
  12. df['TotalCharges'] = df['TotalCharges'].replace(' ', np.nan)  
  13.  
  14. # TotalCharges空值:数据量小,直接删除 
  15. df = df.dropna(subset=['TotalCharges'])  
  16. df.reset_index(drop=True, inplace=True)  # 重置索引 
  17.  
  18. # 转换数据类型 
  19. df['TotalCharges'] = df['TotalCharges'].astype('float'
  20.  
  21. # 转换tenure 
  22. def transform_tenure(x): 
  23.     if x <= 12
  24.         return 'Tenure_1' 
  25.     elif x <= 24
  26.         return 'Tenure_2' 
  27.     elif x <= 36
  28.         return 'Tenure_3' 
  29.     elif x <= 48
  30.         return 'Tenure_4' 
  31.     elif x <= 60
  32.         return 'Tenure_5' 
  33.     else
  34.         return 'Tenure_over_5'  
  35.  
  36. df['tenure_group'] = df.tenure.apply(transform_tenure) 
  37.  
  38. # 数值型和类别型字段 
  39. Id_col = ['customerID'
  40. target_col = ['Churn'
  41.  
  42. cat_cols = df.nunique()[df.nunique() < 10].index.tolist()  
  43. num_cols = [i for i in df.columns if i not in cat_cols + Id_col]  
  44.  
  45. print('类别型字段:\n', cat_cols) 
  46. print('-' * 30)  
  47. print('数值型字段:\n', num_cols) 
  1. 类别型字段: 
  2.  ['gender''SeniorCitizen''Partner''Dependents''PhoneService',  
  3.   'MultipleLines''InternetService''OnlineSecurity'
  4.   'OnlineBackup''DeviceProtection''TechSupport'
  5.   'StreamingTV''StreamingMovies''Contract''PaperlessBilling',  
  6.   'PaymentMethod''Churn''tenure_group'
  7. ------------------------------ 
  8. 数值型字段: 
  9.  ['tenure''MonthlyCharges''TotalCharges'

05、探索性分析

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

1. 目标变量Churn分布

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

  1. df['Churn'].value_counts()  
  2. No     5163 
  3. Yes    1869 
  4. Name: Churn, dtype: int64 
  1. trace0 = go.Pie(labels=df['Churn'].value_counts().index,  
  2.                 values=df['Churn'].value_counts().values, 
  3.                 hole=.5
  4.                 rotation=90
  5.                 marker=dict(colors=['rgb(154,203,228)''rgb(191,76,81)'],  
  6.                             line=dict(color='white', width=1.3)) 
  7.                ) 
  8. data = [trace0]  
  9. layout = go.Layout(title='目标变量Churn分布'
  10.  
  11. fig = go.Figure(data=data, layout=layout) 
  12. py.offline.plot(fig, filename='./html/整体流失情况分布.html'

2.性别

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

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

3. 老年用户

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

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

4. 是否有配偶

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

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

5. 上网时长

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

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

6. 付款方式

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

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

 

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

7. 月费用

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

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

8. 数值型属性相关性

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

  1. plt.figure(figsize=(1510))   
  2. sns.heatmap(df.corr(), linewidths=0.1, cmap='tab20c_r', annot=True) 
  3. plt.title('数值型属性的相关性', fontdict={'fontsize''xx-large''fontweight':'heavy'})  
  4. plt.xticks(fontsize=12
  5. plt.yticks(fontsize=12
  6. plt.show()  

06、特征选择

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

  1. # 删除tenure 
  2. df = df.drop('tenure', axis=1)  
  3.  
  4. from feature_selection import Feature_select 
  5.  
  6. # 划分X和y 
  7. X = df.drop(['customerID''Churn'], axis=1)  
  8. y = df['Churn']    
  9.  
  10. fs = Feature_select(num_method='anova', cate_method='kf', pos_label='Yes'
  11. x_sel = fs.fit_transform(X, y)   
  1. 2020 09:30:02 INFO attr select success! 
  2. After select attr: ['DeviceProtection''MultipleLines''OnlineSecurity',  
  3.                     'TechSupport''tenure_group''PaperlessBilling'
  4.                     'InternetService''PaymentMethod''SeniorCitizen',  
  5.                     'MonthlyCharges''Dependents''Partner''Contract',  
  6.                     'StreamingTV''TotalCharges''StreamingMovies''OnlineBackup'

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

07、建模前处理

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

  1. # 筛选变量 
  2. select_features = x_sel.columns 
  3.  
  4. # 建模数据 
  5. df_model = pd.concat([df['customerID'], df[select_features], df['Churn']], axis=1
  6.  
  7. Id_col = ['customerID'
  8. target_col = ['Churn'
  9.  
  10. # 分类型 
  11. cat_cols = df_model.nunique()[df_model.nunique() < 10].index.tolist()  
  12. # 二分类属性 
  13. binary_cols = df_model.nunique()[df_model.nunique() == 2].index.tolist() 
  14. # 多分类属性 
  15. multi_cols = [i for i in cat_cols if i not in binary_cols]  
  16.  
  17. # 数值型 
  18. num_cols = [i for i in df_model.columns if i not in cat_cols + Id_col]  
  19.  
  20. # 二分类-标签编码 
  21. le = LabelEncoder() 
  22.  
  23. for i in binary_cols: 
  24.     df_model[i] = le.fit_transform(df_model[i])  
  25.  
  26. # 多分类-哑变量转换 
  27. df_model = pd.get_dummies(data=df_model, columns=multi_cols)  
  28. df_model.head()  

08、模型建立和评估

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

  1. # 重新划分 
  2. X = df_model.drop(['customerID''Churn'], axis=1)  
  3. y = df_model['Churn']   
  4.  
  5. # 分层抽样 
  6. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0, stratify=y)  
  7. print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)  
  8.  
  9. #修正索引 
  10. for i in [X_train, X_test, y_train, y_test]: 
  11.     i.index = range(i.shape[0])  
  1. (562531) (140731) (5625,) (1407,) 
  1. # 保存标准化训练和测试数据 
  2. st = StandardScaler() 
  3. num_scaled_train = pd.DataFrame(st.fit_transform(X_train[num_cols]), columns=num_cols) 
  4. num_scaled_test = pd.DataFrame(st.transform(X_test[num_cols]), columns=num_cols)  
  5.  
  6. X_train_sclaed = pd.concat([X_train.drop(num_cols, axis=1), num_scaled_train], axis=1
  7. X_test_sclaed = pd.concat([X_test.drop(num_cols, axis=1), num_scaled_test], axis=1)  

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

假如我们关注roc指标,从模型表现效果来看,Naive Bayes效果最好。我们也可以对模型进行进一步优化,比如对决策树参数进行调优。

  1. parameters = {'splitter': ('best','random'), 
  2.               'criterion': ("gini","entropy"), 
  3.               "max_depth": [*range(320)], 
  4.              } 
  5.  
  6. clf = DecisionTreeClassifier(random_state=25
  7. GS = GridSearchCV(clf, parameters, scoring='f1', cv=10
  8. GS.fit(X_train, y_train) 
  9.  
  10. print(GS.best_params_)  
  11.  
  12. print(GS.best_score_)  
  1. {'criterion''entropy''max_depth'5'splitter''best'
  2. 0.585900839405024 
  1. clf = GS.best_estimator_ 
  2.  
  3. test_pred = clf.predict(X_test) 
  4. print('测试集:\n', classification_report(y_test, test_pred))  
  1. 测试集: 
  2.                precision    recall  f1-score   support 
  3.  
  4.            0       0.86      0.86      0.86      1033 
  5.            1       0.61      0.61      0.61       374 
  6.  
  7.     accuracy                           0.79      1407 
  8.    macro avg       0.73      0.73      0.73      1407 
  9. weighted avg       0.79      0.79      0.79      1407 

将这棵树绘制出来。

  1. import graphviz 
  2. dot_data = tree.export_graphviz(decision_tree=clf, max_depth=3
  3.                                  out_file=None,  
  4.                                  feature_names=X_train.columns, 
  5.                                  class_names=['not_churn''churn'],  
  6.                                  filled=True, 
  7.                                  rounded=True 
  8.                                 ) 
  9. graph = graphviz.Source(dot_data)  

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

  1. imp = pd.DataFrame(zip(X_train.columns, clf.feature_importances_)) 
  2. imp.columns = ['feature''importances'
  3. imp = imp.sort_values('importances', ascending=False) 
  4. imp = imp[imp['importances'] != 0
  5.  
  6. table  = ff.create_table(np.round(imp, 4)) 
  7. py.offline.iplot(table)   

后续优化方向:

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯