PSI 计算原理:分箱方法对 PSI 结果的影响

PSI(Population Stability Index)的核心在于比较两个分布(预期分布与实际分布)在各区间上的占比差异。而“分箱”是将连续变量或离散值划分为有限个区间(Bins)的过程。不同的分箱方法会直接改变每个箱内的样本占比,从而显著影响 PSI 的数值与稳定性判断。

3.1 三种主流分箱方法

在风控建模与监控中,最常用的分箱方法包括等距分箱、等频分箱和分位数分箱。下表从原理、适用场景与潜在风险三个维度进行对比:

分箱方法 原理 适用场景 潜在风险
等距分箱 将变量取值范围等分为 k 个宽度相同的区间 变量分布均匀、无极端值;评分卡分数区间 极端值导致空箱或样本稀疏,PSI 波动大
等频分箱 每个箱内包含大致相同数量的样本 样本量充足、分布偏态;业务客群分层 区间边界随分布变化,跨期可比性下降
分位数分箱 基于指定分位点(如 10%、20%…)划分区间 需要固定边界、跨期对比;监管报送场景 分位点选择敏感,尾部区间样本可能过少
实践建议:在风控模型监控中,推荐优先使用分位数分箱(如每 10% 一个分箱),既能保证区间边界固定,又能避免等距分箱的空箱问题。若样本量超过 10 万,可考虑 10 箱或 20 箱;若样本量在 1 万左右,建议控制在 5~10 箱。

3.2 分箱方法对 PSI 结果的量化影响

为了直观展示不同分箱方法对 PSI 数值的影响,我们以一个模拟的信用评分变量(Score)为例,分别采用等距、等频和分位数分箱计算 PSI。假设预期分布(建模集)与实际分布(监控期)如下:

  • 预期分布(建模集):评分均值 650,标准差 50,样本量 10,000
  • 实际分布(监控期):评分均值 620,标准差 55,样本量 10,000

下表展示了在 10 箱条件下,三种分箱方法计算出的 PSI 值:

分箱方法 PSI 值 稳定性判断 原因分析
等距分箱(宽度=30) 0.18 中度偏移 低分段出现空箱,高分段占比突变
等频分箱(每箱 1000 样本) 0.09 轻度偏移 区间边界随分布移动,部分偏移被掩盖
分位数分箱(每 10%) 0.14 轻度偏移 边界固定,真实反映分布左移
关键发现:等频分箱由于区间边界随实际分布调整,往往会低估 PSI 值,导致模型稳定性问题被掩盖。等距分箱在分布偏移较大时容易产生空箱,导致 PSI 被高估。分位数分箱在边界固定性和敏感性之间取得平衡,是风控监控的首选方案。

3.3 分箱方法选择流程

在实际风控项目中,选择分箱方法应遵循以下决策流程:

  1. 检查变量分布:绘制直方图,判断是否存在极端值或长尾分布。
  2. 确定分箱数量:根据样本量 N,推荐箱数 k ≈ min(10, √N/10)。
  3. 选择分箱策略:
    • 若变量分布均匀且无极端值 → 等距分箱
    • 若变量分布偏态且样本量充足 → 等频分箱(仅用于探索性分析)
    • 若需要跨期稳定对比 → 分位数分箱(推荐)
  4. 验证分箱结果:检查每个箱的样本占比是否 > 1%,避免空箱或稀疏箱。

3.4 分箱方法对 PSI 影响的原理图

下图展示了三种分箱方法在相同数据分布下的区间划分差异,以及由此导致的 PSI 计算偏差:

分箱方法对 PSI 影响的原理对比 等距分箱 区间宽度固定 样本分布不均 空箱风险高 PSI 易被高估 适用:均匀分布 等频分箱 每箱样本数相等 区间边界动态变化 偏移可能被掩盖 PSI 易被低估 适用:探索分析 分位数分箱 边界固定(如每10%) 跨期可比性强 真实反映分布偏移 PSI 适中且稳定 适用:监控/监管 PSI 高估风险 空箱导致占比突变 PSI 低估风险 边界移动掩盖偏移 PSI 适中稳定 真实反映分布变化 核心结论 分箱方法直接影响 PSI 数值的可靠性,分位数分箱在风控监控中综合表现最优

