因子研究PSI监控与告警优化实战教程 - 第1节
1.1 PSI 的定义与数学原理
群体稳定性指标(Population Stability Index, PSI)是衡量两个样本分布之间差异程度的统计量。在风控因子监控中,PSI 用于量化同一因子在建模样本与监控样本之间的分布偏移程度,是判断因子是否发生“客群漂移”的核心指标。
1.1.1 数学定义
PSI 基于信息论中的 KL 散度(Kullback-Leibler Divergence) 对称化改进而来。其计算公式为:
PSI = Σ (P_i - Q_i) × ln(P_i / Q_i)
其中:
- P_i:监控样本在第 i 个分箱中的占比(实际分布)
- Q_i:建模样本在第 i 个分箱中的占比(基准分布)
- ln(P_i / Q_i):自然对数比率,衡量两个分布在该分箱上的差异
- Σ:对所有分箱求和,得到整体偏移量
💡 直观理解:PSI 可以看作“每个分箱上实际占比与基准占比的差异”乘以“差异的权重(对数比率)”的总和。当两个分布完全一致时,每个分箱的 P_i = Q_i,ln(P_i/Q_i) = 0,PSI = 0。
1.1.2 分箱规则
PSI 计算依赖分箱策略,常见分箱方式如下:
| 分箱方式 | 说明 | 适用场景 |
|---|---|---|
| 等距分箱 | 按数值范围等分成 N 段(如 0-10, 10-20, …) | 因子分布均匀,无极端值 |
| 等频分箱 | 按样本量等分成 N 段,每段样本数相同 | 因子分布偏态,需保证每箱有足够样本 |
| 自定义分箱 | 按业务经验或模型分箱点划分 | 已有成熟分箱策略,需保持一致性 |
⚠️ 分箱注意事项:分箱数通常取 10-20 箱。分箱过少会丢失分布细节,分箱过多会导致部分分箱样本量为 0,使 ln(P_i/Q_i) 无法计算。建议监控样本中每箱至少包含 30 个样本。
1.2 PSI 在风控因子监控中的核心价值
在风控模型的生命周期中,因子分布偏移是模型失效的最常见原因之一。PSI 监控的核心价值体现在以下三个层面:
1.2.1 早期预警:发现客群漂移
当宏观经济、政策环境、获客渠道或用户行为发生变化时,因子的分布会随之偏移。PSI 能够量化这种偏移程度,在模型效果明显下降之前发出预警。例如:
- 收入因子:疫情期间收入分布整体左移,PSI 从 0.02 升至 0.15
- 年龄因子:新渠道引入年轻客群,年龄分布右移,PSI 突破 0.10 阈值
- 负债率因子:利率调整后用户负债行为变化,PSI 持续上升
1.2.2 量化评估:辅助模型迭代决策
PSI 提供了一个统一的量化标准,帮助风控团队判断是否需要重新训练模型或调整分箱策略:
| PSI 范围 | 偏移程度 | 建议行动 |
|---|---|---|
| 0.00 - 0.05 | 无显著偏移 | 持续监控,无需干预 |
| 0.05 - 0.10 | 轻度偏移 | 加强监控频率,排查原因 |
| 0.10 - 0.25 | 中度偏移 | 启动模型评估,考虑分箱调整 |
| > 0.25 | 严重偏移 | 立即重新训练模型或回退备用模型 |
1.2.3 归因分析:定位偏移源头
PSI 不仅给出整体偏移量,还能通过分箱贡献度定位具体哪些取值区间发生了显著变化。例如,某因子 PSI 为 0.18,其中“30-40 岁”分箱贡献了 60% 的偏移量,说明该年龄段客群发生了明显变化。
📌 核心价值总结:PSI 是风控因子监控的“仪表盘”——它告诉你分布是否偏移、偏移多大、偏移在哪,为模型稳定性管理提供数据驱动的决策依据。
1.3 PSI 计算流程与示例
下面通过一个完整示例演示 PSI 的计算过程。假设某风控因子“月收入”在建模样本和监控样本中的分布如下:
1.3.1 分箱与占比计算
| 分箱区间(元) | 建模样本 Q_i | 监控样本 P_i | P_i - Q_i | ln(P_i/Q_i) | 分箱贡献 |
|---|---|---|---|---|---|
| 0 - 5000 | 0.20 | 0.25 | 0.05 | 0.2231 | 0.0112 |
| 5000 - 10000 | 0.35 | 0.30 | -0.05 | -0.1542 | 0.0077 |
| 10000 - 20000 | 0.30 | 0.28 | -0.02 | -0.0690 | 0.0014 |
| 20000 - 50000 | 0.12 | 0.14 | 0.02 | 0.1542 | 0.0031 |
| > 50000 | 0.03 | 0.03 | 0.00 | 0.0000 | 0.0000 |
| PSI = Σ 分箱贡献 | 0.0234 | ||||
计算得到 PSI = 0.0234,小于 0.05,说明该因子在监控期间分布稳定,无需干预。
1.4 PSI 监控的完整流程
下图展示了 PSI 监控从数据采集到告警触发的完整链路:
1.5 PSI 与其他稳定性指标的对比
在风控实践中,除了 PSI,还有几种常用的稳定性指标。下表对比了它们的核心差异:
| 指标 | 衡量对象 | 取值范围 | 对极端值敏感度 | 主要用途 |
|---|---|---|---|---|
| PSI | 因子分布偏移 | [0, +∞) | 中等 | 因子级稳定性监控 |
| CSI | 模型分数偏移 | [0, +∞) | 中等 | 模型级稳定性监控 |
| KS | 好坏样本区分度 | [0, 1] | 高 | 模型区分能力评估 |
| IV | 因子预测能力 | [0, +∞) | 高 | 因子筛选与分箱评估 |
🔑 关键区别:PSI 关注的是“分布是否变了”,KS 关注的是“好坏是否分得开”,IV 关注的是“这个因子有没有用”。三者共同构成风控模型监控的“铁三角”。
1.6 PSI 计算的 Python 实现
下面给出一个完整的 PSI 计算函数,可直接用于生产环境:
import numpy as np
import pandas as pd
def calculate_psi(actual, expected, bins=10, bin_type='equal_freq'):
"""
计算群体稳定性指标 (PSI)
Parameters:
-----------
actual : array-like
监控样本(实际分布)
expected : array-like
建模样本(基准分布)
bins : int
分箱数量,默认 10
bin_type : str
分箱方式:'equal_freq'(等频)或 'equal_width'(等距)
Returns:
--------
psi : float
PSI 值
breakdown : DataFrame
每个分箱的详细贡献
"""
# 1. 基于基准分布确定分箱边界
if bin_type == 'equal_freq':
# 等频分箱:按基准分布的分位数划分
percentiles = np.linspace(0, 100, bins + 1)
bin_edges = np.percentile(expected, percentiles)
else:
# 等距分箱:按基准分布的最小最大值等距划分
bin_edges = np.linspace(np.min(expected), np.max(expected), bins + 1)
# 2. 对两个样本进行分箱
actual_bins = np.digitize(actual, bin_edges, right=True)
expected_bins = np.digitize(expected, bin_edges, right=True)
# 3. 计算每个分箱的占比
actual_counts = np.bincount(actual_bins, minlength=bins + 1)[1:bins + 1]
expected_counts = np.bincount(expected_bins, minlength=bins + 1)[1:bins + 1]
actual_pct = actual_counts / len(actual)
expected_pct = expected_counts / len(expected)
# 4. 处理零值:用极小值替代,避免 ln(0)
epsilon = 1e-6
actual_pct = np.clip(actual_pct, epsilon, 1.0)
expected_pct = np.clip(expected_pct, epsilon, 1.0)
# 5. 计算 PSI
psi_value = np.sum((actual_pct - expected_pct) * np.log(actual_pct / expected_pct))
# 6. 构建详细分解表
breakdown = pd.DataFrame({
'bin_start': bin_edges[:-1],
'bin_end': bin_edges[1:],
'expected_pct': expected_pct,
'actual_pct': actual_pct,
'contribution': (actual_pct - expected_pct) * np.log(actual_pct / expected_pct)
})
return psi_value, breakdown
# 使用示例
np.random.seed(42)
expected_data = np.random.normal(5000, 1500, 10000) # 建模样本
actual_data = np.random.normal(5200, 1600, 10000) # 监控样本
psi, breakdown = calculate_psi(actual_data, expected_data, bins=10)
print(f"PSI = {psi:.4f}")
print(f"偏移程度:{'稳定' if psi <= 0.05 else '轻度偏移' if psi <= 0.10 else '中度偏移' if psi <= 0.25 else '严重偏移'}")
💡 代码要点:
- 使用
np.digitize进行高效分箱,避免循环 - 通过
np.clip处理零值,防止 ln(0) 报错 - 返回详细分解表,便于定位偏移源头
- 支持等频和等距两种分箱方式,适应不同场景
1.7 本章小结
PSI 作为风控因子监控的核心指标,其价值在于:
- 数学上:基于 KL 散度对称化,量化两个分布的差异
- 业务上:提供早期预警、量化评估、归因分析三大能力
- 实践上:通过分箱策略和阈值判断,形成完整的监控闭环