4. 风险暴露数据清洗:缺失值处理、异常值检测与处理、数据标准化与归一化技术

在风险暴露评估与A/B测试实践中,原始数据几乎总是包含缺失值、异常值以及量纲不一致的问题。本章聚焦于数据清洗的三大核心环节:缺失值处理、异常值检测与处理、数据标准化与归一化。这些步骤直接影响后续风险模型的稳定性和A/B测试的统计效力。

4.1 缺失值处理

缺失值在风险数据中普遍存在,原因包括用户未填写、系统采集故障、数据合并丢失等。处理策略分为删除、填充和模型预测三类。

策略 方法 适用场景 风险提示
删除 行删除、列删除 缺失比例 < 5%,且随机缺失 可能损失样本量,引入偏差
固定值填充 均值、中位数、众数、常数 数值型特征,缺失比例 5%-20% 降低方差,削弱特征区分度
前向/后向填充 时间序列相邻值填充 时序数据,如日交易量、点击流 依赖数据顺序,不适用于无序数据
模型预测 KNN、回归、随机森林 缺失比例 > 20%,特征间相关性强 计算成本高,可能过拟合
实践建议:在A/B测试中,缺失值处理策略应在实验前统一确定,并保持实验组与对照组一致。切勿在实验过程中根据结果动态调整填充方式,否则会引入实验偏差。

4.2 异常值检测与处理

异常值在风险暴露数据中可能代表欺诈、极端风险事件或数据录入错误。检测方法需结合业务含义与统计分布。

4.2.1 常用检测方法

  • Z-Score 法:假设数据服从正态分布,|Z| > 3 视为异常。适用于对称分布数据。
  • IQR 四分位距法:低于 Q1 - 1.5×IQR 或高于 Q3 + 1.5×IQR 视为异常。对偏态分布更稳健。
  • 孤立森林:基于随机森林的集成方法,适合高维数据,不依赖分布假设。
  • DBSCAN 聚类:基于密度,将低密度区域的点标记为异常,适合发现局部异常。

4.2.2 处理策略

处理方式 操作 适用场景
截尾 将异常值替换为边界值(如 99% 分位数) 保留样本量,避免极端值影响模型
删除 直接移除异常样本 确认异常为录入错误或不可恢复
单独标记 新增二值特征标记是否为异常 异常本身可能携带风险信息
分箱处理 将连续值离散化,异常值归入单独箱体 非线性关系,或异常值比例较高
注意:在A/B测试中,异常值处理必须在实验分组前完成,或至少保证处理逻辑在两组中完全对称。若仅在实验组中截尾异常值,会人为改变组间分布,导致效应估计偏差。
异常值检测与处理流程 原始风险数据 Z-Score 法 IQR 四分位距法 孤立森林 DBSCAN 是否异常? 是 否 截尾 / 删除 / 标记 保留原始值 清洗后风险数据集

4.3 数据标准化与归一化

风险暴露数据通常包含不同量纲的特征(如年龄、收入、交易金额、信用分)。标准化与归一化将特征缩放到统一尺度,避免量纲差异主导模型训练或距离计算。

4.3.1 核心方法对比

方法 公式 输出范围 适用场景
Min-Max 归一化 X' = (X - X_min) / (X_max - X_min) [0, 1] 数据有明确边界,如评分、百分比
Z-Score 标准化 X' = (X - μ) / σ 均值为0,标准差为1 数据近似正态分布,存在异常值
Robust 标准化 X' = (X - Median) / IQR 无固定范围 数据含较多异常值,分布偏态
MaxAbs 归一化 X' = X / |X_max| [-1, 1] 稀疏数据,如文本TF-IDF特征

4.3.2 在A/B测试中的特殊考量

  • 分组独立拟合:标准化参数(均值、标准差、最小值、最大值)应在实验组和对照组中分别计算,避免信息泄露。
  • 时间序列场景:使用滚动窗口或历史数据计算标准化参数,防止未来信息污染。
  • 风险评分卡:归一化后特征可解释性下降,建议保留原始分箱映射表用于业务解读。
关键原则:标准化与归一化是数据预处理步骤,而非模型本身。在A/B测试中,若两组数据分布存在天然差异(如不同用户群),标准化后可能掩盖真实效应。建议在标准化前先进行分布一致性检验(如KS检验)。
标准化与归一化方法对比 原始风险特征 Min-Max 归一化 [0, 1] 有界 Z-Score 标准化 μ=0, σ=1 Robust 标准化 中位数 ± IQR MaxAbs 归一化 [-1, 1] 稀疏 统一尺度特征 选择依据 分布形态 异常值比例 模型算法要求

4.4 代码示例:Python 实现

以下代码演示了缺失值填充、异常值检测与标准化处理的典型流程,适用于风险暴露数据预处理。

import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from scipy import stats

# 示例数据
df = pd.DataFrame({
    'age': [25, 30, np.nan, 35, 40, 28, 32, np.nan, 45, 38],
    'income': [50000, 60000, 55000, 120000, 48000, 52000, 58000, 62000, 70000, 54000],
    'credit_score': [650, 700, 680, 720, 600, 640, 690, 710, 660, 630]
})

# 1. 缺失值处理:用中位数填充
df['age'].fillna(df['age'].median(), inplace=True)

# 2. 异常值检测:IQR 法
Q1 = df['income'].quantile(0.25)
Q3 = df['income'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
df['income_outlier'] = ((df['income'] < lower_bound) | (df['income'] > upper_bound)).astype(int)

# 3. 异常值处理:截尾到边界
df['income_capped'] = df['income'].clip(lower=lower_bound, upper=upper_bound)

# 4. 标准化:Z-Score
scaler = StandardScaler()
df[['age_scaled', 'income_scaled', 'credit_scaled']] = scaler.fit_transform(
    df[['age', 'income_capped', 'credit_score']]
)

# 5. 归一化:Min-Max
minmax_scaler = MinMaxScaler()
df[['age_norm', 'income_norm', 'credit_norm']] = minmax_scaler.fit_transform(
    df[['age', 'income_capped', 'credit_score']]
)

print(df.head())
实践要点:
  • 在A/B测试中,fit_transform 应在实验组和对照组上分别调用,避免使用全量数据拟合参数。
  • 异常值标记特征(如 income_outlier)可作为风险模型的额外输入,提升对极端事件的敏感度。
  • 标准化后的特征不再具有原始业务含义,建议保留原始特征用于业务报告。

4.5 本章小结

风险暴露数据清洗是A/B测试与风险评估的基石。缺失值处理需权衡样本量与偏差;异常值检测应结合业务逻辑与统计方法;标准化与归一化确保特征公平参与模型计算。在实际项目中,建议将清洗逻辑封装为可复用的预处理管道,并在实验设计阶段明确清洗策略,避免事后调整引入偏差。