3. PSI 计算前置准备:数据分箱的概念、等距分箱与等频分箱的区别、分箱数量的选择原则
在计算群体稳定性指标(PSI)之前,必须对连续型特征或概率值进行离散化处理,这一过程称为数据分箱。分箱的质量直接决定了 PSI 计算的准确性与鲁棒性。本节将系统讲解分箱的核心概念、两种主流分箱策略的差异,以及分箱数量的选择原则。
3.1 数据分箱的概念
数据分箱(Binning)是将连续变量划分为若干个离散区间(即“箱”),并将每个原始值映射到其所属的箱中。在 PSI 计算场景中,分箱的目的是将模型输出的概率分数或特征值转化为有限的、可比较的类别,从而计算各箱内样本占比的变化。
核心作用: 分箱将无限连续的数值空间压缩为有限个离散区间,使得分布对比(如训练集 vs. 测试集)成为可能。没有分箱,PSI 将无法计算。
一个有效的分箱应满足以下基本要求:
- 全覆盖: 所有样本值都必须落入某个箱中,不允许遗漏。
- 互斥性: 每个样本只能属于一个箱,区间不能重叠。
- 单调性: 箱的边界通常保持单调递增(或递减),便于解释。
3.2 等距分箱与等频分箱的区别
在 PSI 计算中,最常用的两种分箱策略是等距分箱和等频分箱。两者在划分逻辑、适用场景和优缺点上存在显著差异。
选择建议: 对于模型分数(如信用评分卡),通常优先使用等距分箱,因为分数本身具有业务含义;对于分布极不均匀的特征,等频分箱能避免空箱问题。
3.2.1 等距分箱(Equal-Width Binning)
将变量的取值范围均匀划分为 k 个宽度相等的区间。每个箱的区间长度相同,但箱内样本数量可能差异巨大。
3.2.2 等频分箱(Equal-Frequency Binning)
将变量按数值从小到大排序,然后划分为 k 个区间,使得每个区间包含大致相同数量的样本。箱内样本数均衡,但区间宽度可能差异很大。
| 对比维度 | 等距分箱 | 等频分箱 |
|---|---|---|
| 划分依据 | 数值范围等宽 | 样本数量等量 |
| 箱宽度 | 固定一致 | 可变(数据密集处窄,稀疏处宽) |
| 箱内样本数 | 差异可能很大 | 基本一致 |
| 对异常值敏感度 | 高(异常值会拉宽区间) | 低(异常值被归入首尾箱) |
| PSI 适用场景 | 模型分数、概率输出 | 长尾分布、非均匀分布特征 |
| 空箱风险 | 高(数据稀疏区域可能无样本) | 低(保证每箱有样本) |
| 业务可解释性 | 强(边界为整数或业务阈值) | 弱(边界为分位数,不易解释) |
常见陷阱: 使用等距分箱时,如果数据分布极度偏斜,可能导致大部分样本集中在少数几个箱中,而其他箱近乎为空,造成 PSI 计算失真。此时应改用等频分箱或混合分箱策略。
3.3 分箱数量的选择原则
分箱数量(即 k 值)是 PSI 计算中的关键超参数。箱数过多会导致每个箱内样本过少,统计波动增大;箱数过少则会丢失分布细节,降低 PSI 的敏感性。以下是选择分箱数量的核心原则:
- 样本量驱动原则: 每个箱内至少应包含 5% 的样本(或至少 50 个样本),以保证统计稳定性。对于总样本量 N,建议箱数 k ≤ N / 50。
- 业务语义原则: 在信用评分等场景中,分箱边界应尽量与业务阈值对齐(如 600 分、700 分),此时箱数由业务分段自然决定。
- 经验法则: 对于 PSI 计算,通常推荐 10~20 个箱。10 箱是行业默认标准(对应百分位),20 箱适用于样本量充足且需要更高敏感度的场景。
- 稳定性验证: 建议在 5、10、15、20 四个箱数下分别计算 PSI,观察结果是否稳定。若 PSI 值随箱数剧烈波动,说明分箱方案不可靠。
| 样本量范围 | 推荐箱数 | 分箱策略建议 | 说明 |
|---|---|---|---|
| < 1,000 | 5~8 | 等频分箱 | 样本少,避免空箱 |
| 1,000 ~ 10,000 | 8~12 | 等频或等距 | 默认使用 10 箱 |
| 10,000 ~ 100,000 | 10~20 | 等距分箱 | 样本充足,可增加箱数 |
| > 100,000 | 15~25 | 等距分箱 | 大样本,追求分布细节 |
关键结论: 分箱数量并非越大越好。在 PSI 计算中,10 箱是经过长期实践验证的“黄金标准”,既能捕捉分布偏移,又保持统计稳健性。除非有明确业务理由,否则建议从 10 箱开始。
3.4 分箱边界对齐:训练集与测试集的一致性
在 PSI 计算中,一个极易被忽视但至关重要的细节是:分箱边界必须基于训练集(或基准集)确定,并固定应用于测试集(或待评估集)。绝不能对两个数据集分别独立分箱,否则箱的边界不一致,PSI 将失去可比性。
严重错误: 对训练集和测试集分别进行等频分箱,会导致两个数据集的箱边界完全不同。此时计算的 PSI 反映的是分箱方案差异,而非真实的分布偏移。
正确的做法是:
- 在训练集上确定分箱边界(如等距的区间端点或等频的分位数)。
- 将这些边界作为固定参数,应用到测试集上。
- 计算每个箱在训练集和测试集中的样本占比,进而计算 PSI。
# Python 示例:基于训练集分箱并应用到测试集
import numpy as np
import pandas as pd
def compute_psi(expected, actual, bins=10):
"""
计算 PSI 值
expected: 训练集(基准)分数
actual: 测试集(待评估)分数
bins: 分箱数量
"""
# 1. 基于训练集确定分箱边界(等距)
bin_edges = np.linspace(expected.min(), expected.max(), bins + 1)
# 2. 对训练集和测试集应用相同边界
expected_binned = np.digitize(expected, bin_edges, right=True)
actual_binned = np.digitize(actual, bin_edges, right=True)
# 3. 计算各箱占比
expected_pct = np.bincount(expected_binned, minlength=bins+2)[1:bins+1] / len(expected)
actual_pct = np.bincount(actual_binned, minlength=bins+2)[1:bins+1] / len(actual)
# 4. 处理零占比(加极小值避免除零)
expected_pct = np.clip(expected_pct, 1e-6, 1)
actual_pct = np.clip(actual_pct, 1e-6, 1)
# 5. 计算 PSI
psi = np.sum((actual_pct - expected_pct) * np.log(actual_pct / expected_pct))
return psi
# 使用示例
train_scores = np.random.normal(600, 100, 10000)
test_scores = np.random.normal(620, 110, 10000)
psi_value = compute_psi(train_scores, test_scores, bins=10)
print(f"PSI = {psi_value:.4f}")
最佳实践: 在模型开发阶段,将分箱边界作为模型配置文件的一部分进行保存。在模型监控时,直接加载该配置文件,确保训练集和测试集使用完全相同的分箱逻辑。