手机网站列表 教程,注册网站诚信承诺书,商丘网站制作公司一二三网络推广,西部数码网站管理助手4.0 破解版文章目录 1.数据准备1.1 风控建模特征数据1.2 人行征信数据1.3 据之间的内在逻辑 2 样本设计和特征框架2.1 定义观察期样本2.2 数据EDA(Explore Data Analysis)2.3 梳理特征框架 3 特征构造3.1 静态信息和时间截面特征3.2 未来信息问题3.2.1 未来信息案例3.2.2 时间序列特征的未… 文章目录 1.数据准备1.1 风控建模特征数据1.2 人行征信数据1.3 据之间的内在逻辑 2 样本设计和特征框架2.1 定义观察期样本2.2 数据EDA(Explore Data Analysis)2.3 梳理特征框架 3 特征构造3.1 静态信息和时间截面特征3.2 未来信息问题3.2.1 未来信息案例3.2.2 时间序列特征的未来信息3.2.3 历史信贷特征出现未来信息 3.3 特征构造3.3.1 时序数据特征衍生3.3.2 用户关联特征 1.数据准备
1.1 风控建模特征数据
用户信息 数据来源
1.2 人行征信数据 1.3 据之间的内在逻辑
关系种类 一对一一个用户注册对应有一个注册手机号一对多一个用户有多笔借款多对多一个用户可以登录多个设备一个设备可以有多个用户登录
**举例**下图中蓝色框为二月当期账单红色框为订单
梳理类ER图 任务分析厚数据数据量大常登录首单用户的逾期情况 可以将表结构展示到特征文档中说明取数逻辑
2 样本设计和特征框架
2.1 定义观察期样本
确定观察期定义x时间切面和表现期定Y的标签确认样本数据是否合理
2.2 数据EDA(Explore Data Analysis)
查看数据总体分布 data.shape data.isnull() data.info() data.describe() 查看好坏样本分布差异 data[data[label] 0].describe() # 好用户 data[data[label] 1].describe() # 坏用户 查看单个数据 data.sample(n10,random_state1) 2.3 梳理特征框架 RFM生成新特征 举例行为评分卡中的用户账单还款特征 用户账单关键信息时间、金额、还款、额度
小结在构造特征之前要完成
类ER图样本设计表特征框架图
3 特征构造
3.1 静态信息和时间截面特征 用户静态信息用户的基本信息半年以上不会发生变化 姓名性别年龄 用户时间截面取时间轴上的一个点作为时间截面 截面时间点的购物GVM、银行存款额、逾期最大天数 用户时间序列特征从观察点往前回溯一段时间的数据 过去 一个月的GPS数据过去六个月的银行流水过去一年的逾期记录 用户时间截面特征相关概念 未来信息当前时间截面之后的数据时间截面数据在取数据的时候要避免使用未来信息产生未来信息的直接原因缺少快照表金融相关数据原则上都需要快照表记录所有痕迹额度变化情况多次申请的通过和拒绝情况 缺少快照表的原因 * 快照表消耗资源比较大为了性能不做 * 原有数据表设计人员疏忽没做 * 借用其他业务数据如电商做信贷 快照表每天定时存储一个状态类似于每天2300都拍一张照片每天会把当天的状态进行备份只存储当天的最终状态。日志表每一次操作都会记录不会进行update只有insert操作操作一次插入一条记录。
3.2 未来信息问题
3.2.1 未来信息案例
首次借贷 --》二次借贷–》爬虫授权–》三次借贷 举例 解决方式加入快照表存储
3.2.2 时间序列特征的未来信息
时间序列特征从观察点向前回溯一段时间的数据 以借贷2发生的时间为观测点下表中的未来信息会将大量退货行为的用户认为是坏客户但是上下之后效果会变差。 特征构建时的补救方法 对未来信息窗口外的订单计算有效的特征NMV对未来信息窗口内的订单计算一般特征GMV)
3.2.3 历史信贷特征出现未来信息
举例信用卡每月1日为账单日每月10日为还款日次月10日左右为M1逾期一个月 在上图所示的截面时间如3月5日是看不到2月账单的逾期DPD30的情况的但如果数据库没有快照表会导致我们可以拿到2月账单的DPD30情况解决方案跟上面例子一样分区间讨论可以把账单分成3类 当前未出账账单 最后一个已出账账单 其他已出账账单 只有这个特征可以构建逾期类特征
小结处理未来信息问题
及时增加快照表没有快照表的情况下将数据区分为是否有未来信息的区间分别进行特征构造
3.3 特征构造
3.3.1 时序数据特征衍生
特征聚合将单个特征的多个时间节点取值进行聚合。特征聚合是传统评分卡建模的主要特征构造方法 举例计算每个用户的额度使用率记为特征ft按照时间轴以月份为切片展开 申请前30天内的额度使用率ft1申请前30天至60天内的额度使用率ft2申请前60天至90天内的额度使用率ft3申请前330天至360天内的额度使用率ft12得到一个用户的12个特征
import pandas as pd
import numpy as np
data pd.read_excel(../data/textdata.xlsx)
data.head()可以根据这个时间序列进行基于经验的人工特征衍生例如计算最近P个月特征大于0的月份数
#最近p个月ft0的月份数
def Num(ft,p): #ft 特征名字 p特征大于0的月份数dfdata.loc[:,ft1:ftstr(p)] # 选择ft1 - ftp的数据auto_valuenp.where(df0,1,0).sum(axis1) return ft_numstr(p),auto_value计算最近P个月特征ft等于0的月份数
#最近p个月ft0的月份数
def Num(ft,p): #ft 特征名字 p特征大于0的月份数dfdata.loc[:,ft1:ftstr(p)]auto_valuenp.where(df0,1,0).sum(axis1)return ft_numstr(p),auto_value计算最近P个月特征ft等于0的月份数
#最近p个月ft0的月份数
def zero_cnt(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_valuenp.where(df0,1,0).sum(axis1)return ft_zero_cntstr(p),auto_value计算近p个月特征ft大于0的月份数是否大于等于1
#最近p个月ft0的月份数是否1
def Evr(ft,p):dfdata.loc[:,ft1:ftstr(p)]arrnp.where(df0,1,0).sum(axis1)auto_value np.where(arr,1,0)return ft_evrstr(p),auto_value计算最近p个月特征ft的均值
#最近p个月ft均值
def Avg(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_valuenp.nanmean(df,axis 1 )return ft_avgstr(p),auto_value 计算最近p个月特征ft的和最大值最小
#最近p个月ft和
def Tot(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_valuenp.nansum(df,axis 1)return ft_totstr(p),auto_value#最近(2,p1)个月ft和
def Tot2T(ft,p):dfdata.loc[:,ft2:ftstr(p1)]auto_valuedf.sum(1)return ft_tot2tstr(p),auto_value #最近p个月ft最大值
def Max(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_valuenp.nanmax(df,axis 1)return ft_maxstr(p),auto_value #最近p个月ft最小值
def Min(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_valuenp.nanmin(df,axis 1)return ft_minstr(p),auto_value 其他衍生方法
#最近p个月最近一次ft0到现在的月份数def Msg(ft,p):dfdata.loc[:,ft1:ftstr(p)]df_valuenp.where(df0,1,0)auto_value[]for i in range(len(df_value)):row_valuedf_value[i,:]if row_value.max()0:indexs0auto_value.append(indexs)else:indexs1for j in row_value:if j0:breakindexs1auto_value.append(indexs)return ft_msgstr(p),auto_value#最近p个月最近一次ft0到现在的月份数
def Msz(ft,p):dfdata.loc[:,ft1:ftstr(p)]df_valuenp.where(df0,1,0)auto_value[]for i in range(len(df_value)):row_valuedf_value[i,:]if row_value.max()0:indexs0auto_value.append(indexs)else:indexs1for j in row_value:if j0:breakindexs1auto_value.append(indexs)return ft_mszstr(p),auto_value #当月ft/(最近p个月ft的均值)
def Cav(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value df[ft1]/np.nanmean(df,axis 1 ) return ft_cavstr(p),auto_value #当月ft/(最近p个月ft的最小值)
def Cmn(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value df[ft1]/np.nanmin(df,axis 1 ) return ft_cmnstr(p),auto_value #最近p个月每两个月间的ft的增长量的最大值
def Mai(ft,p):arrnp.array(data.loc[:,ft1:ftstr(p)]) auto_value []for i in range(len(arr)):df_value arr[i,:]value_lst []for k in range(len(df_value)-1):minus df_value[k] - df_value[k1]value_lst.append(minus)auto_value.append(np.nanmax(value_lst)) return ft_maistr(p),auto_value #最近p个月每两个月间的ft的减少量的最大值
def Mad(ft,p):arrnp.array(data.loc[:,ft1:ftstr(p)]) auto_value []for i in range(len(arr)):df_value arr[i,:]value_lst []for k in range(len(df_value)-1):minus df_value[k1] - df_value[k]value_lst.append(minus)auto_value.append(np.nanmax(value_lst)) return ft_madstr(p),auto_value #最近p个月ft的标准差
def Std(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_valuenp.nanvar(df,axis 1)return ft_stdstr(p),auto_value #最近p个月ft的变异系数
def Cva(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_valuenp.nanvar(df,axis 1)/(np.nanmean(df,axis 1 )1e-10)return ft_cvastr(p),auto_value #(当月ft) - (最近p个月ft的均值)
def Cmm(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value df[ft1] - np.nanmean(df,axis 1 ) return ft_cmmstr(p),auto_value #(当月ft) - (最近p个月ft的最小值)
def Cnm(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value df[ft1] - np.nanmin(df,axis 1 ) return ft_cnmstr(p),auto_value #(当月ft) - (最近p个月ft的最大值)
def Cxm(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value df[ft1] - np.nanmax(df,axis 1 ) return ft_cxmstr(p),auto_value # (当月ft) - (最近p个月ft的最大值) / (最近p个月ft的最大值)
def Cxp(ft,p):dfdata.loc[:,ft1:ftstr(p)]temp np.nanmax(df,axis 1 )auto_value (df[ft1] - temp )/ tempreturn ft_cxpstr(p),auto_value #最近p个月ft的极差
def Ran(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value np.nanmax(df,axis 1 ) - np.nanmin(df,axis 1 ) return ft_ranstr(p),auto_value #最近p个月中特征ft的值后一个月相比于前一个月增长了的月份数
def Nci(ft,p):arrnp.array(data.loc[:,ft1:ftstr(p)]) auto_value []for i in range(len(arr)):df_value arr[i,:]value_lst []for k in range(len(df_value)-1):minus df_value[k] - df_value[k1]value_lst.append(minus) value_ng np.where(np.array(value_lst)0,1,0).sum()auto_value.append(np.nanmax(value_ng)) return ft_ncistr(p),auto_value #最近p个月中特征ft的值后一个月相比于前一个月减少了的月份数
def Ncd(ft,p):arrnp.array(data.loc[:,ft1:ftstr(p)]) auto_value []for i in range(len(arr)):df_value arr[i,:]value_lst []for k in range(len(df_value)-1):minus df_value[k] - df_value[k1]value_lst.append(minus) value_ng np.where(np.array(value_lst)0,1,0).sum()auto_value.append(np.nanmax(value_ng)) return ft_ncdstr(p),auto_value #最近p个月中相邻月份ft 相等的月份数
def Ncn(ft,p):arrnp.array(data.loc[:,ft1:ftstr(p)]) auto_value []for i in range(len(arr)):df_value arr[i,:]value_lst []for k in range(len(df_value)-1):minus df_value[k] - df_value[k1]value_lst.append(minus) value_ng np.where(np.array(value_lst)0,1,0).sum()auto_value.append(np.nanmax(value_ng)) return ft_ncnstr(p),auto_value #最近P个月中特征ft的值是否按月份严格递增是返回1否返回0
def Bup(ft,p):arrnp.array(data.loc[:,ft1:ftstr(p)]) auto_value []for i in range(len(arr)):df_value arr[i,:]value_lst []index 0for k in range(len(df_value)-1):if df_value[k] df_value[k1]:breakindex 1if index p: value 1 else:value 0auto_value.append(value) return ft_bupstr(p),auto_value #最近P个月中特征ft的值是否按月份严格递减是返回1否返回0
def Pdn(ft,p):arrnp.array(data.loc[:,ft1:ftstr(p)]) auto_value []for i in range(len(arr)):df_value arr[i,:]value_lst []index 0for k in range(len(df_value)-1):if df_value[k1] df_value[k]:breakindex 1if index p: value 1 else:value 0auto_value.append(value) return ft_pdnstr(p),auto_value #最近P个月中ft的切尾均值这里去掉了数据中的最大值和最小值
def Trm(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value []for i in range(len(df)):trm_mean list(df.loc[i,:])trm_mean.remove(np.nanmax(trm_mean))trm_mean.remove(np.nanmin(trm_mean))tempnp.nanmean(trm_mean) auto_value.append(temp)return ft_trmstr(p),auto_value #当月ft / 最近p个月的ft中的最大值
def Cmx(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value (df[ft1] - np.nanmax(df,axis 1 )) /np.nanmax(df,axis 1 ) return ft_cmxstr(p),auto_value #( 当月ft - 最近p个月的ft均值 ) / ft均值
def Cmp(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value (df[ft1] - np.nanmean(df,axis 1 )) /np.nanmean(df,axis 1 ) return ft_cmpstr(p),auto_value #( 当月ft - 最近p个月的ft最小值 ) /ft最小值
def Cnp(ft,p):dfdata.loc[:,ft1:ftstr(p)]auto_value (df[ft1] - np.nanmin(df,axis 1 )) /np.nanmin(df,axis 1 ) return ft_cnpstr(p),auto_value #最近p个月取最大值的月份距现在的月份数
def Msx(ft,p):dfdata.loc[:,ft1:ftstr(p)]xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdf[_max] np.nanmax(df,axis 1)for i in range(1,p1):df[ftstr(i)] list(df[ftstr(i)] df[_max])del df[_max]df_value np.where(dfTrue,1,0)auto_value[]for i in range(len(df_value)):row_valuedf_value[i,:]indexs1for j in row_value:if j 1:breakindexs1auto_value.append(indexs)return ft_msxstr(p),auto_value#最近p个月的均值/((p,2p)个月的ft均值)
def Rpp(ft,p):df1data.loc[:,ft1:ftstr(p)]value1np.nanmean(df1,axis 1 )df2data.loc[:,ftstr(p):ftstr(2*p)]value2np.nanmean(df2,axis 1 ) auto_value value1/value2return ft_rppstr(p),auto_value #最近p个月的均值 - ((p,2p)个月的ft均值)
def Dpp(ft,p):df1data.loc[:,ft1:ftstr(p)]value1np.nanmean(df1,axis 1 )df2data.loc[:,ftstr(p):ftstr(2*p)]value2np.nanmean(df2,axis 1 ) auto_value value1 - value2return ft_dppstr(p),auto_value #(最近p个月的ft最大值)/ (最近(p,2p)个月的ft最大值)
def Mpp(ft,p):df1data.loc[:,ft1:ftstr(p)]value1np.nanmax(df1,axis 1 )df2data.loc[:,ftstr(p):ftstr(2*p)]value2np.nanmax(df2,axis 1 ) auto_value value1/value2return ft_mppstr(p),auto_value #(最近p个月的ft最小值)/ (最近(p,2p)个月的ft最小值)
def Npp(ft,p):df1data.loc[:,ft1:ftstr(p)]value1np.nanmin(df1,axis 1 )df2data.loc[:,ftstr(p):ftstr(2*p)]value2np.nanmin(df2,axis 1 ) auto_value value1/value2return ft_nppstr(p),auto_value 将上面的衍生方法定义为函数
#定义批量调用双参数的函数
def auto_var2(feature,p):#global data_newtry:columns_name,valuesNum(feature,p)data_new[columns_name]valuesexcept:print(Num PARSE ERROR,feature,p)try:columns_name,valuesNmz(feature,p)data_new[columns_name]valuesexcept:print(Nmz PARSE ERROR,feature,p)try:columns_name,valuesEvr(feature,p)data_new[columns_name]valuesexcept:print(Evr PARSE ERROR,feature,p)try:columns_name,valuesAvg(feature,p)data_new[columns_name]valuesexcept:print(Avg PARSE ERROR,feature,p)try:columns_name,valuesTot(feature,p)data_new[columns_name]valuesexcept:print(Tot PARSE ERROR,feature,p) try:columns_name,valuesTot2T(feature,p)data_new[columns_name]valuesexcept:print(Tot2T PARSE ERROR,feature,p) try:columns_name,valuesMax(feature,p)data_new[columns_name]valuesexcept:print(Tot PARSE ERROR,feature,p)try:columns_name,valuesMax(feature,p)data_new[columns_name]valuesexcept:print(Max PARSE ERROR,feature,p)try:columns_name,valuesMin(feature,p)data_new[columns_name]valuesexcept:print(Min PARSE ERROR,feature,p)try:columns_name,valuesMsg(feature,p)data_new[columns_name]valuesexcept:print(Msg PARSE ERROR,feature,p)try:columns_name,valuesMsz(feature,p)data_new[columns_name]valuesexcept:print(Msz PARSE ERROR,feature,p)try:columns_name,valuesCav(feature,p)data_new[columns_name]valuesexcept:print(Cav PARSE ERROR,feature,p)try:columns_name,valuesCmn(feature,p)data_new[columns_name]valuesexcept:print(Cmn PARSE ERROR,feature,p) try:columns_name,valuesStd(feature,p)data_new[columns_name]valuesexcept:print(Std PARSE ERROR,feature,p) try:columns_name,valuesCva(feature,p)data_new[columns_name]valuesexcept:print(Cva PARSE ERROR,feature,p) try:columns_name,valuesCmm(feature,p)data_new[columns_name]valuesexcept:print(Cmm PARSE ERROR,feature,p) try:columns_name,valuesCnm(feature,p)data_new[columns_name]valuesexcept:print(Cnm PARSE ERROR,feature,p) try:columns_name,valuesCxm(feature,p)data_new[columns_name]valuesexcept:print(Cxm PARSE ERROR,feature,p) try:columns_name,valuesCxp(feature,p)data_new[columns_name]valuesexcept:print(Cxp PARSE ERROR,feature,p)try:columns_name,valuesRan(feature,p)data_new[columns_name]valuesexcept:print(Ran PARSE ERROR,feature,p)try:columns_name,valuesNci(feature,p)data_new[columns_name]valuesexcept:print(Nci PARSE ERROR,feature,p)try:columns_name,valuesNcd(feature,p)data_new[columns_name]valuesexcept:print(Ncd PARSE ERROR,feature,p)try:columns_name,valuesNcn(feature,p)data_new[columns_name]valuesexcept:print(Ncn PARSE ERROR,feature,p)try:columns_name,valuesPdn(feature,p)data_new[columns_name]valuesexcept:print(Pdn PARSE ERROR,feature,p) try:columns_name,valuesCmx(feature,p)data_new[columns_name]valuesexcept:print(Cmx PARSE ERROR,feature,p) try:columns_name,valuesCmp(feature,p)data_new[columns_name]valuesexcept:print(Cmp PARSE ERROR,feature,p) try:columns_name,valuesCnp(feature,p)data_new[columns_name]valuesexcept:print(Cnp PARSE ERROR,feature,p) try:columns_name,valuesMsx(feature,p)data_new[columns_name]valuesexcept:print(Msx PARSE ERROR,feature,p)try:columns_name,valuesNci(feature,p)data_new[columns_name]valuesexcept:print(Nci PARSE ERROR,feature,p)try:columns_name,valuesTrm(feature,p)data_new[columns_name]valuesexcept:print(Trm PARSE ERROR,feature,p)try:columns_name,valuesBup(feature,p)data_new[columns_name]valuesexcept:print(Bup PARSE ERROR,feature,p)try:columns_name,valuesMai(feature,p)data_new[columns_name]valuesexcept:print(Mai PARSE ERROR,feature,p)try:columns_name,valuesMad(feature,p)data_new[columns_name]valuesexcept:print(Mad PARSE ERROR,feature,p)try:columns_name,valuesRpp(feature,p)data_new[columns_name]valuesexcept:print(Rpp PARSE ERROR,feature,p)try:columns_name,valuesDpp(feature,p)data_new[columns_name]valuesexcept:print(Dpp PARSE ERROR,feature,p)try:columns_name,valuesMpp(feature,p)data_new[columns_name]valuesexcept:print(Mpp PARSE ERROR,feature,p)try:columns_name,valuesNpp(feature,p)data_new[columns_name]valuesexcept:print(Npp PARSE ERROR,feature,p)return data_new.columns.size对之前数据应用封装的函数
# 创建空的df
data_new pd.DataFrame()
# 遍历12个月
for p in range(1, 12): # 对所有ft-i和gt-i的列进行特征衍生for inv in [ft, gt]: auto_var2(inv, p) 上面这种无差别聚合方法进行聚合得到的结果常具有较高的共线性但信息量并无明显增加影响模型的鲁棒性和稳定性 评分卡模型对模型的稳定性要求远高于其性能 在时间窗口为1年的场景下p值会通过先验知识人为选择3、6、12等而不是遍历全部取值112 在后续特征筛选时会根据变量的显著性、共线性等指标进行进一步筛选 最近一次current 和历史 history做对比 current/historycurrent-history
3.3.2 用户关联特征
如何评价一个没有内部数据的新客
使用第三方数据把新用户关联到内部用户使用关联到的老客信息评估
用户特征关联可以考虑用倒排表做关联
用户→[特征1,特征2,特征3…]特征→[用户1,用户2,用户3…] 举例用户所在地区的统计特征 将用户申请时的GPS转化为geohash位置块geohash基本原理是将地球理解为一个二维平面将平面递归分解成更小的子块每个子块在一定经纬度范围内拥有相同的编码对每个大小合适的位置块统计申请时点GPS在该位置块的人的信用分当新申请的人查询其所在的位置块的平均信用分作为GPS倒排表特征 倒排表的组成关键主键统计指标 关键主键新用户通过什么数据和平台存量用户发生关联 统计指标使用存量用户的什么特征去评估这个新客户 信贷业务的特征要求 逻辑简单容易构造容易排查错误有强业务解释性 构造特征要从两个维度看数据归纳演绎 归纳从大量数据的结果总结出规律相关关系从数据中只能得到相关性演绎从假设推导出必然的结果因果关系