3. 数据准备与特征工程:数据源介绍、清洗与特征衍生
在信用评分PD模型的生产化部署中,数据准备与特征工程是决定模型性能上限的关键环节。本章将系统讲解征信、行为、多头三大核心数据源的结构与特点,并深入探讨数据清洗、缺失值处理以及特征衍生的方法论,为后续模型训练与serving奠定坚实基础。
3.1 数据源介绍
信用评分模型的数据源通常分为三大类:征信数据、行为数据和多头数据。下表对比了这三类数据源的核心特征与典型字段:
| 数据源类型 | 数据来源 | 核心特征 | 典型字段示例 |
|---|---|---|---|
| 征信数据 | 央行征信、百行征信、朴道征信 | 权威性高、更新频率低(月/季)、覆盖全量信贷记录 | 逾期天数、贷款余额、查询次数、担保信息 |
| 行为数据 | 自有平台(APP、Web、交易系统) | 高频实时、用户画像精准、与还款意愿强相关 | 登录频次、交易金额、还款方式、客服交互记录 |
| 多头数据 | 第三方数据服务商(同盾、百融、前海) | 跨平台借贷行为、时效性高、识别共债风险 | 近7天申请平台数、近30天被查询次数、多头借贷指数 |
实战提示:在serving阶段,征信数据通常作为“慢变量”用于月度或季度模型更新;行为数据作为“快变量”用于实时决策;多头数据则常用于贷前审批和贷中监控的交叉验证。
3.2 数据清洗与缺失值处理
原始数据通常包含大量噪声、异常值和缺失值,必须经过系统化清洗才能用于模型训练。以下是标准的数据清洗流程:
- 格式统一:将日期、金额、百分比等字段转换为标准格式,去除特殊字符和空格。
- 异常值检测:使用IQR(四分位距)或Z-score方法识别并处理极端值,如年龄大于120岁、贷款金额为负数等。
- 重复记录去重:基于主键(如身份证号+申请时间)去除完全重复或逻辑重复的记录。
- 逻辑校验:检查字段间的逻辑一致性,如“放款日期”不应晚于“逾期日期”。
- 缺失值处理:根据缺失率与业务含义选择填充策略。
缺失值处理是数据清洗中的核心难点,下表总结了不同场景下的推荐策略:
| 缺失率 | 业务含义 | 推荐策略 | 注意事项 |
|---|---|---|---|
| < 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天还款次数。
下图展示了特征衍生的完整流程与核心节点:
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阶段特征工程的标准架构:
通过以上数据准备与特征工程方法论,可以为信用评分PD模型提供高质量、可解释的特征输入,从而在serving阶段实现稳定、准确的预测性能。