PSI 数学原理与计算公式

群体稳定性指标(Population Stability Index, PSI)是风控规则引擎中衡量模型或评分分布随时间变化的核心量化工具。本章从数学推导、分箱方法到实际计算步骤,完整拆解 PSI 的计算逻辑。

2.1 PSI 的数学推导

PSI 基于信息论中的 KL 散度(Kullback-Leibler divergence) 对称化改造而来。KL 散度衡量两个概率分布 P 和 Q 之间的非对称差异:

KL(P || Q) = Σ p_i * ln(p_i / q_i)

由于 KL 散度不满足对称性(KL(P||Q) ≠ KL(Q||P)),PSI 采用对称化形式:

PSI = Σ (p_i - q_i) * ln(p_i / q_i)

其中:

  • p_i:当前评分分布在第 i 个分箱中的样本占比
  • q_i:基准评分分布在第 i 个分箱中的样本占比
  • ln(p_i / q_i):自然对数下的分布差异权重

当 p_i 与 q_i 完全一致时,PSI = 0;差异越大,PSI 值越高。

工程要点:实际计算中,当 q_i = 0 时 ln(p_i / q_i) 无定义。建议对空箱做平滑处理(如加极小值 1e-6),或强制将空箱与相邻箱合并。

2.2 分箱方法

分箱是 PSI 计算的前置步骤,直接影响指标敏感度。常用分箱方法对比如下:

分箱方法 原理 适用场景 注意事项
等距分箱 按评分区间等宽划分(如每 50 分一箱) 评分分布均匀、业务含义明确 极端值可能导致空箱
等频分箱 按样本量等比例划分(每箱约 10% 样本) 分布偏态严重、长尾数据 基准与当前分箱边界需保持一致
业务分箱 按风控策略阈值划分(如 0-300、300-600、600-900) 规则引擎直接使用评分卡分段 需定期验证业务分段合理性
聚类分箱 基于 K-Means 或决策树自动寻找最优切点 数据驱动、无先验分段 计算成本高,可解释性弱
常见陷阱:分箱数量过少(如 <5)会掩盖局部漂移;分箱过多(如 >20)会导致噪声放大。推荐风控场景使用 10-15 箱,兼顾敏感度与稳定性。

2.3 实际计算步骤与示例

以下通过一个完整示例演示 PSI 的手工计算过程。假设某风控评分卡输出 0-1000 分,基准分布与当前分布如下:

步骤 1:确定分箱边界(等距分箱,每 200 分一箱)

分箱 区间 基准样本数 当前样本数
1 [0, 200) 500 400
2 [200, 400) 1200 1000
3 [400, 600) 1800 2000
4 [600, 800) 1000 1200
5 [800, 1000] 500 400
合计 5000 5000

步骤 2:计算各箱占比

q1 = 500/5000 = 0.1000    p1 = 400/5000 = 0.0800
q2 = 1200/5000 = 0.2400   p2 = 1000/5000 = 0.2000
q3 = 1800/5000 = 0.3600   p3 = 2000/5000 = 0.4000
q4 = 1000/5000 = 0.2000   p4 = 1200/5000 = 0.2400
q5 = 500/5000 = 0.1000    p5 = 400/5000 = 0.0800

步骤 3:逐箱计算 PSI 分量

箱1: (0.0800 - 0.1000) * ln(0.0800/0.1000) = (-0.0200) * (-0.2231) = 0.00446
箱2: (0.2000 - 0.2400) * ln(0.2000/0.2400) = (-0.0400) * (-0.1823) = 0.00729
箱3: (0.4000 - 0.3600) * ln(0.4000/0.3600) = (0.0400) * (0.1054) = 0.00422
箱4: (0.2400 - 0.2000) * ln(0.2400/0.2000) = (0.0400) * (0.1823) = 0.00729
箱5: (0.0800 - 0.1000) * ln(0.0800/0.1000) = (-0.0200) * (-0.2231) = 0.00446

步骤 4:求和得到 PSI

PSI = 0.00446 + 0.00729 + 0.00422 + 0.00729 + 0.00446 = 0.02772

最终 PSI ≈ 0.028。根据行业经验阈值:

  • PSI < 0.10:分布稳定,无需告警
  • 0.10 ≤ PSI < 0.25:轻度漂移,需关注
  • PSI ≥ 0.25:显著漂移,触发告警

本例 PSI = 0.028,属于稳定范围。

自动化计算提示:生产环境中建议使用 Python 的 scipy.stats.entropy 或自定义向量化函数,避免逐箱循环。以下为参考实现:
import numpy as np

def calculate_psi(expected, actual, bins=10):
    # 等频分箱
    percentiles = np.percentile(expected, np.linspace(0, 100, bins + 1))
    expected_bins = np.histogram(expected, bins=percentiles)[0]
    actual_bins = np.histogram(actual, bins=percentiles)[0]
    
    # 占比 + 平滑
    q = expected_bins / expected_bins.sum() + 1e-6
    p = actual_bins / actual_bins.sum() + 1e-6
    
    # PSI 计算
    psi = np.sum((p - q) * np.log(p / q))
    return psi

2.4 PSI 计算流程可视化

下图完整展示了从原始评分到 PSI 输出的计算链路:

PSI 计算流程 PSI 计算流程 基准评分分布 当前评分分布 等频/等距分箱 计算各箱占比 p_i, q_i 逐箱计算 (p_i - q_i) * ln(p_i / q_i) 求和得到 PSI PSI ≥ 阈值? 是 触发告警 否 分布稳定

2.5 PSI 与 KL 散度的关系

下表总结了 PSI 与 KL 散度的核心差异,帮助理解 PSI 的设计优势:

指标 公式 对称性 取值范围 风控适用性
KL 散度 Σ p_i * ln(p_i / q_i) 非对称 [0, +∞) 不直接使用,方向敏感
PSI Σ (p_i - q_i) * ln(p_i / q_i) 对称 [0, +∞) 直接衡量分布偏移幅度
JS 散度 0.5 * KL(P||M) + 0.5 * KL(Q||M) 对称且有界 [0, ln2] 有界性便于阈值设定
工程建议:PSI 的对称性使其在监控场景中优于 KL 散度——无论基准分布在前还是当前分布在前,计算结果一致。JS 散度虽有界,但风控行业已广泛接受 PSI 的阈值体系,迁移成本较高。

2.6 分箱边界对齐的工程陷阱

实际生产中,基准分布与当前分布的分箱边界必须严格一致。下图展示了边界不对齐导致的 PSI 失真:

分箱边界对齐对比 分箱边界对齐 vs 未对齐 ✅ 边界对齐 0-200 200-400 400-600 600-800 基准与当前使用相同边界 → PSI 准确 ❌ 边界未对齐 0-250 250-500 500-750 750-1000 基准与当前边界不同 → PSI 失真 工程规范 基准分箱边界必须持久化存储,每次计算 PSI 时复用同一组边界 推荐将分箱配置写入规则引擎的元数据表,随模型版本一同管理
生产事故案例:某支付平台因模型升级后未同步分箱边界,导致 PSI 从 0.03 跳变至 0.35,触发误告警。排查发现基准分布使用等距 10 箱,当前分布使用等频 10 箱,边界完全不同。修复后 PSI 回落至 0.04。