4. 数值特征漂移检测(KS检验)
在贷后预警场景中,数值型特征(如收入、负债率、逾期天数)的分布变化是模型失效的核心诱因。KS检验(Kolmogorov-Smirnov Test)是检测数值特征分布漂移的经典非参数方法,无需假设数据服从特定分布,直接比较两个样本的累积分布函数(CDF)差异。
4.1 KS检验原理
KS检验的核心思想:计算训练集(参考集)与生产集(当前集)的累积分布函数之间的最大垂直距离,该距离即为KS统计量。若KS统计量超过临界值,则认为两个样本来自不同分布,即发生特征漂移。
核心公式:
D = max |F₁(x) - F₂(x)|
其中 F₁ 和 F₂ 分别为两个样本的经验累积分布函数,D 为KS统计量。
D = max |F₁(x) - F₂(x)|
其中 F₁ 和 F₂ 分别为两个样本的经验累积分布函数,D 为KS统计量。
KS检验的假设体系:
- 原假设 H₀:两个样本来自同一连续分布(无漂移)
- 备择假设 H₁:两个样本来自不同连续分布(存在漂移)
KS统计量 D 的取值范围为 [0, 1],值越大表示分布差异越显著。当 D 接近 0 时,两个分布几乎重合;当 D 接近 1 时,分布完全分离。
4.2 scipy.stats.ks_2samp 实现
Python 中通过 scipy.stats.ks_2samp 函数直接完成双样本 KS 检验。该函数返回 KS 统计量 D 和 p 值,无需手动计算 CDF。
函数签名:
scipy.stats.ks_2samp(data1, data2, alternative='two-sided', mode='auto')
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| data1 | array_like | 参考集(训练集)数值特征 |
| data2 | array_like | 生产集(当前集)数值特征 |
| alternative | str | 检验方向:'two-sided'(默认)、'less'、'greater' |
| mode | str | 计算方法:'auto'(自动)、'exact'(精确)、'asymp'(近似) |
贷后预警实战代码:
import pandas as pd
import numpy as np
from scipy.stats import ks_2samp
# 模拟数据:训练集 vs 生产集
np.random.seed(42)
train_income = np.random.lognormal(mean=10.5, sigma=0.6, size=5000) # 训练集收入
prod_income = np.random.lognormal(mean=10.8, sigma=0.7, size=5000) # 生产集收入(均值漂移)
# 执行KS检验
stat, p_value = ks_2samp(train_income, prod_income, alternative='two-sided')
print(f"KS统计量 D = {stat:.4f}")
print(f"p值 = {p_value:.6f}")
# 漂移判定
alpha = 0.05
if p_value < alpha:
print("结论:拒绝H₀ → 特征分布发生显著漂移")
else:
print("结论:无法拒绝H₀ → 特征分布稳定")
💡 实战提示:在贷后场景中,建议对每个数值特征单独执行KS检验,并将结果存入特征漂移监控表。对于高基数特征(如收入),KS检验比PSI更敏感;对于低基数特征(如信用评分等级),可结合PSI综合判断。
4.3 p值解读与阈值设定
p值表示在原假设为真(无漂移)的条件下,观察到当前KS统计量或更极端值的概率。p值越小,拒绝原假设的证据越强。
p值解读规则:
| p值范围 | 统计显著性 | 漂移判定 | 贷后预警动作 |
|---|---|---|---|
| p < 0.01 | 高度显著 | 强烈拒绝H₀,存在漂移 | 立即告警,触发模型重训 |
| 0.01 ≤ p < 0.05 | 显著 | 拒绝H₀,存在漂移 | 发出预警,加强监控频率 |
| 0.05 ≤ p < 0.10 | 边缘显著 | 弱证据,建议复查 | 标记为观察特征,增加样本量 |
| p ≥ 0.10 | 不显著 | 无法拒绝H₀,无漂移 | 维持正常监控 |
阈值设定建议:
- 严格阈值(α=0.01):适用于高风险特征(如逾期天数、负债率),减少误报,避免频繁重训
- 标准阈值(α=0.05):适用于大多数数值特征,平衡检测灵敏度与误报率
- 宽松阈值(α=0.10):适用于探索性分析或样本量较小时,提高漂移检出率
⚠️ 大样本陷阱:当样本量极大(如 >10万)时,KS检验对微小差异也会产生显著p值。此时应结合KS统计量 D 的绝对值判断业务意义:即使 p < 0.001,若 D < 0.05,实际漂移程度可忽略,无需触发预警。
4.4 实战:贷后特征漂移监控表
将KS检验集成到贷后预警流水线中,构建特征漂移监控表,实现自动化检测。
import pandas as pd
from scipy.stats import ks_2samp
def ks_drift_detection(ref_df, prod_df, features, alpha=0.05):
"""
批量检测数值特征漂移
ref_df: 训练集DataFrame
prod_df: 生产集DataFrame
features: 待检测特征列表
alpha: 显著性水平
"""
results = []
for feat in features:
stat, p_value = ks_2samp(ref_df[feat].dropna(),
prod_df[feat].dropna())
drift_flag = "漂移" if p_value < alpha else "稳定"
results.append({
"特征": feat,
"KS统计量": round(stat, 4),
"p值": round(p_value, 6),
"判定": drift_flag
})
return pd.DataFrame(results)
# 示例调用
ref_data = pd.DataFrame({
"income": np.random.lognormal(10.5, 0.6, 5000),
"debt_ratio": np.random.beta(2, 5, 5000),
"overdue_days": np.random.poisson(3, 5000)
})
prod_data = pd.DataFrame({
"income": np.random.lognormal(10.8, 0.7, 5000),
"debt_ratio": np.random.beta(2.5, 5, 5000),
"overdue_days": np.random.poisson(5, 5000)
})
monitor_df = ks_drift_detection(ref_data, prod_data,
["income", "debt_ratio", "overdue_days"],
alpha=0.05)
print(monitor_df)
输出示例:
| 特征 | KS统计量 | p值 | 判定 |
|---|---|---|---|
| income | 0.1245 | 0.000003 | 漂移 |
| debt_ratio | 0.0682 | 0.021400 | 漂移 |
| overdue_days | 0.0321 | 0.185000 | 稳定 |
📌 最佳实践:建议将KS检验结果与PSI(群体稳定性指标)结合使用——KS检验对分布形状变化敏感,PSI对分箱后的占比变化敏感。两者同时告警时,漂移可信度更高;仅KS告警时,需关注分布尾部变化。