增长黑客在Thera Bank信贷业务的应用-基于Python数据分析

原创,如有参考的部分,请注明出处,感谢!

目录

一、分析背景与目的

二、分析思路

三、分析正文

1、各因素与贷款情况总析

2、二元关系分析

3、多元关系分析

4、建立模型,提供营销方案数据支持

四、总结与建议

1、客户特征总结

2、获客、激活及留存营销方案建议

一、分析背景与目的

Thera Bank是一家业务快速增长的银行,拥有大量的尚未发生贷款业务的存款客户,为了增加贷款业务的客户量,提升公司的利润,他们随机选取了5000名顾客进行了一次贷款业务的营销宣传尝试,获得了超过9%的转化率。

这次报告的目的,就是分析这次营销活动的结果,哪些因素对于贷款的达成起到了比较重要的作用,为获客、激活、留存和变现的环节提供数据支持,并且给出A/B-test方案,快速验证数据指标间的相关关系是否为因果关系,有针对性的进行营销,获得更高的收益。

二、分析思路

1、各因素与贷款情况总析

先根据各因素数据的特点,进行描述性统计分析,并且初略评估各因素与贷款情况的回归关系。

2、二元关系分析

根据1中的相关性大小,分析影响因素大的数据和贷款的关系。

3、多元关系分析

再根据2中的结果,查看多元分组后,是否存在特殊的情况,从而进行特殊对待。

4、数据建模

利用二分类机器学习模型,以AUC为主,Accuracy为辅,的评估指标,通过特征工程,模型选择,参数调优,模型融合的手段,得到最优的预测模型,从而为激活用户营销方案决策提供数据依据。

5、总结和建议

通过上述分析,在获客,激活,留存三个方面给出有数据支撑的建议,并且通过A/B-test验证某些数据指标间的相关关系,是否存在直接的因果关系。

三、分析正文

3.1、各因素与贷款情况总析

3.1.1、导入数据及理解数据集

现将数据导入python中,输入分析需要的模块

#基础模块
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import seaborn as sns
%matplotlib inline
sns.set(style="ticks")

#模型预处理
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import KFold
from sklearn.pipeline import Pipeline
from sklearn.feature_selection import RFECV
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.metrics import classification_report

#二分类评估器
from sklearn.svm import SVC, LinearSVC
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.naive_bayes import BernoulliNB
from sklearn.linear_model import Perceptron
from sklearn.linear_model import SGDClassifier
from sklearn.linear_model import PassiveAggressiveClassifier
from sklearn.linear_model import LogisticRegressionCV
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier

from sklearn.ensemble import VotingClassifier

#读取营销结果数据
data=pd.read_excel('Bank_Personal_Loan_Modelling.xlsx','Data')
data.columns=['ID', 'Age', 'Experience', 'Income', 'ZIP_Code', 'Family', 'CCAvg',
       'Education', 'Mortgage', 'Personal_Loan', 'Securities_Account',
       'CD_Account', 'Online', 'CreditCard']
#查看数据集的整体情况
data.describe().T

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

查看每一个特征的变量数量

data.apply(lambda x: len(x.unique()))

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

特征解释:

ID:客户账号ID,无实际意义

Age:客户年龄,数值变量

Experience:工作经验,数值变量

Income:年收入,数值变量

ZIP_Code:客户所在地邮编,需要当作字符串处理

Family:家庭人数,离散型数值变量

CCAvg:每月信用卡还款额,数值变量

Education:受教育程度,离散数值变量,1为未毕业,2为毕业生,3为高级毕业生

Mortgage:抵押贷款数,数值变量

Personal_Loan:是否参加这次抵押贷款,布尔变量

Securities_Account:在本银行是否有秘密账户,布尔变量

CD_Account:在本银行是否有存款账户,布尔变量

Online:是否开通网上银行,布尔变量

CreditCard:是否有信用卡,布尔变量

3.1.2、清洗数据集

