数据挖掘期末大作业v3 | 八月更文挑战

2,374 阅读14分钟

代码如下:银联“信贷用户逾期预测”算法大赛总结

文件介绍

  • 01数据预处理

  • 02特征工程

  • 03模型选择 - xgb_model

  • 03模型选择 - ctb_model

  • 03模型选择 - lgb_model

  • 04模型调优

  • 05模型融合

  • 06过采样

  • 06下采样

  • profiling.html( 数据的可视化和统计量)

  • features.csv 特征工程之后的文件

  • lgb_oof_feature_engineering.csv 训练集的中间结果

  • xgb_oof_feature_engineering.csv

  • cbt_oof_feature_engineering.csv

  • lgb_test_feature_engineering.csv 测试集的中间结果

  • xgb_test_feature_engineering.csv

  • cbt_test_feature_engineering.csv

题目介绍

个人信用是整个社会信用的基础,市场交易中所有的经济活动,与个人信用息息相关。一旦个人行为失之约束,就会发生个人失信行为,进而出现集体失信。因此,个人信用体系建设具有极其重要的意义,然而随着经济的发展,越来越重要的信用记录与信用记录的缺失之间的矛盾日益激化,建立完善的信用体系迫在眉睫。随着近年来面向个人的小额贷款业务的不断发展,防范个人信贷欺诈,降低不良率是开展相关业务的首要目标。通过机器学习模型实现对小额信贷业务申请个人欺诈和逾期风险的精准识别,进一步提升金融机构防范欺诈和降低不良率的能力。

如下表所示,数据包含11017条数据,每一条数据包含201个属性,其中主要包括以下几个大类别的信息:身份信息及财产状况,持卡信息,交易信息,放款信息,还款信息,申请贷款信息。

Number of variables 201
Number of observations 11017
Total Missing (%) 14.3%
Total size in memory 16.9 MiB
Average record size in memory 1.6 KiB

模型原理介绍

该项目主要是用到了三个XGBoost,LightGBM,CatBoost,这三个模型都是梯度提升树,各有特点。

2014 年 3 月,XGBOOST 最早作为研究项目,由陈天奇提出

2017 年 1 月,微软发布首个稳定版 LightGBM

2017 年 4 月,俄罗斯顶尖技术公司 Yandex 开源 CatBoost

  • XGBoost XGBoost算法的思想:不断添加树,不断进行特征分裂来生成一棵树,每添加一棵树就是学习一个新的函数来拟合上次的残差,当训练完成后得到K棵树,要预测一个样本的分数,其实就是根据样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点对应一个分数,最后需要将每棵树对应的分数加起来就是该样本的预测值; image.png

  • LightGBM

LightGBM是个快速、分布式的、高性能的基于决策树的梯度提升算法。可以用于分类、回归、排序等机器学习任务中。因为它是基于决策树算法的,它采用最优的leaf-wise策略分裂叶子节点,其它提升算法一般采用的是depth-wise或者level-wise而不是leaf-wise。因此,在LightGBM算法中,当增长到相同的叶子节点,leaf-wise算法比level-wise算法减少更多的loss。因此导致更高的精度,而其他的任何已存在的提升算法都不能够达。与此同时,它的速度也让人感到震惊,这就是该算法名字Light 的原因。Leaf-Wise分裂导致复杂性的增加并且可能导致过拟合。但是这是可以通过设置另一个参数 max-depth来克服,它分裂产生的树的最大深度。总结起来LightGBM采用Histogram算法进行特征选择以及采用Leaf-wise的决策树生长策略,使其在一批以树模型为基模型的boosting算法中脱颖而出。

LightGBM的优势:

更快的训练速度和更高的效率:LightGBM使用基于直方图的算法。例如,它将连续的特征值分桶(buckets)装进离散的箱子(bins),这是的训练过程中变得更快。 更低的内存占用:使用离散的箱子(bins)保存并替换连续值导致更少的内存占用,只保存特征离散化后的值,而这个值一般用8位整型存储就足够了,内存消耗可以降低为原来的1/8。 更高的准确率(相比于其他任何提升算法):它通过leaf-wise分裂方法产生比level-wise分裂方法更复杂的树,这就是实现更高准确率的主要因素。然而,它有时候或导致过拟合,但是我们可以通过设置max-depth参数来防止过拟合的发生。 大数据处理能力:相比于XGBoost,由于它在训练时间上的缩减,它同样能够具有处理大数据的能力。 支持并行学习:特征并行和数据并行。

