4. 数据采集与预处理:从数据库/API获取保单与理赔数据、处理缺失值、异常值检测与处理

实时赔付率预测模型的质量高度依赖输入数据的完整性与准确性。本章聚焦于从生产环境采集原始保单与理赔数据,并完成缺失值填充、异常值识别与清洗,为后续特征工程与模型训练奠定可靠基础。

4.1 数据源与采集策略

实时赔付率模型通常需要融合两类核心数据源:保单主数据(静态属性)与理赔流水数据(动态事件)。采集方式根据系统架构分为数据库直连与API流式接入。

数据源类型 典型表/接口 关键字段示例 采集频率
保单主数据 policy_info policy_id, product_code, underwrite_date, premium, sum_insured, risk_level 每日批量(T+1)
理赔流水数据 claim_transaction claim_id, policy_id, claim_date, claim_amount, claim_type, status 实时/准实时(Kafka/API)
历史赔付率聚合 loss_ratio_agg policy_id, period, earned_premium, incurred_loss, loss_ratio 每日批量
生产环境建议:对于实时预测场景,理赔数据应优先通过消息队列(如Kafka)或REST API接入,避免频繁直连OLTP数据库造成锁表或性能抖动。保单主数据变化频率低,可采用每日增量同步。

4.2 数据采集流程架构

下图展示了从数据源到预处理模块的标准化采集管道,包含批处理与流处理两条路径。

数据采集与预处理管道架构 保单主数据库 MySQL / Oracle 理赔API / Kafka 实时事件流 历史聚合表 Hive / ClickHouse 数据采集层:Sqoop / Flume / Kafka Connect / Logstash 批量拉取 + 实时订阅 预处理模块:缺失值处理 → 异常值检测 → 格式统一 Spark Streaming / Pandas / 自定义UDF 清洗后宽表 → 特征工程

4.3 缺失值处理策略

保单与理赔数据中常见的缺失场景包括:理赔金额未录入、风险等级缺失、保单生效日期为空等。不同字段的缺失机制与业务含义不同,需采用差异化填充策略。

字段 缺失率典型范围 缺失原因 推荐处理方法
claim_amount 5% – 15% 理赔未结案、人工录入遗漏 按险种+地区分组中位数填充
risk_level 2% – 8% 新客户未评级、系统迁移丢失 众数填充或标记为“未知”类别
underwrite_date < 1% 数据接口异常 使用policy_effective_date回填
claim_type 3% – 10% 理赔分类未更新 模型预测分类或标记为“其他”
关键原则:对于实时预测场景,缺失值处理必须在线性时间内完成,避免使用迭代算法。推荐预计算分组统计量(如均值、中位数)并存入查找表,在预处理阶段直接映射填充。

4.4 异常值检测与处理

赔付率相关数据中,异常值通常表现为:理赔金额远超正常范围、保单保费为负值、理赔日期早于保单生效日期等。异常值会严重扭曲模型训练,必须系统化检测与处理。

4.4.1 异常值检测方法对比

方法 适用场景 优点 缺点
Z-Score(3σ) 近似正态分布的连续变量 计算简单,可解释性强 对偏态分布不鲁棒
IQR(四分位距) 偏态分布、含离群点的数据 不受极端值影响 阈值选择较主观
孤立森林 高维数据、非监督场景 线性时间复杂度,适合实时 对局部异常不敏感
业务规则 强约束字段(如保费>0) 零误报,符合监管要求 无法发现未知异常模式

4.4.2 异常值处理流程

下图展示了从检测到处理的完整决策链路,确保异常值被合理识别并处置。

异常值检测与处理决策流程 原始数据输入 异常检测:Z-Score / IQR / 孤立森林 是否异常? 保留 → 特征工程 处理策略:截尾 / 替换 / 标记 根据业务规则与分布特征选择

4.5 数据预处理代码示例

以下Python代码片段展示了使用Pandas对保单数据进行缺失值填充与异常值检测的典型实现,可直接嵌入实时预处理管道。

import pandas as pd
import numpy as np

# 加载原始保单与理赔数据
policy_df = pd.read_parquet('policy_data.parquet')
claim_df = pd.read_parquet('claim_data.parquet')

# 合并为宽表
merged_df = pd.merge(policy_df, claim_df, on='policy_id', how='left')

# ========== 缺失值处理 ==========
# 按险种分组中位数填充理赔金额
claim_median = merged_df.groupby('product_code')['claim_amount'].transform('median')
merged_df['claim_amount'].fillna(claim_median, inplace=True)

# 风险等级众数填充
risk_mode = merged_df['risk_level'].mode()[0]
merged_df['risk_level'].fillna(risk_mode, inplace=True)

# ========== 异常值检测(IQR方法) ==========
def detect_outliers_iqr(series):
    Q1 = series.quantile(0.25)
    Q3 = series.quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    return (series < lower_bound) | (series > upper_bound)

# 对理赔金额进行异常标记
merged_df['claim_amount_outlier'] = detect_outliers_iqr(merged_df['claim_amount'])

# 异常值截尾处理(替换为上下限)
upper_limit = merged_df['claim_amount'].quantile(0.95)
lower_limit = merged_df['claim_amount'].quantile(0.05)
merged_df['claim_amount'] = merged_df['claim_amount'].clip(lower_limit, upper_limit)

# 输出清洗后数据
merged_df.to_parquet('cleaned_data.parquet', index=False)
print(f"清洗完成,共处理 {len(merged_df)} 条记录,异常值占比 {merged_df['claim_amount_outlier'].mean():.2%}")
实时场景注意:上述代码中的groupby操作在超大规模数据(千万级)上可能产生延迟。生产环境建议使用Spark或Flink进行分布式预处理,并将分组统计量预计算后广播到各工作节点。

4.6 数据质量监控指标

在预处理管道上线后,需要持续监控数据质量,确保模型输入稳定。以下为关键监控指标及其告警阈值。

监控指标 计算方式 正常范围 告警阈值
缺失率 缺失值数量 / 总记录数 < 5% > 10%
异常值占比 标记为异常的记录数 / 总记录数 < 3% > 8%
数据延迟 最新记录时间戳与当前时间差 < 30分钟 > 2小时
字段完整性 必填字段非空比例 100% < 99%
最佳实践:将数据质量监控与模型预测结果联动。当某时段缺失率或异常值占比突增时,自动触发模型回滚至上一版本,并发送告警给数据工程团队,避免劣质数据影响赔付率预测准确性。