用户贷款逾期预测

2018-03-15  本文已影响0人  shenyuer

前言:去年参加了数据城堡的算法竞赛,一直没时间记录下来,趁今天来梳理下这个竞赛项目的方方面面。赛题为用户贷款风险预测,目标是利用用户基本信息、用户银行流水、用户信用卡账单以及用户浏览行为4个表的数据预测用户贷款后逾期的概率,其中带标签数据55596条,无标签数据13899条,个人最好成绩是排名前8%。

解决方案概述

此次大赛目标是从用户行为数据分析借款用户的信用状况,来判断其是否逾期。针对需要解决的问题和数据特征,主要从三个方面进行处理:数据预处理,特征工程,模型训练。

首先,由于数据中存在缺失值,因此需要对缺失值数据进行预处理。其次,采用基于学习模型的特征排序方法做了特征选择。然后,针对类别不平衡问题,主要是对少量样本过采样,针对过程中出现的过拟合问题,采用了pca降维以及对特征进行选择的方法。

本文框架如下:

  1. 好坏样本定义说明
  2. 样本概述
  3. 缺失值处理
  4. 构建新特征
  5. 特征选择
  6. 模型
  7. 最终结果

1.好坏样本定义

样本有55596条带标签数据,其中标签为0,1,1表示用户逾期。
正负样本分布如下:

print('训练集中各类别数据的个数:', trains.groupby('标签').size())
训练集中各类数据的个数: 标签
0.0    48413
1.0     7183

可以看出正负样本并不平衡,正样本大概是负样本的7倍,因此存在一个样本不平衡问题。

2.样本概述

提供的近7w条数据中,主要为四个表,分别是用户信息表,银行流水记录,用户浏览行为,信用卡账单。其中字段名如下:
用户信息表:

用户id 性别 职业 教育程度 婚姻状态 户口类型

银行流水记录表:

用户id 时间戳 交易类型 交易金额 工资收入标记

用户浏览行为表:

用户id 时间戳 浏览行为数据 浏览子行为编号

信用卡账单表:

用户id 时间 银行标识 上期账单金额 上期还款金额
调整金额 循环利息 可用余额 预借现金额度 还款状态
信用卡额度 本期账单余额 本期账单最低还款额 消费笔数 本期账单金额

共计27个字段。字段数据都经过举办方脱敏处理,业务信息缺失。

3.缺失值处理

赛题数据中大部分样本都有缺失值,常用的缺失值处理方法是缺失值填充(用同类别数据的特征均值,中值等)

feature=dataset[:]
dataset=dataset.fillna(-1)
d=feature['用户银行流水记录缺失统计']=(dataset==-1).sum(axis=1)

用均值填充缺失值

feature.fillna(feature.mean(),inplace=True)

4.构建新特征

赛题数据含有类别特征,很多算法(如逻辑回归,SVM)只能处理数值型特征,这种情况下需要对类别特征进行编码,这里采用了 One-Hot 编码,得到了 01 特征,解决了分类器不能处理类别特征的问题。

dataset=pd.get_dummies(dataset,
                       columns=dataset[['用户性别','用户职业','用户教育程度',
                                                '用户婚姻状态','用户户口类型']]).drop(['标签'],axis=1)

根据放款时间来划分时间窗口,构建每个表的放款前特征和放款后特征。

# ----------------------------------------银行流水特征------------------------------------------#
print('银行流水记录')
feature = pd.read_csv('../feature/训练放款时间表')
d = pd.read_csv('../feature/银行流水记录表')
d=pd.merge(d,feature,how='left', on = '用户标识')
# ----------------------------------------放款前特征统计------------------------------------------#
print('放款前特征统计')
t = d[(d['流水时间'] <= d['放款时间'])] 
gb1 = t[(t['交易类型'] == 0)].groupby(['用户标识'], as_index=False)  # 收入统计
gb2 = t[(t['交易类型'] == 1)].groupby(['用户标识'], as_index=False)  # 支出统计
gb3 = t[(t['工资收入标记'] == 1)].groupby(['用户标识'], as_index=False)  # 工资收入统计
x1 = gb1['交易金额'].agg({'放款前用户收入笔数': 'count', '放款前用户收入总计': 'sum'})
x2 = gb2['交易金额'].agg({'放款前用户支出笔数': 'count', '放款前用户支出总计': 'sum'})
x3 = gb3['交易金额'].agg({'放款前用户工资收入笔数': 'count', '放款前用户工资收入总计': 'sum'})