通过观察,发现工作经验存在负值,根据经验,工作经验和年龄及受教育程度是高度相关的,所以将工作经验为负值的数值,转换成相同年龄和受教育程度的中位数值。

#过滤出正常的工作经验值数据集和不正常的工作经验布尔值
dfExp=data.query('Experience>0')
negExp=data.Experience<0
mylist=data.loc[negExp]['ID'].tolist()
#对每一个工作经验为负值的样本,用同年龄和教育程度的工作经验均值替代
for id in mylist:
    age=data.query('ID==@id').Age.tolist()[0]
    education=data.query('ID==@id').Education.tolist()[0]
    df_filtered=dfExp.query('Age==@age and Education==@education')
    exp=df_filtered['Experience'].median()
    if exp is np.nan:
        exp=data.Experience.median()
    data.loc[data.query('ID==@id').index, 'Experience'] = exp
#检查处理结果
print(data.Experience.describe())
sns.distplot(data.Experience)

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

3.1.3、数据及数据间关系分析

在分析各数据间关系时,我们有必要先看一下各个数据集,尤其是数值变量的分布情况。

#显示各个数值变量之间的关系
sns.pairplot(data.loc[:,['Age','Experience','Income','ZIP_Code','CCAvg','Mortgage']])

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

从图中可以得出以下结论:

1、年龄和工作经验的分布,接近于平均分布,各个年龄段分布比较合理,分箱时,适合按数值等值分箱;

2、收入,信用卡还款额和房屋抵押租赁,接近于幂律分布,而且没有房屋抵押租赁的用户占大多数,分箱时,最好能特殊情况分出One-Hot特征;

3、城市地址对于其他特征的影响很小,基本可以推断,影响可以忽略不计;

4、随着收入的增多,信用卡的还款值和房屋抵押贷款值的最大值,是线性增加的,这是符合常识的。

接下来,查看一下离散型变量之间的关系。

#画出离散型变量之间的关系
sns.pairplot(data.drop(['Age','Experience','Income','ZIP_Code','CCAvg','Mortgage']\
,axis=1).iloc[:,1:])

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

从图中,可以得出以下结论:

1、家庭、教育、网上银行及信用卡率的分布比较均匀;

2、个人贷款,私密账户率及个人存单率的分布是属于不均衡分布,所以,个人贷款的评估标准,应该以查全率(recall)和查准率(precision)作为评估的标准。

3.1.4、计算各变量之间的相关性

计算各个变量与贷款率之间的关系

#用热图显示各个变量之间的相关关系
f, ax = plt.subplots(figsize=(16, 12))
sns.set()
sns.heatmap(data.drop('ID',axis=1).corr(),annot=True,cmap='YlGnBu')

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

从图中可以看出:

1、和开通信贷强相关的变量有:收入,信用卡还款额及是否有该银行存单账户;

2、和开通信贷弱相关的变量有:受教育程度,房屋抵押贷款数,家庭人数;

3、年龄、工作经验、邮编、是否是私密账户,是否开通网上银行及是否有信用卡,关系都不大;

4、因为年龄、工作经验都是连续的数值变量,所以需要分箱后再做观察,看看是否有某一段存在特殊值。

3.2、二元关系分析

通过上面对于所有数据集的概览,能了解各个变量的自身分布情况,以及与是否开通信贷的关系,接下来,我们来关注上面获取的几个变量,和开通信贷之间的关系。

3.2.1、分类变量

从3.1.4中,我们知道,是否有该银行存单账户是强相关变量,受教育程度,家庭人数是弱项关变量,我们下面来一一看看这三者和开通信贷业务的关系。

#银行存单和开通信贷的关系
print(data.groupby('CD_Account')['Personal_Loan'].agg([np.mean,np.std]))
sns.catplot('CD_Account',hue='Personal_Loan',data=data,kind='count')

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:可以看出,开通了银行存单账户的客户,其申请贷款的可能性是没有开通的6倍多。

