3. 坏样本的数据采集:数据源选择、采样策略与时间窗口对齐
坏样本归因的第一步,也是最容易被低估的一步,是数据采集。如果采集阶段引入偏差,后续所有建模与归因工作都会建立在错误的基础上。本节围绕三个核心问题展开:从哪些数据源获取坏样本、如何通过采样策略平衡样本分布、如何对齐时间窗口以保证因果时序正确。
3.1 数据源选择:坏样本从哪里来
坏样本的定义因业务场景而异。在信贷风控中,坏样本通常指逾期超过特定天数(如 M3+)的客户;在反欺诈场景中,坏样本指被确认的欺诈交易;在营销响应模型中,坏样本指高成本低转化的用户。数据源的选择必须覆盖坏样本的完整生命周期,避免遗漏关键信号。
| 数据源类型 | 典型内容 | 坏样本覆盖范围 | 采集优先级 |
|---|---|---|---|
| 内部交易/行为日志 | 还款记录、交易流水、登录行为 | 直接定义坏样本(逾期、欺诈) | 最高 |
| 外部征信/黑名单 | 央行征信、百行征信、多头借贷 | 补充跨机构坏样本 | 高 |
| 第三方风控数据 | 设备指纹、IP 风险、社交网络 | 识别团伙欺诈、设备关联坏样本 | 中 |
| 人工标注/调查结果 | 贷后催收记录、调查员反馈 | 确认争议样本、修正标签噪声 | 按需 |
实践建议:优先使用内部交易日志作为坏样本主数据源,因为其采集成本低、时间戳精确、可回溯性强。外部数据用于交叉验证和补充,但需注意数据更新延迟和覆盖偏差。
3.2 采样策略:上采样与下采样的选择
坏样本在真实业务中通常是稀有事件(例如欺诈率低于 1%)。直接使用原始分布训练模型会导致模型偏向多数类(好样本),忽略坏样本的规律。采样策略的核心目标是让模型在训练时“看到”足够多的坏样本特征。
3.2.1 下采样(Undersampling)
从多数类(好样本)中随机抽取一部分,使好、坏样本比例接近 1:1 或 1:2。优点是训练速度快、内存占用低;缺点是可能丢弃大量有价值的好样本信息,导致模型泛化能力下降。
3.2.2 上采样(Oversampling)
对少数类(坏样本)进行复制或生成合成样本,使坏样本数量增加。常见方法包括随机复制和 SMOTE(合成少数类过采样技术)。优点是保留全部好样本信息;缺点是容易过拟合,尤其是随机复制会导致模型记住重复样本。
| 策略 | 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 随机下采样 | 随机抽取好样本 | 速度快、内存低 | 丢失信息、泛化差 | 坏样本绝对数量足够(>5000) |
| 随机上采样 | 复制坏样本 | 保留全部好样本 | 易过拟合 | 坏样本极少(<500) |
| SMOTE | 插值生成合成样本 | 缓解过拟合 | 可能生成噪声样本 | 特征空间连续(如数值型) |
| 混合采样 | 上采样+下采样结合 | 平衡信息保留与过拟合 | 参数调优复杂 | 大多数实际项目 |
常见陷阱:不要在验证集或测试集上做任何采样!采样只应用于训练集。验证集和测试集必须保持原始分布,否则模型评估结果会严重失真。
3.3 时间窗口对齐:因果时序是归因的生命线
坏样本归因的核心假设是:特征必须发生在坏样本定义之前。如果特征时间戳晚于坏样本发生时间,模型学到的就是“事后诸葛亮”,无法用于预测。时间窗口对齐需要解决三个问题:观察窗口、表现窗口和特征滞后。
- 观察窗口(Observation Window):用于提取特征的时间段。例如,取申请日前 6 个月的交易行为作为特征。
- 表现窗口(Performance Window):用于定义坏样本的时间段。例如,取放款后 12 个月内是否逾期 M3+。
- 特征滞后(Feature Lag):特征采集时间与坏样本定义时间之间的间隔。必须保证特征采集时间早于坏样本开始时间。
时间窗口对齐公式:
特征采集截止时间 < 表现窗口开始时间
表现窗口长度 = 坏样本定义所需的最短观察期(如 90 天、180 天)
样本标签 = 在表现窗口内是否触发坏样本定义
特征采集截止时间 < 表现窗口开始时间
表现窗口长度 = 坏样本定义所需的最短观察期(如 90 天、180 天)
样本标签 = 在表现窗口内是否触发坏样本定义
3.4 采样与时间窗口的联合实践
在实际项目中,数据采集流程通常按以下步骤执行:
- 定义坏样本标准:与业务方确认逾期天数、欺诈确认流程、损失阈值等。
- 确定时间窗口:设置观察窗口长度(如 6 个月)和表现窗口长度(如 12 个月),确保特征与标签无时间穿越。
- 提取原始样本:从数据源中拉取所有满足时间窗口条件的样本,保留原始时间戳。
- 计算坏样本比例:统计表现窗口内坏样本占比,判断是否需要采样。
- 执行采样策略:根据坏样本绝对数量和特征类型选择上采样、下采样或混合采样。
- 划分训练/验证/测试集:按时间顺序划分(而非随机划分),避免未来信息泄露。
代码示例:基于时间序列的采样与窗口对齐(Python 伪代码)
import pandas as pd
from sklearn.model_selection import train_test_split
# 假设 df 包含字段:user_id, feature_time, label_time, is_bad
# 1. 时间窗口过滤
df = df[(df['feature_time'] < '2023-01-01') & (df['label_time'] >= '2023-01-01')]
df = df[df['label_time'] <= '2024-01-01']
# 2. 计算坏样本比例
bad_ratio = df['is_bad'].mean()
print(f"坏样本比例: {bad_ratio:.4f}")
# 3. 下采样(当坏样本比例 < 0.1 时)
if bad_ratio < 0.1:
good = df[df['is_bad'] == 0]
bad = df[df['is_bad'] == 1]
good_sampled = good.sample(n=len(bad) * 2, random_state=42)
df_balanced = pd.concat([good_sampled, bad])
# 4. 按时间顺序划分(避免未来信息泄露)
df_balanced = df_balanced.sort_values('feature_time')
train_end = int(len(df_balanced) * 0.7)
val_end = int(len(df_balanced) * 0.85)
train = df_balanced.iloc[:train_end]
val = df_balanced.iloc[train_end:val_end]
test = df_balanced.iloc[val_end:]
3.5 常见问题与避坑指南
- 幸存者偏差:只采集了“活到表现窗口结束”的样本,忽略了提前结清或流失的客户。解决方案:对提前结束的样本单独标记,或使用生存分析框架。
- 时间窗口漂移:业务策略变化导致坏样本定义随时间改变(如从 M3 改为 M2)。解决方案:定期重新校准窗口定义,或使用滑动窗口验证。
- 采样后分布偏移:上采样/下采样改变了训练集分布,导致模型在真实分布上表现不佳。解决方案:在验证集上使用原始分布评估,并监控 KS/PSI 指标。
- 数据源不一致:不同数据源的时间戳精度不同(如日志精确到秒,征信精确到天)。解决方案:统一将时间戳对齐到天级别,并在特征滞后中增加缓冲期。
最佳实践:在项目初期建立一个“数据采集清单”,包含数据源名称、字段定义、时间戳格式、更新频率、坏样本覆盖范围。每次迭代前先检查清单,避免重复采集或遗漏关键数据源。