4. 特征工程基础:缺失值与异常值处理

在风控建模中,原始数据几乎不可能完美无缺。缺失值会破坏模型输入完整性,异常值则会扭曲统计分布、拉偏决策边界。本章聚焦两类最基础也最核心的特征工程操作:缺失值处理与异常值检测与处理,为后续特征分层与模型训练打下干净、可靠的数据基础。

4.1 缺失值处理

缺失值产生原因包括用户未填写、数据采集故障、字段不适用等。处理前需先区分缺失机制:

  • 完全随机缺失(MCAR):缺失与数据本身无关,可直接删除或简单填充。
  • 随机缺失(MAR):缺失与其他观测变量相关,适合用模型预测填充。
  • 非随机缺失(MNAR):缺失与缺失值本身相关,处理最复杂,需结合业务逻辑。

4.1.1 均值/中位数/众数填充

这是最快速、最常用的填充方法,适用于不同数据分布类型:

填充方式 适用场景 优点 缺点
均值填充 数值型特征,数据近似正态分布 计算简单,保持整体均值不变 受异常值影响大,会降低方差
中位数填充 数值型特征,数据偏态分布或含异常值 稳健,不受极端值干扰 忽略分布形状信息
众数填充 分类型特征(如婚姻状况、学历) 保留类别分布比例 可能引入偏差,若众数占比过高会弱化特征区分度
风控实践建议:对于收入、年龄等常见数值特征,优先使用中位数填充,因为风控数据通常呈右偏分布(少数高收入群体拉高均值)。对于性别、地区等分类特征,使用众数填充,但需注意若缺失率超过 30%,建议单独编码“未知”类别。

4.1.2 模型预测填充

模型预测填充利用特征间的相关性,将缺失字段作为目标变量,用其他完整特征训练回归或分类模型进行预测。常用方法包括:

  • 线性回归/逻辑回归:适用于线性关系较强的场景,可解释性好。
  • KNN 填充:基于相似样本的均值或众数填充,适合局部结构明显的特征。
  • 随机森林/梯度提升树:能捕捉非线性关系,对异常值稳健,是风控场景的首选。
模型预测填充流程:
1. 将数据分为完整样本(无缺失)和缺失样本。
2. 以缺失特征为 y,其他完整特征为 X,在完整样本上训练预测模型。
3. 用训练好的模型预测缺失样本的 y 值,完成填充。
4. 注意:需避免数据泄露,填充过程应在训练集内交叉验证进行。
# Python 示例:使用随机森林填充缺失值
from sklearn.ensemble import RandomForestRegressor
import pandas as pd
import numpy as np

def rf_impute(df, target_col, feature_cols):
    """随机森林填充缺失值"""
    # 区分完整与缺失样本
    complete = df[df[target_col].notna()]
    missing = df[df[target_col].isna()]

    if len(missing) == 0:
        return df

    # 训练模型
    rf = RandomForestRegressor(n_estimators=100, random_state=42)
    rf.fit(complete[feature_cols], complete[target_col])

    # 预测并填充
    df.loc[df[target_col].isna(), target_col] = rf.predict(missing[feature_cols])
    return df

# 使用示例(假设 data 包含 'income' 和 'age', 'education' 等特征)
# data = rf_impute(data, 'income', ['age', 'education', 'work_years'])
注意:模型预测填充计算成本较高,且可能引入模型偏差。在风控建模中,建议仅对缺失率在 5%~30% 且与其他特征相关性较强的字段使用。缺失率过高时,模型预测结果不可靠,应优先考虑删除或单独编码。
缺失值处理策略选择流程 原始数据含缺失值 判断缺失率 < 5% / 5%~30% / > 30% 直接删除缺失行 模型预测填充 单独编码“未知” 判断数据分布:正态/偏态/分类 正态 → 均值填充 偏态 → 中位数填充 分类 → 众数填充 说明:缺失率判断阈值可根据业务场景调整,风控建模中建议以 5% 和 30% 为参考分界线

4.2 异常值检测与处理

异常值(Outlier)是指显著偏离数据集中趋势的观测值。在风控场景中,异常值可能代表欺诈行为、数据录入错误或极端但真实的用户特征。处理不当会严重影响模型稳定性和区分度。

4.2.1 IQR(四分位距)法