策略:让尽可能多的客户开通该银行存款账单是一个提高申请贷款率的可能选项。

#受教育程度对于申请贷款业务的影响
print(data.groupby('Education')['Personal_Loan'].agg([np.mean,np.std]))
sns.catplot('Education',hue='Personal_Loan',data=data,kind='count')

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:从图中可以看出,没有大学学位的人,对于申请贷款的意愿明显低于受过高等教育的人,但是收到高等教育之后,更高的学历对于申请贷款的可能性的提高很小。

策略:提升贷款申请率的可能方式可以是,尽可能是争取更多的高学历客户。

#家庭人数对于开通贷款业务的影响
print(data.groupby('Family')['Personal_Loan'].agg([np.mean,np.std]))
sns.catplot('Family',hue='Personal_Loan',data=data,kind='count')

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:当家庭人数只有1或者2个人的时候,申请贷款的可能性较低,而当人数达到三人时,申请贷款率猛增,当家庭人数达到四人时,申请贷款率又下降了,很有趣的现象,这种情况下需要结合其他的因素一起观察,将在下一节进行讨论。

策略:可以着重加强对于家庭人数为3的客户的宣传。

3.2.2、数值变量

从3.1.4中,我们得知,收入,信用卡还款额,抵押贷款数对申请贷款是有影响的。

在观察数值变量对于分类变量的影响时,一般有两种方式,第一种是通过箱型图或者小提琴图的方式,另外一种是先将数值变量分箱,然后查看每个箱中目标变量的均值随自变量变化的关系。第一种比较简单,但是观察起来比较费力,第二种操作比较麻烦,但是观察起来很轻松。

我下面先用箱型图和小提琴图做一下分析,然后再主要用第二种方法进行分析。

#分析收入对于申请贷款的影响
print(data.groupby('Personal_Loan')['Income'].agg(['count',np.mean,np.std]))
sns.catplot('Personal_Loan','Income',data=data,kind='violin')
sns.catplot('Personal_Loan','Income',data=data,kind='boxen')

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

从两张图中可以看出,高收入的人明显比低收入的人更愿意申请贷款,这和我们的常识也是相符的。但是这张图,有一个缺陷,就是不能看出,各个收入段的申请贷款的比率,所以我们需要再进行一些处理。

#查看贷款开通率随收入增长的变化
data['Income_Bins']=pd.qcut(data.Income,20)
print(data.groupby('Income_Bins')['Personal_Loan'].agg({'mean':np.mean,'count':'count'}))
data.groupby('Income_Bins')['Personal_Loan'].agg({'Loan_rate':np.mean}).plot()

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:从图中可以看出,当年收入超过82时,贷款意愿会有5倍以上的大幅上升,超过98时,贷款意愿会有将近三倍的大幅提升,而且收入越高,贷款的意愿越强。

策略:可以重点关注年收入大于98的顾客,他们的贷款意愿是极强的。

接下来关注信用卡还款额和房屋抵押贷款数对申请贷款的影响。

#贷款申请率随信用卡还款额和房屋抵押贷款的变化
sns.catplot('Personal_Loan','CCAvg',data=data,kind='boxen')
data['CCAvg_Bins']=pd.qcut(data.CCAvg,20)
print(data.groupby('CCAvg_Bins')['Personal_Loan'].agg({'mean':np.mean,'count':'count'}))
data.groupby('CCAvg_Bins')['Personal_Loan'].agg({'Loan_rate':np.mean}).plot()

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:当每月信用卡还款额大于2.8时,申请贷款率会增大将近4倍。

策略:可以将宣传的重点,放在信用卡还款额大于2.8的客户中。

