4. 数据预处理:缺失值处理、异常值检测、数据标准化与归一化、类别变量编码
在情景分析中,原始风险暴露数据往往存在缺失、噪声、量纲不一和类别混杂等问题。若直接用于建模,会严重扭曲特征与风险之间的真实关系。本章按照“清洗→检测→变换→编码”的流水线顺序,逐一讲解每个环节的核心方法与风控场景下的特殊考量。
4.1 缺失值处理
缺失值在风控数据中极为常见,原因包括客户未填写、系统采集故障、数据源断连等。处理策略分为三类:删除、填充和模型预测。
| 策略 | 适用场景 | 风控注意事项 |
|---|---|---|
| 删除(行/列) | 缺失比例 < 5% 且随机缺失 | 避免删除后样本量过少导致统计显著性下降 |
| 均值/中位数填充 | 连续型变量,低缺失率 | 会压缩方差,可能弱化风险区分能力 |
| 众数填充 | 类别型变量 | 若众数占比过高,会引入偏误 |
| 前向/后向填充 | 时间序列型风险指标 | 需确保时间顺序正确,避免未来信息泄露 |
| KNN / 回归预测填充 | 缺失率 10%–30%,变量间相关性较强 | 计算成本高,需注意过拟合 |
| 标记缺失(单独编码) | 缺失本身具有业务含义(如“未申请”) | 推荐在风控场景中优先考虑 |
风控实践提示: 对于“收入”“负债比”等关键风险特征,建议先分析缺失模式(MCAR/MAR/MNAR),再选择填充策略。若缺失与违约率显著相关,应保留“缺失”作为一个独立状态。
4.2 异常值检测
异常值在风控中可能是欺诈行为、录入错误或极端信用事件。检测方法需结合业务逻辑与统计分布。
常用检测方法对比
| 方法 | 原理 | 风控适用性 |
|---|---|---|
| Z-Score 法 | |Z| > 3 视为异常 | 适用于近似正态分布的特征(如年龄) |
| IQR 四分位法 | 超出 Q1-1.5IQR 或 Q3+1.5IQR | 适用于偏态分布(如收入、负债) |
| 孤立森林 | 基于树模型隔离异常点 | 高维特征下的欺诈检测 |
| DBSCAN 聚类 | 密度低且远离核心簇的点 | 适用于有聚集模式的风险特征 |
| 业务规则阈值 | 如“单日交易金额 > 100 万” | 必须优先于统计方法 |
注意: 不要机械地删除所有异常值。在风控场景中,某些“异常”恰恰是高风险的标志(如短期内频繁申请贷款)。建议先标记异常值,再结合情景分析判断是否剔除或单独建模。
4.3 数据标准化与归一化
不同风险特征往往具有不同的量纲和取值范围(如年龄 0–100,收入 0–10⁷)。标准化和归一化可以消除量纲影响,使模型(尤其是距离敏感模型)稳定收敛。
核心方法对比
| 方法 | 公式 | 输出范围 | 风控适用场景 |
|---|---|---|---|
| Z-Score 标准化 | \( z = \frac{x - \mu}{\sigma} \) | 均值 0,标准差 1 | 逻辑回归、SVM、PCA 等需要正态假设的模型 |
| Min-Max 归一化 | \( x' = \frac{x - x_{\min}}{x_{\max} - x_{\min}} \) | [0, 1] | 神经网络、KNN、深度学习 |
| Robust 缩放 | \( x' = \frac{x - Q_2}{Q_3 - Q_1} \) | 受异常值影响小 | 收入、负债比等含极端值的特征 |
| MaxAbs 缩放 | \( x' = \frac{x}{\max(|x|)} \) | [-1, 1] | 稀疏数据或已中心化的特征 |
关键原则: 标准化参数(μ, σ, min, max 等)必须从训练集计算,再应用到验证集和测试集,避免数据泄露。在情景分析中,不同情景下的数据分布可能发生偏移,建议定期重新估计缩放参数。
4.4 类别变量编码
风控数据中包含大量类别变量,如“职业”“地区”“贷款用途”。大多数模型无法直接处理字符串,需要转换为数值形式。
编码方法对比
| 编码方法 | 转换方式 | 维度变化 | 风控适用性 |
|---|---|---|---|
| 标签编码 | 类别 → 整数 0,1,2,… | 1 列 | 有序类别(如信用等级 A<B<C) |
| 独热编码 | 每个类别 → 二进制列 | k 列(k 为类别数) | 无序类别,类别数较少(< 20) |
| 频率编码 | 类别 → 该类别出现频率 | 1 列 | 高基数类别(如地区代码) |
| 目标编码 | 类别 → 该类别下目标均值 | 1 列 | 需防止过拟合,配合交叉验证使用 |
| WOE 编码 | 类别 → 证据权重 | 1 列 | 评分卡模型专用,与逻辑回归天然适配 |
避坑指南: 独热编码后若类别数过多(如“地区”有 300 个值),会导致维度灾难。此时优先使用频率编码或目标编码。WOE 编码在风控评分卡中效果优异,但需要先进行分箱处理。
编码选择决策步骤
- 判断类别是否有序:有序 → 标签编码;无序 → 进入下一步。
- 判断类别基数:基数 ≤ 10 → 独热编码;基数 > 10 → 进入下一步。
- 判断模型类型:树模型 → 标签编码或频率编码;线性模型 → 目标编码或 WOE 编码。
- 验证编码稳定性:在验证集上检查编码后的特征分布是否与训练集一致。
情景分析特别提醒: 在不同情景(如经济上行 vs 下行)下,类别变量的分布可能发生显著变化。例如“行业”变量在衰退期某些行业的违约率飙升。建议对每个情景分别计算编码映射,或使用情景不变的频率编码。
4.5 预处理流水线整合
在实际风控项目中,上述四个步骤需要按固定顺序组装成一条预处理流水线。推荐使用 sklearn.pipeline.Pipeline 或自定义函数链,确保每个步骤的参数只从训练集学习。
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
# 定义数值型特征流水线
numeric_pipeline = Pipeline([
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
# 定义类别型特征流水线
categorical_pipeline = Pipeline([
('imputer', SimpleImputer(strategy='most_frequent')),
('encoder', OneHotEncoder(handle_unknown='ignore'))
])
# 组合预处理
preprocessor = ColumnTransformer([
('num', numeric_pipeline, numeric_features),
('cat', categorical_pipeline, categorical_features)
])
# 在训练集上 fit,在验证/测试集上 transform
X_train_processed = preprocessor.fit_transform(X_train)
X_test_processed = preprocessor.transform(X_test)
流水线优势: 避免数据泄露、代码可复用、便于情景对比。在情景分析中,可以为每个情景(基准、乐观、悲观)分别维护一条流水线,或使用统一的流水线但重新 fit 参数。