3. PSI指标详解:群体稳定性指标的数学原理、计算公式、分箱策略与业务解读

群体稳定性指标(Population Stability Index, PSI)是风控模型监控中最核心的量化指标之一。它衡量的是模型评分或关键特征在两个时间窗口(通常为建模样本 vs. 当前样本,或上一监控周期 vs. 当前周期)之间的分布偏移程度。PSI 值越大,说明群体分布变化越剧烈,模型失效或业务环境发生结构性改变的风险越高。

3.1 数学原理与计算公式

PSI 的数学基础是信息论中的 Kullback-Leibler 散度(相对熵)的对称化变体。它通过比较两个分布在各分箱上的占比差异,量化整体偏移幅度。

标准计算公式:

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

其中:
- Expected_i = 基准分布(如建模样本)在第 i 个分箱中的占比
- Actual_i   = 当前分布(如实时交易样本)在第 i 个分箱中的占比
- i = 1, 2, ..., N(N 为分箱总数)

计算步骤分解:

  1. 分箱:将模型评分或特征值域划分为 N 个区间(通常 10~20 箱)。
  2. 统计占比:分别计算基准分布和当前分布落在每个箱内的样本比例。
  3. 计算单箱贡献:对每个箱,计算 (Actual% - Expected%) × ln(Actual% / Expected%)。
  4. 求和:将所有箱的贡献值相加,得到最终 PSI 值。
⚠ 零值处理:当某个分箱中 Actual% 或 Expected% 为 0 时,ln(0) 无定义。实际工程中通常采用两种方式:① 将 0 替换为一个极小正数(如 0.0001);② 合并空箱到相邻箱,确保每个箱都有非零占比。

3.2 分箱策略详解

分箱方式直接影响 PSI 计算的稳定性和敏感性。不同的分箱策略适用于不同的业务场景和数据类型。

分箱策略 方法描述 适用场景 优点 缺点
等距分箱 将值域按固定宽度均匀切分 评分卡分数(如 300~850 分) 实现简单,箱边界固定,便于跨周期对比 数据分布不均时可能出现空箱或样本稀疏箱
等频分箱 按样本量均分,每箱包含相同数量的样本 特征分布偏态严重时 避免空箱,每箱统计量稳定 箱边界随样本分布变化,跨周期对比时边界不一致
最优分箱 基于决策树或卡方检验自动寻找最佳切分点 特征与目标变量关系复杂时 信息损失最小,分箱结果可解释性强 计算开销大,依赖目标变量,不适合纯分布监控
业务规则分箱 根据业务经验或监管要求定义箱边界 监管报送、风险等级划分 业务含义清晰,便于合规解释 可能忽略数据内在分布特征
推荐实践:在实时交易风控巡检中,建议对模型评分采用等距分箱(如每 50 分一箱),对连续型特征采用等频分箱(如 10 箱),对离散型特征按业务规则分箱。分箱数量一般控制在 10~20 箱,过少会掩盖局部偏移,过多则引入噪声。

3.3 PSI 阈值与业务解读

PSI 的数值大小直接对应群体稳定性的不同等级。以下是业界通用的解读标准:

PSI 范围 稳定性等级 业务含义 建议动作
PSI < 0.1 稳定 群体分布无显著变化,模型表现可预期 正常监控,无需干预
0.1 ≤ PSI < 0.25 轻度偏移 群体分布出现一定变化,需关注趋势 增加监控频率,排查业务或数据源变化
PSI ≥ 0.25 严重偏移 群体分布发生结构性改变,模型可能失效 立即触发告警,启动模型重训或业务规则调整
阈值不是绝对的:上述阈值是经验值,实际应用中应根据业务风险容忍度调整。例如,在反欺诈场景中,PSI > 0.15 就可能需要立即响应;而在用户画像分析场景中,PSI < 0.3 可能仍可接受。建议结合历史数据为每个监控指标建立个性化的基线阈值。

3.4 PSI 计算流程与架构

下图展示了实时交易风控巡检中 PSI 计算的完整数据流与架构设计:

