文章目录
- 1.招商银行2020FinTech精英训练营数据赛道比赛简介
- 一、赛题背景
- 二、课题研究要求
- 三、评价指标
- AUC的介绍
- 四、数据说明
- 2.数据处理部分
- 1.对用户标签数据的处理
- 确失数据
- 然后是对于那些\N和~的乱数据,
- 好了,现在来处理那些字母型的属性
- 2.对用户交易数据的处理——按周统计
- 1.按周统计收入和支出和对应次数
- 2按周统计各支付方式的次数、金额以及每种支付方式的占比
- 3.统计每周每个人收支一级分类为1、2、3的次数和金额
- 3.对用户APP行为的处理
- 4.数据融合
- 3.建模调参部分
- lightgbm模型
1.招商银行2020FinTech精英训练营数据赛道比赛简介
一、赛题背景
在当今大数据时代,信用评分不仅仅用在办理信用卡、贷款等金融场景,类似的评分产品已经触及到我们生活的方方面面,比如借充电宝免押金、打车先用后付等,甚至在招聘、婚恋场景都有一席之地。
招行作为金融科技的先行者,APP月活用户数上亿,APP服务不仅涵盖资金交易、理财、信贷等金融场景,也延伸到饭票、影票、出行、资讯等非金融场景,可以构建用户的信用评分,基于信用评分为用户提供更优质便捷的服务。
二、课题研究要求
本次大赛为参赛选手提供了两个数据集(训练数据集和评分数据集),包含用户标签数据、过去60天的交易行为数据、过去30天的APP行为数据。希望参赛选手基于训练数据集,通过有效的特征提取,构建信用违约预测模型,并将模型应用在评分数据集上,输出评分数据集中每个用户的违约概率。
三、评价指标
AUC:AUC的全名是Area Under Curve,
AUC的介绍
AUC的定义很复杂:分别随机从政府样本集中抽取一个正负样本,正样本的预测值大于负样本的概率。
简单来说就是就是ROC曲线下的面积,理论最小值为0.5。
我们先来看看混淆矩阵:
混淆矩阵中有着TN、FP、FN、TP的概念,其意义如下:
True negative(TN),称为真阴率,表明实际是负样本预测成负样本的样本数。
False positive(FP),称为假阳率,表明实际是负样本预测成正样本的样本数。
False negative(FN),称为假阴率,表明实际是正样本预测成负样本的样本数。
True positive(TP),称为真阳率,表明实际是正样本预测成正样本的样本数。
然后看看混淆矩阵:
由此引出True Positive Rate(真阳率)、False Positive(伪阳率)两个概念:
ROC就可以登场了:ROC曲线的横轴是FPRate,纵轴是TPRate,当二者相等时,即y=x,如下图。
所以说,AUC就说希望尽可能提高1样本的分类准确率,对于本题来说就是要尽可能找去信用不好的用户。
如果大家有兴趣多了解一下,推荐大家一个知天易or逆天难的博客:https://blog.csdn.net/u013019431/article/details/93138953
四、数据说明
1.训练数据集_tag.csv,评分数据集_tag.csv提供了训练数据集和评分数据集的用户标签数据;
2.训练数据集_trd.csv,评分数据集_trd.csv提供了训练数据集和评分数据集的用户60天交易行为数据;
3.训练数据集_beh.csv,评分数据集_ beh.csv提供了训练数据集和评分数据集的用户30天APP行为数据;
4.数据说明.xlsx为数据集字段说明和数据示例;
5.提交样例:
5.1采⽤UTF-8⽆BOM编码的txt⽂件提交,⼀共提交⼀份txt⽂件。
5.2输出评分数据集中每个用户违约的预测概率,输出字段为:用户标识和违约预测概率,用\t分割,每个用户的预测结果为一行,注意不能有遗漏的数据或多出的数据。
2.数据处理部分
1.对用户标签数据的处理
确失数据
首先查看我们的数据,发现有很三列缺失值挺多,建议不要。
然后是对于那些\N和~的乱数据,
这些数据我也把它们当成了确失数据,个人猜测可能是用户填写的时候不小心按了回车键吧。
那么这里怎么处理呢,我用到了随机森林填充的方法,这种方法适用于几个个特征大量数据缺失,其他特征却很完整的情况。
首先找到我们完整的列,即不含空值也不含那些乱七八糟的数据的列。
然后找到那些不完整的列,由于发现有三列是字母型的列,先删除他们,之后再处理
接下来定义我们的随机森林替换函数,并使用
from sklearn.ensemble import RandomForestRegressor
def add_wrong(df,col):
process_df = df.loc[:,(col,'age','l6mon_daim_aum_cd','bk1_cur_year_mon_avg_agn_amt_cd','pl_crd_lmt_cd','perm_crd_lmt_cd','cur_debit_cnt','cur_credit_cnt','cur_debit_min_opn_dt_cnt','cur_credit_min_opn_dt_cnt','cur_debit_crd_lvl')]
#仅选取部分列,
#f分成已知特征值和位置特征值两部分
know = process_df.loc[(process_df[col]!='\\N') & (process_df[col]!='~')].as_matrix()
unknow = process_df.loc[(process_df[col]=='\\N') | (process_df[col]=='~')].as_matrix()
Y = know[:,0]
X = know[:,1:]
rfr = RandomForestRegressor(random_state = 0, n_estimators=200, max_depth=3, n_jobs = -1)
rfr.fit(X,Y)
predicted = rfr.predict(unknow[:,1:])
df.loc[(df[col]=='\\N') | (df[col]=='~'),col] = predicted
return df
for col in a:
add_wrong(data_tag,col)
好了,现在来处理那些字母型的属性
如何把字母型的变成数字型的我的另一篇文章也说到了三种改变数据类型的方法,这里就看一下代码,提一下,这里会把A、B、0以外的数据变成空值。
class_mapping = {label: idx for idx, label in [[0,'A'],[1,'B'],[2,'O'],[3,'Z']]}
data_tag['mrg_situ_cd'] = data_tag['mrg_situ_cd'].map(class_mapping)
data_tag.mrg_situ_cd.value_counts()
最后,同样用随机森林来填补一下缺失值就好啦
from sklearn.ensemble import RandomForestRegressor
def add_missing(df,col):
process_df = df.loc[:,(col,'age','l6mon_daim_aum_cd','bk1_cur_year_mon_avg_agn_amt_cd','pl_crd_lmt_cd','perm_crd_lmt_cd','cur_debit_cnt','cur_credit_cnt','cur_debit_min_opn_dt_cnt','cur_credit_min_opn_dt_cnt','cur_debit_crd_lvl')]
#仅选取部分列,
#f分成已知特征值和位置特征值两部分
know = process_df[process_df[col].notnull()].as_matrix()
unknow = process_df[process_df[col].isnull()].as_matrix()
Y = know[:,0]
X = know[:,1:]
rfr = RandomForestRegressor(random_state = 0, n_estimators=200, max_depth=3, n_jobs = -1)
rfr.fit(X,Y)
predicted = rfr.predict(unknow[:,1:])
df.loc[df[col].isnull(), col] = predicted
return df
2.对用户交易数据的处理——按周统计
考虑到银行的很多业务都是按周开展的,所以我按周来统计了一些信息,怎么按周统计或是按月统计,我的这篇文章也总结了,
首先就是把时间格式化并变成索引:
data_trd['trx_tm'] = pd.to_datetime(data_trd['trx_tm']) #将数据类型转换为日期类型
data_trd = data_trd.set_index('trx_tm') # 将date设置为index
1.按周统计收入和支出和对应次数
data_trd_group = data_trd.groupby(['id','Dat_Flg1_Cd']).resample('w').sum()
data_trd_group_weekly_amt_iao=data_trd_group.pivot_table (index ='id' , columns= ['trx_tm','Dat_Flg1_Cd'],values='cny_trx_amt' ,aggfunc='sum') .fillna(0)
结果是这个样子的:
data_trd_group_times = data_trd.groupby(['id','Dat_Flg1_Cd']).resample('w').count()
data_trd_group_times.drop(['id','Dat_Flg1_Cd'], axis=1, inplace=True)
data_trd_group_weekly_times_iao=data_trd_group_times.pivot_table (index ='id' , columns= ['trx_tm','Dat_Flg1_Cd'],values='cny_trx_amt' ,aggfunc='sum') .fillna(0)
2按周统计各支付方式的次数、金额以及每种支付方式的占比
类似于1
3.统计每周每个人收支一级分类为1、2、3的次数和金额
类似于1
3.对用户APP行为的处理
这部分数据没用,能力有限,不好意思。
4.数据融合
就是将tag表和交易表合在一起,我用的是并集合并,缺失值填充为-10.
3.建模调参部分
lightgbm模型
LightGBM是个快速的,分布式的,高性能的基于决策树算法的梯度提升框架。可用于排序,分类,回归以及很多其他的机器学习任务中。2017年1月,微软发布首个稳定版LightGBM,对于一个新的算法,大家都习惯和以前的算法进行对比,反正只需知道一件事:LightGBM牛逼就行了。
在不同数据集上的对比
计算速度的对比,完成相同的训练量XGBoost通常耗费的时间是LightGBM的数倍之上,在higgs数据集上,它们的差距更是达到了15倍以上。
LightGBM的具体情况,可以看我转载的一篇大佬博客:
https://blog.csdn.net/lamusique/article/details/95631638
本题中的调参:看了调参教程,发现用了之后对我的帮助真的好小,除了耽误我的时间当然,可能别的情况下调参会很有用。
给大家提供一个初始值,然后自己尝试一下改改bagging_fraction、feature_fraction、learning_rate、max_depth、num_leaves这些值就差不多了,
params = {
'boosting_type': 'gbdt','objective':'binary','num_leaves':15,'n_estimators':20000, 'early_stopping_rounds':5000,
'learning_rate':0.01, 'max_depth':6,
'metric':'auc',
'bagging_fraction':0.8, 'feature_fraction': 0.7, # 样本采样\特征采用率
'reg_alpha':0.5, 'reg_lambda': 0.3
}
值得一提的是,如何拆分测试集和验证集呢,这里用到了sklearn里的train_test_split方法:
# 训练集、验证集、测试集的划分
import lightgbm as lgb
from sklearn.cross_validation import train_test_split
X_train, X_valid, y_train, y_valid = train_test_split(data[:-4000].drop(['flag'], axis=1), data[:-4000]['flag'],test_size=4000,random_state=2)
y_train = y_train.ravel()
train_data = lgb.Dataset(X_train, y_train) # 将数据保存到LightGBM二进制文件将使加载更快
valid_data = lgb.Dataset(X_valid, y_valid)
X_test = data[-4000:].drop(['flag'], axis=1)
好啦,以上就是本人第一次参加数据分析类比赛的小小心得,希望对你有点帮助。如果觉得我写的好的话,求收藏求点赞求关注。