【风控】稳定性指标PSI

一、PSI(Population Stability Index)的定义与原理

  1. 概念

    • PSI 用于衡量"预期分布"(通常取训练集或基准样本)与"实际分布"(验证集、线上新数据等)在各分箱(score bin)上的偏移程度。
    • 数值越小表示两者分布越接近,模型或特征越稳定;数值越大则提示分布发生了显著漂移。
  2. 计算公式
    P S I = ∑ i = 1 K ( p i − q i )   ln ⁡ ( p i q i ) \mathrm{PSI} = \sum_{i=1}^K \bigl(p_i - q_i\bigr)\,\ln\Bigl(\tfrac{p_i}{q_i}\Bigr) PSI=i=1∑K(pi−qi)ln(qipi)

    其中:

    • p i p_i pi:第 i i i个分箱中"实际分布"占比
    • q i q_i qi:第 i i i个分箱中"预期分布"占比
    • K K K:分箱总数(常见10~20个)
  3. 分箱策略

    • 等频分箱:每箱样本数相同,能保证每箱都有统计意义,适合数据量稳定的场景。
    • 等距分箱:每箱取值区间相同,能直观反映分数分布形态。
    • 自定义分箱:结合业务经验对重要阈值(如决策边界)进行细化分箱。
    • 注意 :极端值或零占比会导致 ln ⁡ ( p i / q i ) \ln(p_i/q_i) ln(pi/qi)趋于无穷,可在计算前对 p i p_i pi, q i q_i qi 做小量平滑(如加 ϵ = 1 0 − 6 \epsilon=10^{-6} ϵ=10−6)。
  4. 常用阈值

    • PSI < 0.10:分布基本无漂移,模型/变量稳定
    • 0.10 ≤ PSI < 0.25:存在中等漂移,需要关注
    • PSI ≥ 0.25:分布显著漂移,建议排查并重新建模

二、PSI计算流程

确定比较对象

  • 明确两个需要比较的样本分布:
    • 期望分布(expected):通常是模型训练集样本;
    • 实际分布(actual) :通常是验证集、线上样本或跨时间段样本。
      分箱处理(以训练集为基准)
  • 将变量的取值区间划分为多个"箱"(bins):
    • 连续变量推荐使用等频或等距分箱;
    • 离散变量可以按照原始类别,必要时合并低频类别;
    • 分箱数量建议设为 10 或 20,避免过粗或过细。
      统计每个分箱的占比
  • 在每个分箱中,分别统计 expected 和 actual 样本的数量;
  • 转化为百分比(即每个分箱中样本数除以总样本数)形成两个分布。
    计算每个分箱的差异值
  • 对于每个分箱,计算 expected 和 actual 之间的占比差异;
  • 利用差异程度与比值变化评估每个分箱的"变化强度"。
    求和得到总体 PSI 值
  • 将所有分箱的差异值汇总,得到最终 PSI 指标。
    判读 PSI 结果
  • 小于 0.1:分布基本一致,变量稳定;
  • 0.1 ~ 0.25:轻度偏移,可关注;
  • 大于 0.25:显著偏移,建议替换或重新评估。

三、KL 散度(Kullback--Leibler Divergence)的定义与原理

  1. Shannon 熵
    对离散分布 P P P: H ( P ) = − ∑ x P ( x )   ln ⁡ P ( x ) H(P) = -\sum_x P(x)\,\ln P(x) H(P)=−x∑P(x)lnP(x)
  2. KL 散度 D K L ( P   ∥   Q ) = ∑ x P ( x )   ln ⁡ P ( x ) Q ( x ) D_{\mathrm{KL}}(P \,\|\, Q) = \sum_x P(x)\,\ln\frac{P(x)}{Q(x)} DKL(P∥Q)=x∑P(x)lnQ(x)P(x)
    • 物理含义 :用分布 Q Q Q来近似真实分布 P P P,需要额外的信息量(Nats)。
    • 性质
      1. 非负性: D K L ( P ∥ Q ) ≥ 0 D_{\mathrm{KL}}(P\|Q)\ge0 DKL(P∥Q)≥0,当且仅当P=QP=Q时为0;
      2. 非对称性: D K L ( P ∥ Q ) ≠ D K L ( Q ∥ P ) D_{\mathrm{KL}}(P\|Q) \neq D_{\mathrm{KL}}(Q\|P) DKL(P∥Q)=DKL(Q∥P)。

