4. 特征分层方法论:基于信息量(IV)的分层、基于缺失率的分层、基于稳定性(PSI)的分层

在风控特征工程中,特征分层是连接特征加工与模型训练的关键桥梁。合理的分层策略能显著提升样本抽样的代表性,并降低因特征分布偏移导致的模型衰减风险。本节系统阐述三种主流分层方法:信息量(IV)分层、缺失率分层与稳定性(PSI)分层,并给出在 Spark 环境下的实现要点。

4.1 基于信息量(IV)的分层

信息量(IV, Information Value)是衡量特征对二分类目标变量区分能力的经典指标。IV 值越高,特征对好坏样本的区分度越强。基于 IV 分层,旨在将特征按预测能力划分为不同层级,用于指导特征筛选与抽样权重分配。

IV 计算公式:
IV = Σ ( (Good_i / Good_total) - (Bad_i / Bad_total) ) * ln( (Good_i / Good_total) / (Bad_i / Bad_total) )

其中,Good_i 和 Bad_i 分别表示第 i 个分箱中好样本与坏样本的数量。

IV 分层阈值参考:
  • IV < 0.02:无预测能力,建议剔除。
  • 0.02 ≤ IV < 0.10:弱预测能力,可保留但需谨慎。
  • 0.10 ≤ IV < 0.30:中等预测能力,常用特征。
  • IV ≥ 0.30:强预测能力,核心特征。

在 Spark 中,可通过 groupBy 与聚合函数实现 IV 的分布式计算。以下为基于分箱后的 IV 计算代码片段:

import org.apache.spark.sql.functions._

// 假设 df 包含字段: feature_bin, label (1=坏, 0=好)
val ivDF = df.groupBy("feature_bin")
  .agg(
    sum(when(col("label") === 0, 1).otherwise(0)).alias("good_cnt"),
    sum(when(col("label") === 1, 1).otherwise(0)).alias("bad_cnt")
  )
  .withColumn("good_dist", col("good_cnt") / sum("good_cnt").over())
  .withColumn("bad_dist", col("bad_cnt") / sum("bad_cnt").over())
  .withColumn("woe", log(col("good_dist") / col("bad_dist")))
  .withColumn("iv_contrib", (col("good_dist") - col("bad_dist")) * col("woe"))

val totalIV = ivDF.agg(sum("iv_contrib")).first().getDouble(0)
基于信息量(IV)的特征分层流程 基于信息量(IV)的特征分层流程 原始特征 分箱 → WOE → IV计算 IV值 IV ≥ 0.02? 剔除特征 保留并分层 分层结果:弱(0.02~0.10) / 中(0.10~0.30) / 强(≥0.30)

4.2 基于缺失率的分层

缺失率是衡量特征数据完整性的核心指标。高缺失率特征可能引入噪声或偏差,低缺失率特征则更可靠。基于缺失率分层,有助于在抽样时对特征质量进行差异化处理,例如对高缺失率特征进行标记或填充策略调整。

缺失率区间 分层标签 推荐处理策略
[0%, 5%) 低缺失 直接使用,无需特殊处理
[5%, 20%) 中缺失 均值/中位数填充,或增加缺失指示列
[20%, 50%) 高缺失 优先使用模型预测填充,或考虑剔除
[50%, 100%] 极高缺失 建议剔除,或仅保留缺失指示列

Spark 中计算特征缺失率的典型实现:

import org.apache.spark.sql.functions._

// 计算每列缺失率
val missingRateDF = df.select(
  df.columns.map(c => 
    (sum(when(col(c).isNull || col(c) === "" || col(c).isNaN, 1).otherwise(0)) / count("*")).alias(s"${c}_missing_rate")
  ): _*
)
注意:缺失率分层应与业务含义结合。例如,某些风控特征(如“逾期天数”)的缺失可能代表“未逾期”,而非数据缺失,此时不应按常规缺失率处理。

4.3 基于稳定性(PSI)的分层

群体稳定性指标(PSI, Population Stability Index)用于衡量特征在时间维度上的分布偏移程度。PSI 越大,特征越不稳定,模型在跨时间样本上的表现越可能衰减。基于 PSI 分层,可识别出需要重点监控或重新建模的特征。

PSI 计算公式:
PSI = Σ ( (Actual_i / Actual_total) - (Expected_i / Expected_total) ) * ln( (Actual_i / Actual_total) / (Expected_i / Expected_total) )

其中,Actual 为当前样本分布,Expected 为基准样本分布。

PSI 区间 分层标签 风控含义
[0, 0.10) 稳定 特征分布无显著变化,可继续使用
[0.10, 0.25) 轻度偏移 需关注,建议检查业务逻辑
[0.25, +∞) 严重偏移 特征已失效,需重新开发或剔除

Spark 中计算 PSI 的分布式实现:

import org.apache.spark.sql.functions._

// 假设 actualDF 为当前样本,expectedDF 为基准样本,均包含分箱字段 bin
val actualDist = actualDF.groupBy("bin").count().withColumnRenamed("count", "actual_cnt")
val expectedDist = expectedDF.groupBy("bin").count().withColumnRenamed("count", "expected_cnt")

val psiDF = actualDist.join(expectedDist, Seq("bin"), "outer")
  .na.fill(0)
  .withColumn("actual_pct", col("actual_cnt") / sum("actual_cnt").over())
  .withColumn("expected_pct", col("expected_cnt") / sum("expected_cnt").over())
  .withColumn("psi_contrib", (col("actual_pct") - col("expected_pct")) * log(col("actual_pct") / col("expected_pct")))

val totalPSI = psiDF.agg(sum("psi_contrib")).first().getDouble(0)
三种特征分层方法对比架构 三种特征分层方法对比架构 特征分层 基于IV分层 区分预测能力 基于缺失率分层 评估数据完整性 基于PSI分层 监控分布偏移 特征筛选权重 抽样分层依据 填充策略选择 特征质量标记 模型监控触发 特征淘汰决策 三种分层方法可独立使用,也可组合形成多维分层策略 例如:高IV + 低缺失 + 高PSI → 核心监控特征

4.4 三种分层方法的综合对比

维度 IV 分层 缺失率分层 PSI 分层
核心目标 衡量预测能力 衡量数据完整性 衡量分布稳定性
计算依赖 需要标签(好坏样本) 仅需特征自身 需要两个时间窗口的分布
分层输出 弱/中/强预测力 低/中/高/极高缺失 稳定/轻度偏移/严重偏移
Spark 实现复杂度 中等(需分箱+聚合) 低(简单聚合) 中等(需跨数据集Join)
在抽样中的应用 按IV权重分配抽样比例 对高缺失特征降权或标记 对不稳定特征进行分层校验
最佳实践建议:在风控特征工程中,推荐先进行缺失率分层清洗低质量特征,再通过 IV 分层筛选强预测特征,最后用 PSI 分层监控特征的跨时间稳定性。三层递进可形成完整的特征质量评估体系。