feature = pd.merge(feature, x1, how='left', on='用户标识')
feature = pd.merge(feature, x2, how='left', on='用户标识')
feature = pd.merge(feature, x3, how='left', on='用户标识')

feature['放款前用户收入支出笔数差值'] = feature['放款前用户收入笔数'] - feature['放款前用户支出笔数']
feature['放款前用户收入支出总计差值'] = feature['放款前用户收入总计'] - feature['放款前用户支出总计']
feature['放款前用户非工资收入笔数'] = feature['放款前用户收入笔数'] - feature['放款前用户工资收入笔数']
feature['放款前用户非工资收入总计'] = feature['放款前用户收入总计'] - feature['放款前用户工资收入总计']

构建新特征后特征维度达到164维。

5.特征选择

构建特征后,特征维度达到164维,多维特征一方面可能会导致维数灾难,另一方面很容易导致过拟合,因此需要做降维处理,常见的降维方法有 PCA。除了采用降维算法之外,也可以用特征选择来降低特征维度。特征选择的方法很多:卡方检验、皮尔森相关系数、正则化方法(L1, L2)、基于模型的特征选择方法。

# 特征选择,基于卡方检验
# trains=SelectKBest(chi2,k=20).fit_transform(trains,target)

# 基于惩罚项的特征选择法
# trains=SelectFromModel(LogisticRegression(penalty='l1',C=0.1)).fit_transform(trains,target)

# 基于树模型的特征选择

# trains=SelectFromModel(GradientBoostingClassifier()).fit_transform(trains,target)

# 降维,基于pca

pca=PCA(n_components=50)

trains=pca.fit_transform(trains)
test=pca.fit_transform(test)

6.模型

这里主要尝试了LR和XGB,在效果上XGB更好,可能是因为XGB在训练的同时会进行特征选择。

parameters= [{
                  'max_depth':[3,5,7], ##5)
                  'learning_rate':[0.1,0.5, 1.0],#0.1
                  'subsample':[0.75,0.8,0.85,0.9],#0.8
                  'min_child_weight':[1,3,5]#5

                  }]
#parameters= [{'n_estimators':[100,200,500,1000]
#                  }]
clf = GridSearchCV(xgb.XGBClassifier(n_estimators=100,gamma=0,scale_pos_weight=1),
                   param_grid=parameters,scoring='roc_auc',n_jobs=4,iid=False,cv=5)
print('开始训练')
clf.fit(x_train, y_train)

参数解释:
learning_rate:学习速率
min_child_weight :这个参数用来控制过拟合,如果数值太大可能会导致欠拟合。
max_depth:设置树的最大深度,控制过拟合,如果树的深度太大会导致过拟合
subsample:对原数据集进行随机采样来构建单个树。这个参数代表了在构建树时候对原数据集采样的百分比。eg:如果设为0.8表示随机抽取样本中80%的个体来构建树
scale_pos_weight:在样本类别十分不平衡时,参数设定为一个正值,可以使算法更快收敛
模型结果:

AUC:0.87

特征重要性输出:

image.png

可见最重要特征有用户性别、用户职业、用户婚姻状态、用户教育程度、用户户口类型、放款前浏览行为数据、放款前浏览行为数据最小值、放款前浏览子行为编号_8
可见除了基本信息外,用户的浏览行为是强有力的特征。

7.最终结果

不同方法及模型线下表现效果:

预处理 AUC(LR) AUC(XGB)
标准化处理 0.8726 0.8722
特征选择(卡方检验) 0.8742 0.8723
基于惩罚项的特征选择 0.8741 0.8723
基于树模型 0.8741 0.8711

构建新特征后:

预处理 AUC(LR) AUC(XGB)
构建放款前后新特征 0.8973
优化用户特征 0.9172

最终结果以逾期概率的形式上传到平台:

userid,probability
55597,0.3506719172000885
55598,0.3657565116882324
55599,0.3827580213546753
55600,0.36820918321609497
55601,0.34563612937927246
55602,0.36067867279052734
55603,0.36357182264328003
55604,0.3907186985015869
55605,0.34469443559646606
55606,0.3836720585823059
55607,0.3370608389377594
55608,0.38630616664886475
55609,0.3718336224555969
提交结果 image.png

第一名成绩为0.4746,与之相比我还有很大差距,但经过这次比赛我学到了很多,主要是关于解决问题的思路,感谢诸位大神的博客,这次主要参考了微额借款用户人品预测大赛冠军的解决方案。
以上就是这次比赛的大概内容了!

上一篇 下一篇

猜你喜欢

热点阅读