项目背景
拍拍贷“魔镜风控系统”基于400多个数据维度来对当前用户的信用状态进行评估,通过历史数据每个借款人的性别、年龄、籍贯、学历信息、通讯方式、网站登录信息、第三方时间信息等用户信息以及对应的分类标签,在此基础上结合新发标的用户信息,得到用户六个月内逾期率的预测,为金融平台提供关键的决策支持。
数据格式
数据下载–点这里
这里面包含三期数据,每期数据内容和格式相同,这里面包括两部分信息:
一部分是Master
PPD_dat_1.csv
PPD_dat_2.csv
PPD_dat_3.csv
一部分是Log info
PPD_daht_1_LogInfo.csv PPD_daht_2_LogInfo.csv PPD_daht_3_LogInfo.csv
一部分是Update info
PPD_daht_1_Userupdate.csv
PPD_daht_2_Userupdate.csv
PPD_daht_3_Userupdate.csv
数据清洗
数据摘要
特征工程
模型选择
交叉检验
变量评估和处理
参数优化
在特征工程和模型选择之后,有一项重要且考验耐心的工作,那就是调参。通常情况下,要做以下步骤:
1. 调参之前,理解模型和参数的含义。(否则你很可能不知道调参的粒度和调参的方向)
2. 先用单数据集,从默认值开始,手工逐个调整,对于参数范围大的采取等比数列的方式增加/减少粒度,对于参数范围小的采取等差数列的方式增加/减少粒度。这样做的结果是对各个参数确定了一个合理的范围。
3. 然后可以采用交叉验证和组合搜索的方法来自动得到最优参数,这个过程可能较长,所以这里交叉验证的折数不要太大。另外折数小除了节约时间以外,同时也因为数据集的不同,避免在最后的结果上造成过拟合
模型融合
4 算法实现过程及其代码细节
4.1 数据清理
引入的包
"""
Created on Sat Jun 18 10:06:28 2016
@author: Yes,boy!
"""
import pandas as pd
import numpy as np
path = "D:/InAction/PPDS/data"
title = "PPD"
第一部分是处理主表:
我们首先构造一个函数Read_concat_csv,来实现几份数据的合并,通过pandas.concat 来实现。
#输入:文件名列表,read_csv方法中的参数字典
#输出:合并后的数据集
def Read_concat_csv(file,par_csv={}):
da = pd.concat(map(lambda x:pd.read_csv(x,**par_csv),file))
return da
这里面有三处语法细节:
1. pd.read_csv()
2. map()
3. concat
接着构造一个对数据不统一情况的处理,比如北京和北京市,河南和河南省,以及多余的空格
#输入:一个字符串
#输出:处理掉空格、市、省的字符串
def Del_string(xstr):
xstrc = xstr.strip().strip(u"市").strip(u"省")
if xstrc=="":
xstrc = np.nan
return xstrc
这里面有一个语法细节:strip()
接下来是对主表开始处理:
par_csv = dict(index_col = 0, encoding = "GB18030", parse_dates = ["ListingInfo"], na_values = [-1],
converters = dict(zip(*[["UserInfo_{}".format(i) for i in [9, 2, 4, 8, 20, 7, 19]], [Del_string]*7])))#六列地名,一列通讯
file_dat = ["{}/{}_dat_{}.csv".format(path, title, 1+x) for x in range(3)]
file_dav = ["{}/{}_dav.csv".format(path, title)]
dat = Read_concat_csv(file_dat, par_csv)
dav = Read_concat_csv(file_dav, par_csv)
#np.save("{}/{}_irt.npy".format(path, title), list(dat.index))
#np.save("{}/{}_irv.npy".format(path, title), list(dav.index))
da = pd.concat([dat, dav])
第二部分是处理Log 和 Update 表
def Read_History(file, icid, ictime, par_csv = {}):
'''Organize Time-Dependent Historical Records
Parameters
----------
file: a list of file name
icid: column name of id
ictime: a list of 2 column names: [basetime, recordtime]
par_csv: other parameters for pd.read_csv
set_index(list) 把list 中的列都变成index
sort_index() 对 index 进行升序排列
'''
par = {"parse_dates": ictime}
par.update(par_csv)
dah = Read_concat_csv(file, par)
dahb = (dah.assign(Id = dah[icid], Time = (dah[ictime[1]] - dah[ictime[0]]).astype('timedelta64[D]')).set_index(["Id", "Time"])
.drop([icid]+ictime, axis = 1).sort_index())
return(dahb)
接下来对两个表调用函数进行处理
““
dah1 = Read_History(file = [“{}/{}_dah{}_LogInfo.csv”.format(path, title, x) for x in [“t_1”, “t_2”, “t_3”, “v”]],
icid = ‘Idx’, ictime = [‘Listinginfo1’, ‘LogInfo3’])
dah2 = Read_History(file = [“{}/{}_dah{}_Userupdate.csv”.format(path, title, x) for x in [“t_1”, “t_2”, “t_3”, “v”]],
icid = ‘Idx’, ictime = [‘ListingInfo1’, ‘UserupdateInfo2’],
par_csv = {“converters”: {“UserupdateInfo1”: lambda x: x.lower()}})
“`