XGBoost和LightGBM的对比如下:

  • CatBoost

CatBoost主要有以下五个特性:

无需调参即可获得较高的模型质量,采用默认参数就可以获得非常好的结果,减少在调参上面花的时间 支持类别型变量,无需对非数值型特征进行预处理 快速、可扩展的GPU版本,可以用基于GPU的梯度提升算法实现来训练你的模型,支持多卡并行 提高准确性,提出一种全新的梯度提升机制来构建模型以减少过拟合 快速预测,即便应对延时非常苛刻的任务也能够快速高效部署模型

XGBoost,LightGBM 和 CatBoost对比:

image.png

分类问题评价指标

很明显这是一个二分类问题。分类算法常见的评估指标如下:

  1. 混淆矩阵(Confuse Matrix)

(1)若一个实例是正类,并且被预测为正类,即为真正类TP(True Positive ) (2)若一个实例是正类,但是被预测为负类,即为假负类FN(False Negative ) (3)若一个实例是负类,但是被预测为正类,即为假正类FP(False Positive ) (4)若一个实例是负类,并且被预测为负类,即为真负类TN(True Negative )

  1. 准确率(Accuracy) 准确率是常用的一个评价指标,但是不适合样本不均衡的情况。
Accuracy=TP+TNTP+TN+FP+FNAccuracy = \frac{TP + TN}{TP + TN + FP + FN}
  1. 精确率(Precision) 又称查准率,正确预测为正样本(TP)占预测为正样本(TP+FP)的百分比。
Precision=TPTP+FPPrecision = \frac{TP}{TP + FP}
  1. 召回率(Recall) 又称为查全率,正确预测为正样本(TP)占正样本(TP+FN)的百分比。
Recall=TPTP+FNRecall = \frac{TP}{TP + FN}
  1. F1 Score 精确率和召回率是相互影响的,精确率升高则召回率下降,召回率升高则精确率下降,如果需要兼顾二者,就需要精确率、召回率的结合F1 Score。
F1Score=21Precision+1RecallF1-Score = \frac{2}{\frac{1}{Precision} + \frac{1}{Recall}}
  1. P-R曲线(Precision-Recall Curve) P-R曲线是描述精确率和召回率变化的曲线

image.png

  1. ROC(Receiver Operating Characteristic)

ROC空间将假正例率(FPR)定义为 X 轴,真正例率(TPR)定义为 Y 轴。 TPR:在所有实际为正例的样本中,被正确地判断为正例之比率。

TPR=TPTP+FNTPR = \frac{TP}{TP + FN}

FPR:在所有实际为负例的样本中,被错误地判断为正例之比率。

FPR=FPFP+TNFPR = \frac{FP}{FP + TN}
  1. AUC(Area Under Curve) AUC(Area Under Curve)被定义为 ROC曲线 下与坐标轴围成的面积,显然这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围在0.5和1之间。AUC越接近1.0,检测方法真实性越高;等于0.5时,则真实性最低,无应用价值。

对于金融风控预测类常见的评估指标如下:

1、KS(Kolmogorov-Smirnov) KS统计量由两位苏联数学家A.N. Kolmogorov和N.V. Smirnov提出。在风控中,KS常用于评估模型区分度。区分度越大,说明模型的风险排序能力(ranking ability)越强。 K-S曲线与ROC曲线类似,不同在于:ROC曲线将真正例率和假正例率作为横纵轴; K-S曲线将真正例率和假正例率都作为纵轴,横轴则由选定的阈值来充当。 公式如下:

KS=max(TPRFPR)KS=max(TPR-FPR)

KS不同代表的不同情况,一般情况KS值越大,模型的区分能力越强,但是也不是越大模型效果就越好,如果KS过大,模型可能存在异常,所以当KS值过高可能需要检查模型是否过拟合。以下为KS值对应的模型情况,但此对应不是唯一的,只代表大致趋势。

KS(%) 好坏区分能力
20以下 不建议采用
20-40 较好
41-50 良好
51-60 很强
61-75 非常强
75以上 过于高,疑似存在问题