sns.catplot('Personal_Loan','Mortgage',data=data,kind='boxen')
data['Mortgage_Bins']=pd.cut(data.Mortgage,10)
print(data.groupby('Mortgage_Bins')['Personal_Loan'].agg({'mean':np.mean,'count':'count'}))
data.groupby('Mortgage_Bins')['Personal_Loan'].agg({'Loan_rate':np.mean}).plot()

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:当房屋抵押值大于254时,贷款申请的意愿有明显的提升,当大于508时,一半以上的人,都会申请房屋抵押贷款。

策略:可以根据这三段,采取不同的营销策略。

3.3、多元关系分析

从3.2中,我们得到有六个变量对于申请贷款是有关系的,分别是:

离散变量:存单账号,受教育水平,家庭人数

数值变量:收入,信用卡还款额,房屋抵押贷款值

目标值:申请贷款

3.3.1、两数值变量

我们先从方便的,数值变量入手进行分析。

#多数值变量对于贷款率的影响
sns.pairplot(data.loc[:,['Personal_Loan','Income','CCAvg','Mortgage']],\
             diag_kind='kde',vars=['Income','CCAvg','Mortgage'],\
             hue='Personal_Loan',plot_kws={'alpha':0.3})

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:

1、低收入和低信用卡还款额的用户,显然不喜欢申请贷款,而且两者的边界特别明显;

2、相同收入下,信用卡还款额多的用户,也不愿意申请贷款;

3.3.2、离散变量组合

在进行变量组合之前,有必要再对选取出来的7个变量做一下相关性分析。

#用热图对七个变量进行相关性分析
f, ax = plt.subplots(figsize=(16, 12))
sns.set()
sns.heatmap(data[['Personal_Loan','Income','CCAvg','Mortgage','Family',\
'Education','CD_Account']].corr(),annot=True,cmap='YlGnBu')

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:

1、从图中可以看出三个数值变量之间的两两关系分别是:0.11,0.21,0.65,显然和上面的分析吻合;

2、三个离散数值变量之间的两两关系分别是:0.065,0.014,0.014,显然相互之间没有很大的相关性,所以可以一次看一下,进行检验;

3、存款存单和收入及信用卡月还款之间有一定的联系(0.17,0.14),可以查看下这三者和贷款申请的关系,因为受教育程度和申请意愿关系也比较大,所以再加上受教育程度,看看这个5者的关系。

#存单账户及受教育程度和收入及信用卡月还款于申请贷款的关系
sns.relplot('Income','CCAvg',hue='Personal_Loan',\
data=data,col='CD_Account',row='Education')

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:

1、存单账户中的高收入人群,对于贷款的意愿是极高的;

2、低收入人群,不论是不是该银行的存单账号,对于申请贷款的意愿都是极低的。

3、当收入在110以上,信用卡月还款额度在3以上且有大学文聘的客户,申请贷款意愿在97%以上。

#查看收入在110以上,月信用卡还款额在3以上的申请贷款意愿度
print(data.query('Income>110 and CCAvg>3').groupby(['Education','CD_Account'])\
['Personal_Loan'].agg({'count':'count','loan':np.sum,'mean':np.mean,'std':np.std})\
.sort_values('mean',ascending=False))

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

#三个离散变量于申请贷款的关系
print(data.groupby(['Family','Education','CD_Account'])\
      ['Personal_Loan'].agg({'count':'count',\
                             'loan':np.sum,'mean':np.mean,\
                             'std':np.std}).sort_values('mean',ascending=False))
sns.catplot('Family',hue='Personal_Loan',row='CD_Account',\
            col='Education',data=data,kind='count')

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

结论:这里的结论都能根据上面离散变量的情况推导出来,有一点很惊讶,就是转化率为0的那列,就算是银行存单账户,但是是两个人,且没有受过教育时,居然没有一个申请贷款,里面的原因很多,可能是他们根本不知道有这件事,也可能这29人都是一次活动中申请的银行账户等等。

3.4、建立模型,提出营销方案

根据之前的分析,接下来可以在这三方面做些事情:

1、在获客上,根据分析获得的高申请贷款意愿客户的特征,有针对性的去获取更多的客户,使得客户的贷款转化率得到提升;

2、在用户激活上,根据已经进行过实验的客户数据,建立营销方案模型,对银行中的其他存量客户,进行精准的营销,提高申请贷款客户的数量;

3、在用户留存上,对于一些能显著提高贷款转化率的特征,可以让银行的业务经理对客户进行跟进,比如说对于开通存单账户的客户,有相应的优惠,提升存量客户开通的可能性等等。

3.4.1、建立营销方案模型

可以将申请贷款的问题,简化为机器学习中的二元分类问题,3.1-3.3已经对现有数据进行了分析,接下来需要以下几个步骤,去建立相应的模型:

1、明确目标及评估指标

2、特征工程

3、模型选择及超参数调节

4、模型融合

5、检验结果及优化

3.4.1.1、明确目标及评估指标

这次的目标是为了能精准的确定大概率可能申请贷款的用户,目前还不清楚具体的每一个用户的营销成本,因为该预测集是严重的不平衡集(反类:正类=9:1),所以我们选择ROC曲线的AUC值作为我们的一个评判标准,另外将查全率(recall)和查准率(precision)及f-1分数作为辅助的指标,一切根据具体的营销成本核算为准。

3.4.1.2、特征工程

根据3.3的分析,选择收入(Income),月信用卡还款(CCAvg),房屋抵押贷款值(Mortgage),是否为存单用户(CD_Account),受教育程度(Education)和家庭人数(Family)六个特征进行特征工程。

#将连续数值变量分箱
data['Income_Bins']=pd.qcut(data.Income,10,labels=range(0,10)).astype(int)
data['CCAvg_Bins']=pd.qcut(data.CCAvg,10,labels=range(0,10)).astype(int)
data['Mortgage_Bins']=pd.cut(data.Mortgage,10,labels=range(0,10)).astype(int)

#因为收入和月信用卡还款额分别在110和3处,存在明显的边界,所以额外生成两个特征
data['Income_110']=np.where(data.Income>110,1,0)
data['CCAvg_3']=np.where(data.CCAvg>3,1,0)

#生成用于模型训练的数据集,及拆分成训练集和测试集
columns=data.columns.drop(['ID','Age','Experience','Income','ZIP_Code','CCAvg','Mortgage','Personal_Loan','Securities_Account','Online','CreditCard'])
train=data[columns]
y=data.Personal_Loan.values
X_train,X_test,y_train,y_test=train_test_split(train,y,random_state=0)

print(X_train.shape)
print(y_train.shape)

(3750, 8)
(3750,)

3.4.1.3、模型选择及超参数调节

获得训练集和测试集之后,先进行一次Baseline,获得二分类模型对于这组数据的大概准确度,挑选几个,进行后面的优化和模型融合。

#定义非平衡集的Baseline函数
def baseline_imbalanced_dataset(X_train,y_train,X_test,y_test):
    MLA=[AdaBoostClassifier(),BaggingClassifier(),ExtraTreesClassifier(),\
    GradientBoostingClassifier(),RandomForestClassifier(),\
    GaussianProcessClassifier(),LogisticRegressionCV(),\
    PassiveAggressiveClassifier(),SGDClassifier(),\
    Perceptron(),BernoulliNB(),GaussianNB(),KNeighborsClassifier(),\
    SVC(probability=True),LinearSVC(),DecisionTreeClassifier()]
    MLA_compare=[]
    for alg in MLA:
        MLA_dict={}
        alg.random_state=0
        MLA_name=alg.__class__.__name__
        score=cross_val_score(alg,X_train,y_train,cv=5)
        score_mean=round(score.mean(),4)
        score_std=round(score.std(),4)
        alg.fit(X_train,y_train)
        try:
            auc=roc_auc_score(y_test,alg.predict_proba(X_test)[:,1])
        except:
            auc=roc_auc_score(y_test,alg.decision_function(X_test))
        MLA_dict['Auc']=round(auc,4)
        MLA_dict['name']=MLA_name
        MLA_dict['accuracy']=score_mean
        MLA_dict['std']=score_std
        MLA_compare.append(MLA_dict)
    MLA_df=pd.DataFrame(MLA_compare)
    MLA_df.set_index('name',inplace=True)
    return MLA_df.sort_values('Auc',ascending=False)

