svc预测概率_携程客户流失概率预测

本文介绍了一次通过分析用户行为数据来预测携程客户流失的比赛,旨在了解用户画像并找到影响流失的关键因素。数据经过脱敏处理,包括订单、客户行为和酒店三个方面的特征。通过数据预处理、特征工程、模型训练(如SVM、Logistic Regression等)和评估,最终得出模型预测概率。
摘要由CSDN通过智能技术生成

携程作为中国领先的综合性旅行服务公司,每天向超过2.5亿会员提供全方位的旅行服务,在这海量的网站访问量中,我们可分析用户的行为数据来挖掘潜在的信息资源。其中,客户流失率是考量业务成绩的一个非常关键的指标。此次竞赛的目的是为了深入了解用户画像及行为偏好,找到最优算法,挖掘出影响用户流失的关键因素,从而更好地完善产品设计、提升用户体验!

一、数据来源及说明

此次使用训练集数据userlostprob_train.txt,为2016.05.15-2016.05.21期间一周的访问数据。为保护客户隐私,已经将数据经过了脱敏,和实际商品的订单量、浏览量、转化率等有一些差距,但不影响问题的可解性。

将特征信息整理分为三组:订单、客户行为、酒店,相关说明如下:

image.png

二、数据导入及数据探索

import numpy as np

import pandas as pd

import seaborn as sns

import matplotlib.pyplot as plt

from sklearn.decomposition import PCA

%matplotlib inline

df = pd.read_csv(r"./userlostprob_train.txt",sep="\t",encoding="UTF-8")

df.head()

image.png

查看数据类型:df.info()

d和arrival字段需要处理

image.png

查看行列统计:df.shape

(689945, 51)

有689945行数据,51个字段

查看缺失值占比:df.isna.mean()

数据的缺失情况比较严重,有44列存在不同程度的缺失,最多的特征列缺失比例接近88%

image.png

查看标记统计:df['label'].value_counts()

0代表用户没有流失,1为已经流失

image.png

查看描述统计:df.describe().T

1.有些特征列存在极值的情况,后面在进行缺失值填充的时候需要注意分布形态;

2.极值需要处理,减小异常点对预测的影响;

3.有些特征存在负值,需要进行处理

image.png

三、特征工程

3.1 数据预处理

3.1.1 离散型数据处理

将访问时间与到达时间相减得到提前预定天数作为新的特征

然后将无用特征删除

df['arrival']=pd.to_datetime(df['arrival'])

df['d']=pd.to_datetime(df['d'])

df['day_advanced']=(df['arrival']-df['d']).dt.days

df.drop(['firstorder_bu','sampleid','d','arrival'],axis=1,inplace=True)

3.1.2 异常值处理

将customer_value_profit、ctrip_profits中的负值按0处理

将delta_price1、delta_price2、lowestprice中的负值按中位数处理

fillAbnormalWith0 = ['customer_value_profit','ctrip_profits']

fillAbnormalWithMedian = ['delta_price1','delta_price2','lowestprice']

for col in fillAbnormalWith0:

df.loc[df[col]<0,col] = 0

for col in fillAbnormalWithMedian:

df.loc[df[col]<0,col] = df[col].median()

3.1.3 缺失值处理

3.1.3.1 删除缺失值大于80%的特征

数据缺失值过多,信息失真,故而删除

df.drop(['historyvisit_7ordernum'],axis=1,inplace=True)

3.1.3.2 缺失率>40%的特征列 填充为0

为了保留原有特征包含的信息,对缺失值较多的特征列没有采用删除的手段,而是采取了将缺失值填充为0的措施。

fillNaWith0 = ['historyvisit_totalordernum', #近1年用户历史订单数

'historyvisit_avghotelnum', #近3个月用户历史日均访问酒店数

'ordercanceledprecent', #用户一年内取消订单率

'historyvisit_visit_detailpagenum'] # 7天内访问酒店详情页数

for col in fillNaWith0:

df.loc[df[col].isna(),col] = 0

3.1.3.3 缺失率>30%的特征列 填充为-999

缺失率大于30%仍属于缺失值比较高的情况,为了减弱填充值对原有信息的影响,这里选择填充没有实际含义的高维极值-999。

fillNaWith999 = ['ordercanncelednum', # 取消订单数

'starprefer', # 星级偏好

"consuming_capacity", # 消费能力指数

'delta_price1', # 用户偏好价格-24小时浏览最多酒店价格

'price_sensitive', # 价格敏感指数

'ordernum_oneyear', # 年订单数

'avgprice', # 平均价格

'delta_price2', # 用户偏好价格-24小时浏览酒店平均价格

'customer_value_profit', # 客户近一年的价值

'ctrip_profits', # 客户价值

'lasthtlordergap', # 一年内距离上次下单时长

'cr' ] # 用户转化率