数据挖掘过程

主要流程

import pandas_profiling
pfr = pandas_profiling.ProfileReport(df_train)
pfr.to_file("./profiling.html")

可视化:查看数据的分布情况

样本分布饼图如学习,样本有不均衡的问题,未逾期的和逾期的比例是4:1。可使用过采样下采样的方法处理一下

image.png

其他字段也是类似的查看其分布,例如x_001。主要指标如下图所示有最大值,最小值,Q1,Q3,均值,方差,偏差。

Quantile statistics

Minimum 0
5-th percentile 0
Q1 0
Median 0
Q3 0
95-th percentile 1
Maximum 1
Range 1
Interquartile range 0

Descriptive statistics

Standard deviation 0.36254
Coef of variation 2.3292
Kurtosis 1.6102
Mean 0.15565
MAD 0.26285
Skewness 1.9
Sum 1710
Variance 0.13144
Memory size 86.1 KiB

频率分布直方图,如下图所示 image.png

image.png

image.png

其他详细信息见:profiling.html

数据预处理

缺失值处理

缺失值大于一半的属性如下图所示:

image.png

缺失的主要是:交易信息,放款信息,还款信息,申请贷款信息。这些缺失值比例中大于60%,选择删除,低于60的暂时用零做填充

数据箱型图

image.png

结合profiling.html箱型图数据可知分布都比较单一,x_014(投资理财类标志)0和1各占一半左右。

相关性分析

对数据进行相关性分析,如下图所示,相关性较强的都是每个大类中的字段。例如申请贷款信息中的(x_188-x_199)的数据相关性就很强。

特征工程

此处对特征进行构建,构建的思路是两个:

  1. 基于模型的表达能力,以及需要什么样的特征,将原先的特征重新进行编码(特征转换)
  2. 对特征进行组合构建,构建更多具有表示能力的特征

基于模型的表达能力的特征

  1. 将身份信息以及财产信息进行编码,0-1进行组合编码(提高模型的表示能力)

比例特征构建

  1. 借记卡的比例特征(各种借记卡所占的比例)
  2. 贷记卡的比例特征(各种贷记卡所占的比例)
  3. 银行卡的比例特征(各种银行卡所占的比例)
  4. 失败还款笔数占比
  5. 失败申请贷款的占比

标准差还原特征(反映信息的波动)

  1. 将数据中的标准差进行还原

均值特征

  1. 每张卡(例如信用)交易金额等;
  2. 每笔(例如异地每笔)交易金额等;
  3. 每笔还款金额等
  4. 每笔商旅,保险,家装,金融等的均值特征
  5. 每个月的平均交易笔数
  6. 每个月的交易金额
  7. 每笔放款金额,每个机构的放款笔数,每个机构的放款金额
  8. 每个机构的平均还款金额,每个机构的
  9. 每个机构的贷款金额
  10. 其他均值特征

趋势特征

  1. 90天与30天的申请贷款机构的趋势,180天与90天的申请贷款机构的趋势,180天与30天的申请贷款机构的趋势
  2. 90天与30天的成功申请贷款机构的趋势,180天与90天的成功申请贷款机构的趋势,180天与30天的成功申请贷款机构的趋势
  3. 90天与30天的申请贷款笔数的趋势,180天与90天的申请贷款笔数的趋势,180天与30天的申请贷款笔数的趋势

模型选择

切分训练集和测试集0.8作为训练集,0.2作为测试集合

# df_train = pd.read_csv('/home/mw/input/tianchi6504/model_sample.csv')
df = pd.read_csv('/home/mw/work/features.csv',index_col =0)

df_train, df_test, train_y, test_y = train_test_split(df, df.y, test_size=0.2, random_state=1, stratify=df.y)
df_train.y = train_y

df_test.y = test_y

df_train.reset_index()

df_train.head()

LGB

五折交叉验证,在测试集中分出一份验证集

kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=seed)
for fold_id, (trn_idx, val_idx) in enumerate(
        kfold.split(df_train[feature_names],df_train[ycol])):
    X_train = df_train.iloc[trn_idx][feature_names]
    Y_train = df_train.iloc[trn_idx][ycol]

    X_val = df_train.iloc[val_idx][feature_names]
    Y_val = df_train.iloc[val_idx][ycol]

