相关文章推荐
小眼睛的红豆  ·  WPF ...·  1 年前    · 
没读研的炒粉  ·  if if else sql server-掘金·  1 年前    · 
个性的小虾米  ·  (十一)Electron ...·  1 年前    · 
Python:用户画像与用户续订预测分析

Python:用户画像与用户续订预测分析

一、分析背景及数据来源

1.1、分析背景:

本文基于营销数据,描绘用户画像,并根据用户相关特征,对用户是否续约进行预测分析。用户画像是根据用户的基础属性、社会属性、行为特征、心理特征等信息抽象出的一个标签化用户模型,而标签是通过对用户信息分析高度精炼的特征符号。

用户画像的作用主要在于:

  1. 培养用户思维,产品研发前,让我们可以站在用户角度去设计产品和营销方案;
  2. 精准营销,产品推向市场时,可帮我们分析产品潜在用户,针对不同画像的用户进行相应的营销活动;
  3. 提升产品,产品推向市场后,用户画像可帮我们更聚焦的洞察用户需求,对产品进行针对性的提升。

1.2、数据集来源:

二、提出问题

本文主要探究两个问题:

三、理解数据

四、数据清洗

导入常用数据分析包、可视化包、及数据集

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from pyecharts.charts import Sankey
from pyecharts import options as opts
#可视化包中文及字符正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
#忽略警告提示
import warnings
warnings.filterwarnings('ignore')
source=pd.read_csv(r'/Users/项目实战/Kaggle-用户画像与用户续订预测分析/WA_Fn-UseC_-Marketing-Customer-Value-Analysis.csv')
source.head()

3.1、选取子集

本次分析中,预测分析所需字段暂不明确,故所有字段保留。

3.2、删除重复值

判断是否存在重复值:

any(source.duplicated(subset=['Customer']))

结果输出为False,证明数据集不存在重复值。

3.3、缺失值处理

查询每列数据缺失率

source.apply(lambda x: sum(x.isnull())/len(x), axis=0)

可以发现,该数据集不存在缺失值。

3.4、数据排序

本次数据集中不需要排序处理。

3.5、异常值处理

查看异常值(使用四分位法判断)

#下四分位数
Q1=source.Income.quantile(q=0.25)
#上四分位数
Q3=source.Income.quantile(q=0.75)
IQR=Q3-Q1
print('是否超过上限判断:',any(source.Income>Q3+1.5*IQR))
print('是否超过下限判断:',any(source.Income<Q1-1.5*IQR))

以上方法使用‘Income’列为例,使用同样的方法可以查询各列的最大最小值均符合正常逻辑,故判断不存在异常值。

四、分析建模

本文通过python进行可视化展示和客户续约预测

导入预测所需的机器学习分析包

#导入数据分析包
import sklearn
from sklearn import preprocessing #数据预处理“https://blog.csdn.net/weixin_40807247/article/details/82793220”
from sklearn.preprocessing import LabelEncoder #编码转换
from sklearn.preprocessing import StandardScaler#归一化处理 “https://blog.csdn.net/wzyaiwl/article/details/90549391”
from sklearn.model_selection import StratifiedShuffleSplit #分层抽样功能 “https://blog.csdn.net/wtzhu_13/article/details/93903868”
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 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 statsmodels.api as sm #详情介绍:Introduction - statsmodels

4.1、用户画像

4.1.1、基础属性

1、用户性别分布

#查看各性别人数
gender_data =source.groupby('Gender')['Customer'].count()
#数据转换为dataframe类型
gender_data=gender_data.to_frame()
gender_data
plt.figure(figsize=(8,5),dpi=80)
plt.pie(gender_data['Customer'],labels=gender_data.index,colors=["#1F6ED4","#B9EDF8"],autopct="%1.1f%%",shadow=False,startangle=30,pctdistance=0.6)
plt.axis("equal")
plt.legend(loc="best")
plt.title("用户画像——性别分布",fontsize=15)
plt.show()

结论:可以看出用户性别分布大致相等,没有明显区别。

2、用户地域分布

#查看用户地域分布
loc_data=source.groupby(['Location Code','State'])['Customer'].count()
#转换数据类型
loc_data=loc_data.to_frame()
#重置索引方便后续处理数据
loc_data=loc_data.reset_index()
loc_data

使用python绘制桑葚图进行可视化展示:

#设置节点
nodes=[]
for i in range(2):
    values = loc_data.iloc[:,i].unique()
    for values in values:
        dic={}
        dic["name"]=values
        nodes.append(dic)
nodes
#定义边界和流量
linkes=[]
for i in loc_data.values:
    dic={}
    dic["source"]=i[0]
    dic["target"]=i[1]
    dic["value"]=i[2]
    linkes.append(dic)
linkes
#绘制桑基图
pic = (Sankey().add("Customer",nodes,linkes,
                   linestyle_opt=opts.LineStyleOpts(opacity=0.3,curve=0.5,color="source"),
                    label_opts=opts.LabelOpts(position="right"),
                    node_gap=30).
       set_global_opts(title_opts=opts.TitleOpts(title="客户地域分布桑基图"))
pic.render(path="/Users/shenzhengang/Downloads/客户地域分布桑基图.html")

结论:可以看出用户主要分布在郊区,可能因为上下班距离远,开车更方便,有车群体规模更大。其中又以加利福尼亚州的用户占比最多。

3、用户教育水平

#查看用户教育情况分布
education_data=source.groupby('Education')['Customer'].count()
#转换数据类型
education_data=education_data.to_frame()
education_data
#绘图
plt.figure(figsize=(10,5),dpi=80)
rects=plt.bar(x=range(len(education_data.index)),height=education_data["Customer"],label="user_num",color='#1F6ED4')
#添加轴刻度
plt.xticks(range(len(education_data.index)),education_data.index,fontsize=12)
#添加轴标签
plt.xlabel("教育水平")
plt.ylabel("用户数")
#添加柱状数据
for rect in rects:
    height = rect.get_height()
    plt.text(rect.get_x()+rect.get_width()/2,height+10,str(height),ha="center")
    #添加其他标签
plt.legend(loc="best")
plt.title("用户教育水平分布",fontsize=15)
plt.show()

结论:可以看出硕士和博士的用户人数明显少于学士、高等教育学历和高中及以下学历的人数。

4、用户年收入分布

#划分收入区间
bins = [0, 10000, 30000, 50000, 70000,90000,max(source['Income'])+1]
#划分用户收入数据
income_data=pd.cut(source['Income'], bins, right=False)
#统计各收入区间用户人数
income_data=pd.value_counts(income_data)
income_data
#统计各收入区间用户人数
income_data=pd.value_counts(income_data)
#重置索引名称
income_data.index=['1万以下','1万-3万','3万-5万','5万-7万','7万-9万','9万以上']
#重置行名称
income_data.columns=['user_num']
income_data
#绘图
plt.figure(figsize=(10,5),dpi=80)
rects=plt.bar(range(len(income_data.index)),income_data["user_num"],label="user_num",color='#1F6ED4')
#设置x轴刻度
plt.xticks(range(len(income_data.index)),income_data.index,fontsize=10)
#设置轴标签
plt.xlabel("收入水平")
plt.ylabel("用户数")
#设置桩顶数据
for rect in rects:
    height=rect.get_height()
    plt.text(rect.get_x()+rect.get_width()/2,height+10,str(height),ha="center",)
#设置其他标签
plt.legend(loc="best")
plt.title("用户收入分布",fontsize=15)
plt.show()

结论:用户收入区间,用户收入主要集中在5万以下。

5、用户车辆情况

#用户拥有车型分布数据
vehicel_data=source.groupby(['Vehicle Size','Vehicle Class'])['Customer'].count()
#转换数据类型
vehicel_data=vehicel_data.to_frame()
#重置索引方便后续处理数据
vehicel_data=vehicel_data.reset_index()
vehicel_data
#绘制桑基图
#设置节点
nodes = []
for i in range(2):
    values = vehicel_data.iloc[:,i].unique()
    for value in values:
        dic={}
        dic["name"]=value




    

        nodes.append(dic)
nodes
#设置边界和流量
linkes=[]
for i in vehicel_data.values:
    dic={}
    dic["source"]=i[0]
    dic["target"]=i[1]
    dic["value"]=i[2]
    linkes.append(dic)
linkes
#绘制桑基图
pic = Sankey().add("Customer",nodes,linkes,
                   linestyle_opt=opts.LineStyleOpts(opacity=0.3,curve=0.5,color="source"),
                   label_opts=opts.LabelOpts(position="left"),
                   node_gap=30).set_global_opts(title_opts=opts.TitleOpts(title="客户车型分布桑基图"))
pic.render(path="/Users/shenzhengang/Downloads/客户车型分布桑基图.html")

结论:可以看出用户主要以中型车和四门车是主流。

4.1.2、社会属性

1、婚姻状态

#婚姻状况用户画像
marital_data=source.groupby('Marital Status')['Customer'].count()
#修改数据格式
marital_data=marital_data.to_frame()
#重置行名称
marital_data.columns=['user_num']
#绘图
plt.figure(figsize=(10,5),dpi=80)
rects=plt.bar(range(len(marital_data.index)),marital_data["user_num"],label="user_num",color='#1F6ED4')
#标注横坐标刻度
plt.xticks(range(len(marital_data.index)),marital_data.index)
#添加柱顶数据
for rect in rects:
    height = rect.get_height()
    plt.text(rect.get_x()+rect.get_width()/2,height+10,str(height),ha="center")
#标注轴标签
plt.xlabel("婚姻状态")
plt.ylabel("用户数")
#添加其他标签
plt.legend(loc="best")
plt.title("用户婚姻状态分布情况",fontsize=15)
plt.show()

结论:用户主要是已婚状态,其次为单身状态。

2、职业状态

#职业状态用户画像
employstatus_data=source.groupby('EmploymentStatus')['Customer'].count()
#修改数据格式
employstatus_data=employstatus_data.to_frame()
#重置行名称
employstatus_data.columns=['user_num']
employstatus_data
#绘图
plt.figure(figsize=(10,5),dpi=80)
rects=plt.bar(range(len(employstatus_data.index)),employstatus_data["user_num"],label="user_num",color='#1F6ED4')
#绘制横轴刻度
plt.xticks(range(len(employstatus_data.index)),employstatus_data.index)
#绘制柱顶数据
for rect in rects:
    height = rect.get_height()
    plt.text(rect.get_x()+rect.get_width()/2,height+10,str(height),ha="center")
#绘制轴标签
plt.xlabel("就业状态")
plt.ylabel("用户数")
#绘制其他标签
plt.legend(loc="best")
plt.title("用户就业状态分布",fontsize=15)
plt.show()

结论:可以看出用户有稳定工作的为主,结合用户收入分布,用户群体主要是有稳定工作的中下收入人员。

4.1.3、行为特征

1、选择的产品类型

#保险类型
policy_data=source.groupby('Policy Type')['Customer'].count()
#修改数据格式
policy_data=policy_data.to_frame()
#重置行名称
policy_data.columns=['user_num']
policy_data
#绘图
plt.figure(figsize=(10,5),dpi=80)
rects=plt.bar(range(len(policy_data.index)),policy_data["user_num"],label="user_num",color='#1F6ED4')
#绘制横坐标刻度
plt.xticks(range(len(policy_data.index)),policy_data.index)
#绘制柱状图顶数据
for rect in rects:
    height = rect.get_height()
    plt.text(rect.get_x()+rect.get_width()/2,height+10,str(height),ha="center")
#绘制轴标签
plt.xlabel("保险类型")
plt.ylabel("用户数")
#绘制其他标签
plt.legend(loc="best")
plt.title("用户保险类型分布",fontsize=15)
plt.show()

结论:选择的产品类型主要是私人产品类型为主。

2、客户来源渠道

#客户来源渠道
sale_channel_data=source.groupby('Sales Channel')['Customer'].count()
#修改数据格式
sale_channel_data=sale_channel_data.to_frame()
#重置行名称
sale_channel_data.columns=['user_num']
sale_channel_data
#绘图
plt.figure(figsize=(10,5),dpi=80)
rects=plt.bar(range(len(sale_channel_data.index)),sale_channel_data["user_num"],label="user_num")
#添加横坐标轴刻度
plt.xticks(range(len(sale_channel_data.index)),sale_channel_data.index)
#添加柱顶数据
for rect in rects:
    height=rect.get_height()
    plt.text(rect.get_x()+rect.get_width()/2,height+10,str(height),ha="center")
#添加轴标签
plt.xlabel("客户来源渠道")
plt.ylabel("用户数")
#添加其他标签
plt.legend(loc="best")
plt.title("用户来源渠道分布",fontsize=15)
plt.show()

结论:可以看出用户主要来源于代理商和分支机构两个渠道。

3、客户终身价值

#设置区间
bins = [0, 10000, 30000, 50000, 80000,max(source['Customer Lifetime Value'])+1]
#划分客户终身价值分布
lifevalue_data=pd.cut(source['Customer Lifetime Value'], bins, right=False)
#统计各收入区间用户人数
lifevalue_data=pd.value_counts(lifevalue_data)
#修改数据格式
lifevalue_data=lifevalue_data.to_frame()
#重置行名称
lifevalue_data.columns=['user_num']
lifevalue_data

结论:可以看出客户终身价值主要在1万以下,2万以下的占绝对数量。

4.2、用户续约预测分析

本次预测以客户是否续约(对应字段为Response)为预测目的,进行相关性预测探究

4.2.1、选择数据

#查看数据大小
source.shape
#查看数据集详细信息
source.info()

因为之前已经进行过数据清洗工作,所以这里可以直接开始分析工作。

#定义图例中的数据为百分比标签添加
def annot_plot(ax):
    #data to plot
    ax.spines["top"].set_visible(False)#设置顶部边框为空
    ax.spines["right"].set_visible(False)#设置右侧边框为空
    for p in ax.patches:
        ax.annotate(f"{p.get_height()*100/source.shape[0]:.2f}%",(p.get_x()+p.get_width()/2,p.get_height()),
                   ha="center",va="center",fontsize=11,color="black",rotation=0,xytext=(0,10),textcoords="offset points")

4.2.2、离散变量与用户续约率的探索分析

1、客户续订率分布

#续订率
ax = sns.countplot("Response",data=source)
plt.ylabel("续订率")
annot_plot(ax)
plt.show()

结论:可以看出客户续约率占比较少,仅占14.32%,数据分布不均衡,所以后续在拆分训练数据集和测试数据集时,采用分层交叉验证来确保训练集和测试集都包含每个类样本的人数。

2、不同续约类型的续约率

#续订类型
ax=sns.countplot("Response",hue="Renew Offer Type",data = source)
plt.ylabel("续订率")
plt.legend(loc="upper right")
annot_plot(ax)
plt.show()

结论:offer1和offer2是最多续订的保险类型,offer3和offer4则几乎没有续订。

3、不同销售渠道的续约率

#销售渠道
ax = sns.countplot("Response",hue="Sales Channel",data=source)
plt.ylabel("续订率")
annot_plot(ax)
plt.show()

结论:可以看出代理商渠道的续订率最高,约等于其他三个渠道之和。

4、续订率与婚姻状态的关系

#续订率与婚姻状态的关系
ax=sns.countplot("Response",hue="Marital Status",data=source)
plt.ylabel("续订率")
annot_plot(ax)
plt.show()




结论:可以看出在所有续订客户中,已婚的用户占比最高,在续订客户中超过一半。此外离异用户占比不多,但是在该人群续约占比却比较高。

5、不同就业状态的续约率

#就业状态
ax=sns.countplot("Response",hue="EmploymentStatus",data = source)
plt.ylabel("续订率")
annot_plot(ax)
plt.show()

结论:可以看出稳定就业的用户续订率最高,超过其他就业状态之和,但是社会人群还是以稳定就业占绝大多数。其中值得注意的是退休状态的用户,其续约率较高,可能是年纪大精力有限不愿变化,粘性比较高。

4.2.3、连续变量与用户续约率的探索分析

1、出险金额的续约分布情况

#出险金额
sns.boxplot(x="Response",y="Total Claim Amount",data = source)
plt.ylabel("不同续订状态的用户出险金额分布情况")
plt.show()

结论:可以看出续订与不续订的用户的出险金额分布大体一致,其中不续约用户的出险金额异常值超出正常范围的较多 ( 正常数据范围:四分之一分位-1.5*IQR至四分之三分位+1.5*IQR被认为是合理值,范围之外的数据认为是异常值)

2 、收入群体的续订率分布情况

#不同收入群体的续订率
sns.boxplot(x="Response",y="Income",data=source)
plt.ylabel("不同续订状态的客户收入分布情况")
plt.show()

结论:可以看出续订用户的收入下限明显高于不续订用户的,而高分位处的收入增长则对是否续订影响较小。

4.2.4、数据预测提取特征

1、数据归一化处理

对预测目标Response进行归一化处理,替换为0和1。

#数据归一化处理
source["Response"]=source["Response"




    
].apply(lambda x:0 if x =="No" else 1)
source.head()

2、提取特征

其中预测的目标Response和代表用户ID的Customer列舍去不用,使用pd.factorize()方法。

#提取特征
charges = source.drop(["Response","Customer"],axis=1)
corrDf = charges.apply(lambda x: pd.factorize(x)[0])
corrDf.head()

3、构造相关性矩阵

#构造相关性矩阵
corrDf=corrDf.corr()
corrDf

4、使用热力图显示相关性系数矩阵

#使用热力图构建相关性系数矩阵
plt.figure(figsize=(12,8))
ax = sns.heatmap(corr,xticklabels=corr.columns,yticklabels=corr.columns,
                linewidths=0.2,cmap = "YlGnBu",annot=True)
plt.title("Correlation between variables")
plt.show()

结论:从上图可以看出,客户终身价值,客户收入,客户所在区域,每月续费金额,客户出险总金额,保险覆盖范围,车辆类型之间存在较强相关性,并且都呈正相关关系。

5、使用onehot编码探究各用户特征与续约率之间的关系

#使用one_hot编码
ont_hot_data = pd.get_dummies(source.iloc[:,1:22])
ont_hot_data.head()
#客户是否续订与各变量之间的相关性
plt.figure(figsize=(12,5))
ont_hot_data.corr()["Response"].sort_values(ascending=False).plot(kind="bar")
plt.title("客户是否续订与各变量之间的关系")
plt.show()

结论:可以看出只有客户就业状态、续订保险类型、客户所在地区、婚姻状态、销售来源渠道、车辆尺寸、车辆类型、保险类型、学历、总出险金额、每月续订费用与客户是否续订有相关性,其他变量对客户续订预测影响较小。

4.2.5、特征数据预处理

1 、选取子集

#提取数据集中与用户是否续订相关的客户特征
customer_value = source[["EmploymentStatus","Renew Offer Type","Location Code","Marital Status",
                                            "Sales Channel","Vehicle Class","Vehicle Size","Policy",
                                             "Total Claim Amount","Education","Monthly Premium Auto"]]
#提取用户ID
customer_value_id = source["Customer"]
customer_value.head()

2、数据处理:对连续变量进行标准化处理

#对总出险金额进行标准化处理
scaler = StandardScaler(copy=False)
#fit_transform()先拟合数据,然后转化它讲其转化为标准形式
scaler.fit_transform(customer_value[["Total Claim Amount","Monthly Premium Auto"]])
#替换数据
customer_value[["Total Claim Amount","Monthly Premium Auto"]]=scaler.fit_transform(customer_value[["Total Claim Amount","Monthly Premium Auto"]])
customer_value.head()

3、查看异常值

#使用箱线图查看是否存在异常值
plt.figure(figsize=(8,4))
numbox = sns.boxplot(data = customer_value_comvar[["Total Claim Amount","Monthly Premium Auto"]],palette="Set2")
plt.title("检查总出险金额和每月续费金额异常值")
plt.show()

结论:异常值较多,需对异常值进行处理,但是考虑到直接删除会导致数据量减少太多,因此这里对两列数据同时都为异常数据的列进行删除处理。

4、删除异常值

"""定义函数:
    这种方法允许输入是nan值
    df: 表示dataFrame类型
    n: 表示被多少个特征同时判定为异常点才输出
    features: 表示检测异常点的特征"""
def detect_outliers(data,n,features):
    outlier_indices=[]
    for col in




    
 features:
        #第一个四分位点
        Q1=np.percentile(data[col],25)
        #第三个四分位点
        Q3=np.percentile(data[col],75)
        IQR = Q3-Q1
        #上限和下限
        lower_limit=Q1-1.5*IQR
        upper_limit=Q3+1.5*IQR
        #查询异常值的
        outlier_col = data[(data[col]<lower_limit)|(data[col]>upper_limit)].index
        outlier_indices.extend(outlier_col)
    from collections import Counter
    outlier_indices=Counter(outlier_indices)
    #若被n个特征同时判定为异常点才输出
    more_outliers = list(k for k,v in outlier_indices.items() if v>=n)
    return more_outliers
#为了避免异常数据处理过多,这里设置被两个特征值同时判定为异常值的数据
outlisers = detect_outliers(customer_value,2,["Total Claim Amount","Monthly Premium Auto"])
outlisers

对特征数据集删除异常值

#删除异常值
customer_value = customer_value.drop(outlisers, axis=0).reset_index(drop=True)
customer_value.head()

对总体数据集删除异常值,便于后续选取验证数据。

#删除异常值
customer_value_data = source.drop(outlisers,axis=0).reset_index(drop=True)
customer_value_data.head()

5、查看异常值清理情况

#检查异常值是否清理完成
plt.figure(figsize=(8,4))
numbox = sns.boxplot(data = customer_value[["Total Claim Amount","Monthly Premium Auto"]],palette="Set2")
plt.title("检查总出险金额和每月续费金额异常值")
plt.show()

结论:可以看出异常值清理后的连续变量分布情况。

6、离散变量特征处理

#查看对象类型字段里面的存在的值
def uni(columnlabel):
    print(columnlabel,"---",customer_value[columnlabel].unique())
customerobject = customer_value.select_dtypes(["object"])
for i in range(0,len(customerobject.columns)):
    uni(customerobject.columns[i])

对离散变量进行编码

#使用scikit-learn标签编码,将分类数据转换为证数编码
def labelencode(columnlabel):
    customer_value[columnlabel]=LabelEncoder().fit_transform(customer_value[columnlabel])
#进行标签编码
for i in range(0,len(customerobject.columns)):
    labelencode(customerobject.columns[i])
for i in range(0,len(customerobject.columns)):
    uni(customerobject.columns[i])

4.2.6、构建模型

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

拆分数据集时,由于我们的数据集是不平衡的,所以最好使用分层交叉验证来确保训练集和测试集都包含每个类样本的保留人数。 交叉验证函数StratifiedShuffleSplit,分层抽样功能保每个标签对应的样本的比例,是从样本数据中随机按比例选择训练数据和测试数据 参数n_splite是将训练数据分成train/test对的组数,可根据需要进行设置,默认为10 参数test_size和train_size是用来设置train/test对中train和test所占的比例 参数random_state 控制是将样本随机打乱。

X=customer_value
y=customer_value_data["Response"].values
spl = StratifiedShuffleSplit(n_splits=5,test_size=0.2,random_state=0)
print(spl)
print("训练数据集和测试数据集被分成的组数:",spl.get_n_splits(X,y))
#目标y值
customer_value_data["Response"].values

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

#建立训练数据集和测试数据集
for train_index,test_index in spl.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]