实时交易 PSI 监控架构图 实时交易流水 Kafka / Flink 实时接入 基准分布快照 HDFS / Hive 离线存储 特征工程 评分 / 特征提取 分箱计算 等距 / 等频 / 业务规则分箱 PSI 指标计算 Σ (Actual% - Expected%) × ln(Actual% / Expected%) 告警与巡检输出 PSI > 0.25 → 触发告警 / 写入巡检报表 关键配置 分箱数: 10~20 阈值: 0.1 / 0.25

3.5 PSI 与 KS、Gini 的对比

在风控模型监控体系中,PSI 常与区分度指标(KS、Gini)配合使用。下表清晰展示了三者的核心差异:

维度 PSI(群体稳定性) KS(区分度) Gini(排序能力)
监控对象 模型评分或特征的分布偏移 好坏样本的累计分布差异 模型对好坏样本的排序能力
计算基础 两个时间窗口的分布对比 同一时间窗口的好坏样本对比 ROC 曲线下面积
业务含义 群体是否发生结构性变化 模型能否有效区分好坏客户 模型排序的准确度
触发告警 PSI > 0.25 KS 下降 > 20% Gini 下降 > 15%
监控频率 每日 / 每小时 每周 / 每日 每周 / 每月
最佳实践:在实时交易风控巡检中,建议将 PSI 作为前置预警指标,KS 和 Gini 作为后验验证指标。当 PSI 触发轻度偏移时,立即排查业务原因;若 PSI 持续恶化,再结合 KS/Gini 判断模型是否需要重训。

3.6 PSI 在 SQL 中的实现示例

以下 SQL 代码展示了如何在 Hive/Spark SQL 中实现 PSI 计算,适用于离线批量巡检场景:

-- 步骤1:对基准分布和当前分布分别进行等频分箱并统计占比
WITH base_dist AS (
  SELECT
    CASE
      WHEN score < 300 THEN '0-300'
      WHEN score < 350 THEN '300-350'
      WHEN score < 400 THEN '350-400'
      WHEN score < 450 THEN '400-450'
      WHEN score < 500 THEN '450-500'
      WHEN score < 550 THEN '500-550'
      WHEN score < 600 THEN '550-600'
      WHEN score < 650 THEN '600-650'
      WHEN score < 700 THEN '650-700'
      ELSE '700+'
    END AS score_bin,
    COUNT(*) AS base_cnt
  FROM model_scores_base
  GROUP BY 1
),
current_dist AS (
  SELECT
    CASE
      WHEN score < 300 THEN '0-300'
      WHEN score < 350 THEN '300-350'
      WHEN score < 400 THEN '350-400'
      WHEN score < 450 THEN '400-450'
      WHEN score < 500 THEN '450-500'
      WHEN score < 550 THEN '500-550'
      WHEN score < 600 THEN '550-600'
      WHEN score < 650 THEN '600-650'
      WHEN score < 700 THEN '650-700'
      ELSE '700+'
    END AS score_bin,
    COUNT(*) AS current_cnt
  FROM model_scores_current
  WHERE dt = '2025-03-01'
  GROUP BY 1
),
-- 步骤2:计算各箱占比和 PSI 贡献
psi_calc AS (
  SELECT
    b.score_bin,
    b.base_cnt,
    c.current_cnt,
    b.base_cnt / SUM(b.base_cnt) OVER() AS base_pct,
    c.current_cnt / SUM(c.current_cnt) OVER() AS current_pct
  FROM base_dist b
  FULL OUTER JOIN current_dist c ON b.score_bin = c.score_bin
)
-- 步骤3:汇总 PSI 值
SELECT
  ROUND(SUM(
    (current_pct - base_pct) * LN(current_pct / base_pct)
  ), 6) AS psi_value
FROM psi_calc
WHERE base_pct > 0 AND current_pct > 0;  -- 过滤空箱
Spark 优化提示:在 PySpark 中,可以使用 approxQuantile() 函数动态计算等频分箱边界,避免硬编码。对于实时流计算(Structured Streaming),建议将 PSI 计算封装为 foreachBatch 中的微批处理,每 5 分钟输出一次当前 PSI 值到监控看板。