for col in fillNaWith999:

df.loc[df[col].isna(),col] = -999

3.1.3.4 缺失率<30%的特征列 填充为均值或中位数

缺失值小于30%的特征列根据其分布形态不同选择填充不同的值,

分布近似于正态分布的特征列填充为均值,呈偏态分布的特征则填充为中位数。

fillNaWithMedian =['landhalfhours', # 24小时登陆时长

'lastpvgap', # 一年内距上次访问时长

'commentnums', # 酒店评论数

'novoters', # 酒店当前评论人数

'cancelrate', # 当前酒店历史取消率

'hoteluv', # 当前酒店历史UV

'hotelcr', # 当前酒店历史转化率

'cr_pre', # 24小时历史浏览次数最多酒店历史cr

'lowestprice', # 当前酒店可定最低价

'lowestprice_pre2', # 24h 访问酒店可预定最低价

'commentnums_pre', # 24小时历史浏览次数最多酒店点评数

'commentnums_pre2', # 24小时历史浏览酒店点评数均值

'novoters_pre2', # 24小时历史浏览酒店评分人数均值

'novoters_pre', # 24小时历史浏览次数最多酒店评分人数

'deltaprice_pre2_t1', # 24小时内已访问酒店价格与对手价差均值

'lowestprice_pre', # 24小时内已访问次数最多酒店可订最低价

'uv_pre', # 24小时历史浏览次数最多酒店历史uv

'uv_pre2', # 24小时历史浏览酒店历史uv均值

'businessrate_pre2', # 24小时内已访问酒店商务属性指数均值

'cityuvs', # 昨日访问当前城市同入住日期的app uv数

'cityorders', # 昨日提交当前城市同入住日期的app订单数

'visitnum_oneyear' ] # 年访问次数

fillNaWithMean = [ 'businessrate_pre', # 24小时历史浏览次数最多酒店商务属性指数

'customereval_pre2', # 24小时历史浏览酒店客户评分均值

'cancelrate_pre'] # 24小时内已访问次数最多酒店历史取消率

for col in fillNaWithMedian:

df.loc[df[col].isna(),col] = df[col].median()

for col in fillNaWithMean:

df.loc[df[col].isna(),col] = df[col].mean()

3.1.4 极值处理

有些特征明显有异常大和异常小的值,这里使用99%分位数替换。

for i in df.columns:

df.loc[df[i]>np.percentile(df[i],99),i]=np.percentile(df[i],99)

3.1.5 特殊列处理

'decisionhabit_user'用户决策习惯列缺失值也比较多,但是绝大部分值位于40以下,可以40为分界点,将特征列转换为二值形式

df['decisionhabit_user'] = df['decisionhabit_user'].map(lambda x:1 if x>40 else 0)

3.2 相关性分析

3.2.1 按照用户特征和酒店特征分组

# 用户特征

user_features=['visitnum_oneyear','starprefer','sid','price_sensitive','ordernum_oneyear','ordercanncelednum','ordercanceledprecent','lastpvgap',

'lasthtlordergap','landhalfhours','iforderpv_24h','historyvisit_totalordernum','historyvisit_avghotelnum','h',

'delta_price2','delta_price1','decisionhabit_user','customer_value_profit','ctrip_profits','cr','consuming_capacity','avgprice']

# 酒店特征

hotel_features=['hotelcr','hoteluv','commentnums','novoters','cancelrate','lowestprice','cr_pre','uv_pre','uv_pre2','businessrate_pre',

'businessrate_pre2','customereval_pre2','commentnums_pre','commentnums_pre2','cancelrate_pre','novoters_pre','novoters_pre2',

'deltaprice_pre2_t1','lowestprice_pre','lowestprice_pre2','firstorder_bu','historyvisit_visit_detailpagenum']

# 用户特征相关性矩阵

corr_user = df[user_features].corr()

# 生成用户特征的相关性矩阵

corr_hotel = rawdf[hotel_features].corr()

3.2.2 绘制热力图

3.2.2.1用户信息特征的相关性矩阵热度图

fig,ax = plt.subplots(figsize=(18, 12))

sns.heatmap(corr_user, xticklabels=True, yticklabels=True, square=False, linewidths=.5, annot=True, cmap='Oranges')

plt.savefig('./Photo/用户特征的相关性分析.jpg',dpi=400, bbox_inches='tight')

plt.show()

image.png

3.2.2.2 酒店信息特征的相关性矩阵热度图

fig,ax = plt.subplots(figsize=(18, 12))

sns.heatmap(corr_hotel, xticklabels=True, yticklabels=True, square=False, linewidths=.5, annot=True, cmap='Oranges_r')

plt.savefig('./Photo/酒店信息特征的相关性分析.jpg',dpi=400, bbox_inches='tight')

