4. 数据预处理:缺失值处理、异常值检测、数据标准化与归一化技术在保险数据中的应用
在保险精算建模中,原始数据通常来自承保系统、理赔系统、第三方征信等异构源,存在大量缺失、异常和量纲不一致的问题。本章聚焦于数据预处理的核心环节,确保输入模型的数据质量满足坏样本归因分析的要求。
核心原则:保险数据预处理必须兼顾统计合理性(不引入偏差)与业务可解释性(保留风险区分度)。任何预处理操作都应记录转换参数,以便在模型上线时对生产数据执行相同的变换。
4.1 缺失值处理
保险数据中缺失值的产生原因包括:客户未填写、系统未采集、数据清洗异常等。处理策略需根据缺失机制(MCAR、MAR、MNAR)和变量重要性选择。
4.1.1 缺失机制与处理策略对比
| 缺失机制 | 定义 | 保险场景示例 | 推荐处理方式 |
|---|---|---|---|
| 完全随机缺失(MCAR) | 缺失与观测数据无关 | 系统随机丢包导致的年龄字段缺失 | 删除或均值/中位数填充 |
| 随机缺失(MAR) | 缺失与其他观测变量相关 | 高收入人群更倾向不填写职业信息 | 多重插补(MICE)或模型预测填充 |
| 非随机缺失(MNAR) | 缺失与未观测到的因素相关 | 高风险客户故意隐瞒既往病史 | 单独编码为“未知”类别,或使用Heckman校正 |
4.1.2 常用填充方法
- 统计填充:数值型用均值/中位数,分类型用众数。适用于MCAR且缺失率<5%的场景。
- 模型预测填充:使用KNN、随机森林或线性回归预测缺失值。适用于MAR且变量间相关性较强的场景。
- 多重插补(MICE):生成多个完整数据集,合并估计结果。适用于缺失率较高(5%~30%)且需要保留不确定性的场景。
- 缺失指示变量:新增二值变量标记是否缺失,保留缺失信息。适用于MNAR或缺失本身具有预测意义的场景(如“是否填写收入”可能反映客户风险意识)。
保险业务避坑:对于“理赔金额”等关键响应变量,若缺失率超过30%,建议优先排查数据采集链路问题,而非盲目填充。对于“既往病史”等敏感字段,填充时需注意隐私合规要求。
4.2 异常值检测
保险数据中的异常值可能源于录入错误(如年龄200岁)、欺诈行为(如理赔金额异常高)或真实但极端的风险特征(如超高保额客户)。检测方法需区分全局异常与局部异常。
4.2.1 异常值检测方法对比
| 方法 | 适用场景 | 保险应用示例 | 优缺点 |
|---|---|---|---|
| Z-Score(3σ原则) | 近似正态分布的单变量 | 检测年龄字段中的极端值 | 简单快速,但对偏态分布不鲁棒 |
| IQR(四分位距法) | 偏态分布的单变量 | 检测理赔金额中的离群点 | 不受极端值影响,适合保险长尾分布 |
| 孤立森林(Isolation Forest) | 高维数据、多变量 | 检测欺诈理赔组合模式 | 线性时间复杂度,适合大规模数据 |
| DBSCAN聚类 | 密度分布不均的数据 | 检测异常保单组合 | 可发现局部异常,但参数敏感 |
4.2.2 异常值处理策略
- 截尾(Winsorization):将异常值替换为指定百分位数的值(如1%和99%分位数)。适用于数值型变量,保留样本量。
- 删除:仅当确认异常值由录入错误导致且占比<1%时使用。
- 单独编码:将异常值归为“高/低风险”类别,保留业务含义。
- 模型鲁棒化:使用对异常值不敏感的模型(如树模型、Huber回归),避免预处理过度修正。
精算实践建议:对于“保费/保额比”等比率变量,建议先进行对数变换再检测异常值,因为原始尺度下长尾分布会导致大量“假异常”。同时,异常值检测阈值应结合业务容忍度动态调整,而非机械套用统计规则。
4.3 数据标准化与归一化
保险数据中变量量纲差异巨大(如年龄20~80岁 vs 保额10万~1000万)。标准化与归一化确保不同量纲的变量在模型中具有可比性,尤其对距离敏感模型(如KNN、SVM、逻辑回归)至关重要。
4.3.1 标准化与归一化方法对比
| 方法 | 公式 | 输出范围 | 适用场景 |
|---|---|---|---|
| Z-Score标准化 | \( z = \frac{x - \mu}{\sigma} \) | 无固定范围,均值为0,标准差为1 | 数据近似正态分布,或模型假设特征服从高斯分布 |
| Min-Max归一化 | \( x' = \frac{x - \min}{\max - \min} \) | [0, 1] | 数据有明确边界,或需要保持稀疏性(如神经网络输入层) |
| Robust标准化 | \( x' = \frac{x - \text{median}}{\text{IQR}} \) | 无固定范围,受异常值影响小 | 数据包含异常值,或分布严重偏态 |
| MaxAbs归一化 | \( x' = \frac{x}{\max(|x|)} \) | [-1, 1] | 稀疏数据或已中心化的数据 |
4.3.2 保险场景选择指南
- 逻辑回归/线性模型:优先使用Z-Score标准化,确保系数可比。
- 神经网络/深度学习:推荐Min-Max归一化到[0,1]或[-1,1],加速收敛。
- 树模型(随机森林、XGBoost):通常不需要标准化,但若特征工程中包含距离计算(如聚类特征),则需标准化。
- 聚类/降维(K-Means、PCA):必须标准化,否则量纲大的变量会主导距离计算。
实操注意:标准化参数(均值、标准差、最小值、最大值)必须从训练集计算,并保存为pickle或JSON文件,用于验证集和测试集的变换。切勿在全体数据上计算后再拆分,否则会导致数据泄露。
4.4 数据预处理流程总览
以下SVG图展示了保险数据预处理的完整流程,从原始数据到模型就绪数据的三个核心阶段:缺失值处理、异常值检测、标准化与归一化。
4.5 代码示例:保险数据预处理流水线
以下Python代码展示了使用scikit-learn构建保险数据预处理流水线的完整过程,包含缺失值填充、异常值截尾和标准化。
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
# 模拟保险数据
data = pd.DataFrame({
'age': [25, 45, np.nan, 35, 60, 28, 52, np.nan, 40, 33],
'income': [50000, 120000, 80000, np.nan, 200000, 45000, 150000, 95000, np.nan, 70000],
'claim_amount': [2000, 5000, 15000, 3000, 100000, 2500, 8000, 4000, 6000, 3500],
'is_fraud': [0, 0, 1, 0, 1, 0, 0, 0, 0, 0]
})
# 分离特征和标签
X = data.drop('is_fraud', axis=1)
y = data['is_fraud']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
# 定义数值型特征的预处理流水线
numeric_features = ['age', 'income', 'claim_amount']
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')), # 缺失值用中位数填充
('scaler', StandardScaler()) # Z-Score标准化
])
# 组合预处理
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features)
]
)
# 完整流水线(此处以逻辑回归为例)
from sklearn.linear_model import LogisticRegression
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('classifier', LogisticRegression(random_state=42))
])
# 训练模型
pipeline.fit(X_train, y_train)
# 评估
score = pipeline.score(X_test, y_test)
print(f"测试集准确率: {score:.3f}")
# 保存预处理参数(用于生产环境)
import joblib
joblib.dump(pipeline.named_steps['preprocessor'], 'insurance_preprocessor.pkl')
关键要点:
- 使用
ColumnTransformer对不同类型特征应用不同预处理策略,避免“一刀切”。 - 缺失值填充和标准化参数仅从训练集学习,测试集和验证集使用相同的变换。
- 将预处理和模型封装在同一个
Pipeline中,确保交叉验证时不会发生数据泄露。 - 生产环境中使用
joblib保存预处理对象,保证线上线下一致。
4.6 保险数据预处理避坑清单
| 常见错误 | 后果 | 正确做法 |
|---|---|---|
| 在全体数据上计算标准化参数后再拆分 | 数据泄露,模型评估过于乐观 | 先拆分,再在训练集上fit,在测试集上transform |
| 对类别型变量直接标准化 | 破坏类别语义,引入虚假距离 | 先进行One-Hot编码或目标编码,再标准化数值部分 |
| 忽略时间序列顺序进行缺失值填充 | 使用未来信息填充过去,导致时序泄露 | 使用滚动窗口或前向填充,保持时间顺序 |
| 对理赔金额等长尾变量直接使用Z-Score | 异常值导致均值和标准差失真 | 先进行对数变换或使用Robust标准化 |
| 删除大量缺失样本(缺失率>10%) | 样本量减少,引入选择偏差 | 优先使用多重插补或缺失指示变量 |
精算合规提醒:在保险监管环境中(如IFRS 17、Solvency II),数据预处理步骤必须完整记录在模型文档中,包括缺失值填充方法的选择理由、异常值检测阈值、标准化参数来源。建议使用DVC(Data Version Control)或MLflow追踪每次预处理的参数变化。