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计算的完整步骤:
- 确定分箱边界:基于期望分布,将数据划分为 k 个区间(通常 k=10 或 k=20)
- 计算期望占比:统计期望分布中每个分箱的样本数,除以总样本数得到 Expected_i
- 计算实际占比:使用相同的分箱边界,统计实际分布中每个分箱的样本数,除以总样本数得到 Actual_i
- 计算每个分箱的贡献值:(Actual_i - Expected_i) × ln(Actual_i / Expected_i)
- 求和:将所有分箱的贡献值相加,得到最终的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通常与特征重要性、模型性能指标(如AUC、KS)等一起展示,形成完整的模型监控体系。当PSI告警触发时,数据分析师需要结合业务背景,深入分析导致分布漂移的根本原因,并采取相应的模型维护措施。