输出数据集大小

#输出数据集大小
print("原始数据集特征:",X.shape,
     "训练数据集特征:",X_train.shape,
      "测试数据集特征:",X_test.shape)
print("原始数据标签:",y.shape,
     "训练数据标签:",y_train.shape,
     "测试数据标签:",y_test.shape)

2、选取机器学习算法

#选择机器学习算法
#使用分类算法,这里选择8种分类算法
Classifiers =[
    ["Random Forest",RandomForestClassifier()],
    ["Support Vector Machine",SVC()],
    ["LogisticRegression",LogisticRegression()],
    ["KNN",KNeighborsClassifier()],
    ["Naive Bayes",GaussianNB()],
    ["Decision Tree",DecisionTreeClassifier()],
    ["AdaBoostClassifier",AdaBoostClassifier()],
    ["GradientBoostingClassifier",GradientBoostingClassifier()],
]

3、训练模型

#训练模型
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)
    f1=f1_score(y_test,y_pred)
    class_eva = pd.DataFrame([recall,precision,f1])
    Classify_result.append(class_eva)
    name=pd.Series(name)
    names.append(name)
    y_pred=pd.Series(y_pred)
    prediction.append(y_pred)

4、评估模型

#评估模型
"""recall召回率:原本为对的当中,预测为对的比例(值越大越好,1为理想状态)
   precision精确率:预测为对的当中,原本为对的比例(值越大越好,1为理想状态)
   F1-Score F1分数:指标综合了Precision和recall的产出结果
   F1-Score取值范围0-1,1代表模型输出的结果最好,0代表模型输出结果最差
names = pd.DataFrame(names)
names=names[0].tolist()
# names
result = pd.concat(Classify_result,axis=1)
result.columns =names
result.index=["recall","precision","F1score"]
result

结论:在8种分类算法种,随机森林(Random Forest)F1score最大,为96.87%,其次为为决策树,f1score为88.80%

4.2.7、实施方案

#预测数据集特征(这里没有预测数据集,我们选择最后100行作为需要预测的数据集)
pred_X = customer_value.tail(100)
#提取customerID
pred_id = customer_value_id.tail(100)
#使用随机森林方法,对预测数据集的客户续订情况进行预测
model = RandomForestClassifier()