2. PSI指标基础:群体稳定性指标

群体稳定性指标(Population Stability Index,PSI)是反洗钱模型监控中最核心的量化指标之一。它用于衡量模型评分或特征分布在两个不同时间点(或两个不同样本集)之间的偏移程度。当PSI超过阈值时,意味着模型所依赖的数据分布发生了显著变化,模型可能已不再适用于当前环境,需要及时告警和调整。

2.1 PSI的定义

PSI通过比较两个概率分布(或分数分布)的差异来量化群体稳定性。在反洗钱场景中,通常比较的是:

  • 期望分布(Expected):模型训练集或基准期的评分/特征分布
  • 实际分布(Actual):当前监控期的评分/特征分布

PSI值越大,说明两个分布的差异越大,群体稳定性越差。业界通用的PSI阈值如下:

PSI范围 稳定性判断 建议操作
PSI < 0.1 无显著偏移 模型稳定,无需干预
0.1 ≤ PSI < 0.25 轻度偏移 需关注,排查可能的原因
PSI ≥ 0.25 严重偏移 立即告警,需重新训练或调整模型
💡 提示: 在反洗钱监管合规中,PSI监控是模型风险管理(Model Risk Management, MRM)的必备环节。监管机构通常要求金融机构定期提交模型稳定性报告,PSI是其中的关键指标。

2.2 PSI的数学公式与计算逻辑

PSI的计算基于信息论中的KL散度(Kullback-Leibler divergence),其数学公式如下:

PSI = Σ (Actual_i - Expected_i) × ln(Actual_i / Expected_i)

其中:
- i 表示第 i 个分箱(bin)
- Actual_i  = 实际分布中第 i 个分箱的样本占比
- Expected_i = 期望分布中第 i 个分箱的样本占比
- ln 为自然对数

计算PSI需要先将连续型评分或特征进行分箱(Binning)处理。常用的分箱方法包括等距分箱、等频分箱和自定义分箱。以下是PSI计算的完整步骤:

  1. 确定分箱边界:基于期望分布,将数据划分为 k 个区间(通常 k=10 或 k=20)
  2. 计算期望占比:统计期望分布中每个分箱的样本数,除以总样本数得到 Expected_i
  3. 计算实际占比:使用相同的分箱边界,统计实际分布中每个分箱的样本数,除以总样本数得到 Actual_i
  4. 计算每个分箱的贡献值:(Actual_i - Expected_i) × ln(Actual_i / Expected_i)
  5. 求和:将所有分箱的贡献值相加,得到最终的PSI值
⚠️ 避坑提醒: 当某个分箱的 Expected_i 或 Actual_i 为 0 时,ln(0) 无定义。实际计算中,通常对占比为 0 的分箱做平滑处理(如加一个极小值 0.0001),或直接跳过该分箱。建议在分箱时确保每个分箱都有足够的样本量。

以下是一个PSI计算的Python代码示例:

import numpy as np

def calculate_psi(expected, actual, bins=10):
    """
    计算群体稳定性指标(PSI)
    
    参数:
        expected: 期望分布(基准期)的评分数组
        actual: 实际分布(监控期)的评分数组
        bins: 分箱数量,默认10
    
    返回:
        psi: PSI值
    """
    # 基于期望分布确定分箱边界
    bin_edges = np.percentile(expected, np.linspace(0, 100, bins + 1))
    
    # 计算期望分布的分箱占比
    expected_counts, _ = np.histogram(expected, bins=bin_edges)
    expected_pct = expected_counts / len(expected)
    
    # 计算实际分布的分箱占比(使用相同边界)
    actual_counts, _ = np.histogram(actual, bins=bin_edges)
    actual_pct = actual_counts / len(actual)
    
    # 平滑处理:避免除以0或取ln(0)
    expected_pct = np.clip(expected_pct, 0.0001, 1)
    actual_pct = np.clip(actual_pct, 0.0001, 1)
    
    # 计算PSI
    psi = np.sum((actual_pct - expected_pct) * np.log(actual_pct / expected_pct))
    
    return psi

# 示例用法
expected_scores = np.random.normal(0.5, 0.1, 10000)
actual_scores = np.random.normal(0.55, 0.12, 10000)
psi_value = calculate_psi(expected_scores, actual_scores)
print(f"PSI = {psi_value:.4f}")

2.3 PSI的统计学意义

从统计学角度看,PSI衡量的是两个概率分布之间的差异程度。它与以下几个统计概念密切相关:

统计概念 与PSI的关系 说明
KL散度 PSI = KL(P||Q) + KL(Q||P) PSI是KL散度的对称化版本,衡量两个分布的双向差异
卡方检验 PSI ≈ χ² / (2N) 当分布差异较小时,PSI与卡方统计量近似线性相关
JS散度 JS散度 = PSI / 2 JS散度是PSI的归一化版本,取值范围为[0, 1]
交叉熵 PSI = 交叉熵 - 信息熵 PSI反映了实际分布相对于期望分布的额外不确定性

在反洗钱模型监控中,PSI的统计学意义体现在以下三个方面:

  • 分布漂移检测:PSI能够敏感地捕捉到评分分布的整体偏移,包括均值漂移、方差变化和形状变化
  • 模型失效预警:当PSI超过阈值时,说明模型训练时的数据分布与当前实际数据分布不一致,模型预测能力可能下降
  • 业务环境变化指示:PSI升高往往对应着业务环境的变化,如监管政策调整、客户群体变化、数据采集方式变更等
📌 关键理解: PSI不是衡量模型预测准确性的指标,而是衡量模型输入分布稳定性的指标。一个稳定的模型不一定准确,但一个不稳定的模型几乎必然不准确。在反洗钱场景中,PSI告警是模型风险管理的“第一道防线”。
PSI计算流程与统计学意义 数据准备 等频/等距分箱 计算期望/实际占比 PSI = Σ (Actual_i - Expected_i) × ln(Actual_i / Expected_i) 每个分箱贡献值求和 阈值判断:PSI < 0.1 / 0.1~0.25 / ≥ 0.25 统计学意义 KL散度的对称化 → 分布漂移检测 → 模型失效预警 → 业务环境变化指示 与卡方检验、JS散度、交叉熵等统计量密切相关

在实际的反洗钱模型看板中,PSI通常与特征重要性、模型性能指标(如AUC、KS)等一起展示,形成完整的模型监控体系。当PSI告警触发时,数据分析师需要结合业务背景,深入分析导致分布漂移的根本原因,并采取相应的模型维护措施。