介绍
拍拍贷是一家互联网金融公司,在2016年拍拍贷举办“魔镜杯”风险算法大赛,首度公开真实的历史数据,旨在寻求高效准确的预测算法, 为公司投资人提供决策依据,促进健康高效的互联网金融。
数据
为保护用户隐私安全,项目所用数据均已经经过脱敏处理。
数据主要分为3个表:Master、Log_Info、Userupdate_Info
每一行代表一个样本(一笔成功成交借款),每个样本包含200多个各类字段。
1.Master
主要字段 | 描述 |
---|---|
idx | 每一笔贷款的unique key,可以与另外2个文件里的idx相匹配 |
UserInfo | 借款人特征字段 |
WeblogInfo | Info网络行为字段 |
Education | 学历学籍字段 |
ThirdParty_Info_PeriodN | 第三方数据时间段N字段 |
SocialNetwork | 社交网络字段 |
LinstingInfo | 借款成交时间 |
Target | 违约标签(1/0,违约/正常)测试集不包含target字段 |
1 | train_master.info() |
2.Log_Info
借款人的登陆信息。
主要字段 | 描述 |
---|---|
ListingInfo | 借款成交时间 |
LogInfo1 | 操作代码 |
LogInfo2 | 操作类别 |
LogInfo3 | 登陆时间 |
idx | 每一笔贷款的unique key |
1 | train_loginfo.info() |
3.Userupdate_Info
借款人修改信息。
主要字段 | 描述 |
---|---|
ListingInfo1 | 借款成交时间 |
UserupdateInfo1 | 修改内容 |
UserupdateInfo2 | 修改时间 |
idx | 每一笔贷款的unique key |
1 | train_userinfo.info() |
比赛规则
参赛团队需要基于训练集数据构建预测模型,使用模型计算测试集的评分(评分数值越高,表示越有可能出现贷款违约)。
模型评价标准:
定义:本次比赛采用AUC来评判模型的效果。AUC即以False Positive Rate为横轴,True Positive Rate为纵轴的ROC (Receiver Operating Characteristic)curve下方的面积的大小。
$$AUC=\frac{\sum_{i} S_{i}}{M \times N}$$
其中,M为正样本个数,N为负样本个数,M*N为正负样本对的个数。$S_{i}$为第i个正负样本对的得分,定义如下:
$$S_{i}=\begin{cases}
1 & score_{i-p} > score_{i-n} \\
0.5 & score_{i-p} = score_{i-n} \\
0 & score_{i-p} < score_{i-n}
\end{cases}$$
其中,
$score_{i-p}$为正负样本对中,模型给正样本的评分,
$score_{i-n}$为正负样本对中,模型给负样本的评分,
AUC值在[0,1]区间,越高越好。
数据清洗
缺失值处理
删除缺失数据
Master表信息缺失情况相对比较为严重。
统计各字段的缺失情况:
1 | null_sum = train_master.isnull().sum() |
num | ratio | |
---|---|---|
WeblogInfo_3 | 29030 | 0.967667 |
WeblogInfo_1 | 29030 | 0.967667 |
UserInfo_11 | 18909 | 0.630300 |
UserInfo_13 | 18909 | 0.630300 |
UserInfo_12 | 18909 | 0.630300 |
WeblogInfo_20 | 8050 | 0.268333 |
WeblogInfo_21 | 3074 | 0.102467 |
WeblogInfo_19 | 2963 | 0.098767 |
WeblogInfo_2 | 1658 | 0.055267 |
WeblogInfo_4 | 1651 | 0.055033 |
删除缺失严重的行:
1 | train_master.drop(['WeblogInfo_3', 'WeblogInfo_1', 'UserInfo_11', 'UserInfo_13', 'UserInfo_12', 'WeblogInfo_20'],axis=1,inplace=True) |
删除缺失严重的行:
1 | record_nan=train_master.isnull().sum(axis=1).sort_values(ascending=False) |
1 | Before train_master shape (30000, 222) |
缺失填充
填充缺失值要根据字段的属性进行合理填充,在没有字段信息的情况下,根据数据分布情况填充。
在缺失数据较少的情况下,用频率最高的值填充;在缺失数据较多的情况下,用均值填充。
1 | print('Before all nan num{}'.format(train_master.isnull().sum() |
1 | Before all nan num: 9808 |
异常值处理
本文在处理离群点时,先通过特征分类
将数值型特征单独列出来。
通过画图的方式,发现离群点。
1 | import seaborn as sbn |
1 | 29189 lines before drop |
删除数值型离群点,剩下28074个样本。
特征分类
- 二值特征
主要是0/1特征,即特征只取两种值:0或者1 - 连续值特征
取值为有理数的特征,特征取值个数不定,例如距离特征,特征取值为是0~正无穷。 - 枚举值特征
主要是特征有固定个数个可能值,例如今天周几,只有7个可能值:周1,周2,…,周日。
这块内容主要是特征转换,本文涉及以下几种转换情况:
- 非二值特征转换为二值特征
检查所有特征值的分布,若出现频率最高的值占该特征所有取值情况高达50%,那么就可以将该特征转换为二值特征。 - 连续值特征转换为枚举特征
当连续值特征的取值范围过小时,可将每个值单独作为一类,即将连续值特征转换为枚举特征。
1 | """-----------------------筛选二值特征--开始------------------""" |
数据转换
特征转换
1 | #将挑选出的特征转换为二值特征 |
对数转换
为提高模型拟合程度,通常要求样本分布呈现(近似)正态分布。
去除离群点
后的数值特征分布情况:
明显数据分布偏左,可以采取对数转换的方法将数据分布变得更均匀:
解析时间
解析时间,并将解析后的时间字段加入主表master信息中:
1 | import arrow |
解析时间数据后,整个master表多了7列:
1 | before train_master_ shape (28074, 223) |
转换登陆信息
登陆信息:
Idx | Listinginfo1 | LogInfo1 | LogInfo2 | LogInfo3 | |
---|---|---|---|---|---|
0 | 10001 | 2014-03-05 | 107 | 6 | 2014-02-20 |
1 | 10001 | 2014-03-05 | 107 | 6 | 2014-02-23 |
2 | 10001 | 2014-03-05 | 107 | 6 | 2014-02-24 |
3 | 10001 | 2014-03-05 | 107 | 6 | 2014-02-25 |
4 | 10001 | 2014-03-05 | 107 | 6 | 2014-02-27 |
统计每笔交易登陆次数、交易成功时间戳(包含借款、还款等)、登陆次数、登陆间隔时长、最新登陆时间戳、相同操作次数,得到转换后的登陆信息:
loginfo_num | loginfo_LogInfo1_unique_num | XXX | loginfo_LogInfo12_unique_num | |
---|---|---|---|---|
0 | 3 | 26 | XXX | 8 |
1 | 5 | 11 | XXX | 4 |
2 | 8 | 125 | XXX | 13 |
3 | 12 | 199 | XXX | 11 |
4 | 16 | 15 | XXX | 7 |
转换修改信息
修改信息:
Idx | ListingInfo1 | UserupdateInfo1 | UserupdateInfo2 | |
---|---|---|---|---|
0 | 10001 | 2014/03/05 | _EducationId | 2014/02/20 |
1 | 10001 | 2014/03/05 | _HasBuyCar | 2014/02/20 |
2 | 10001 | 2014/03/05 | _LastUpdateDate | 2014/02/20 |
3 | 10001 | 2014/03/05 | _MarriageStatusId | 2014/02/20 |
4 | 10001 | 2014/03/05 | _MobilePhone | 2014/02/20 |
统计每笔交易修改信息次数、修改字段数、修改时间次数、间隔天数、最新修改时间戳、按照UserupdateInfo1
信息分别统计,得到转换后的修改信息:
Idx | userinfo_num | XXX | userinfo_Position_num | |
---|---|---|---|---|
0 | 3 | 13 | XXX | 0 |
1 | 5 | 13 | XXX | 0 |
2 | 8 | 14 | XXX | 0 |
3 | 12 | 14 | XXX | 0 |
4 | 16 | 13 | XXX | 0 |
枚举特征编码
pandas的get_dummies()函数:
参数:
columns:要编码的DataFrame中的列名称。如果列为None,则将转换具有对象或类别dtype的所有列。
1 | drop_columns= ['Idx', 'ListingInfo', 'UserInfo_20', 'UserInfo_19','UserInfo_8','UserInfo_7','UserInfo_4','UserInfo_2','ListingInfo_timestamp', 'loginfo_last_day_timestamp', |
建模工作前的数据处理工作基本就是以上内容,还包括合并三个表、删除不相关字段、添加at_home
字段,增加家乡字段信息,可能与是否违约相关。
算法建模
标准化
创建训练集及验证集,并对训练集做标准化处理:
1 | from sklearn.preprocessing import StandardScaler |
得到训练集及验证集的大小:
1 | (28074, 443) (28074,) |
交叉验证
选择StratifiedKFold
S折交叉验证法,确保训练集中每一类的比例是相同的。
1 | from sklearn.model_selection import StratifiedKFold |
分类算法评估
AUC、精确度、召回率:
1 | from sklearn.model_selection import cross_val_score |
算法
评估以下分类算法:
- 线性分类器
LogisticRegression - 广义线性分类器
RidgeClassifier - 集成方法分类器
RandomForestClassifier、AdaBoostClassifier、XGBClassifier - 支持向量机分类器
SVC、LinearSVC
通过评估方法选择分类效果较好的LogisticRegression、XGBClassifier、AdaBoostClassifier三种模型,最终通过投票的方式聚合三种模型。
1 | from sklearn.ensemble import VotingClassifier |
最终达到的效果:
1 | voting: auc:0.800663, recall:0.001285, accuracy:0.944433 |