4 特征构造

本文详细介绍了在信贷风控中特征构造的过程,包括数据准备、静态信息与时间截面特征、时间序列特征的构造,以及如何处理缺失值和未来信息。强调了在特征构造前需要梳理数据内在逻辑、构建特征框架,并介绍了时间序列特征的重要性,如额度使用率的计算。同时,讨论了分箱、WOE编码等特征变换方法,以及用户关联特征的构建,提出特征工程应遵循简单、归纳与演绎的原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4 特征构造

学习目标

  • 知道未来信息的概念,及处理未来信息的方法
  • 掌握从原始数据构造出新特征的方法
  • 掌握特征变换的方法
  • 掌握缺失值处理的方法

1 数据准备

1.1 梳理数据的内在逻辑

关系种类

一对一:一个用户有一个注册手机号

一对多:一个用户多笔借款

多对多:一个用户可以登录多个设备,一个设备可以有多个用户登录

  • 举例

下图中,蓝色框为二月当期账单,红色框为订单

在这里插入图片描述

梳理类ER图
在这里插入图片描述

  • 任务:分析厚数据常登陆首单用户的逾期情况
    在这里插入图片描述

  • 可以将表结构展示到特征文档当中,说明取数逻辑
    在这里插入图片描述

1.2 样本设计和特征框架

  • 定义观察期样本
  • 确定观察期(定X时间切面)和表现期(定Y的标签)
  • 确认样本数目是否合理
  • 数据EDA
  • 看数据总体分布
    • data.shape
    • data.isnull()
    • data.info()
    • data.describe()
  • 看好坏样本分布差异
    • data[data[label]==0].describe() 好用户
    • data[data[label]==1].describe() 坏用户
  • 看单个数据
    • data.sample(n=10,random_state=1)
  • 梳理特征框架
  • RFM生成新特征

举例 行为评分卡中的用户账单还款特征

  • 用户账单关键信息:时间,金额,还款,额度
    在这里插入图片描述

  • 小结:在构建特征前,要完成

  • 类ER图

  • 样本设计表

  • 特征框架表

2 特征构造

2.1 静态信息特征和时间截面特征

用户静态信息特征

  • 用户的基本信息(半年内不会变化)

用户时间截面特征

  • 未来信息当前时间截面之后的数据
  • 时间截面数据在取数的时候要小心,**避免使用未来信息 **
  • 产生未来信息最直接的原因:缺少快照表
  • 金融相关数据原则上都需要快照表记录所有痕迹(额度变化情况,多次申请的通过和拒绝情况…)

缺少快照表的可能原因

  • 快照表消耗资源比较大,为了性能不做
  • 原有数据表设计人员疏忽,没做
  • 借用其他业务数据(如电商)做信贷

举例

首次借贷 二次借贷 爬虫授权 三次借贷

——————————————————————→

用户 借款 授权爬虫 逾期
u1 l11 N 0
u1 l12 N 0
u1 l13 Y 0
u2 l21 N 0
u2 l22 N 0
u2 l23 Y 1
u3 l11 N 0
u3 l12 N 0
u3 l13 Y 0

实际存储

用户 授权
u1 Y
u2 Y
u3 Y
用户 借款 逾期
u1 l11 0
u1 l12 0
u1 l13 0
u2 l21 0
u2 l22 0
u2 l23 1
u3 l11 0
u3 l12 0
u3 l13 0

join 结果

用户 借款 授权爬虫 逾期
u1 l11 Y 0
u1 l12 Y 0
u1 l13 Y 0
u2 l21 Y 0
u2 l22 Y 0
u2 l23 Y 1
u3 l11 Y 0
u3 l12 Y 0
u3 l13 Y 0

解决方案: 加入快照表

用户 授权 时间
u1 Y t3
u2 Y t3
u3 Y t3

2.2 时间序列特征

用户时间序列特征
  • 从观察点往前回溯一段时间的数据
    在这里插入图片描述
时间序列特征衍生

特征聚合:将单个特征的多个时间节点取值进行聚合。特征聚合是传统评分卡建模的主要特征构造方法。

  • 举例,计算每个用户的额度使用率,记为特征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()

显示结果