找到f1最大时的阈值:

max_f1 = 0
Threshold = 0
for i in range(200,400):
    f1 = f1_score(df_oof['y'], df_oof['pred'] >i * 1e-3,average='macro')
    # f1 = f1_score(df_oof['y'].astype('int64'), (df_oof['pred'] >=i * 1e-3).astype('int64'),average='weighted')
    if max_f1 < f1:
        max_f1 = f1
        Threshold =  i

max_f1 ,Threshold * 1e-3
评价标准AUCAccuracyRecall(macro)F1Score (macro)Precision (macro)KS
训练集0.7690.7700.6500.6450.6410.419
测试集0.8070.8010.6780.6800.6820.496

P-R曲线:

image.png

ROC曲线的绘制:

image.png

LightGBM决策图:

image.png

混淆矩阵:

image.png

字段重要程度:

特征工程构造的x_196/x_188字段影响最大

CAT

评价标准AUCAccuracyRecall(macro)F1Score (macro)Precision (macro)KS
测试集0.7770.7890.6480.6520.6580.437
测试集0.8180.8160.6750.6870.7030.525

ROC曲线的绘制:

image.png

P-R曲线:

image.png

混淆矩阵绘制:

image.png

XGB

评价标准AUCAccuracyRecall(macro)F1Score (macro)Precision (macro)KS
训练集0.7780.7850.6760.6500.6540.436
测试集0.8320.8190.6860.6960.7080.529

虽然XGBoost的测试AUC可以到0.832,训练集却只有0.778。这可能和测试集和训练集的划分有关。

ROC曲线的绘制:

image.png

P-R曲线:

image.png

混淆矩阵绘制:

数据主要集中在对角线上

image.png

过采样与下采样

下采样(LGB)
df_train.y.value_counts()
mini = min(df_train.y.value_counts().tolist())
df_0 = df_train[df_train.y==0].head(mini)
df_1 = df_train[df_train.y==1].head(mini)
df_train = pd.concat([df_0,df_1],axis=0)
df_train.shape

下采样结果如下,下采样后性能反而有所下降,可能是样本减少的原因。

评价标准AUCAccuracyRecall(macro)F1Score (macro)Precision (macro)KS
训练集0.7550.6970.6970.6950.7000.396
测试集0.8000.7000.7370.6460.6530.490
过采样(LGB)
from imblearn.over_sampling import SMOTE
oversampler=SMOTE(random_state=0)
# user_id = df_train['user_id']
df_train, y_resampled = oversampler.fit_resample(df_train[features], df_train.y)
df_train['y'] = y_resampled
df_train['user_id'] = [i for i in range(sum(df_train.y.value_counts().tolist()))]
df_train.y.value_counts()
df_train.head()

LGB使用过采样的数据的表现,训练集的AUC可以达到0.92,但是测试集仅仅是0.809,明显是过拟合了。不具有可信度。

评价标准AUCAccuracyRecall(macro)F1Score (macro)Precision (macro)KS
训练集0.9200.8380.8380.8380.8390.680
测试集0.8090.8030.6710.6760.6830.486

综上所述,无论是下采样还是过采样,都不可取。

ensemble

评价标准AUCAccuracyRecall(macro)F1Score (macro)Precision (macro)KS
测试集0.8280.8060.7140.7040.6960.428

P-R曲线的绘制:

image.png

ROC曲线的绘制:

image.png

参数优化

  • 网格搜索

  • 贝叶斯调参

在使用之前需要先安装包bayesian-optimization,运行如下命令即可:

pip install bayesian-optimization

贝叶斯调参的主要思想是:给定优化的目标函数(广义的函数,只需指定输入和输出即可,无需知道内部结构以及数学性质),通过不断地添加样本点来更新目标函数的后验分布(高斯过程,直到后验分布基本贴合于真实分布)。简单的说,就是考虑了上一次参数的信息,从而更好的调整当前的参数。

贝叶斯调参的步骤如下: 定义优化函数(rf_cv) 建立模型 定义待优化的参数 得到优化结果,并返回要优化的分数指标

from sklearn.model_selection import cross_val_score