plt.show()

image.png

3.3 PCA降维

c_value=['customer_value_profit','ctrip_profits'] # 用户价值

consume_level=['avgprice','consuming_capacity'] # 用户消费水平

price_prefer=['delta_price1','delta_price2'] # 用户偏好价格

hotel_hot=['commentnums','novoters'] # 酒店热度

hotel_hot_pre=['commentnums_pre','novoters_pre'] # 24小时内浏览次数最多的酒店热度

hotel_hot_pre2=['commentnums_pre2','novoters_pre2'] # 24小时内浏览酒店的平均热度

print('PCA降维前数据维度是:{}'.format(df.shape))

pca=PCA(n_components=1)

df['c_value']=pca.fit_transform(df[c_value])

df['consume_level']=pca.fit_transform(df[consume_level])

df['price_prefer']=pca.fit_transform(df[price_prefer])

df['hotel_hot']=pca.fit_transform(df[hotel_hot])

df['hotel_hot_pre']=pca.fit_transform(df[hotel_hot_pre])

df['hotel_hot_pre2']=pca.fit_transform(df[hotel_hot_pre2])

df.drop(c_value,axis=1,inplace=True)

df.drop(consume_level,axis=1,inplace=True)

df.drop(price_prefer,axis=1,inplace=True)

df.drop(hotel_hot,axis=1,inplace=True)

df.drop(hotel_hot_pre,axis=1,inplace=True)

df.drop(hotel_hot_pre2,axis=1,inplace=True)

df.drop('historyvisit_totalordernum',axis=1,inplace=True) # 把重复列删除

print('PCA降维后数据维度是:{}'.format(df.shape))

PCA降维前数据维度是:(689945, 48)

PCA降维后数据维度是:(689945, 41)

3.4 数据标准化

from sklearn.preprocessing import StandardScaler

y=df['label']

x=df.drop('label',axis=1)

scaler = StandardScaler()

scaler.fit(x)

X= scaler.transform(x)

四、建模与模型评估

4.1 数据划分

# 导入相关模块

from sklearn.model_selection import GridSearchCV

from sklearn.model_selection import train_test_split

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size= 0.2,random_state=2020)

4.2 逻辑回归

from sklearn.linear_model import LogisticRegression

from sklearn.metrics import classification_report

from sklearn import metrics

lr = LogisticRegression() # 实例化一个LR模型

lr.fit(X_train,y_train) # 训练模型

y_prob = lr.predict_proba(X_test)[:,1] # 预测1类的概率

y_pred = lr.predict(X_test) # 模型对测试集的预测结果

fpr_lr,tpr_lr,threshold_lr = metrics.roc_curve(y_test,y_prob) # 获取真阳率、伪阳率、阈值

auc_lr = metrics.auc(fpr_lr,tpr_lr) # AUC得分

score_lr = metrics.accuracy_score(y_test,y_pred) # 模型准确率

print('模型准确率为:{0},AUC得分为:{1}'.format(score_lr,auc_lr))

print('============================================================')

print(classification_report(y_test,y_pred,labels=None,target_names=None,sample_weight=None, digits=2))

image.png

4.3 朴素贝叶斯

from sklearn.naive_bayes import GaussianNB

gnb = GaussianNB() # 实例化一个LR模型

gnb.fit(X_train,y_train) # 训练模型

y_prob = gnb.predict_proba(X_test)[:,1] # 预测1类的概率

y_pred = gnb.predict(X_test) # 模型对测试集的预测结果

fpr_gnb,tpr_gnb,threshold_gnb = metrics.roc_curve(y_test,y_prob) # 获取真阳率、伪阳率、阈值

auc_gnb = metrics.auc(fpr_gnb,tpr_gnb) # AUC得分

score_gnb = metrics.accuracy_score(y_test,y_pred) # 模型准确率

print('模型准确率为:{0},AUC得分为:{1}'.format(score_gnb,auc_gnb))

print('============================================================')

print(classification_report(y_test, y_pred, labels=None, target_names=None, sample_weight=None, digits=2))

image.png

4.4 SVM

from sklearn.svm import SVC

svc = SVC(kernel='rbf',C=1,max_iter=100).fit(X_train,y_train)

y_prob = svc.decision_function(X_test) # 决策边界距离

y_pred = svc.predict(X_test) # 模型对测试集的预测结果

fpr_svc,tpr_svc,threshold_svc = metrics.roc_curve(y_test,y_prob) # 获取真阳率、伪阳率、阈值

auc_svc = metrics.auc(fpr_svc,tpr_svc) # 模型准确率

score_svc = metrics.accuracy_score(y_test,y_pred)

print('模型准确率为:{0},AUC得分为:{1}'.format(score_svc,auc_svc))

print('============================================================')