IQR 法基于数据分布的分位数,不假设数据服从特定分布,适用于偏态数据。定义如下:

  • Q1:第一四分位数(25% 分位数)
  • Q3:第三四分位数(75% 分位数)
  • IQR = Q3 - Q1
  • 下界 = Q1 - 1.5 × IQR
  • 上界 = Q3 + 1.5 × IQR

超出 [下界, 上界] 范围的值被视为异常值。对于极端异常,可使用 3 × IQR 作为更严格的阈值。

# Python 示例:IQR 异常值检测
import numpy as np
import pandas as pd

def detect_outliers_iqr(data, column, multiplier=1.5):
    """使用 IQR 方法检测异常值"""
    Q1 = data[column].quantile(0.25)
    Q3 = data[column].quantile(0.75)
    IQR = Q3 - Q1

    lower_bound = Q1 - multiplier * IQR
    upper_bound = Q3 + multiplier * IQR

    outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
    return outliers, lower_bound, upper_bound

# 使用示例
# outliers, low, up = detect_outliers_iqr(df, 'loan_amount')
# print(f"检测到 {len(outliers)} 个异常值,范围: [{low:.2f}, {up:.2f}]")

4.2.2 Z-score 法

Z-score 法基于正态分布假设,通过计算每个数据点与均值的标准差倍数来识别异常值。公式为:

Z = (x - μ) / σ

通常认为 |Z| > 3 的数据点为异常值(对应正态分布 99.7% 置信区间外)。对于风控数据,也可使用更严格的 |Z| > 2.5 或更宽松的 |Z| > 3.5,取决于业务容忍度。

IQR vs Z-score 对比:
IQR 法:不依赖正态假设,对偏态数据稳健,适合收入、负债等长尾分布特征。
Z-score 法:依赖正态假设,对异常值本身敏感(均值和标准差会被异常值拉偏),适合近似正态的特征如年龄、信用分。
# Python 示例:Z-score 异常值检测
from scipy import stats
import numpy as np

def detect_outliers_zscore(data, column, threshold=3):
    """使用 Z-score 方法检测异常值"""
    z_scores = np.abs(stats.zscore(data[column].dropna()))
    outlier_indices = np.where(z_scores > threshold)[0]
    outliers = data.iloc[outlier_indices]
    return outliers, z_scores

# 使用示例
# outliers, z = detect_outliers_zscore(df, 'credit_score', threshold=3)
# print(f"检测到 {len(outliers)} 个异常值")

4.2.3 异常值处理策略

检测到异常值后,需根据业务含义和建模目标选择处理方式:

处理方式 适用场景 操作方法 风控注意事项
删除 明显的数据录入错误、采样噪声 直接删除异常行或替换为 NaN 删除比例不宜超过 5%,否则会损失样本代表性
截尾(Winsorize) 极端值真实存在但需控制影响 将异常值替换为上下界值(如 1% 和 99% 分位数) 风控评分卡中常用,保留极端用户的排序信息
视为缺失 不确定异常值是否真实,保留后续填充机会 将异常值标记为 NaN,再用缺失值处理方法处理 适合与模型预测填充结合,减少信息损失
单独编码 异常值本身具有业务含义(如欺诈标记) 创建二值特征“是否为异常值” 风控中强烈推荐,异常值可能蕴含高风险信号
异常值检测与处理决策流程 原始特征数据 选择检测方法:IQR 或 Z-score IQR 法(偏态数据) Z-score 法(正态数据) 选择处理策略 删除 截尾 视为缺失 单独编码 提示:风控场景中建议优先使用“截尾”或“单独编码”,保留异常值可能蕴含的欺诈或高风险信息

4.3 本章小结

  • 缺失值处理:根据缺失率和数据分布选择均值/中位数/众数填充或模型预测填充,注意避免数据泄露。
  • 异常值检测:IQR 法适合偏态数据,Z-score 法适合正态数据,两者可结合使用。
  • 异常值处理:删除、截尾、视为缺失、单独编码四种策略,风控场景中推荐截尾和单独编码。
  • 工程实践:所有填充和检测操作都应在训练集上拟合参数,再应用到验证集和测试集,避免未来信息泄露。
进阶提示:在风控建模中,缺失值和异常值本身可能就是重要特征。建议创建“是否缺失”和“是否异常”的二值特征作为模型输入,往往能提升模型对风险模式的捕捉能力。