3. 数据准备与特征工程:数据源介绍、清洗与特征衍生

在信用评分PD模型的生产化部署中,数据准备与特征工程是决定模型性能上限的关键环节。本章将系统讲解征信、行为、多头三大核心数据源的结构与特点,并深入探讨数据清洗、缺失值处理以及特征衍生的方法论,为后续模型训练与serving奠定坚实基础。

3.1 数据源介绍

信用评分模型的数据源通常分为三大类:征信数据、行为数据和多头数据。下表对比了这三类数据源的核心特征与典型字段:

数据源类型 数据来源 核心特征 典型字段示例
征信数据 央行征信、百行征信、朴道征信 权威性高、更新频率低(月/季)、覆盖全量信贷记录 逾期天数、贷款余额、查询次数、担保信息
行为数据 自有平台(APP、Web、交易系统) 高频实时、用户画像精准、与还款意愿强相关 登录频次、交易金额、还款方式、客服交互记录
多头数据 第三方数据服务商(同盾、百融、前海) 跨平台借贷行为、时效性高、识别共债风险 近7天申请平台数、近30天被查询次数、多头借贷指数
实战提示:在serving阶段,征信数据通常作为“慢变量”用于月度或季度模型更新;行为数据作为“快变量”用于实时决策;多头数据则常用于贷前审批和贷中监控的交叉验证。

3.2 数据清洗与缺失值处理

原始数据通常包含大量噪声、异常值和缺失值,必须经过系统化清洗才能用于模型训练。以下是标准的数据清洗流程:

  1. 格式统一:将日期、金额、百分比等字段转换为标准格式,去除特殊字符和空格。
  2. 异常值检测:使用IQR(四分位距)或Z-score方法识别并处理极端值,如年龄大于120岁、贷款金额为负数等。
  3. 重复记录去重:基于主键(如身份证号+申请时间)去除完全重复或逻辑重复的记录。
  4. 逻辑校验:检查字段间的逻辑一致性,如“放款日期”不应晚于“逾期日期”。
  5. 缺失值处理:根据缺失率与业务含义选择填充策略。

缺失值处理是数据清洗中的核心难点,下表总结了不同场景下的推荐策略:

缺失率 业务含义 推荐策略 注意事项
< 5% 随机缺失 均值/中位数填充 连续变量用中位数,离散变量用众数
5% - 30% 有偏缺失 模型预测填充(KNN、回归)或单独编码 需验证填充值是否引入偏差
> 30% 结构性缺失 单独作为“缺失”类别或删除变量 优先保留业务含义强的变量
特定场景 “未逾期”导致逾期天数缺失 填充为0 需结合业务规则判断
代码示例:使用Python进行缺失值处理
import pandas as pd
import numpy as np

# 加载原始数据
df = pd.read_csv('raw_data.csv')

# 1. 格式统一:将日期列转为datetime
df['apply_date'] = pd.to_datetime(df['apply_date'], errors='coerce')

# 2. 异常值处理:贷款金额大于100万视为异常,用中位数替换
loan_cap = df['loan_amount'].median()
df.loc[df['loan_amount'] > 1_000_000, 'loan_amount'] = loan_cap

# 3. 缺失值处理
# 连续变量:用中位数填充
df['income'].fillna(df['income'].median(), inplace=True)
# 离散变量:用众数填充
df['education'].fillna(df['education'].mode()[0], inplace=True)
# 结构性缺失:单独编码为-1
df['overdue_days'].fillna(-1, inplace=True)

# 4. 逻辑校验:删除放款日期晚于逾期日期的记录
df = df[df['loan_date'] <= df['overdue_date']]

print(f"清洗后数据量: {len(df)} 条")

3.3 特征衍生方法论