customer_id ft1 ft2 ft3 ft4 ft5 ft6 ft7 ft8 ft9 gt3 gt4 gt5 gt6 gt7 gt8 gt9 gt10 gt11 gt12
0 111 9 11.0 12 13 18 10 12 NaN NaN 10 0 18 10 12 NaN NaN NaN NaN NaN
1 112 11 -11.0 10 10 13 13 10 NaN NaN 10 10 13 13 10 NaN NaN NaN NaN NaN
2 113 0 11.0 10 12 6 10 0 25.0 10.0 10 12 6 10 0 25.0 10.0 NaN NaN NaN
3 114 -7 -1.0 9 8 7 0 -19 10.0 11.0 10 10 12 0 -19 10.0 11.0 NaN NaN NaN
4 115 11 NaN 6 10 0 17 19 10.0 30.0 6 10 0 17 19 10.0 30.0 15.0 NaN NaN

5 rows × 26 columns

  • 可以根据这个时间序列进行基于经验的人工特征衍生,例如计算最近P个月特征大于0的月份数
#最近p个月,ft>0的月份数
def Num(ft,p):  #ft 特征名字 p特征大于0的月份数
    df=data.loc[:,ft+'1':ft+str(p)]
    # np.where df>0  向量计算  会拿着每一个数跟0做比较, 返回的也是一个数组
    # 条件为true 返回1  条件为False 返回0
    auto_value=np.where(df>0,1,0).sum(axis=1)
    return ft+'_num'+str(p),auto_value
  • 计算最近P个月特征ft等于0的月份数
#最近p个月,ft=0的月份数
def zero_cnt(ft,p):
    df=data.loc[:,ft+'1':ft+str(p)]
    auto_value=np.where(df==0,1,0).sum(axis=1)
    return ft+'_zero_cnt'+str(p),auto_value
  • 计算近p个月特征ft大于0的月份数是否大于等于1
#最近p个月,ft>0的月份数是否>=1     
def Evr(ft,p):
    df=data.loc[:,ft+'1':ft+str(p)]
    arr=np.where(df>0,1,0).sum(axis=1)
    auto_value = np.where(arr,1,0)
    return ft+'_evr'+str(p),auto_value  
  • 计算最近p个月特征ft的均值
#最近p个月,ft均值
def Avg(ft,p):
    df=data.loc[:,ft+'1':ft+str(p)]
    auto_value=np.nanmean(df,axis = 1 )
    return ft+'_avg'+str(p),auto_value    
  • 计算最近p个月特征ft的和,最大值,最小值
#最近p个月,ft和
def Tot(ft,p):
    df=data.loc[:,ft+'1':ft+str(p)]
    auto_value=np.nansum(df,axis = 1)
    return ft+'_tot'+str(p),auto_value

#最近(2,p+1)个月,ft和
def Tot2T(ft,p):
    df=data.loc[:,ft+'2':ft+str(p+1)]
    auto_value=df.sum(1)
    return ft+'_tot2t'+str(p),auto_value  

#最近p个月,ft最大值
def Max(ft,p):
    df=data.loc[:,ft+'1':ft+str(p)]
    auto_value=np.nanmax(df,axis = 1)
    return ft+'_max'+str(p),auto_value 

#最近p个月,ft最小值
def Min(ft,p):
    df=data.loc[:,ft+'1':ft+str(p)]
    auto_value=np.nanmin(df,axis = 1)
    return ft+'_min'+str(p),auto_value 
  • 其余衍生方法
#最近p个月,最近一次ft>0到现在的月份数

def Msg(ft,p):
    df=data.loc[:,ft+'1':ft+str(p)]
    df_value=np.where(df>0,1,0)
    auto_value=[]
    for i in range(len(df_value)):
        row_value=df_value[i,:]
        if row_value.max()<=0:
            indexs='0'
            auto_value.append(indexs)
        else:
            indexs=1
            for j in row_value:
                if j>0:
                    break
                indexs+=1
            auto_value.append(indexs)
    return ft+'_msg'+str(p),auto_value


#最近p个月,最近一次ft=0到现在的月份数
def Msz(ft,p):
    df=data.loc[:,ft+'1':ft+str(p)]
    df_value=np.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值