baseline_imbalanced_dataset(X_train,y_train,X_test,y_test)

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

可以看到,在没有调参数前,一般的模型正确率普遍都在90%以上,最高的是梯度提升机(GradientBoostingClassifier),并且它的AUC值高达99.71%,堪称完美。

因为此次的预测结果非常好,我们可以选取其中的最好的三个模型(GradientBoosting,GaussianProcess,SVC),进行参数调节,之后再试试模型融合的效果。

#定义超参数调节类,调节超参数
class SubestimatorOfStacking():
    '''使用stacking模型融合时,快捷的类
    参数
    ---------------
    alg:estimator
    param_grid:grid of parameter for estimator
    '''
    def __init__(self,alg,param_grid,random_state=0,n_jobs=None):
        self.alg=alg
        self.param_grid=param_grid
        self.random_state=random_state
        self.alg.random_state=self.random_state
        self.n_jobs=n_jobs

    def fit(self,X,y,rfecv=False):
        self.X_train=X
        self.y_train=y
        self.rfecv_=rfecv
        self.grid=GridSearchCV(self.alg,self.param_grid,cv=5)
        self.grid.n_jobs=self.n_jobs
        self.grid.fit(self.X_train,self.y_train)
        self.best_estimator_=self.grid.best_estimator_
        self.best_params_=self.grid.best_params_
        print('The best score after GridSearchCV is '+str(self.grid.best_score_)+'.')
        if self.rfecv_:
            self.rfecv=RFECV(self.best_estimator_,min_features_to_select=int(self.X_train.shape[1]/2),cv=5)
            self.rfecv.fit(self.X_train,self.y_train)
            self.best_features_=self.X_train.columns[self.rfecv.get_support()]
            self.features_=pd.Series(self.rfecv.estimator_.feature_importances_,index=self.best_features_).sort_values(ascending=False)
            print('The best score after RFECV is '+str(self.rfecv.grid_scores_.max())+'.')
            print('The number of selected features is '+str(self.rfecv.n_features_)+'.')
            print('If you want get the top features,please use self.best_features_.')
        else:
            self.features_=self.X_train.columns
        self.cv_results_=pd.DataFrame(self.grid.cv_results_)
        self.cv_results_heatmap_=self.cv_results_.pivot_table(values='mean_test_score',columns=self.cv_results_.columns[4],index=self.cv_results_.columns[5])
        sns.heatmap(self.cv_results_heatmap_,annot=True)
        print('The best params is {}'.format(self.grid.best_params_))
        return self

    def stacking(self,X,y,X_test,NFolds=5,reduce_features=0,from_importancest=False,use_best_features=False):
        self.use_best_features=use_best_features
        self.from_importancest=from_importancest
        self.reduce_features=reduce_features   
        if self.rfecv_:
            self.features_=pd.Series(self.rfecv.estimator_.feature_importances_,index=self.best_features_).sort_values(ascending=self.from_importancest)
            self.stacking_features_len_=len(self.features_.index)-self.reduce_features
            self.columns_=self.features_.index[:self.stacking_features_len_]
            self.X_train=X[self.columns_].values
            self.X_test=X_test[self.columns_].values
        else:
            self.stacking_features_len_=len(self.features_)-self.reduce_features
            self.columns_=self.features_[:self.stacking_features_len_]
            self.X_train=X[self.columns_].values
            self.X_test=X_test[self.columns_].values
        self.y_train=y
        self.NFolds=NFolds
        ntrain=self.X_train.shape[0]
        ntest=self.X_test.shape[0]
        self.oof_train=np.zeros((ntrain,))
        self.oof_test=np.zeros((ntest,))
        oof_test_df=np.empty((self.NFolds,ntest))
        kf=KFold(n_splits=self.NFolds,random_state=self.random_state)

        for i,(train_index,test_index) in enumerate(kf.split(self.X_train)):
            X_tr=self.X_train[train_index]
            y_tr=self.y_train[train_index]
            X_te=self.X_train[test_index]

            self.best_estimator_.fit(X_tr,y_tr)
            y_te=self.best_estimator_.predict(X_te)
            self.oof_train[test_index]=y_te
            oof_test_df[i,:]=self.best_estimator_.predict(X_test)
        self.oof_test=oof_test_df.mean(axis=0)
        self.oof_train=self.oof_train.reshape(-1,1)
        self.oof_test=self.oof_test.reshape(-1,1)
        return self.oof_train,self.oof_test
    def fit_predict(self,X,y,test):
        self.best_estimator_.fit(X,y)
        return self.best_estimator_.predict(test)

