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 计算失真。此时应改用等频分箱或混合分箱策略。
等距分箱与等频分箱对比示意图 等距分箱 vs 等频分箱对比 等距分箱(宽度相等) 箱1 箱2 箱3 箱4 样本数: 80% 15% 4% 1% 等频分箱(样本数相等) 箱1 箱2 箱3 箱4 宽度: 窄 窄 中 宽 等距分箱:箱宽固定,样本分布不均 等频分箱:样本数固定,箱宽自适应

3.3 分箱数量的选择原则

分箱数量(即 k 值)是 PSI 计算中的关键超参数。箱数过多会导致每个箱内样本过少,统计波动增大;箱数过少则会丢失分布细节,降低 PSI 的敏感性。以下是选择分箱数量的核心原则:

  1. 样本量驱动原则: 每个箱内至少应包含 5% 的样本(或至少 50 个样本),以保证统计稳定性。对于总样本量 N,建议箱数 k ≤ N / 50。
  2. 业务语义原则: 在信用评分等场景中,分箱边界应尽量与业务阈值对齐(如 600 分、700 分),此时箱数由业务分段自然决定。
  3. 经验法则: 对于 PSI 计算,通常推荐 10~20 个箱。10 箱是行业默认标准(对应百分位),20 箱适用于样本量充足且需要更高敏感度的场景。
  4. 稳定性验证: 建议在 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 箱开始。
分箱数量选择决策流程 分箱数量选择决策流程 确定总样本量 N N < 1000? 是 5~8 箱 否 有业务阈值? 是 按业务分段 否 默认使用 10 箱 验证:5/10/15/20 箱 PSI 稳定性

3.4 分箱边界对齐:训练集与测试集的一致性

在 PSI 计算中,一个极易被忽视但至关重要的细节是:分箱边界必须基于训练集(或基准集)确定,并固定应用于测试集(或待评估集)。绝不能对两个数据集分别独立分箱,否则箱的边界不一致,PSI 将失去可比性。

严重错误: 对训练集和测试集分别进行等频分箱,会导致两个数据集的箱边界完全不同。此时计算的 PSI 反映的是分箱方案差异,而非真实的分布偏移。

正确的做法是:

  1. 在训练集上确定分箱边界(如等距的区间端点或等频的分位数)。
  2. 将这些边界作为固定参数,应用到测试集上。
  3. 计算每个箱在训练集和测试集中的样本占比,进而计算 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}")
最佳实践: 在模型开发阶段,将分箱边界作为模型配置文件的一部分进行保存。在模型监控时,直接加载该配置文件,确保训练集和测试集使用完全相同的分箱逻辑。