背景与分析方法
本文是接着航空公司客户价值分析,这是拓展考虑的部分,这里简单的将它做了一下。在客户管理中,客户流失也是一个非常重要的问题。客户流失对利润增长形成的负面影响非常大,客户与航空公司之间的关系越耐久,给航空公司带来的利润就回越高。所以流失一个客户,比获得一个新客户对公司的损失更大。
客户流失分析针对老客户停止分析预测,这里的老客户定义为飞行次数大于6次的客户。用航空公司客户信息数据来停止分类模型训练,预测将来客户的类别归属:未流失、准流失或已流失。
特征选择
这里直接采用之前清洗好的数据集来停止特征选择,这里选择的关键属性有:会员卡级别、客户类型、平均乘机时间间隔、平均折扣率、积分兑换次数、非乘机积分总和、单位里程票价以及单位里程积分等。其中客户类型需要停止挑选定义,单位里程票价和单位里程积分需要停止计算。
选择代码如下:- import pandas as pd
- #读数据
- input_file = '../data/cleaned.xls'
- output_file = '../tmp/selected.xls'
- data = pd.read_excel(input_file)
- #选取特征
- data['单位里程票价'] = (data['SUM_YR_1'] + data['SUM_YR_2'])/data['SEG_KM_SUM']
- data['单位里程积分'] = (data['P1Y_BP_SUM'] + data['L1Y_BP_SUM'])/data['SEG_KM_SUM']
- data['飞行次数比例'] = data['L1Y_Flight_Count'] / data['P1Y_Flight_Count'] #第二年飞行次数与第一年飞行次数的比例
- #挑选出老客户(飞行次数大于6次的为老客户)
- data = data[data['FLIGHT_COUNT'] > 6]
- #选择特征
- data = data[['FFP_TIER','飞行次数比例','AVG_INTERVAL',
- 'avg_discount','EXCHANGE_COUNT','Eli_Add_Point_Sum','单位里程票价','单位里程积分']]
- #导出
- data.to_excel(output_file,index=None)
复制代码 然后停止客户类别的定义添加,代码如下:- import pandas as pd
- input_file = '../tmp/selected.xls'
- output_file = '../tmp/classfication.xls'
- data = pd.read_excel(input_file)
- data['客户类型'] = None
- for i in range(len(data)):
- #第一、二年飞行次数比例小于50%的客户定义为已流失
- if data['飞行次数比例'][i] < 0.5:
- data['客户类型'][i] = 0 #0代表已流失
- #第一、二年飞行次数比例在[0.5,0.9)之间的客户定义为准流失
- if (data['飞行次数比例'][i] >= 0.5) & (data['飞行次数比例'][i] < 0.9) :
- data['客户类型'][i] = 1 #1代表准流失
- #第一、二年飞行次数比例大于等于90%的客户定义为未流失
- if data['飞行次数比例'][i] >= 0.9:
- data['客户类型'][i] = 2 #2代表未流失
- #导出
- data.to_excel(output_file,index=None)
复制代码 到这里根本上将可以用来训练的数据集准备好了,但是还需要一定的处置。
规范化处置
查看之前选择完的数据集,如下图所示,发现其跨度还是比较大,需要停止规范化处置。
处置的代码如下:- import pandas as pd
- #读数
- input_file = '../tmp/classfication.xls'
- output_file = '../tmp/std.xls'
- data = pd.read_excel(input_file)
- #去掉飞行次数比例
- data = data[['FFP_TIER','AVG_INTERVAL','avg_discount','EXCHANGE_COUNT',
- 'Eli_Add_Point_Sum','单位里程票价','单位里程积分','客户类型']]
- #规范化
- data.loc[:,:'单位里程积分'] = (data.loc[:,:'单位里程积分'] - data.loc[:,:'单位里程积分'].mean(axis = 0)) \
- / (data.loc[:,:'单位里程积分'].std(axis = 0))
- #导出
- data.to_excel(output_file,index=None)
复制代码 到这里就把能用来停止模型训练的数据集准备好了,下面就需要停止模型的选择以及模型参数的选择了。
模型选择
在本文中主要对两个算法停止了测试,分别是决策树以及SVM算法。采用了交叉验证的方法,来测试哪个模型表现得好,主要代码如下所示:- import pandas as pd
- from sklearn.model_selection import cross_val_score
- from sklearn.tree import DecisionTreeClassifier
- from sklearn.svm import SVC
- input_file = '../tmp/std.xls'
- data = pd.read_excel(input_file)
- #划分X,y
- X = data.loc[:,:'单位里程积分'].values
- y = data.loc[:,'客户类型'].values
- #模型选择使用交叉验证法来评估模型
- model1 = DecisionTreeClassifier()
- model2 = SVC(kernel='rbf')
- score1 = cross_val_score(model1,X,y,cv=5)
- score2 = cross_val_score(model2,X,y,cv=5)
- print('决策树模型得分:{:.2f}'.format(score1.mean()))
- print('SVM模型得分:{:.2f}'.format(score2.mean()))
复制代码 结果如下图所示:
可以看到在还没有对SVM停止参数选择优化的时候,SVM得分已经远远超越了决策树,所以在本次流失分析中,初步选择SVM模型停止此次的分类模型训练。
模型参数选择
在这里使用网格搜索法来选取SVM的最优参数,即确定C、gamma的值,代码如下:- import pandas as pd
- from sklearn.model_selection import train_test_split
- from sklearn.model_selection import GridSearchCV
- from sklearn.svm import SVC
- import joblib
- #读取数据
- input_file = '../tmp/std.xls'
- output_file = '../tmp/loss.pkl'
- data = pd.read_excel(input_file)
- #划分训练集、测试集
- X = data.loc[:,:'单位里程积分'].values
- y = data.loc[:,'客户类型'].values
- X_train,X_test,y_train,y_test = train_test_split(X,y,train_size = 0.8)
- #采用网格搜索法来寻找SVC的最优参数
- svc = SVC(kernel='rbf')
- params = {'gamma':[0.1,1.0,10.0],
- 'C':[1.0,10.0,100.0]}
- grid_search = GridSearchCV(svc,params,cv=5)
- grid_search.fit(X_train,y_train)
- print('模型最高分 {:.2f}'.format(grid_search.score(X_test,y_test)))
- print('最优参数为: {}'.format(grid_search.best_params_))
复制代码 执行结果如下:
可以看到模型得分并不是很高,最佳参数也出来了,暂且就这样用用吧,接下来用最佳参数来训练模型并保管。- svc = SVC(kernel='rbf',C=1.0,gamma=1.0)
- svc.fit(X_train,y_train)
- joblib.dump(svc,output_file)
复制代码 这样就将模型保管好了,后面再用模型来停止预测。
模型预测
这里就只用测试集的一组数据停止测试了,看是否预测分类正确,代码如下:- import joblib
- from model import X_test,y_test
- #导入模型
- model = joblib.load('../tmp/loss.pkl')
- #预测分类
- y_predict = model.predict([X_test[0]])
- print(y_predict)
- print(y_test[0])
复制代码 运行结果如下所示:
如上图所示,这一组预测是正确的,预测的结果是2代表未流失,实际结果也是未流失,说明预测正确,虽然这次的模型得分不高但主要是用来练一下手,有兴趣的可以下来看采用什么办法来进步模型得分。 |