1. 样本偏差概述

1.1 什么是样本偏差

样本偏差(Sample Bias)是指用于建模的样本集合与模型实际应用的目标总体之间,在分布、结构或特征上存在系统性差异。在金融风控领域,这种偏差直接导致模型在真实场景中的预测能力下降,甚至产生严重的决策失误。

从数学角度定义:设训练样本集为 S_train,目标总体为 P_target,若 P(S_train) ≠ P(P_target),则存在样本偏差。偏差程度可用分布距离度量,如 KL 散度或 Wasserstein 距离。

核心公式: 模型泛化误差 = 训练误差 + 分布偏移误差 + 噪声误差。样本偏差直接放大“分布偏移误差”项。
样本偏差概念示意图 训练样本 S_train 历史审批通过样本 坏账率: 2.1% 目标总体 P_target 全量申请用户 真实坏账率: 5.8% 样本偏差 分布不一致 ⚠ 训练样本无法代表目标总体 → 模型失效

1.2 为什么在金融特征工程中至关重要

金融风控模型直接关联资金安全与合规要求,样本偏差带来的影响远高于其他领域:

影响维度 具体表现 后果严重性
模型性能 训练集 AUC 0.85,上线后 AUC 骤降至 0.62 高 — 直接导致风控失效
特征有效性 重要特征在总体中分布偏移,IV 值大幅下降 中高 — 特征工程白费
决策公平性 对特定客群产生系统性误判 高 — 合规风险、监管处罚
业务收益 拒绝优质客户或准入高风险客户 高 — 直接经济损失
模型迭代 偏差累积导致模型衰退加速 中 — 维护成本激增
实战经验: 在信贷风控项目中,样本偏差是导致模型上线后“断崖式下跌”的首要原因。特征工程阶段若不处理偏差,后续所有特征筛选、分箱、WOE 编码都会建立在错误的基础上。

1.3 偏差的常见来源

金融特征工程中的样本偏差主要来自以下六个方面:

  1. 选择偏差(Selection Bias): 训练样本仅来自历史审批通过的客户,未包含被拒绝的客户。这是信贷风控中最典型的偏差来源。
  2. 时间偏差(Temporal Bias): 训练数据来自特定时间段(如经济上行期),但模型应用于不同经济周期。
  3. 幸存者偏差(Survivorship Bias): 仅观察存续客户,忽略了已流失、违约或注销的客户。
  4. 采样偏差(Sampling Bias): 为平衡正负样本比例,对数据进行过采样或欠采样,改变了原始分布。
  5. 渠道偏差(Channel Bias): 不同获客渠道的客群质量差异显著,但训练数据仅覆盖部分渠道。
  6. 标签偏差(Label Bias): 标签定义不一致或存在延迟,如“逾期30天”与“逾期90天”的坏账定义差异。
样本偏差六大来源 样本偏差来源 选择偏差 仅含审批通过样本 时间偏差 经济周期不一致 幸存者偏差 忽略流失/违约客户 采样偏差 过采样/欠采样改变分布 渠道偏差 客群质量渠道间差异 标签偏差 标签定义不一致/延迟 💡 识别偏差来源是特征工程的第一步,也是最重要的一步
⚠ 常见误区: 很多从业者认为“样本量足够大就能消除偏差”。实际上,样本量大但偏差方向一致时,只会放大错误。例如,100万条历史审批通过样本,依然无法代表被拒绝的客群。

1.4 偏差影响量化示例

以下代码展示如何通过 PSI(群体稳定性指标)量化样本偏差:

import numpy as np

def calculate_psi(expected, actual, bins=10):
    """计算群体稳定性指标 PSI"""
    # 分箱
    expected_bins = np.histogram(expected, bins=bins)[0] / len(expected)
    actual_bins = np.histogram(actual, bins=bins)[0] / len(actual)
    
    # 处理零值
    expected_bins = np.clip(expected_bins, 0.0001, 1)
    actual_bins = np.clip(actual_bins, 0.0001, 1)
    
    # 计算 PSI
    psi = np.sum((actual_bins - expected_bins) * np.log(actual_bins / expected_bins))
    return psi

# 示例:训练集与真实分布偏差
train_score = np.random.normal(0.6, 0.1, 10000)  # 训练集评分分布
real_score = np.random.normal(0.45, 0.15, 10000) # 真实分布

psi_value = calculate_psi(train_score, real_score)
print(f"PSI = {psi_value:.4f}")
# PSI > 0.25 表示显著偏移,需进行偏差校正
PSI 判断标准: PSI < 0.1 表示无显著偏移;0.1 ≤ PSI ≤ 0.25 表示轻度偏移,需监控;PSI > 0.25 表示严重偏移,必须进行样本偏差校正。