四、KL 散度与 PSI 之间的关系

将 PSI 公式展开,可分解为两部分:
P S I = ∑ i ( p i − q i ) ln ⁡ p i q i = ∑ i p i ln ⁡ p i q i    −    ∑ i q i ln ⁡ p i q i = D K L ( P ∥ Q )    +    D K L ( Q ∥ P ) \begin{aligned} \mathrm{PSI} &= \sum_i (p_i - q_i)\ln\frac{p_i}{q_i} \\ &= \sum_i p_i\ln\frac{p_i}{q_i} \;-\; \sum_i q_i\ln\frac{p_i}{q_i} \\ &= D_{\mathrm{KL}}(P\|Q) \;+\; D_{\mathrm{KL}}(Q\|P) \end{aligned} PSI=i∑(pi−qi)lnqipi=i∑pilnqipi−i∑qilnqipi=DKL(P∥Q)+DKL(Q∥P)

  • 解读:PSI=双向 KL 散度之和,是一种对称化的分布差异度量。
  • 优势 :相比单向的 KL 散度,PSI 同时考虑了 P → Q P\to Q P→Q和 Q → P Q\to P Q→P两个方向的信息损失,更为全面。

五、PSI 在实际风控业务中的应用

  1. 特征筛选

    • 以训练期(INS)样本分布为基准,按月/周计算新样本(OOT/OOS)上各特征的 PSI。
    • 剔除 PSI 较高(>0.25)的特征,确保入模变量的长期稳定。
  2. 模型监控

    • 模型上线后,持续按时间窗口计算整体分数 PSI 曲线。
    • 当 PSI 突然跳升时,需立刻排查:
      • 是否样本群体发生变化?
      • 是否数据源采集出异常?
      • 是否外部政策或市场波动影响?
  3. 多层次评估

    • 时间粒度:可分月、周、日。
    • 层次粒度:贷款层面、申请层面、核心人群分层。
    • 联合分析:结合 EDD(探索性数据分析)中的分位数对比,判断分布偏移的方向。
  4. 最佳实践

    • 平滑处理:对零值、极小占比做加 ϵ \epsilon ϵ避免数值问题。
    • 动态阈值:可结合业务接受度灵活调整 PSI 报警线。
    • 可视化:制作 PSI 报表(折线图 + 报警带)便于一目了然。

六、PSI 的 Python 计算示例

python 复制代码
import numpy as np
import pandas as pd

def calculate_psi(expected, actual, bins=10, eps=1e-6):
    """
    计算 Population Stability Index(PSI)。
    
    参数:
        expected: array-like, 基准样本的一维数值 array
        actual:   array-like, 验证样本的一维数值 array
        bins:     int or sequence, 分箱数或分箱边界
        eps:      float, 用于平滑避免除零/对数问题
    
    返回:
        psi_value: float, PSI 总值
        psi_table: DataFrame, 各箱的 q, p, psi_i
    """
    # 1. 生成分箱:使用训练样本的分位数
    if isinstance(bins, int):
        quantiles = np.linspace(0, 1, bins + 1)
        bin_edges = np.unique(np.quantile(expected, quantiles))
    else:
        bin_edges = np.array(bins)
    
    # 2. 计算各箱占比
    e_counts, _ = np.histogram(expected, bins=bin_edges)
    a_counts, _ = np.histogram(actual,   bins=bin_edges)
    q = e_counts / e_counts.sum()
    p = a_counts / a_counts.sum()
    
    # 3. 平滑
    q = np.where(q == 0, eps, q)
    p = np.where(p == 0, eps, p)
    
    # 4. 计算每箱 psi,以及总 psi
    psi_i = (p - q) * np.log(p / q)
    psi_value = np.sum(psi_i)
    
    # 5. 构造结果表格
    psi_table = pd.DataFrame({
        'bin_left' : bin_edges[:-1],
        'bin_right': bin_edges[1:],
        'exp_pct'  : q,
        'act_pct'  : p,
        'psi_i'    : psi_i
    })
    return psi_value, psi_table