#输入三个模型的调参范围
param_grid_GradientBoostingClassifier={'learning_rate':\
[0.005,0.007,0.01,0.02,0.03],'n_estimators':[600,800,1000,1200,1400],\
'random_state':[0]}
param_grid_SVC={'C':[200,250,300,350,400],'gamma':[0.02,0.03,0.04],\
'random_state':[0]}
param_grid_GaussianProcessClassifier={'max_iter_predict':\
[50,100,200,500,1000,2000],'random_state':[0]}


#将三者的参数输入进行网格搜索
gbc=SubestimatorOfStacking(GradientBoostingClassifier(),\
param_grid_GradientBoostingClassifier).fit(X_train,y_train)
svc=SubestimatorOfStacking(SVC(),param_grid_SVC).fit(X_train,y_train)
gpc=SubestimatorOfStacking(GaussianProcessClassifier(),\
param_grid_GaussianProcessClassifier).fit(X_train,y_train)

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

#看一下三者的AUC值的大小
print('The AUC of GradientBoostingClassifier is '\
+str(roc_auc_score(y_test,gbc.best_estimator_.decision_function(X_test))))
print('The AUC of SVC is '\
+str(roc_auc_score(y_test,svc.best_estimator_.decision_function(X_test))))
print('The AUC of GaussianProcessClassifier is '\
+str(roc_auc_score(y_test,gpc.best_estimator_.predict_proba(X_test)[:,1])))

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

可以看出,调节参数后,AUC值也是有所提升的。

3.4.1.4、模型融合

因为梯度增强机(GradientBoostingClassifier)本身就是多个决策树用boosting方法融合后的结果,下面再用voting和staking两种方法进行融合,尝试能不能获得更好的结果。

#创建投票评估器
vc=VotingClassifier([('gbc',gbc.best_estimator_),('gpc',gpc.best_estimator_),('svc',svc.best_estimator_)],weights=[3,1,2],voting='hard')

#构建stacking评估器
gbc_train,gbc_test=gbc.stacking(X_train,y_train,X_test,NFolds=3)
svc_train,svc_test=svc.stacking(X_train,y_train,X_test,NFolds=3)
gpc_train,gpc_test=gpc.stacking(X_train,y_train,X_test,NFolds=3)

#将这三组数据统一到训练和测试集,我们可以看一下,这个的预测结果的相关性,评估的好坏,当然是越不相关越好,因为这样才能让各个模型挖掘出更多的信息
base_train=pd.DataFrame({'gbc':gbc_train.ravel(),'gpc':gpc_train.ravel(),'svc':svc_train.ravel()})
base_test=pd.DataFrame({'gbc':gbc_test.ravel(),'gpc':gpc_test.ravel(),'svc':svc_test.ravel()})

