精华内容
下载资源
问答
  • 之前我们用Python写了员工流失预测模型,这次我们试试Python预测电信用户的流失。 01、商业理解 流失客户是指那些曾经使用过产品或服务,由于对产品失去兴趣等种种原因,不再使用产品或服务的顾客。 电信服务公司...

     

     CDA数据分析师 出品  

    作者:真达、Mika

    数据:真达  

    【导读】

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

    01、商业理解

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

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

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

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

    02、数据理解

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

    03、数据读入和概览

    首先导入所需包。

    # 数据处理
    import numpy as np 
    import pandas as pd 
    
    # 可视化
    import matplotlib.pyplot as plt 
    import seaborn as sns 
    import plotly as py 
    import plotly.graph_objs as go 
    import plotly.figure_factory as ff 
    
    # 前处理
    from sklearn.preprocessing import LabelEncoder
    from sklearn.preprocessing import StandardScaler
    
    # 建模
    from sklearn.linear_model import LogisticRegression
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.tree import DecisionTreeClassifier
    from sklearn import tree 
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.naive_bayes import GaussianNB
    from sklearn.neural_network import MLPClassifier
    from sklearn.svm import SVC
    from lightgbm import LGBMClassifier
    from xgboost import XGBClassifier
    
    # 模型评估
    from sklearn.model_selection import train_test_split, GridSearchCV
    from sklearn.metrics import confusion_matrix, accuracy_score, classification_report
    from sklearn.metrics import roc_auc_score, roc_curve, scorer
    from sklearn.metrics import recall_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()  

    04、数据初步清洗

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

    • OnlineSecurity、OnlineBackup、DeviceProtection、TechSupport、StreamingTV、StreamingMovies:错误值处理
    • TotalCharges:异常值处理
    • tenure:自定义分箱
    • 定义类别型和数值型字段
    # 错误值处理
    repl_columns = ['OnlineSecurity', 'OnlineBackup', 'DeviceProtection', 
                    'TechSupport','StreamingTV', 'StreamingMovies']
    
    for i in repl_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
    def transform_tenure(x):
        if x <= 12:
            return 'Tenure_1'
        elif x <= 24:
            return 'Tenure_2'
        elif x <= 36:
            return 'Tenure_3'
        elif x <= 48:
            return 'Tenure_4'
        elif x <= 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 for i in df.columns if i not in cat_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分布

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

    df['Churn'].value_counts() 
    No     5163
    Yes    1869
    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.性别

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

    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. 上网时长

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

    • 用户的在网时长越长,表示用户的忠诚度越高,其流失的概率越低;
    • 新用户在1年内的流失率显著高于整体流失率,为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、特征选择

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

    # 删除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 select success!
    After select attr: ['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() 

    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) 
    
    #修正索引
    for i 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) 

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

    假如我们关注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)) 
    测试集:
                   precision    recall  f1-score   support
    
               0       0.86      0.86      0.86      1033
               1       0.61      0.61      0.61       374
    
        accuracy                           0.79      1407
       macro avg       0.73      0.73      0.73      1407
    weighted avg       0.79      0.79      0.79      1407

    将这棵树绘制出来。

    import graphviz
    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) 

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

    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)  

    后续优化方向:

    • 数据:分类技术应用在目标类别分布越均匀的数据集时,其所建立之分类器通常会有比较好的分类效能。针对数据在目标字段上分布不平衡,可采用过采样和欠采样来处理类别不平衡问题;
    • 属性:进一步属性筛选方法和属性组合;
    • 算法:参数调优;调整预测门槛值来增加预测效能。

     

    展开全文
  • 作者:真达、Mika数据:真达【导读】今天教大家如何用Python写一个电信用户流失预测模型。公众号后台,回复关键字“电信”获取完整数据。之前我们用Python写了员工流失预测模型,...

    作者:真达、Mika

    数据:真达  

    【导读】

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

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

    ????????????

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

    01

    商业理解

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

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

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

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

    02

    数据理解

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

    03

    数据读入和概览

    首先导入所需包。

    # 数据处理
    import numpy as np 
    import pandas as pd 
    
    # 可视化
    import matplotlib.pyplot as plt 
    import seaborn as sns 
    import plotly as py 
    import plotly.graph_objs as go 
    import plotly.figure_factory as ff 
    
    # 前处理
    from sklearn.preprocessing import LabelEncoder
    from sklearn.preprocessing import StandardScaler
    
    # 建模
    from sklearn.linear_model import LogisticRegression
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.tree import DecisionTreeClassifier
    from sklearn import tree 
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.naive_bayes import GaussianNB
    from sklearn.neural_network import MLPClassifier
    from sklearn.svm import SVC
    from lightgbm import LGBMClassifier
    from xgboost import XGBClassifier
    
    # 模型评估
    from sklearn.model_selection import train_test_split, GridSearchCV
    from sklearn.metrics import confusion_matrix, accuracy_score, classification_report
    from sklearn.metrics import roc_auc_score, roc_curve, scorer
    from sklearn.metrics import recall_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()  
    

    04

    数据初步清洗

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

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

    • TotalCharges:异常值处理

    • tenure:自定义分箱

    • 定义类别型和数值型字段

    # 错误值处理
    repl_columns = ['OnlineSecurity', 'OnlineBackup', 'DeviceProtection', 
                    'TechSupport','StreamingTV', 'StreamingMovies']
    
    for i in repl_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
    def transform_tenure(x):
        if x <= 12:
            return 'Tenure_1'
        elif x <= 24:
            return 'Tenure_2'
        elif x <= 36:
            return 'Tenure_3'
        elif x <= 48:
            return 'Tenure_4'
        elif x <= 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 for i in df.columns if i not in cat_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分布

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

    df['Churn'].value_counts() 
    No     5163
    Yes    1869
    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.性别

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

    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. 上网时长

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

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

    • 新用户在1年内的流失率显著高于整体流失率,为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

    特征选择

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

    # 删除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 select success!
    After select attr: ['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() 
    

    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) 
    
    #修正索引
    for i 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) 
    

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

    假如我们关注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)) 
    
    测试集:
                   precision    recall  f1-score   support
    
               0       0.86      0.86      0.86      1033
               1       0.61      0.61      0.61       374
    
        accuracy                           0.79      1407
       macro avg       0.73      0.73      0.73      1407
    weighted avg       0.79      0.79      0.79      1407
    

    将这颗树绘制出来。

    import graphviz
    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) 
    

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

    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)  
    

    后续优化方向:

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

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

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

    本文出品:CDA数据分析师(ID: cdacdacda)

    近期开班情况

    课程详情请扫码咨询

    展开全文
  • 源自:数据分析不是个事儿作者:启方客户流失是所有与消费者挂钩行业都会关注的点。因为发展一个新客户是需要一定成本的,一旦客户流失,成本浪费不说,挽回一个客户的成本更大。今天分享一个用户流失...

    源自:数据分析不是个事儿

    作者:启方

    客户流失是所有与消费者挂钩行业都会关注的点。因为发展一个新客户是需要一定成本的,一旦客户流失,成本浪费不说,挽回一个客户的成本更大。

    今天分享一个用户流失预测,以电信行业为例。

    所以,电信行业在竞争日益激烈当下,如何挽留更多用户成为一项关键业务指标。为了更好运营用户,这就要求要了解流失用户的特征,分析流失原因,预测用户流失,确定挽留目标用户并制定有效方案。

    一、提出问题

    1、哪些用户可能会流失?

    2、流失概率更高的用户有什么共同特征?

    二、理解数据

    1、采集数据
    本数据集来自DF ,数据源地址:
    https://www.datafountain.cn/dataSets/35/details#

    本数据集描述了电信用户是否流失以及其相关信息,共包含7044条数据,共20个字段,介绍下各个字段:

    • customerID :用户ID。

    • gender:性别。(Female & Male)

    • SeniorCitizen :老年人 (1表示是,0表示不是)

    • Partner :是否有配偶 (Yes or No)

    • Dependents :是否经济独立 (Yes or No)

    • tenure :客户的职位(0-72,共73个职位)

    • PhoneService :是否开通电话服务业务 (Yes or No)

    • MultipleLines:是否开通了多线业务(Yes 、No or No phoneservice 三种)

    • InternetService:是否开通互联网服务 (No, DSL数字网络,fiber optic光纤网络 三种)

    • OnlineSecurity:是否开通网络安全服务(Yes,No,No internetserive 三种)

    • OnlineBackup:是否开通在线备份业务(Yes,No,No internetserive 三种)

    • DeviceProtection:是否开通了设备保护业务(Yes,No,No internetserive 三种)

    • TechSupport:是否开通了技术支持服务(Yes,No,No internetserive 三种)

    • StreamingTV:是否开通网络电视(Yes,No,No internetserive 三种)

    • StreamingMovies:是否开通网络电影(Yes,No,No internetserive 三种)

    • Contract:签订合同方式 (按月,一年,两年)

    • PaperlessBilling:是否开通电子账单(Yes or No)

    • PaymentMethod:付款方式(bank transfer,credit card,electronic check,mailed check)

    • MonthlyCharges:月费用

    • TotalCharges:总费用

    • Churn:该用户是否流失(Yes or No)

    2、导入数据


    3、查看数据集信息

    三、数据清洗

    1、查找缺失值

    数据集中有5174名用户没流失,有1869名客户流失,数据集不均衡。

    2、查看数据类型

    TotalCharges表示总费用,这里为对象类型,需要转换为float类型

    3、转换类型

    再次查找缺失值:

    这里存在11个缺失值,由于数量不多我们可以直接删除这些行

    4、处理缺失值

    5、数据归一化处理

    四、数据可视化呈现

    1、查看流失客户占比


    由图中结果可以看出,流失客户占整体客户的26.6%。

    2、性别、老年人、配偶、亲属对流客户流失率的影响

    性别、老年人占比结果

    配偶、亲属占比结果

    可以看出,男性与女性用户之间的流失情况基本没有差异,而在老年用户中流失占比明显比非老年用户更高,在所有数据中未婚与已婚人数基本持平,但未婚中流失人数比已婚中的流失人数高出了快一倍,从经济独立情况来看,经济未独立的用户流失率要远远高于经济独立的用户。

    3、提取特征

    4、构造相关性矩阵

    5、使用热地图显示相关系数

    结论:

    从上图可以看出,互联网服务、网络安全服务、在线备份业务、设备保护业务、技术支持服务、网络电视和网络电影之间存在较强的相关性,多线业务和电话服务之间也有很强的相关性,并且都呈强正相关关系。

    6、使用one-hot编码

    7、电信用户是否流失与各变量之间的相关性

    由图上可以看出,变量gender 和 PhoneService 处于图形中间,其值接近于 0 ,这两个变量对电信客户流失预测影响非常小,可以直接舍弃。

    8、网络安全服务、在线备份业务、设备保护业务、技术支持服务、网络电视、网络电影和无互联网服务对客户流失率的影响

    由上图可以看出,在网络安全服务、在线备份业务、设备保护业务、技术支持服务、网络电视和网络电影六个变量中,没有互联网服务的客户流失率值是相同的,都是相对较低。

    这可能是因为以上六个因素只有在客户使用互联网服务时才会影响客户的决策,这六个因素不会对不使用互联网服务的客户决定是否流失产生推论效应。

    9、签订合同方式对客户流失率的影响

    由图上可以看出,签订合同方式对客户流失率影响为:按月签订 > 按一年签订 > 按两年签订,这可能表明,设定长期合同对留住现有客户更有效。

    10、付款方式对客户流失率的影响

    由图上可以看出,在四种支付方式中,使用Electronic check的用户流流失率最高,其他三种支付方式基本持平,因此可以推断电子账单在设计上影响用户体验。

    五、数据预处理

    由前面结果可知,CustomerID表示每个客户的随机字符,对后续建模不影响,我这里选择删除CustomerID列;gender 和 PhoneService 与流失率的相关性低,可直接忽略。

    对客户的职位、月费用和总费用进行去均值和方差缩放,对数据进行标准化:

    使用箱线图查看数据是否存在异常值:

    由以上结果可以看出,在三个变量中不存在明显的异常值。

    查看对象类型字段中存在的值:

    综合之前的结果来看,在六个变量中存在No internet service,即无互联网服务对客户流失率影响很小,这些客户不使用任何互联网产品,因此可以将No internet service 和 No 是一样的效果,可以使用 No 替代 No internet service。

    使用Scikit-learn标签编码,将分类数据转换为整数编码:

    六、构建模型

    1、建立训练数据集和测试数据集

    2、选择机器学习算法

    3、训练模型

    4、评估模型

    召回率(recall)的含义是:原本为对的当中,预测为对的比例(值越大越好,1为理想状态)
    精确率、精度(precision)的含义是:预测为对的当中,原本为对的比例(值越大越好,1为理想状态)
    F1分数(F1-Score)指标综合了Precision与Recall的产出的结果

    F1-Score的取值范围从0到1的,1代表模型的输出最好,0代表模型的输出结果最差。

    综上所述,在10种分类算法中朴素贝叶斯(Naive Bayes)的F1分数最大为63.31%,所以使用朴素贝叶斯模型效果最好。

    七、实施方案

    八、结论

    通过上述分析,我们可以大致勾勒出容易流失的用户特征:

    老年用户与未婚且经济未独立的青少年用户更容易流失。

    电话服务对用户的流失没有直接的影响。

    提供的各项网络服务项目能够降低用户的流失率。

    签订合同越久,用户的留存率越高。

    采用electronic check支付的用户更易流失。

    针对上述诊断结果,可有针对性的对此提出建议:
    推荐老年用户与青少年用户采用数字网络,且签订2年期合同(可以各种辅助优惠等营销手段来提高2年期合同的签订率),若能开通相关网络服务可增加用户粘性,因此可增加这块业务的推广,同时考虑改善电子账单支付的用户体验。

    最后,分享源码:

    # coding: utf-8
    
    
    # # 电信客户流失预测
    
    
    # ## 1、导入数据
    
    
    # In[1]:
    
    
    import numpy as np
    import pandas as pd 
    import os
    
    
    
    
    # In[2]:
    
    
    # 导入相关的包
    import matplotlib.pyplot as plt
    import seaborn as sns
    from pylab import rcParams
    import matplotlib.cm as cm
    
    
    import sklearn
    from sklearn import preprocessing
    from sklearn.preprocessing import LabelEncoder               # 编码转换
    from sklearn.preprocessing import StandardScaler
    from sklearn.model_selection import StratifiedShuffleSplit
    
    
    from sklearn.ensemble import RandomForestClassifier          # 随机森林
    from sklearn.svm import SVC, LinearSVC                       # 支持向量机
    from sklearn.linear_model import LogisticRegression          # 逻辑回归
    from sklearn.neighbors import KNeighborsClassifier           # KNN算法
    from sklearn.naive_bayes import GaussianNB                   # 朴素贝叶斯
    from sklearn.tree import DecisionTreeClassifier              # 决策树分类器
    from xgboost import XGBClassifier
    from catboost import CatBoostClassifier
    from sklearn.ensemble import AdaBoostClassifier
    from sklearn.ensemble import GradientBoostingClassifier     
    
    
    from sklearn.metrics import classification_report, precision_score, recall_score, f1_score
    from sklearn.metrics import confusion_matrix
    from sklearn.model_selection import GridSearchCV
    from sklearn.metrics import make_scorer
    from sklearn.ensemble import VotingClassifier
    
    
    from sklearn.decomposition import PCA
    from sklearn.cluster import KMeans
    from sklearn.metrics import silhouette_score
    
    
    import warnings
    warnings.filterwarnings('ignore')
    
    
    get_ipython().magic('matplotlib inline')
    
    
    
    
    # In[3]:
    
    
    # 读取数据文件
    telcom=pd.read_csv(r"F:\data\WA_Fn-UseC_-Telco-Customer-Churn.csv")
    
    
    
    
    # ## 2、查看数据集信息
    
    
    # In[4]:
    
    
    telcom.head(10)
    
    
    
    
    # In[5]:
    
    
    # 查看数据集大小
    telcom.shape
    
    
    
    
    # In[6]:
    
    
    # 获取数据类型列的描述统计信息
    telcom.describe()
    
    
    
    
    # ## 3、数据清洗
    
    
    # In[7]:
    
    
    # 查找缺失值
    pd.isnull(telcom).sum()
    
    
    
    
    # In[8]:
    
    
    telcom["Churn"].value_counts()
    
    
    
    
    # 数据集中有5174名用户没流失,有1869名客户流失,数据集不均衡。
    
    
    # In[9]:
    
    
    telcom.info()
    
    
    
    
    # TotalCharges表示总费用,这里为对象类型,需要转换为float类型  
    
    
    # In[10]:
    
    
    telcom['TotalCharges']=telcom['TotalCharges'].convert_objects(convert_numeric=True) # convert_numeric=True表示强制转换数字(包括字符串),不可转换的值变为NaN
    telcom["TotalCharges"].dtypes
    
    
    
    
    # In[11]:
    
    
    # 再次查找是否存在缺失值
    pd.isnull(telcom["TotalCharges"]).sum()
    
    
    
    
    # 这里存在11个缺失值,由于数量不多我们可以直接删除这些行
    
    
    # In[12]:
    
    
    # 删除缺失值所在的行
    telcom.dropna(inplace=True)
    telcom.shape
    
    
    
    
    # In[13]:
    
    
    # 数据归一化处理
    # 对Churn 列中的值 Yes和 No分别用 1和 0替换,方便后续处理
    telcom['Churn'].replace(to_replace = 'Yes', value = 1,inplace = True)
    telcom['Churn'].replace(to_replace = 'No', value = 0,inplace = True)
    telcom['Churn'].head()
    
    
    
    
    # In[14]:
    
    
    telcom['Churn'].replace(to_replace='Yes', value=1, inplace=True)
    telcom['Churn'].replace(to_replace='No',  value=0, inplace=True)
    telcom['Churn'].head()
    
    
    
    
    # ## 4、数据可视化呈现
    
    
    # In[15]:
    
    
    # 查看流失客户占比
    """
    画饼图参数:
    labels  (每一块)饼图外侧显示的说明文字
    explode  (每一块)离开中心距离
    startangle  起始绘制角度,默认图是从x轴正方向逆时针画起,如设定=90则从y轴正方向画起
    shadow   是否阴影
    labeldistance label  绘制位置,相对于半径的比例, 如<1则绘制在饼图内侧
    autopct   控制饼图内百分比设置,可以使用format字符串或者format function
         '%1.1f'指小数点前后位数(没有用空格补齐)
    pctdistance 类似于labeldistance,指定autopct的位置刻度
    radius   控制饼图半径
    """
    churnvalue=telcom["Churn"].value_counts()
    labels=telcom["Churn"].value_counts().index
    
    
    rcParams["figure.figsize"]=6,6
    plt.pie(churnvalue,labels=labels,colors=["whitesmoke","yellow"], explode=(0.1,0),autopct='%1.1f%%', shadow=True)
    plt.title("Proportions of Customer Churn")
    plt.show()
    
    
    
    
    # In[16]:
    
    
    # 性别、老年人、配偶、亲属对流客户流失率的影响
    f, axes = plt.subplots(nrows=2, ncols=2, figsize=(10,10))
    
    
    plt.subplot(2,2,1)
    gender=sns.countplot(x="gender",hue="Churn",data=telcom,palette="Pastel2") # palette参数表示设置颜色,这里设置为主题色Pastel2
    plt.xlabel("gender")
    plt.title("Churn by Gender")
    
    
    plt.subplot(2,2,2)
    seniorcitizen=sns.countplot(x="SeniorCitizen",hue="Churn",data=telcom,palette="Pastel2")
    plt.xlabel("senior citizen")
    plt.title("Churn by Senior Citizen")
    
    
    plt.subplot(2,2,3)
    partner=sns.countplot(x="Partner",hue="Churn",data=telcom,palette="Pastel2")
    plt.xlabel("partner")
    plt.title("Churn by Partner")
    
    
    plt.subplot(2,2,4)
    dependents=sns.countplot(x="Dependents",hue="Churn",data=telcom,palette="Pastel2")
    plt.xlabel("dependents")
    plt.title("Churn by Dependents")
    
    
    
    
    # In[17]:
    
    
    # 提取特征
    charges=telcom.iloc[:,1:20]
    # 对特征进行编码
    """
    离散特征的编码分为两种情况:
    1、离散特征的取值之间没有大小的意义,比如color:[red,blue],那么就使用one-hot编码
    2、离散特征的取值有大小的意义,比如size:[X,XL,XXL],那么就使用数值的映射{X:1,XL:2,XXL:3}
    """
    corrDf = charges.apply(lambda x: pd.factorize(x)[0])
    corrDf .head()
    
    
    
    
    # In[18]:
    
    
    # 构造相关性矩阵
    corr = corrDf.corr()
    corr
    
    
    
    
    # In[19]:
    
    
    # 使用热地图显示相关系数
    '''
    heatmap    使用热地图展示系数矩阵情况
    linewidths 热力图矩阵之间的间隔大小
    annot      设定是否显示每个色块的系数值
    '''
    plt.figure(figsize=(20,16))
    ax = sns.heatmap(corr, xticklabels=corr.columns, yticklabels=corr.columns, 
                     linewidths=0.2, cmap="YlGnBu",annot=True)
    plt.title("Correlation between variables")
    
    
    
    
    # 结论:从上图可以看出,互联网服务、网络安全服务、在线备份业务、设备保护业务、技术支持服务、网络电视和网络电影之间存在较强的相关性,多线业务和电话服务之间也有很强的相关性,并且都呈强正相关关系。
    
    
    # In[20]:
    
    
    # 使用one-hot编码
    tel_dummies = pd.get_dummies(telcom.iloc[:,1:21])
    tel_dummies.head()
    
    
    
    
    # In[21]:
    
    
    # 电信用户是否流失与各变量之间的相关性
    plt.figure(figsize=(15,8))
    tel_dummies.corr()['Churn'].sort_values(ascending = False).plot(kind='bar')
    plt.title("Correlations between Churn and variables")
    
    
    
    
    # 由图上可以看出,变量gender 和 PhoneService 处于图形中间,其值接近于 0 ,这两个变量对电信客户流失预测影响非常小,可以直接舍弃。
    
    
    # In[22]:
    
    
    # 网络安全服务、在线备份业务、设备保护业务、技术支持服务、网络电视、网络电影和无互联网服务对客户流失率的影响
    covariables=["OnlineSecurity", "OnlineBackup", "DeviceProtection", "TechSupport", "StreamingTV", "StreamingMovies"]
    fig,axes=plt.subplots(nrows=2,ncols=3,figsize=(16,10))
    for i, item in enumerate(covariables):
        plt.subplot(2,3,(i+1))
        ax=sns.countplot(x=item,hue="Churn",data=telcom,palette="Pastel2",order=["Yes","No","No internet service"])
        plt.xlabel(str(item))
        plt.title("Churn by "+ str(item))
        i=i+1
    plt.show()
    
    
    
    
    # 由上图可以看出,在网络安全服务、在线备份业务、设备保护业务、技术支持服务、网络电视和网络电影六个变量中,没有互联网服务的客户流失率值是相同的,都是相对较低。
    # 
    # 这可能是因为以上六个因素只有在客户使用互联网服务时才会影响客户的决策,这六个因素不会对不使用互联网服务的客户决定是否流失产生推论效应。
    
    
    # In[23]:
    
    
    # 签订合同方式对客户流失率的影响
    sns.barplot(x="Contract",y="Churn", data=telcom, palette="Pastel1", order= ['Month-to-month', 'One year', 'Two year'])
    plt.title("Churn by Contract type")
    
    
    
    
    # 由图上可以看出,签订合同方式对客户流失率影响为:按月签订 > 按一年签订 > 按两年签订,这可能表明,设定长期合同对留住现有客户更有效。
    
    
    # In[24]:
    
    
    # 付款方式对客户流失率的影响
    plt.figure(figsize=(10,5))
    sns.barplot(x="PaymentMethod",y="Churn", data=telcom, palette="Pastel1", order= ['Bank transfer (automatic)', 'Credit card (automatic)', 'Electronic check','Mailed check'])
    plt.title("Churn by PaymentMethod type")
    
    
    
    
    # 由图上可以看出,在四种支付方式中,使用Electronic check的用户流流失率最高,其他三种支付方式基本持平,因此可以推断电子账单在设计上影响用户体验。
    
    
    
    
    
    
    
    
    # ## 5、数据预处理
    
    
    # 由前面结果可知,CustomerID表示每个客户的随机字符,对后续建模不影响,我这里选择删除CustomerID列;gender 和 PhoneService 与流失率的相关性低,可直接忽略。
    
    
    # In[26]:
    
    
    telcomvar=telcom.iloc[:,2:20]
    telcomvar.drop("PhoneService",axis=1, inplace=True)
    
    
    # 提取ID
    telcom_id = telcom['customerID']
    
    
    telcomvar.head()
    
    
    
    
    # In[27]:
    
    
    # 对客户的职位、月费用和总费用进行去均值和方差缩放,对数据进行标准化
    """
    标准化数据,保证每个维度的特征数据方差为1,均值为0,使得预测结果不会被某些维度过大的特征值而主导。
    """
    scaler = StandardScaler(copy=False)
    # fit_transform()的作用就是先拟合数据,然后转化它将其转化为标准形式
    scaler.fit_transform(telcomvar[['tenure','MonthlyCharges','TotalCharges']])
    
    
    
    
    # In[28]:
    
    
    # tranform()的作用是通过找中心和缩放等实现标准化
    telcomvar[['tenure','MonthlyCharges','TotalCharges']]=scaler.transform(telcomvar[['tenure','MonthlyCharges','TotalCharges']])
    
    
    
    
    # In[29]:
    
    
    # 使用箱线图查看数据是否存在异常值
    plt.figure(figsize = (8,4))
    numbox = sns.boxplot(data=telcomvar[['tenure','MonthlyCharges','TotalCharges']], palette="Set2")
    plt.title("Check outliers of standardized tenure, MonthlyCharges and TotalCharges")
    
    
    
    
    # 由以上结果可以看出,在三个变量中不存在明显的异常值
    
    
    # In[30]:
    
    
    # 查看对象类型字段中存在的值
    def uni(columnlabel):
        print(columnlabel,"--" ,telcomvar[columnlabel].unique())  # unique函数去除其中重复的元素,返回唯一值
    
    
    telcomobject=telcomvar.select_dtypes(['object'])
    for i in range(0,len(telcomobject.columns)):
        uni(telcomobject.columns[i])
    
    
    
    
    # 综合之前的结果来看,在六个变量中存在No internet service,即无互联网服务对客户流失率影响很小,这些客户不使用任何互联网产品,因此可以将No internet service 和 No 是一样的效果,可以使用 No 替代 No internet service
    
    
    # In[31]:
    
    
    telcomvar.replace(to_replace='No internet service', value='No', inplace=True)
    telcomvar.replace(to_replace='No phone service', value='No', inplace=True)
    for i in range(0,len(telcomobject.columns)):
        uni(telcomobject.columns[i])
    
    
    
    
    # In[32]:
    
    
    # 使用Scikit-learn标签编码,将分类数据转换为整数编码
    def labelencode(columnlabel):
        telcomvar[columnlabel] = LabelEncoder().fit_transform(telcomvar[columnlabel])
    
    
    for i in range(0,len(telcomobject.columns)):
        labelencode(telcomobject.columns[i])
    
    
    for i in range(0,len(telcomobject.columns)):
        uni(telcomobject.columns[i])
    
    
    
    
    # ## 6、构建模型
    
    
    # ### (1)建立训练数据集和测试数据集
    
    
    # In[33]:
    
    
    """
    我们需要将数据集拆分为训练集和测试集以进行验证。
    由于我们所拥有的数据集是不平衡的,所以最好使用分层交叉验证来确保训练集和测试集都包含每个类样本的保留人数。
    交叉验证函数StratifiedShuffleSplit,功能是从样本数据中随机按比例选取训练数据(train)和测试数据(test)
    参数 n_splits是将训练数据分成train/test对的组数,可根据需要进行设置,默认为10
    参数test_size和train_size是用来设置train/test对中train和test所占的比例
    参数 random_state控制是将样本随机打乱
    """
    X=telcomvar
    y=telcom["Churn"].values
    
    
    sss=StratifiedShuffleSplit(n_splits=5, test_size=0.2, random_state=0)
    print(sss)
    print("训练数据和测试数据被分成的组数:",sss.get_n_splits(X,y))
    
    
    
    
    # In[34]:
    
    
    # 建立训练数据和测试数据
    for train_index, test_index in sss.split(X, y):
        print("train:", train_index, "test:", test_index)
        X_train,X_test=X.iloc[train_index], X.iloc[test_index]
        y_train,y_test=y[train_index], y[test_index]
    
    
    
    
    # In[35]:
    
    
    # 输出数据集大小
    print('原始数据特征:', X.shape,
          '训练数据特征:',X_train.shape,
          '测试数据特征:',X_test.shape)
    
    
    print('原始数据标签:', y.shape,
          '   训练数据标签:',y_train.shape,
          '   测试数据标签:',y_test.shape)
    
    
    
    
    # ### (2)选择机器学习算法
    
    
    # In[36]:
    
    
    # 使用分类算法,这里选用10种分类算法
    Classifiers=[["Random Forest",RandomForestClassifier()],
                 ["Support Vector Machine",SVC()],
                 ["LogisticRegression",LogisticRegression()],
                 ["KNN",KNeighborsClassifier(n_neighbors=5)],
                 ["Naive Bayes",GaussianNB()],
                 ["Decision Tree",DecisionTreeClassifier()],
                 ["AdaBoostClassifier", AdaBoostClassifier()],
                 ["GradientBoostingClassifier", GradientBoostingClassifier()],
                 ["XGB", XGBClassifier()],
                 ["CatBoost", CatBoostClassifier(logging_level='Silent')]  
    ]
    
    
    
    
    # ### (3)训练模型
    
    
    # In[37]:
    
    
    Classify_result=[]
    names=[]
    prediction=[]
    for name,classifier in Classifiers:
        classifier=classifier
        classifier.fit(X_train,y_train)
        y_pred=classifier.predict(X_test)
        recall=recall_score(y_test,y_pred)
        precision=precision_score(y_test,y_pred)
        class_eva=pd.DataFrame([recall,precision])
        Classify_result.append(class_eva)
        name=pd.Series(name)
        names.append(name)
        y_pred=pd.Series(y_pred)
        prediction.append(y_pred)
    
    
    
    
    # ### (4)评估模型
    
    
    # In[38]:
    
    
    # 评估模型
    """
    召回率(recall)的含义是:原本为对的当中,预测为对的比例(值越大越好,1为理想状态)
    精确率、精度(precision)的含义是:预测为对的当中,原本为对的比例(值越大越好,1为理想状态)
    F1分数(F1-Score)指标综合了Precision与Recall的产出的结果
    F1-Score的取值范围从0到1的,1代表模型的输出最好,0代表模型的输出结果最差。
    """
    
    
    names=pd.DataFrame(names)
    names=names[0].tolist()
    result=pd.concat(Classify_result,axis=1)
    result.columns=names
    result.index=["recall","precision","f1score"]
    result
    
    
    
    
    # 综上所述,在10种分类算法中朴素贝叶斯(Naive Bayes)的F1分数最大为63.31%,所以使用朴素贝叶斯模型效果最好。
    
    
    # ## 7、实施方案
    
    
    # 预测数据集特征(由于没有提供预测数据集,这里选取后10行作为需要预测的数据集)
    pred_X = telcomvar.tail(10)
    
    
    # 提取customerID
    pre_id = telcom_id.tail(10)
    
    
    # 使用朴素贝叶斯方法,对预测数据集中的生存情况进行预测
    model = GaussianNB()
    model.fit(X_train,y_train)
    pred_y = model.predict(pred_X)
    
    
    # 预测结果
    predDf = pd.DataFrame({'customerID':pre_id, 'Churn':pred_y})
    predDf
    

         精 彩 文 章 

    END
    最后说个题外话,相信大家都知道视频号了,随着灰度范围扩大,越来越多的小伙伴都开通了视频号。小詹也开通了一个视频号,会分享互联网那些事、读书心得与副业经验,欢迎扫码关注,和小詹一起向上生长!「没有开通发布权限的尽量多互动,提升活跃度可以更快开通哦」
    
    
    展开全文
  • python数据分析实例:客户流失预警模型 客户流失是电信行业最重要的服务方面之一。客户流失的广义说法是因为客户自己或运营商违反服务协议而终止客户服务的行为。 流失预测流程一共分为四个步骤,分别为(1)数据...

    python数据分析实例:客户流失预警模型

    客户流失是电信行业最重要的服务方面之一。客户流失的广义说法是因为客户自己或运营商违反服务协议而终止客户服务的行为。

    流失预测流程一共分为四个步骤,分别为(1)数据预处理(2)特征选择(3)模型选择(4)模型评估

    1. 数据理解

    数据取自于kaggle平台分享的数据集,共有21个字段7043条记录。 数据主要包括影响客户流失的各种因素(性别、是否为老年人、客户是否有合作伙伴、客户是否有依赖关系、客户在公司停留的月数、客户是否有电话服务、客户是否有多条线路、客户的互联网服务提供商、客户是否有网上安全等)以及客户是否已经流失的对应记录。 字段基本说明如下:
    在这里插入图片描述

    可以发现,数据质量良好,没有缺失数据。

    2.探索性分析

    2.1 描述性统计

    df.describe().T
    

    在这里插入图片描述
    从上述描述性分析结果可以看出:

    是否老年人:范围0~1, 中位数0, 均值0.162147, 总体来说老年客户占比小;

    客户在公司停留的月数:范围0~72, 中位数29, 均值32.371149;

    每月收取的费用:范围18.25~118.75, 中位数70.35, 均值64.761692;

    从中可以看出离散型变量较多,适合用RF模型进行预测

    3. 数据预处理

    由于sklearn在建模时不接受类别型变量,我们主要对数据做以下处理,以方便后续建模分析:

    1. 性别、合同时长、支付方式是定类型变量, 对其进行one-hot编码。
    # 哑变量
    df_dummies = pd.get_dummies(df,prefix=' ')
    

    4. 建模分析

    from sklearn.model_selection import train_test_split, GridSearchCV
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.metrics import classification_report, f1_score, roc_curve, plot_roc_curve
    #划分测试集和训练集
    x = df_dummies.drop('churn', axis=1)
    y = df_dummies['churn']
    
    X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, stratify=y, random_state=2020)
    print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
    #采用基尼系数,树的深度为5去预测节点
    clf = DecisionTreeClassifier(criterion='gini', max_depth=5, random_state=25)
    clf.fit(X_train, y_train)
    train_pred = clf.predict(X_train)
    test_pred = clf.predict(X_test)
    
    print('训练集:', classification_report(y_train, train_pred))
    print('-' * 60)
    print('测试集:', classification_report(y_test, test_pred))
    #查看个变量之间的相关系数
    imp = pd.DataFrame([*zip(X_train.columns,clf.feature_importances_)], columns=['vars', 'importance'])
    imp.sort_values('importance', ascending=False)
    imp = imp[imp.importance!=0]
    
    
    rf_model = RandomForestClassifier(n_estimators=1000, oob_score=True, n_jobs=-1,
                                      random_state=0)
    parameters = {'max_depth': np.arange(3, 17, 1) }
    GS = GridSearchCV(rf_model, param_grid=parameters, cv=10)
    GS.fit(X_train, y_train)
    
    print(GS.best_params_)
    

    在本例中,使用决策树训练结果在这里插入图片描述
    可以看出准确率很低,1类 f1score只有0.6

    相关度分析:
    在这里插入图片描述
    可以看出合同月制对客户流失有很大影响,其次电子支付也有一定影响

    最后采用rf并使用网格搜索进行参数调优之后,模型准确率如下

    {'criterion': 'gini', 'max_depth': 20, 'splitter': 'best'}
    0.9500813177648042
    

    模型的f1_score=0.95 明显提升

    随机森林的优点较多,简单总结:

    训练可以高度并行化,对于大数据时代的大样本训练速度有优势
    由于随机选择特征时只考虑特征子集,因此样本特征维度很高时仍然高效
    训练后,可以给出各个特征的重要性
    由于采用了随机采样,方差小,泛化能力强
    相比Boosting,实现简单

    RF的缺点:在噪声较大的分类或者回归问题上会过拟合。

    在本例中,因为有几个字段是连续性变量,模型容易过拟合,泛化能力下降,后续可以通过分箱,或者采用boosting学习器方法下的XGboost提升模型泛化能力

    展开全文
  • 利用python建立客户流失预警模型(下)——建立模型 前言 上一部分已经完成了对数据的整理与分析,接下来建立数据分析模型。 首先,建立分类模型预测客户是否会流失。逻辑回归,决策树,随机森林,xgboost等可用于...
  • 分类问题属于机器学习问题的类别,其中给定一组功能,任务是预测离散值。分类问题的一些常见示例是,预测肿瘤是否为癌症,或者学生是否可能...因此,我们的任务是根据各种客户特征预测客户流失。 $ pip ins...
  • 在对客户流失与否的影响因素进行模型研究之前,首先对各解释变量与被解释变量进行两变量独立性分析,以初步判断影响流失的因素,进而建立客户流失预测模型 二、数据集 主要变量说明如下: #subscriberID="个人客户的...
  • 机器学习分类模型预测银行的客户流失。 嗨,访客们! 我是数据科学的新手,但我正在通过使用在线可用数据集将所有学习实践付诸实践。 我已经使用Python生成了机器学习分类模型! 我仍在学习,随着我学到更多,我...
  • 作者:Carl Dawson编译:ronghuaiyang导读借用生存分析的方法来进行用户流失的预测,用到了Cox Proportional Hazards模型客户流失率很难预测。在你...
  • 本实战课程通过一个详细的动手实验帮助你使用IBM Watson Studio构建一个银行业中常见的预测客户流失模型。通过动手实验,你将会掌握如何使用Python创建SK-Learn模型,以及如何使用可视化的画布模式训练模型
  • 客户流失预测该项目包含美国马萨诸塞州零售超市的数据。 超市连锁店面临着很高的客户流失率,结果导致整体销售额下降,从而导致利润下降。 为了扭转顾客流失,商店希望向他们不会流失的顾客分发折扣券。 为了确定将...
  • 此外,我们将使用流行的Python库(例如Tensorflow,Keras)和机器学习技术(例如Adam Optimizer)来训练ANN模型预测客户流失率。 数据:客户数据存储在: 论文:ANN案例研究论文: 研究论文 代码:Artificial_...
  • 客户流失分析 失去一个老用户会带来巨大的损失,大概需要公司拉新10个新用户才能予以弥补。如何预测客户即将流失,让公司采取合适的挽回措施,是每个公司都要关注的重点问题。 目标 利用类神经网络构建用户流失...
  • 客户流失分析 失去一个老用户会带来巨大的损失,大概需要公司拉新10个新用户才能予以弥补。如何预测客户即将流失,让公司采取合适的挽回措施,是每个公司都要关注的重点问题。 目标 利用类神经网络构建用户流失分析...
  • 他是基于Pareto/NBD模型假设设计的概率预测模型。 BG/NBD模型是用于描述非契约客户关系情境下重复购买行为。 即用户可以随时购买产品,无时间约束。 该模型可利用用户历史交易数据(RFM)来预测未来每个用户的交易次数...
  • 注意: 3X项目仅使用Python 3.X和Tableau 10.0及更高版本进行分析 PPT-包含业务问题和转换为DS问题 Tableau-EDA洞察 功能选择 各种分类模型 最终PPT-解释 报告 安装 $ pip install imblearn # For Smote 问题陈述 ...
  • 使用Python进行机器学习 由IBM在Coursera上提供 我了解了机器学习的目的及其在现实世界中的应用。 我对机器学习主题进行了概述,... 癌症检测,预测经济趋势,预测客户流失,推荐引擎等等。 最终的Capston项目: 证书:
  • 使用Keras和Scikit-Learn的银行数据集的客户流失预测模型 从零开始实施随机森林,并在UCI存储库的Sonar数据集上建立分类器 示例数据集上Python中的简单线性回归 Python在样本数据集上的多元回归 PCA和使用Python缩放...
  • Project5:用户流失预测在此项目中,我们使用监督学习模型来识别将来可能会停止使用服务的客户。 此外,我们将分析影响用户保留率的主要因素。 Project6:文档聚类和主题建模在此项目中,我们使用无监督学习模型将...
  • final-project-DSE200x-源码

    2021-04-05 19:14:35
    来自Kaggle的电子商务数据集“电子商务客户流失分析和预测”用于探索我们是否可以使用现有客户数据来预测客户是否流失。 为了探索该分类任务,使用了逻辑回归,决策树和K折交叉验证方法。 调查结果显示准确性得分从...
  • Repository-源码

    2021-03-28 01:07:27
    我的投资组合 我的投资组合 目录 介绍 欢迎来到我很棒的数据科学项目组合。 在我的回购中,您可以使用统计方法和最新的机器学习模型为某些现实世界中的业务问题... 当客户流失率高于增长率时,该公司的客户群就会遭受
  • lifetime_value-源码

    2021-04-15 11:52:47
    这种建模方法使我们能够捕获流失概率并同时考虑LTV的重尾性,并且还允许对点预测进行简单的不确定性量化。 提出的损失函数可用于线性模型和深度神经网络(DNN)。 我们还提倡使用标准化的Gini系数来量化模型歧视,...
  • 我的数据科学档案 MyDataSciencePortfolio由以下工具赞助。... :backhand_index_pointing_down: :backhand_index_pointing_down: :victory_hand_selector: :victory_hand_selector: ...客户流失研究 流失率是重要的业
  • LucasEzBM-源码

    2021-03-26 03:20:00
    在这段时间里,我已经针对商业问题开发了解决方案,例如识别客户​​流失,确定客户的交叉销售优先级,降低CAC值,预测商店销售额以及根据从广告网站上抓取的数据创建EDA。 每个项目的详细信息在下面的项目中进行...

空空如也

空空如也

1 2
收藏数 34
精华内容 13
关键字:

客户流失预测模型python

python 订阅