3. 样本切分实战:基于放款时间戳的滑动窗口切分、跨时间段的样本稳定性检验
在额度模型开发中,样本切分不是简单的随机抽样。由于信贷业务存在明显的时序依赖——宏观经济、客群结构、风控策略都会随时间变化——因此必须采用基于放款时间戳的滑动窗口切分,并辅以跨时间段的样本稳定性检验,才能保证模型在未来的真实表现。
3.1 为什么不能随机切分?
随机切分(如 70% 训练 / 30% 测试)假设样本独立同分布,这在信贷场景中几乎不成立:
| 切分方式 | 适用场景 | 信贷风险 |
|---|---|---|
| 随机切分 | A/B 测试、横截面数据 | 未来样本信息泄露,高估模型效果 |
| 时间序列切分 | 信贷、风控、时序预测 | 模拟真实上线环境,避免时间穿越 |
⚠️ 常见陷阱: 如果训练集包含 2023 年 12 月的样本,而测试集包含 2023 年 6 月的样本,模型会“看到”未来的逾期表现,导致验证 AUC 虚高 0.05~0.10。
3.2 滑动窗口切分策略
基于放款时间戳,我们采用滑动窗口(Sliding Window)进行样本切分。核心参数包括:
- 窗口长度:训练集覆盖的时间跨度(如 12 个月)
- 验证/测试偏移:训练集结束时间点到验证集开始时间点的间隔(如 1 个月)
- 步长:每次滑动的时间长度(如 3 个月)
以下是一个典型的滑动窗口切分流程:
3.3 实战切分步骤
以某消费金融公司额度模型为例,放款时间戳范围为 2022-01 至 2024-06,我们执行以下切分:
- 确定观察期与表现期:额度模型通常使用 6 个月表现期(如是否逾期 30+)。
- 设定窗口参数:训练窗口 12 个月,验证窗口 3 个月,测试窗口 3 个月,步长 3 个月。
- 生成切分时间点:从 2023-01 开始,每 3 个月生成一组训练/验证/测试切分。
- 剔除表现期不足的样本:对于测试集,必须确保放款时间 + 6 个月表现期 ≤ 当前数据截止时间。
💡 关键代码片段: 基于 Pandas 的滑动窗口切分
import pandas as pd
from datetime import timedelta
def sliding_window_split(df, date_col='loan_date', window_months=12,
gap_months=1, test_months=3, step_months=3):
"""
基于放款时间戳的滑动窗口切分
"""
df = df.sort_values(date_col).reset_index(drop=True)
min_date = df[date_col].min()
max_date = df[date_col].max()
splits = []
current_start = min_date
while current_start + timedelta(days=window_months*30) <= max_date:
train_end = current_start + timedelta(days=window_months*30)
val_start = train_end + timedelta(days=gap_months*30)
val_end = val_start + timedelta(days=test_months*30)
test_end = val_end + timedelta(days=test_months*30)
if test_end > max_date:
break
train_mask = (df[date_col] >= current_start) & (df[date_col] < train_end)
val_mask = (df[date_col] >= val_start) & (df[date_col] < val_end)
test_mask = (df[date_col] >= val_end) & (df[date_col] < test_end)
splits.append({
'train': df[train_mask].index.tolist(),
'val': df[val_mask].index.tolist(),
'test': df[test_mask].index.tolist(),
'train_period': f'{current_start.date()} ~ {train_end.date()}',
'val_period': f'{val_start.date()} ~ {val_end.date()}',
'test_period': f'{val_end.date()} ~ {test_end.date()}'
})
current_start += timedelta(days=step_months*30)
return splits
3.4 跨时间段的样本稳定性检验
切分完成后,必须检验不同时间窗口的样本分布是否稳定。常用的检验方法包括:
| 检验方法 | 适用变量类型 | 阈值 | 说明 |
|---|---|---|---|
| PSI (Population Stability Index) | 连续变量(分箱后) | PSI < 0.1 | 衡量整体分布偏移 |
| KS 检验 | 连续变量 | p-value > 0.05 | 检验两个分布是否相同 |
| 卡方检验 | 分类变量 | p-value > 0.05 | 检验类别分布是否一致 |
| 特征缺失率对比 | 所有变量 | 差异 < 5% | 检验数据质量是否稳定 |
3.5 PSI 计算与解读
PSI 是信贷风控中最常用的稳定性指标,计算公式如下:
PSI = Σ (实际占比_i - 预期占比_i) * ln(实际占比_i / 预期占比_i)
其中:
- 预期占比_i:训练集在第 i 个分箱中的样本比例
- 实际占比_i:验证/测试集在第 i 个分箱中的样本比例
PSI 的判定标准:
- PSI < 0.1:分布稳定,无需处理
- 0.1 ≤ PSI < 0.25:轻度偏移,需监控
- PSI ≥ 0.25:严重偏移,需重新训练或调整特征
💡 实战建议: 在额度模型中,建议对以下关键特征进行 PSI 检验:收入、负债率、征信查询次数、历史逾期天数。如果某个特征的 PSI 连续两个窗口超过 0.2,应考虑特征工程层面的修正(如分箱调整、WOE 平滑)。
3.6 稳定性检验报告模板
每次切分后,应输出一份稳定性检验报告,格式如下:
3.7 稳定性检验后的处理策略
根据稳定性检验结果,采取相应的处理措施:
- PSI < 0.1:特征保留,直接用于模型训练。
- 0.1 ≤ PSI < 0.25:尝试分箱调整或 WOE 平滑;若调整后仍不稳定,则降权使用。
- PSI ≥ 0.25:分析偏移原因(如策略调整、客群变化),若无法解释则剔除该特征。
⚠️ 重要提醒: 稳定性检验不是一次性工作。在模型上线后,应建立月度/季度监控机制,持续跟踪特征的 PSI 变化。一旦发现 PSI 持续上升,应及时触发模型重训流程。
3.8 本章小结
基于放款时间戳的滑动窗口切分是额度模型开发的基础步骤,它保证了训练集、验证集、测试集在时间上的严格隔离。跨时间段的样本稳定性检验(尤其是 PSI)则是模型泛化能力的“体检报告”。只有通过稳定性检验的样本切分,才能用于后续的特征筛选和模型训练。