sns.heatmap(base_train.corr(),annot=True)
sns.heatmap(base_test.corr(),annot=True)

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

#将stacking后的数据集选择新的模型进行训练,参数都是最后一步的范围确定
param_grid_AdaBoostClassifier={'learning_rate':[0.005,0.007,0.01,0.012,0.015],\
'n_estimators':[30,40,50,60,70],'random_state':[0]}

abc_stacking=SubestimatorOfStacking(AdaBoostClassifier(),\
param_grid_AdaBoostClassifier).fit(base_train,y_train)

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

3.4.1.5、检验结果及优化

#比较Gradientboosting,SVC,Gaussianprocess,Voting和Staking五种方式的最后结果。
gbc_score=cross_val_score(gbc.best_estimator_,train,y,cv=10)
svc_score=cross_val_score(svc.best_estimator_,train,y,cv=10)
gpc_score=cross_val_score(gpc.best_estimator_,train,y,cv=10)
vc_score=cross_val_score(vc,train,y,cv=10)
abc_stacking_score=cross_val_score(abc_stacking.best_estimator_,base_train,y_train,cv=10)

scores_df=pd.DataFrame({'GradientBoosting':gbc_score,'SVC':svc_score,'GaussianProcess':gpc_score,'Voting':vc_score,'Stacking':abc_stacking_score})
scores_df.plot(kind='box')

print('The test score of staking is {0:.4f}'.format(abc_stacking.best_estimator_.score(base_test,y_test)))
print('The test score of GradientBoosting is {0:.4f}'.format(gbc.best_estimator_.score(X_test,y_test)))
print('The AUC value of staking is {0:.4f}'.format(roc_auc_score(y_test,abc_stacking.best_estimator_.decision_function(base_test))))
print('The AUC value of GradientBoosting is {0:.4f}'.format(roc_auc_score(y_test,gbc.best_estimator_.decision_function(X_test))))

《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》
《增长黑客在Thera Bank信贷业务的应用-基于Python数据分析》

总结:从准确及其误差范围来看,staking方法确实优于梯度提升机,但是stacking的AUC值发生了巨大的滑坡,推测是由于阈值在变化的某一区域,假正例的变化存在异常,综合考虑后,在没有考虑营销成本的情况下,选择梯度提升机作为最后的模型。

四、总结与建议

4.1、总结

1、 在所有特征中,有三个连续数值特征(收入,信用卡还款额,房屋抵押额)和三个离散数值特征(银行存单客户,受教育程度,家庭人数)是对申请贷款率有较大的影响的;

2、在银行有存单账户的客户,申请贷款的意愿远高于没有的,有大学学位的客户高于没有的,家庭人数为三人时,存款意愿最高;

3、低收入和低信用卡还款额的用户,显然不喜欢申请贷款,而且两者的边界特别明显,并且在相同收入下,信用卡还款额到收入极限的用户,也不愿意申请贷款;

4、当收入在110以上,信用卡月还款额度在3以上且有大学文聘的客户,申请贷款意愿在97%以上;

5、在有银行存单账户的顾客中,除了没有大学文聘且单身或者家庭人数只有两人的,申请贷款的意愿都相当高,成功率在43%以上。

4.2、建议和方案

1、在留存及变现方面,对于已经进行过贷款宣传的客户,可以在银行存单方面下功夫,促进其成为银行存单用户,再进行A/Btest,看银行存单用户在转换过程中,对于申请贷款的实际影响;

2、在激活方面,对于还没有进行宣传贷款的客户,可以利用3.4中优化的模型,对其进行精准的营销,减少营销的成本;

3、在获取客户方面,对于业务人员的工作,应该将收入,信用卡还款额,房屋抵押额,是否有意愿开通存单,受教育程度和家庭人数六个方面作为拓展新客户的标准,以最小的投入,达到最好的成果。

    原文作者:蛋壳先生Dank
    原文地址: https://zhuanlan.zhihu.com/p/51819396
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