#导入相关库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
#不展示警告信息
import warnings
warnings.filterwarnings('ignore')
#图中正常展示中文标签
plt.rcParams['font.sans-serif'] = ['simhei']
#展示负号
plt.rcParams['axes.unicode_minus'] = False
#读取数据
users_data = pd.read_excel('用户流失分析.xlsx')
#查看数据前五行
users_data.head()
常用登陆设备 | 城市等级 | 顾客ID | 婚姻状况 | 年龄分组 | 上月客户的首选订单类别 | 性别 | 仓库到顾客地址的距离_公里 | 订单数量较去年增加_单 | 顾客对服务的满意度 | 距上次下单天数_天 | 上月订单数量_单 | 上月平均折扣金额 | 上月使用的优惠券数量_张 | 上月投诉次数 | 使用APP时间_时 | 使用平台时间_月 | 用户关注的主播数量 | 用户流失标签 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Mobile Phone | 3 | 50001 | Single | 3 | Laptop & Accessory | Female | 6.0 | 11.0 | 2.0 | 5.0 | 1.0 | 159.93 | 1.0 | 1.0 | 3.0 | 4.0 | 9.0 | 1.0 |
1 | Phone | 1 | 50002 | Single | 4 | Household | Male | 8.0 | 15.0 | 3.0 | 0.0 | 1.0 | 120.90 | 0.0 | 1.0 | 3.0 | 9.0 | 7.0 | 1.0 |
2 | Phone | 1 | 50003 | Single | 4 | Household | Male | 30.0 | 14.0 | 3.0 | 3.0 | 1.0 | 120.28 | 0.0 | 1.0 | 2.0 | 9.0 | 6.0 | 1.0 |
3 | Phone | 3 | 50004 | Single | 4 | Laptop & Accessory | Male | 15.0 | 23.0 | 5.0 | 3.0 | 1.0 | 134.07 | 0.0 | 0.0 | 2.0 | 3.0 | 8.0 | 1.0 |
4 | Phone | 1 | 50005 | Single | 3 | Household | Male | 12.0 | 11.0 | 5.0 | 3.0 | 1.0 | 129.60 | 1.0 | 0.0 | 3.0 | 3.0 | 3.0 | 1.0 |
#查看数据类型及缺失情况
users_data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5630 entries, 0 to 5629 Data columns (total 19 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 常用登陆设备 5630 non-null object 1 城市等级 5630 non-null int64 2 顾客ID 5630 non-null int64 3 婚姻状况 5630 non-null object 4 年龄分组 5630 non-null int64 5 上月客户的首选订单类别 5630 non-null object 6 性别 5630 non-null object 7 仓库到顾客地址的距离_公里 5630 non-null float64 8 订单数量较去年增加_单 5630 non-null float64 9 顾客对服务的满意度 5630 non-null float64 10 距上次下单天数_天 5630 non-null float64 11 上月订单数量_单 5630 non-null float64 12 上月平均折扣金额 5630 non-null float64 13 上月使用的优惠券数量_张 5630 non-null float64 14 上月投诉次数 5630 non-null float64 15 使用APP时间_时 5630 non-null float64 16 使用平台时间_月 5630 non-null float64 17 用户关注的主播数量 5630 non-null float64 18 用户流失标签 5630 non-null float64 dtypes: float64(12), int64(3), object(4) memory usage: 835.8+ KB
#查看数据的描述型统计信息
users_data.describe()
城市等级 | 顾客ID | 年龄分组 | 仓库到顾客地址的距离_公里 | 订单数量较去年增加_单 | 顾客对服务的满意度 | 距上次下单天数_天 | 上月订单数量_单 | 上月平均折扣金额 | 上月使用的优惠券数量_张 | 上月投诉次数 | 使用APP时间_时 | 使用平台时间_月 | 用户关注的主播数量 | 用户流失标签 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 | 5630.000000 |
mean | 1.654707 | 52815.500000 | 3.688988 | 15.639896 | 15.674600 | 3.066785 | 4.459325 | 2.870160 | 177.223030 | 1.716874 | 0.284902 | 2.934636 | 10.612611 | 4.214032 | 0.168384 |
std | 0.915389 | 1625.385339 | 1.023999 | 8.339095 | 3.591058 | 1.380194 | 3.570626 | 2.939615 | 49.207036 | 1.857640 | 0.451408 | 0.705528 | 8.257343 | 2.583586 | 0.374240 |
min | 1.000000 | 50001.000000 | 1.000000 | 5.000000 | 11.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 1.000000 | 0.000000 |
25% | 1.000000 | 51408.250000 | 3.000000 | 9.000000 | 13.000000 | 2.000000 | 2.000000 | 1.000000 | 145.770000 | 1.000000 | 0.000000 | 2.000000 | 3.000000 | 2.000000 | 0.000000 |
50% | 1.000000 | 52815.500000 | 4.000000 | 14.000000 | 15.000000 | 3.000000 | 3.000000 | 2.000000 | 163.280000 | 1.000000 | 0.000000 | 3.000000 | 9.000000 | 3.000000 | 0.000000 |
75% | 3.000000 | 54222.750000 | 4.000000 | 20.000000 | 18.000000 | 4.000000 | 7.000000 | 3.000000 | 196.392500 | 2.000000 | 1.000000 | 3.000000 | 15.000000 | 6.000000 | 0.000000 |
max | 3.000000 | 55630.000000 | 6.000000 | 127.000000 | 26.000000 | 5.000000 | 46.000000 | 16.000000 | 324.990000 | 16.000000 | 1.000000 | 5.000000 | 63.000000 | 22.000000 | 1.000000 |
#数据类型转化函数
def col(st):
x = str(int(st))
return x
#数据类型转换
users_data['城市等级'] = users_data['城市等级'].apply(col)
users_data['年龄分组'] = users_data['年龄分组'].apply(col)
#查看转换后的数据类型
users_data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5630 entries, 0 to 5629 Data columns (total 19 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 常用登陆设备 5630 non-null object 1 城市等级 5630 non-null object 2 顾客ID 5630 non-null int64 3 婚姻状况 5630 non-null object 4 年龄分组 5630 non-null object 5 上月客户的首选订单类别 5630 non-null object 6 性别 5630 non-null object 7 仓库到顾客地址的距离_公里 5630 non-null float64 8 订单数量较去年增加_单 5630 non-null float64 9 顾客对服务的满意度 5630 non-null float64 10 距上次下单天数_天 5630 non-null float64 11 上月订单数量_单 5630 non-null float64 12 上月平均折扣金额 5630 non-null float64 13 上月使用的优惠券数量_张 5630 non-null float64 14 上月投诉次数 5630 non-null float64 15 使用APP时间_时 5630 non-null float64 16 使用平台时间_月 5630 non-null float64 17 用户关注的主播数量 5630 non-null float64 18 用户流失标签 5630 non-null float64 dtypes: float64(12), int64(1), object(6) memory usage: 835.8+ KB
#生成哑变量
#drop_first=True,去除互斥变量
users_data = pd.get_dummies(users_data,drop_first=True)
#查看生成哑变量后的数据
users_data.head()
顾客ID | 仓库到顾客地址的距离_公里 | 订单数量较去年增加_单 | 顾客对服务的满意度 | 距上次下单天数_天 | 上月订单数量_单 | 上月平均折扣金额 | 上月使用的优惠券数量_张 | 上月投诉次数 | 使用APP时间_时 | ... | 年龄分组_3 | 年龄分组_4 | 年龄分组_5 | 年龄分组_6 | 上月客户的首选订单类别_Grocery | 上月客户的首选订单类别_Household | 上月客户的首选订单类别_Laptop & Accessory | 上月客户的首选订单类别_Mobile Phone | 上月客户的首选订单类别_Others | 性别_Male | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 50001 | 6.0 | 11.0 | 2.0 | 5.0 | 1.0 | 159.93 | 1.0 | 1.0 | 3.0 | ... | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
1 | 50002 | 8.0 | 15.0 | 3.0 | 0.0 | 1.0 | 120.90 | 0.0 | 1.0 | 3.0 | ... | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
2 | 50003 | 30.0 | 14.0 | 3.0 | 3.0 | 1.0 | 120.28 | 0.0 | 1.0 | 2.0 | ... | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
3 | 50004 | 15.0 | 23.0 | 5.0 | 3.0 | 1.0 | 134.07 | 0.0 | 0.0 | 2.0 | ... | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
4 | 50005 | 12.0 | 11.0 | 5.0 | 3.0 | 1.0 | 129.60 | 1.0 | 0.0 | 3.0 | ... | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
5 rows × 30 columns
#查看生成哑变量后的列及数据类型
users_data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5630 entries, 0 to 5629 Data columns (total 30 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 顾客ID 5630 non-null int64 1 仓库到顾客地址的距离_公里 5630 non-null float64 2 订单数量较去年增加_单 5630 non-null float64 3 顾客对服务的满意度 5630 non-null float64 4 距上次下单天数_天 5630 non-null float64 5 上月订单数量_单 5630 non-null float64 6 上月平均折扣金额 5630 non-null float64 7 上月使用的优惠券数量_张 5630 non-null float64 8 上月投诉次数 5630 non-null float64 9 使用APP时间_时 5630 non-null float64 10 使用平台时间_月 5630 non-null float64 11 用户关注的主播数量 5630 non-null float64 12 用户流失标签 5630 non-null float64 13 常用登陆设备_Pad 5630 non-null uint8 14 常用登陆设备_Phone 5630 non-null uint8 15 城市等级_2 5630 non-null uint8 16 城市等级_3 5630 non-null uint8 17 婚姻状况_Married 5630 non-null uint8 18 婚姻状况_Single 5630 non-null uint8 19 年龄分组_2 5630 non-null uint8 20 年龄分组_3 5630 non-null uint8 21 年龄分组_4 5630 non-null uint8 22 年龄分组_5 5630 non-null uint8 23 年龄分组_6 5630 non-null uint8 24 上月客户的首选订单类别_Grocery 5630 non-null uint8 25 上月客户的首选订单类别_Household 5630 non-null uint8 26 上月客户的首选订单类别_Laptop & Accessory 5630 non-null uint8 27 上月客户的首选订单类别_Mobile Phone 5630 non-null uint8 28 上月客户的首选订单类别_Others 5630 non-null uint8 29 性别_Male 5630 non-null uint8 dtypes: float64(12), int64(1), uint8(17) memory usage: 665.4 KB
#计算相关系数并生成excel文件
users_data.drop('顾客ID',axis=1).corr().to_excel('用户流失_相关系数.xlsx')
#拆分自变量和因变量
x = users_data.drop(['顾客ID','用户流失标签'],axis=1)
y = users_data['用户流失标签']
#拆分训练集和测试集
#random_state随机数种子,保证每次运行结果一样
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=1000)
#导入相关包
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
#建立逻辑回归模型
lr_model = LogisticRegression()
#训练模型
lr_model.fit(x_train,y_train)
#模型预测值
y_prob_lr = lr_model.predict_proba(x_test)[:,1]
#计算ROC
print("逻辑回归模型ROC得分:",roc_auc_score(y_test,y_prob_lr))
逻辑回归模型ROC得分: 0.8724545228782516
#导入相关包
from sklearn.tree import DecisionTreeClassifier
#决策树模型
dc_model = DecisionTreeClassifier()
#训练模型
dc_model.fit(x_train,y_train)
#模型预测值
y_prob_dc = dc_model.predict_proba(x_test)[:,1]
#计算ROC
print("决策树模型ROC得分:",roc_auc_score(y_test,y_prob_dc))
决策树模型ROC得分: 0.892313900788477
#导入相关包
from sklearn.naive_bayes import GaussianNB
# 朴素贝叶斯模型
nb_model = GaussianNB()
#训练模型
nb_model.fit(x_train,y_train)
#模型预测值
y_prob_nb = nb_model.predict_proba(x_test)[:,1]
#计算ROC
print("朴素贝叶斯模型ROC得分:",roc_auc_score(y_test,y_prob_nb))
朴素贝叶斯模型ROC得分: 0.7840897332422755
#导入相关包
from sklearn.neighbors import KNeighborsClassifier
#K近邻算法
knn_model = KNeighborsClassifier(n_neighbors=3)
#训练模型
knn_model.fit(x_train,y_train)
#模型预测值
y_prob_knn = knn_model.predict_proba(x_test)[:,1]
#计算ROC
print("K近邻算法ROC得分:",roc_auc_score(y_test,y_prob_knn))
K近邻算法ROC得分: 0.8675679311272531
#导入相关包
from sklearn.ensemble import RandomForestRegressor
#随机森林模型
rfr_model = RandomForestRegressor()
#训练模型
rfr_model.fit(x_train,y_train)
#模型预测值
y_prob_rfr = rfr_model.predict(x_test)
#计算ROC
print("随机森林模型ROC得分:",roc_auc_score(y_test,y_prob_rfr))
随机森林模型ROC得分: 0.9844464622006995
#导入相关包
from sklearn.ensemble import AdaBoostClassifier
#AdaBoost算法
AB_model = AdaBoostClassifier(random_state=2022)
#训练模型
AB_model.fit(x_train,y_train)
#模型预测值
y_prob_AB = AB_model.predict_proba(x_test)[:,1]
#计算ROC
print("AdaBoost算法ROC得分:",roc_auc_score(y_test,y_prob_AB))
AdaBoost算法ROC得分: 0.9072892738146976
#导入相关包
from sklearn.ensemble import GradientBoostingClassifier
#GBDT
GBDT_model = GradientBoostingClassifier(random_state=2022)
#训练模型
GBDT_model.fit(x_train,y_train)
#模型预测值
y_prob_GBDT = GBDT_model.predict_proba(x_test)[:,1]
#计算ROC
print("AdaBoost算法ROC得分:",roc_auc_score(y_test,y_prob_GBDT))
AdaBoost算法ROC得分: 0.9312371950083813
# 没安装 lightgbm包的进行安装
!pip install lightgbm
Requirement already satisfied: lightgbm in c:\users\situminqi\anaconda3\lib\site-packages (3.3.2) Requirement already satisfied: scikit-learn!=0.22.0 in c:\users\situminqi\anaconda3\lib\site-packages (from lightgbm) (0.24.2) Requirement already satisfied: scipy in c:\users\situminqi\anaconda3\lib\site-packages (from lightgbm) (1.7.1) Requirement already satisfied: wheel in c:\users\situminqi\anaconda3\lib\site-packages (from lightgbm) (0.37.0) Requirement already satisfied: numpy in c:\users\situminqi\anaconda3\lib\site-packages (from lightgbm) (1.20.3) Requirement already satisfied: joblib>=0.11 in c:\users\situminqi\anaconda3\lib\site-packages (from scikit-learn!=0.22.0->lightgbm) (1.1.0) Requirement already satisfied: threadpoolctl>=2.0.0 in c:\users\situminqi\anaconda3\lib\site-packages (from scikit-learn!=0.22.0->lightgbm) (2.2.0)
#导入相关包
from lightgbm import LGBMClassifier
#LightGBM
LGBM_model = LGBMClassifier(learning_rate=0.1,random_state=2022,metric='roc')
#训练模型
LGBM_model.fit(x_train,y_train)
#模型预测值
y_prob_lgbm = LGBM_model.predict_proba(x_test)[:,1]
#计算ROC
print("LightGBM算法ROC得分:",roc_auc_score(y_test,y_prob_lgbm))
LightGBM算法ROC得分: 0.9847555928064404
#将ROC结果存进DataFrame中
roc_data = pd.DataFrame([['逻辑回归',roc_auc_score(y_test,y_prob_lr)],
['决策树',roc_auc_score(y_test,y_prob_dc)],
['朴素贝叶斯',roc_auc_score(y_test,y_prob_nb)],
['K近邻算法',roc_auc_score(y_test,y_prob_knn)],
['随机森林',roc_auc_score(y_test,y_prob_rfr)],
['AdaBoost',roc_auc_score(y_test,y_prob_AB)],
['GBDT',roc_auc_score(y_test,y_prob_GBDT)],
['LightGBM',roc_auc_score(y_test,y_prob_lgbm)]],columns=['机器学习方法','默认参数下的ROC得分'])
roc_data.to_excel('用户流失_各算法ROC得分.xlsx')
#GridSearch寻找最优模型参数
from sklearn.model_selection import GridSearchCV
parameters = {'num_leaves':range(2,30,2),
'n_estimators':range(10,100,10),
'learning_rate':[0.05,0.1,0.15,0.2,0.25,0.3]
}
LGBM_model = LGBMClassifier()
grid_search = GridSearchCV(LGBM_model,parameters,scoring='roc_auc',cv=5)
grid_search.fit(x_train,y_train)
grid_search.best_params_
{'learning_rate': 0.3, 'n_estimators': 90, 'num_leaves': 24}
#最优模型下的LightGBM算法
from lightgbm import LGBMClassifier
LGBM_model_best = LGBMClassifier(learning_rate=0.2,n_estimators=90,num_leaves=24,random_state=2022,metric='roc_auc')
LGBM_model_best.fit(x_train,y_train)
y_prob_lgbm_best = LGBM_model_best.predict_proba(x_test)[:,1]
print("LightGBM算法ROC得分:",roc_auc_score(y_test,y_prob_lgbm_best))
LightGBM算法ROC得分: 0.987554582893566
#将ROC结果存进DataFrame中
LightGBM_roc_data = pd.DataFrame([['LightGBM','未优化',roc_auc_score(y_test,y_prob_lgbm)],
['LightGBM','网格搜索参数调优',roc_auc_score(y_test,y_prob_lgbm_best)]],columns=['机器学习方法','优化情况','ROC得分'])
LightGBM_roc_data.to_excel('用户流失_LBGM算法优化情况.xlsx')
features = x.columns
importances = LGBM_model_best.feature_importances_
feat_importances = pd.DataFrame()
feat_importances['特征名称'] = features
feat_importances['特征重要性'] = importances
feat_importances.sort_values('特征重要性',ascending=False).to_excel('用户流失_LGBM算法特征重要性.xlsx')