# 示例用法
if __name__ == '__main__':
    # 假设 exp_scores, act_scores 为两个一维 numpy 数组
    exp_scores = np.random.normal(loc=0.5, scale=0.1, size=10000)
    act_scores = np.random.normal(loc=0.52, scale=0.12, size=10000)
    
    psi_val, psi_df = calculate_psi(exp_scores, act_scores, bins=10)
    print(f"总体 PSI = {psi_val:.4f}")
    print(psi_df)

七、疑问

为什么KL 散度可以描述分布稳定性?

KL 散度(Kullback--Leibler divergence)之所以能够用来描述分布的"稳定性",主要基于以下几点:
非负性与零点条件 D K L ( P ∥ Q ) = ∑ x P ( x )   ln ⁡ P ( x ) Q ( x ) D_{\mathrm{KL}}(P\|Q) = \sum_x P(x)\,\ln\frac{P(x)}{Q(x)} DKL(P∥Q)=x∑P(x)lnQ(x)P(x)

对任意两离散分布 P , Q P,Q P,Q,有

  • D K L ( P ∥ Q ) ≥ 0 D_{\mathrm{KL}}(P\|Q)\ge0 DKL(P∥Q)≥0,
  • 当且仅当 P = Q P=Q P=Q时, D K L ( P ∥ Q ) = 0 D_{\mathrm{KL}}(P\|Q)=0 DKL(P∥Q)=0。
    这就保证了:两分布完全一致时,KL 散度为零;分布越不一致,KL 散度越大

信息增益的度量

从信息论角度,KL散度可以理解为"如果真实分布是 P P P,却用 Q Q Q去描述,需要额外多少信息量 N a t s Nats Nats才能不丢失信息"。

  • 当用基准(训练)分布 Q Q Q去预测或编码新数据,其实新数据的真实分布是 P P P;
  • KL 散度正是衡量这种"模型失配"导致的平均额外信息量或意外程度。
    如果分布没有漂移(即在线数据与训练数据分布相同),这种"失配信息"就为零;如果漂移严重,则额外信息量大,KL 散度也大。

PSI描述稳定性的直观说明?

  • PSI 会把"新数据占比 -- 训练数据占比"算出来,再乘以一个"惩罚系数"(就是 ln ⁡ ( 新占比 旧占比 ) \ln(\tfrac{\text{新占比}}{\text{旧占比}}) ln(旧占比新占比))。
  • 这个惩罚系数越大,表示"在这个区间里人头变化的相对程度"越大,我们就更要"给分布漂移一个高分"------也就是 PSI 的那一部分越大。
  • 最后把所有区间的"差异分"加起来,就得到一个总分:PSI。
  • 分数越低,说明新旧两批样本在所有拼图块里分布得越来越一样,越稳定;分数越高,就代表某些区间出现了明显偏移,模型或特征可能不再适用了。
相关推荐
深度之眼12 分钟前
2025时间序列都有哪些创新点可做——总结篇
人工智能·深度学习·机器学习·时间序列
胡耀超15 分钟前
附1:深度解读:《金融数据安全 数据安全分级指南》——数据分类的艺术专栏系列
大数据·金融·数据治理·生命周期·数据分类·政策法规
CODE_RabbitV20 分钟前
【深度强化学习 DRL 快速实践】近端策略优化 (PPO)
算法
晓数29 分钟前
【硬核干货】JetBrains AI Assistant 干货笔记
人工智能·笔记·jetbrains·ai assistant
jndingxin33 分钟前
OpenCV 图形API(60)颜色空间转换-----将图像从 YUV 色彩空间转换为 RGB 色彩空间函数YUV2RGB()
人工智能·opencv·计算机视觉
Sherlock Ma1 小时前
PDFMathTranslate:基于LLM的PDF文档翻译及双语对照的工具【使用教程】
人工智能·pytorch·语言模型·pdf·大模型·机器翻译·deepseek
知舟不叙1 小时前
OpenCV中的SIFT特征提取
人工智能·opencv·计算机视觉
Wendy_robot1 小时前
【滑动窗口+哈希表/数组记录】Leetcode 438. 找到字符串中所有字母异位词
c++·算法·leetcode
程序员-King.1 小时前
day49—双指针+贪心—验证回文串(LeetCode-680)
算法·leetcode·贪心算法·双指针
kadog1 小时前
PubMed PDF下载 cloudpmc-viewer-pow逆向
前端·javascript·人工智能·爬虫·pdf