特征衍生是从原始数据中构造新特征的过程,旨在提升模型的区分能力和鲁棒性。以下是三种核心的特征衍生方法:

  • 统计聚合衍生:对时间序列或分组数据进行聚合计算,如近3个月的平均消费金额、近6个月的最大逾期天数。
  • 交叉组合衍生:将两个或多个特征进行数学运算或逻辑组合,如“收入/负债比”、“年龄×授信额度”。
  • 时间窗口衍生:基于固定时间窗口(7天、30天、90天)计算统计量,如近7天申请次数、近30天还款次数。

下图展示了特征衍生的完整流程与核心节点:

特征衍生流程图 特征衍生方法论流程图 原始数据 统计聚合衍生 均值/最大/最小/计数 交叉组合衍生 加减乘除/逻辑运算 时间窗口衍生 7天/30天/90天 特征筛选(IV/相关性/VIF) 最终特征集 说明:特征衍生后必须经过IV值筛选、相关性分析和VIF多重共线性检验,才能进入模型训练

3.4 特征衍生实战案例

以多头数据为例,展示如何从原始“申请记录”表中衍生出高价值特征:

代码示例:多头数据特征衍生
import pandas as pd
import numpy as np

# 原始多头数据:每行代表一次申请记录
multi_head = pd.DataFrame({
    'user_id': ['U001', 'U001', 'U001', 'U002', 'U002'],
    'apply_date': ['2024-01-05', '2024-01-10', '2024-01-20', '2024-01-08', '2024-01-15'],
    'platform': ['平台A', '平台B', '平台C', '平台A', '平台D'],
    'loan_amount': [5000, 10000, 8000, 3000, 12000]
})
multi_head['apply_date'] = pd.to_datetime(multi_head['apply_date'])

# 设定观察日期
obs_date = pd.Timestamp('2024-01-25')

# 1. 统计聚合:近30天申请次数
agg_features = multi_head.groupby('user_id').agg(
    total_applications=('apply_date', 'count'),
    total_loan_amount=('loan_amount', 'sum'),
    avg_loan_amount=('loan_amount', 'mean')
).reset_index()

# 2. 时间窗口:近7天申请次数
multi_head['days_diff'] = (obs_date - multi_head['apply_date']).dt.days
recent_7d = multi_head[multi_head['days_diff'] <= 7].groupby('user_id').agg(
    recent_7d_applications=('apply_date', 'count')
).reset_index()

# 3. 交叉组合:申请次数 × 平均金额
agg_features['application_intensity'] = agg_features['total_applications'] * agg_features['avg_loan_amount']

# 合并特征
final_features = agg_features.merge(recent_7d, on='user_id', how='left')
final_features.fillna(0, inplace=True)

print(final_features)
避坑指南:特征衍生时需注意“数据泄露”问题。例如,使用未来信息(如观察日之后的还款记录)构造特征会导致模型在serving阶段失效。务必确保所有衍生特征仅基于历史数据计算。

3.5 特征工程serving注意事项

在模型serving阶段,特征工程需要与训练阶段保持严格一致,否则会导致预测偏差。以下是关键注意事项:

  • 特征对齐:serving时使用的特征名称、类型、衍生逻辑必须与训练时完全一致,建议使用特征配置文件(如YAML或JSON)进行版本管理。
  • 缺失值处理一致性:serving时使用的填充值(如中位数、众数)必须与训练时相同,建议将填充参数固化到模型pipeline中。
  • 时间窗口对齐:serving时的时间窗口计算基准(如“当前时间”)必须与训练时的观察点对齐,避免使用未来数据。
  • 性能优化:对于高并发serving场景,建议将特征衍生逻辑预编译为SQL UDF或使用特征存储(Feature Store)进行缓存。

下图展示了serving阶段特征工程的标准架构:

Serving阶段特征工程架构 Serving阶段特征工程架构 实时请求数据 特征存储 特征计算引擎 模型预测 PD评分输出 说明:特征存储缓存高频特征,特征计算引擎负责实时衍生,确保serving与训练特征逻辑一致

通过以上数据准备与特征工程方法论,可以为信用评分PD模型提供高质量、可解释的特征输入,从而在serving阶段实现稳定、准确的预测性能。