2. 样本构建基础:样本定义、样本与特征、标签的关系
在风险归因模型中,样本是模型学习的“原材料”。样本构建的质量直接决定了模型能否准确捕捉风险因子与违约/损失之间的因果关系。本节从最基础的三个概念出发,厘清样本、特征、标签的定义及其内在联系。
2.1 样本定义:从“数据点”到“风险单元”
在金融风控场景中,一个样本(Sample)通常对应一个风险单元——即模型在某一时刻对某一主体(客户、账户、交易、产品)的风险状态进行预测的最小分析单位。样本的定义需要明确三个维度:
| 维度 | 说明 | 示例 |
|---|---|---|
| 主体维度 | 被评估的对象是谁 | 客户ID、设备ID、商户ID |
| 时间维度 | 在哪个时间点或时间窗口进行评估 | 2024-01-15 的申请、2024Q1 的账户表现 |
| 业务维度 | 在哪个业务环节或产品线中评估 | 信贷申请、交易授权、贷后监控 |
关键原则:一个样本必须唯一标识一个“主体-时间-业务”三元组。重复或模糊的样本定义会导致模型训练时出现数据泄露或标签泄漏。
2.2 样本与特征、标签的关系:模型学习的“三角结构”
风险归因模型的核心学习过程可以抽象为:利用特征(Features)预测标签(Label),而样本(Sample)是承载这一映射关系的容器。三者构成一个不可分割的三角结构:
2.3 样本构建的三种基本模式
根据业务场景和标签获取方式的不同,样本构建通常分为以下三种模式:
- 截面样本(Cross-sectional):在单一时间点对多个主体采样,每个主体只产生一个样本。适用于申请评分卡、一次性评估。
- 时间序列样本(Time-series):对同一主体在多个时间点重复采样,每个时间点产生一个样本。适用于贷后监控、交易反欺诈。
- 面板样本(Panel):结合截面和时间序列,对多个主体在多个时间点采样,形成三维数据结构。适用于风险归因、因果推断。
| 模式 | 样本数量 | 时间维度 | 典型应用 | 注意事项 |
|---|---|---|---|---|
| 截面样本 | N(主体数) | 无 | 申请评分卡 | 需确保时间点一致,避免时间偏差 |
| 时间序列样本 | T(时间点数) | 有 | 交易监控 | 需处理自相关性和时间依赖性 |
| 面板样本 | N × T | 有 | 风险归因模型 | 需处理个体效应和时间效应 |
2.4 特征与标签的时间对齐:避免“未来信息”污染
在风险归因模型中,特征必须严格在标签之前或同时获取,绝不能使用标签发生之后的信息作为特征。这是样本构建中最容易出错、也最致命的陷阱。
⚠️ 常见错误:使用“逾期后30天的还款行为”作为特征来预测“是否逾期”。这相当于用结果预测结果,会导致模型在训练时表现极好,但在实际部署时完全失效。
正确的时间对齐策略如下:
- 观察窗口(Observation Window):用于提取特征的时间区间,通常为标签发生前的一段时间(如过去6个月)。
- 表现窗口(Performance Window):用于定义标签的时间区间,通常为观察窗口之后的一段时间(如未来12个月)。
- 间隔期(Gap):观察窗口结束与表现窗口开始之间的缓冲期,用于确保特征信息完全可用。
2.5 样本构建的常见陷阱与避坑指南
💡 实践建议:在构建样本时,始终问自己三个问题:
1. 这个样本代表哪个风险单元?(主体-时间-业务)
2. 特征是否全部来自标签之前?(时间对齐)
3. 标签是否真实反映了风险结果?(标签质量)
1. 这个样本代表哪个风险单元?(主体-时间-业务)
2. 特征是否全部来自标签之前?(时间对齐)
3. 标签是否真实反映了风险结果?(标签质量)
| 陷阱 | 表现 | 后果 | 解决方案 |
|---|---|---|---|
| 未来信息泄露 | 特征包含标签之后的信息 | 模型过拟合,上线后失效 | 严格按时间窗口切分,设置间隔期 |
| 样本重复 | 同一风险单元出现多次 | 模型偏向重复样本,泛化能力差 | 按主体-时间-业务去重 |
| 标签定义模糊 | 标签边界不清晰或主观性强 | 模型学习目标不一致 | 制定明确的标签定义文档 |
| 特征与标签时间错位 | 特征和标签来自不同时间尺度 | 模型无法建立因果关系 | 统一时间粒度,对齐窗口 |
2.6 样本构建的代码示例:Python 实现
以下代码展示了如何使用 Python 构建一个简单的风险归因样本集,包含特征提取、标签定义和时间对齐:
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
# 模拟原始交易数据
np.random.seed(42)
n_customers = 1000
dates = pd.date_range('2023-01-01', '2024-06-30', freq='D')
# 构建样本:每个客户每月一个样本
samples = []
for cust_id in range(n_customers):
# 随机选择开户日期
open_date = np.random.choice(dates)
# 生成12个月的月度样本
for month_offset in range(12):
sample_date = open_date + timedelta(days=month_offset*30)
if sample_date > datetime(2024, 6, 30):
break
# 特征:过去3个月的交易统计(观察窗口)
past_3m_start = sample_date - timedelta(days=90)
# 模拟特征值
features = {
'customer_id': cust_id,
'sample_date': sample_date,
'avg_transaction_amt': np.random.exponential(500),
'transaction_count': np.random.poisson(10),
'max_delay_days': np.random.randint(0, 30),
'utilization_rate': np.random.beta(2, 5)
}
# 标签:未来6个月是否逾期超过30天(表现窗口)
future_6m_end = sample_date + timedelta(days=180)
# 模拟逾期标签
label = 1 if np.random.random() < 0.15 else 0
features['label'] = label
samples.append(features)
# 构建DataFrame
df = pd.DataFrame(samples)
print(f"样本总数: {len(df)}")
print(f"正样本比例: {df['label'].mean():.2%}")
print("\n样本前5行:")
print(df.head())
输出说明:上述代码生成了一个包含客户ID、样本日期、4个特征和1个标签的样本集。每个样本代表一个客户在特定月份的风险状态,特征来自过去3个月,标签定义在未来6个月,严格遵循时间对齐原则。