"""定义优化函数"""
def rf_cv_lgb(num_leaves, max_depth, bagging_fraction, feature_fraction, bagging_freq, min_data_in_leaf, 
              min_child_weight, min_split_gain, reg_lambda, reg_alpha):
    # 建立模型
    model_lgb = lgb.LGBMClassifier(boosting_type='gbdt', bjective='binary', metric='auc',
                                   learning_rate=0.1, n_estimators=5000,
                                   num_leaves=int(num_leaves), max_depth=int(max_depth), 
                                   bagging_fraction=round(bagging_fraction, 2), feature_fraction=round(feature_fraction, 2),
                                   bagging_freq=int(bagging_freq), min_data_in_leaf=int(min_data_in_leaf),
                                   min_child_weight=min_child_weight, min_split_gain=min_split_gain,
                                   reg_lambda=reg_lambda, reg_alpha=reg_alpha,
                                   n_jobs= 8
                                  )
    
    val = cross_val_score(model_lgb, X_train_split, y_train_split, cv=5, scoring='roc_auc').mean()
    
    return val
from bayes_opt import BayesianOptimization
"""定义优化参数"""
bayes_lgb = BayesianOptimization(
    rf_cv_lgb, 
    {
        'num_leaves':(10, 200),
        'max_depth':(3, 20),
        'bagging_fraction':(0.5, 1.0),
        'feature_fraction':(0.5, 1.0),
        'bagging_freq':(0, 100),
        'min_data_in_leaf':(10,100),
        'min_child_weight':(0, 10),
        'min_split_gain':(0.0, 1.0),
        'reg_alpha':(0.0, 10),
        'reg_lambda':(0.0, 10),
    }
)

"""开始优化"""
bayes_lgb.maximize(n_iter=10)

通过贝叶斯优化得到的最优参数如下:

最优参数
bagging_fraction0.82
bagging_freq12
feature_fraction0.67
max_depth19
min_child_weight7
min_data_in_leaf92
min_split_gain0.56
num_leaves178
reg_alpha9
reg_lambda1

实验结果对比

利用stacking方法将CatBoost,LightGBM,XGBoost三个方法五折交叉验证预测结果作为新的字段,利用逻辑回归再去预测,得到的效果如下。AUC,Accuracy, Recall ,F1 Score ,Precision, KS都达到了最佳。

评价标准(测试集)AUCAccuracyRecallF1 ScorePrecisionKS
CatBoost0.8180.8160.6750.6870.7030.525
LightGBM0.8070.8010.6780.6800.6820.496
XGBoost0.8320.8190.6860.6960.7080.529
ensemble0.8280.8060.7140.7040.6960.428

总结

通过该项目将数据挖掘课上所学的知识全部串联起来,从数据预处理,特征工程,模型选择,到模型调优,最后模型融合。最终AUC也能取得不错的分数达到0.83。可以给小额信贷业务的风控做一个参考。但是这分数有一定的限制,一定程度上是数据样本较小的原因,才10k数据。本文的优点数据挖掘的流程规范,给出了较好的特征构建的思路;另外本文不足是,由于时间仓促也仅仅只考虑了使用树模型,没有考虑深度学习等其他模型。

参考文献

马晓君, 宋嫣琦, 常百舒, 等. 基于 CatBoost 算法的 P2P 违约预测模型应用研究[J]. 统计与信息论坛, 2020, 7

邱伟栋. 基于 LightGBM 模型的 P2P 网贷违约预测研究[D]. 江西财经大学, 2020.

于玲, 吴铁军. 集成学习: Boosting 算法综述[D]. , 2004.

王奕森, 夏树涛. 集成学习之随机森林算法综述[J]. 信息通信技术, 2018, 1.

彭润泽. 基于 Stacking 集成学习算法的个人信用评估模型[J]. Statistics and Application, 2017, 6: 411.

Anna Veronika Dorogush, Andrey Gulin, Gleb Gusev, Nikita Kazeev, Liudmila Ostroumova Prokhorenkova, Aleksandr Vorobev "Fighting biases with dynamic boosting". arXiv:1706.09516, 2017

Anna Veronika Dorogush, Vasily Ershov, Andrey Gulin "CatBoost: gradient boosting with categorical features support". Workshop on ML Systems at NIPS 2017

扫码_搜索联合传播样式-标准色版.png