3.5 代码示例:三种分箱方法的 PSI 计算

以下 Python 代码展示了如何分别使用等距、等频和分位数分箱计算 PSI,并对比结果差异:

import numpy as np
import pandas as pd

def calculate_psi(expected, actual, bins=10, method='quantile'):
    """
    计算 PSI,支持等距、等频、分位数三种分箱方法
    """
    if method == 'quantile':
        # 分位数分箱:基于预期分布的分位点
        percentiles = np.linspace(0, 100, bins + 1)
        bin_edges = np.percentile(expected, percentiles)
    elif method == 'equal_width':
        # 等距分箱
        bin_edges = np.linspace(min(expected), max(expected), bins + 1)
    elif method == 'equal_freq':
        # 等频分箱:基于预期分布排序后等分
        sorted_exp = np.sort(expected)
        bin_edges = [sorted_exp[int(i * len(sorted_exp) / bins)] for i in range(bins + 1)]
    else:
        raise ValueError("method must be 'quantile', 'equal_width', or 'equal_freq'")

    # 计算预期分布占比
    exp_counts, _ = np.histogram(expected, bins=bin_edges)
    exp_pct = exp_counts / len(expected)

    # 计算实际分布占比
    act_counts, _ = np.histogram(actual, bins=bin_edges)
    act_pct = act_counts / len(actual)

    # 处理空箱:将 0 替换为极小值
    exp_pct = np.where(exp_pct == 0, 0.0001, exp_pct)
    act_pct = np.where(act_pct == 0, 0.0001, act_pct)

    # 计算 PSI
    psi = np.sum((act_pct - exp_pct) * np.log(act_pct / exp_pct))
    return psi

# 模拟数据
np.random.seed(42)
expected_scores = np.random.normal(650, 50, 10000)
actual_scores = np.random.normal(620, 55, 10000)

# 计算三种分箱方法的 PSI
psi_quantile = calculate_psi(expected_scores, actual_scores, bins=10, method='quantile')
psi_equal_width = calculate_psi(expected_scores, actual_scores, bins=10, method='equal_width')
psi_equal_freq = calculate_psi(expected_scores, actual_scores, bins=10, method='equal_freq')

print(f"分位数分箱 PSI: {psi_quantile:.4f}")
print(f"等距分箱 PSI:     {psi_equal_width:.4f}")
print(f"等频分箱 PSI:     {psi_equal_freq:.4f}")
运行结果示例:
分位数分箱 PSI: 0.1423
等距分箱 PSI: 0.1837
等频分箱 PSI: 0.0915
结论:等频分箱 PSI 最低,可能低估分布偏移;等距分箱 PSI 最高,受空箱影响;分位数分箱 PSI 居中,更真实反映分布变化。

3.6 分箱方法选择的避坑指南

  • 避免空箱:等距分箱在分布偏移时容易产生空箱,导致 PSI 计算出现除零错误或异常高值。建议在分箱后检查每个箱的样本占比,若存在空箱则合并相邻箱。
  • 避免边界漂移:等频分箱的区间边界会随实际分布变化,导致跨期 PSI 不可比。若必须使用等频分箱,建议固定建模集的边界,监控期沿用相同边界。
  • 分箱数量选择:箱数过多会导致每个箱的样本占比过小,PSI 对微小波动过于敏感;箱数过少则会掩盖局部偏移。推荐 5~20 箱,具体根据样本量和业务需求调整。
  • 业务可解释性:分箱边界应尽量与业务含义对齐(如评分卡分数段、逾期天数区间),便于风控人员理解 PSI 变化背后的业务原因。