print(classification_report(y_test, y_pred, labels=None, target_names=None, sample_weight=None, digits=2))

image.png

4.4 决策树

from sklearn import tree

dtc = tree.DecisionTreeClassifier() # 建立决策树模型

dtc.fit(X_train,y_train) # 训练模型

y_prob = dtc.predict_proba(X_test)[:,1] # 预测1类的概率

y_pred = dtc.predict(X_test) # 模型对测试集的预测结果

fpr_dtc,tpr_dtc,threshod_dtc= metrics.roc_curve(y_test,y_prob) # 获取真阳率、伪阳率、阈值

score_dtc = metrics.accuracy_score(y_test,y_pred)

auc_dtc = metrics.auc(fpr_dtc,tpr_dtc)

print('模型准确率为:{0},AUC得分为:{1}'.format(score_dtc,auc_dtc))

print('============================================================')

print(classification_report(y_test,y_pred,labels=None,target_names=None,sample_weight=None, digits=2))

image.png

4.5 随机森林

from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier() # 建立随机森林分类器

rfc.fit(X_train,y_train) # 训练随机森林模型

y_prob = rfc.predict_proba(X_test)[:,1] # 预测1类的概率

y_pred=rfc.predict(X_test) # 模型对测试集的预测结果

fpr_rfc,tpr_rfc,threshold_rfc = metrics.roc_curve(y_test,y_prob) # 获取真阳率、伪阳率、阈值

auc_rfc = metrics.auc(fpr_rfc,tpr_rfc) # AUC得分

score_rfc = metrics.accuracy_score(y_test,y_pred) # 模型准确率

print('模型准确率为:{0},AUC得分为:{1}'.format(score_rfc,auc_rfc))

print('============================================================')

print(classification_report(y_test,y_pred,labels=None,target_names=None,sample_weight=None, digits=2))

image.png

4.6 XGBoost

import xgboost as xgb

# 读入训练数据集和测试集

dtrain=xgb.DMatrix(X_train,y_train)

dtest=xgb.DMatrix(X_test)

# 设置xgboost建模参数

params={'booster':'gbtree','objective': 'binary:logistic','eval_metric': 'auc',

'max_depth':8,'gamma':0,'lambda':2,'subsample':0.7,'colsample_bytree':0.8,

'min_child_weight':3,'eta': 0.2,'nthread':8,'silent':1}

# 训练模型

watchlist = [(dtrain,'train')]

bst=xgb.train(params,dtrain,num_boost_round=500,evals=watchlist)

# 输入预测为正类的概率值

y_prob=bst.predict(dtest)

# 设置阈值为0.5,得到测试集的预测结果

y_pred = (y_prob >= 0.5)*1

# 获取真阳率、伪阳率、阈值

fpr_xgb,tpr_xgb,threshold_xgb = metrics.roc_curve(y_test,y_prob)

auc_xgb = metrics.auc(fpr_xgb,tpr_xgb) # AUC得分

score_xgb = metrics.accuracy_score(y_test,y_pred) # 模型准确率

print('模型准确率为:{0},AUC得分为:{1}'.format(score_xgb,auc_xgb))

print('============================================================')

print(classification_report(y_test,y_pred,labels=None,target_names=None,sample_weight=None, digits=2))

image.png

4.7 模型比较

plt.style.use('bmh')

plt.figure(figsize=(13,10))

plt.plot(fpr_lr,tpr_lr,label='lr: {0:.3f}'.format(score_lr)) # 逻辑回归

plt.plot(fpr_gnb,tpr_gnb,label='gnb:{0:.3f}'.format(score_gnb)) # 朴素贝叶斯

plt.plot(fpr_svc,tpr_svc,label='svc:{0:.3f}'.format(score_svc)) # 支持向量机

plt.plot(fpr_dtc,tpr_dtc,label='dtc:{0:.3f}'.format(score_dtc)) # 决策树

plt.plot(fpr_rfc,tpr_rfc,label='rfc:{0:.3f}'.format(score_rfc)) # 随机森林

plt.plot(fpr_rfc,tpr_rfc,label='xgb:{0:.3f}'.format(score_xgb)) # XGBoost

plt.legend(loc='lower right',prop={'size':25})

plt.xlabel('伪阳率')

plt.ylabel('真阳率')

plt.title('ROC曲线')

plt.savefig('./Photo/模型比较图.jpg',dpi=400, bbox_inches='tight')

plt.show()

image.png

4.8 重要特征

from xgboost import plot_importance

fig,ax = plt.subplots(figsize=(15,15))

plot_importance(bst,height=0.5,ax=ax,max_num_features=40,color='chocolate')

plt.savefig('./Photo/重要特征图.jpg',dpi=400, bbox_inches='tight')

plt.show()

image.png

后期可以交由运营部门重点监控这些指标。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值