当前位置: 首页 > 后端技术 > Python

范例-教你用python写一个电信客户流失预测模型

时间:2023-03-26 18:41:04 Python

CDA数据分析师出品:振达、米卡资料:振达【攻略】今天教大家用Python写一个电信客户流失预测模型。之前我们用Python写了一个员工流失预测模型,这次尝试用Python来预测电信用户的流失。01.业务理解流失客户是指曾经使用过产品或服务,但由于对产品失去兴趣等各种原因不再使用产品或服务的客户。电信服务公司、互联网服务提供商、保险公司等经常将流失分析和流失率作为其关键业务指标之一,因为留住老客户的成本远低于获得新客户的成本。预测分析使用流失预测模型通过评估客户流失的风险倾向来预测客户流失。由于这些模型生成了流失概率的排名列表,因此它们可以有效地针对流失概率高的潜在客户实施客户保留营销计划。下面我们将教大家如何用Python编写一个电信用户流失预测模型。下面是具体步骤和关键代码。02.数据理解本次分析的数据来自IBMSampleDataSets,统计的是某电信公司一段时间内的消费数据。一共7043条客户数据,每条客户数据包含21个字段,包括1个客户ID字段,19个输入字段和1个目标字段-Churn(Yes表示流失,No表示不流失),输入字段主要包括以下三个指标三个维度:用户画像指标、消费品指标、消费信息指标。具体字段说明如下:03.数据导入及概览首先导入需要的包。数据处理importnumpyasnpimportpandasaspd可视觉化importmatplotlib.pyplotaspltimportseabornassnsimportplotlyaspyimportplotly.graph_objsasgoimportplotly.figure_factoryasff前处理fromsklearn.preprocessingimportLabelEncoderfromsklearn.preprocessingimportStandardScalerfromsklearn模。linear_modelimportLogisticRegressionfromsklearn.neighborsimportKNeighborsClassifierfromsklearn.treeimportDecisionTreeClassifierfromsklearnimporttreefromsklearn.ensembleimportRandomForestClassifierfromsklearn.naive_bayesimportGaussianNBfromsklearn.neural_networkimportMLPClassifierfromsklearn.svmimportSVCfromlightgbmimportLGBMClassifierfromxgboostimportXGBClassifier模型评估fromsklearn.model_selectionimporttrain_test_split,GridSearchCVfromsklearn.metrics导入confusion_matrix,accuracy_score,classification_reportfromsklearn.metrics导入roc_auc_score,roc_curve,scorerfromsklearn.metrics导入recall_score,precision_score,f1_score,cohen_kappa_scorepd.set_option('display.max_columns',None)读入数据集df=pd.read_csv('./Telco-Customer-Churn.csv')df.head()04.初步清洗数据先Data清洗工作,包括错误值和异常值的处理,分类类型和数值字段类型。清理部分包括:OnlineSecurity、OnlineBackup、DeviceProtection、TechSupport、StreamingTV、StreamingMovies:错误值处理TotalCharges:异常值处理tenure:自定义分箱并定义类别和数值字段错误值处理repl_columns=['OnlineSecurity','OnlineBackup','DeviceProtection','TechSupport','StreamingTV','StreamingMovies']foriinrepl_columns:df[i]=df[i].replace({'Nointernetservice':'No'})replacevalueSeniorCitizendf["SeniorCitizen"]=df["SeniorCitizen"].replace({1:"Yes",0:"No"})替换值TotalChargesdf['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')转换tenuredeftransform_tenure(x):ifx<=12:return'Tenure_1'elifx<=24:return'Tenure_2'el如果x<=36:返回rn'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=[iforiindf.columnsifinotincat_cols+id_col]print('类别字段:n',cat_cols)print('-'*30)print('数字字段:n',num_cols)类别字段:['性别','SeniorCitizen','Partner','Dependents','PhoneService','MultipleLines','InternetService','OnlineSecurity','OnlineBackup','DeviceProtection','TechSupport','StreamingTV','StreamingMovies','Contract','PaperlessBilling','PaymentMethod','Churn','tenure_group']数值字段:['tenure','MonthlyCharges','TotalCharges']05.探索性分析对指标进行归纳整理,包括用户画像指标和消费产品指标,消费信息指标探索影响的关键因素ng用户流失。1.初步清洗后目标变量流失分布的大小为7032条记录,其中流失客户1869条,占比26.6%,非流失客户73.4%。df['Churn'].value_counts()No5163Yes1869Name:Churn,dtype:int64trace0=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='目标变量流失分布')fig=go.Figure(data=data,layout=layout)py.offline.plot(fig,filename='./html/Overallchurndistribution.html')2.性别分析表明,男性和女性的客户流失比例没有显着差异。plot_bar(input_col='gender',target_col='Churn',title_name='性别与流失的关系')3.老年用户流失率较高,为41.68%,是非老年用户的近两倍.一些原因需要进一步探讨。plot_bar(input_col='SeniorCitizen',target_col='Churn',title_name='老年用户与流失的关系')4.是否有配偶从婚姻状况来看,数据显示未婚的流失比例人比已婚的人高出13%。plot_bar(input_col='Partner',target_col='Churn',title_name='是否有配偶和是否失散的关系')5.分析了在线时间,从这方面可以得出两个结论:用户在线时间越长,说明用户忠诚度越高,流失概率越低;新用户一年内流失率明显高于整体流失率,为47.68%。plot_bar(input_col='tenure_group',target_col='Churn',title_name='在线时间与流失率的关系')6.支付方式支付方式方面,选择电子支票支付方式的用户流失率最高,达到45.29%,其他三种支付方式的流失率相差不大。pd.crosstab(df['PaymentMethod'],df['Churn'])plot_bar(input_col='PaymentMethod',target_col='Churn',title_name='支付方式及是否流失')7.整体月费,随着月费的增加,流失用户比例呈现高低变化,月消费在80-100元的用户相对较高。plot_histogram(input_col='MonthlyCharges',title_name='月费与是否丢失的关系')8.数值属性相关性从相关矩阵可以看出,用户的交易周期与总费用高度相关,交易周期越长,总成本越高。每月消费与总消费之间存在显着相关性。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。特征选择采用统计验证的方法进行特征筛选。droptenuredf=df.drop('tenure',axis=1)fromfeature_selectionimportFeature_select除X和yX=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)202009:30:02信息属性选择成功!选择属性后:['DeviceProtection'、'MultipleLines'、'OnlineSecurity'、'TechSupport'、'tenure_group'、'PaperlessBilling'、'InternetService'、'PaymentMethod'、'SeniorCitizen'、'MonthlyCharges'、'Dependents'、'Partner','Contract','StreamingTV','TotalCharges','StreamingMovies','OnlineBackup']功能筛选后,性别和电话服务字段被删除。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=[iforiincat_colsifinotinbinary_cols]numericnum_cols=[iforiindf_model.columnsifinotincat_cols+Id_col]binaryclassification-labelencodingle=LabelEncoder()foriinbinary_cols:df_model[i]=le.fit_transform(df_model[i])multi-category-dummyvariableconversiondf_model=pd.get_dummies(data=df_model,columns=multi_cols)df_model.head()08.模型建立和评估首先使用分层抽样将数据分为训练集和测试集。repartitionX=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)[X_train,X_test,y_train,y_test]中i的正确索引: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)然后建立一系列的基准模型并比较效果。如果关注roc指数,从模型性能的角度来看,朴素贝叶斯效果最好。我们还可以进一步优化模型,比如调整决策树的参数。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.585900839405024clf=GS.best_estimator_test_pred=clf.predict(X_test)print('testset:n',classification_report(y_test,test_pred))测试集:precisionrecallf1-scoresupport00.860.860.86103310.610.610.61374accuracy0.791407macroavg0.730.730.731407weightedavg0.790.790.791407绘制树。导入graphvizdot_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)输出决策树属性重要性排序: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)后续优化方向:数据:分类技术当应用于目标类别分布较为均匀的数据集,其建立的分类器通常具有较好的分类性能。针对目标领域数据分布不均衡,可以使用过采样和欠采样来处理类别不均衡的问题;属性:进一步的属性筛选方法和属性组合;算法:参数调整;调整预测阈值以提高预测性能。