2. 样本构建基础:样本定义、样本与特征、标签的关系

在风险归因模型中,样本是模型学习的“原材料”。样本构建的质量直接决定了模型能否准确捕捉风险因子与违约/损失之间的因果关系。本节从最基础的三个概念出发,厘清样本、特征、标签的定义及其内在联系。

2.1 样本定义:从“数据点”到“风险单元”

在金融风控场景中,一个样本(Sample)通常对应一个风险单元——即模型在某一时刻对某一主体(客户、账户、交易、产品)的风险状态进行预测的最小分析单位。样本的定义需要明确三个维度:

维度 说明 示例
主体维度 被评估的对象是谁 客户ID、设备ID、商户ID
时间维度 在哪个时间点或时间窗口进行评估 2024-01-15 的申请、2024Q1 的账户表现
业务维度 在哪个业务环节或产品线中评估 信贷申请、交易授权、贷后监控
关键原则:一个样本必须唯一标识一个“主体-时间-业务”三元组。重复或模糊的样本定义会导致模型训练时出现数据泄露或标签泄漏。

2.2 样本与特征、标签的关系:模型学习的“三角结构”

风险归因模型的核心学习过程可以抽象为:利用特征(Features)预测标签(Label),而样本(Sample)是承载这一映射关系的容器。三者构成一个不可分割的三角结构:

样本、特征、标签的三角关系 样本 (Sample) 主体-时间-业务 三元组 特征 (Features) X = {x₁, x₂, ..., xₙ} 标签 (Label) Y = {0, 1} 或连续值 三角关系说明 • 样本 → 特征:每个样本对应一组特征向量,描述该风险单元的状态 • 样本 → 标签:每个样本对应一个真实结果(标签),作为学习目标 • 特征 → 标签:模型学习特征与标签之间的映射关系 f(X) → Y

2.3 样本构建的三种基本模式

根据业务场景和标签获取方式的不同,样本构建通常分为以下三种模式:

  1. 截面样本(Cross-sectional):在单一时间点对多个主体采样,每个主体只产生一个样本。适用于申请评分卡、一次性评估。
  2. 时间序列样本(Time-series):对同一主体在多个时间点重复采样,每个时间点产生一个样本。适用于贷后监控、交易反欺诈。
  3. 面板样本(Panel):结合截面和时间序列,对多个主体在多个时间点采样,形成三维数据结构。适用于风险归因、因果推断。
模式 样本数量 时间维度 典型应用 注意事项
截面样本 N(主体数) 无 申请评分卡 需确保时间点一致,避免时间偏差
时间序列样本 T(时间点数) 有 交易监控 需处理自相关性和时间依赖性
面板样本 N × T 有 风险归因模型 需处理个体效应和时间效应

2.4 特征与标签的时间对齐:避免“未来信息”污染

在风险归因模型中,特征必须严格在标签之前或同时获取,绝不能使用标签发生之后的信息作为特征。这是样本构建中最容易出错、也最致命的陷阱。

⚠️ 常见错误:使用“逾期后30天的还款行为”作为特征来预测“是否逾期”。这相当于用结果预测结果,会导致模型在训练时表现极好,但在实际部署时完全失效。

正确的时间对齐策略如下:

  • 观察窗口(Observation Window):用于提取特征的时间区间,通常为标签发生前的一段时间(如过去6个月)。
  • 表现窗口(Performance Window):用于定义标签的时间区间,通常为观察窗口之后的一段时间(如未来12个月)。
  • 间隔期(Gap):观察窗口结束与表现窗口开始之间的缓冲期,用于确保特征信息完全可用。
特征与标签的时间对齐示意图 t₀ t₁ t₂ t₃ 观察窗口(特征提取) 间隔 表现窗口(标签定义) 特征 X 标签 Y 时间对齐规则: 特征必须在 t₁ 之前完全获取;标签在 t₂ 到 t₃ 之间定义;间隔期确保特征信息不会“看到”未来。

2.5 样本构建的常见陷阱与避坑指南

💡 实践建议:在构建样本时,始终问自己三个问题:
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个月,严格遵循时间对齐原则。