4、特征工程基础:时间窗口特征、聚合特征、比率特征、文本特征提取(如理赔描述)

在保险精算坏样本归因分析中,原始理赔数据通常以事务日志形式存在,无法直接用于模型训练。特征工程是将原始日志转化为结构化、可计算特征的关键步骤。本章聚焦于四类核心特征:时间窗口特征、聚合特征、比率特征以及文本特征,并结合理赔场景给出具体实现。

核心原则:特征工程必须与业务逻辑对齐。例如,理赔次数的时间窗口不应跨越保单生效日;文本特征需关注理赔描述中的“拒赔”、“欺诈”、“事故原因”等关键词。

4.1 时间窗口特征

时间窗口特征用于捕捉理赔行为在特定时间段内的统计规律。常见的窗口类型包括:固定长度窗口(如过去30天)、滑动窗口(如过去7天滚动)以及业务周期窗口(如保单年度内)。

窗口类型 定义 保险精算应用场景
固定长度窗口 以当前时间点为基准,向前取固定天数 过去90天内理赔次数、过去180天内赔付金额
滑动窗口 按天/周滚动计算统计量 近7天日均报案量、近30天赔付率趋势
业务周期窗口 以保单生效日为起点,按自然月/季度划分 保单年度内累计出险次数、免赔期内理赔行为
事件间隔窗口 两次理赔事件之间的时间差 相邻两次车险报案间隔天数、医疗险住院间隔
实战案例:在车险理赔归因中,构建“过去30天同一被保险人理赔次数”特征,若该值超过3次,则坏样本概率显著上升。代码实现如下:
import pandas as pd

# 假设 df 包含 claim_date, policy_id, claim_amount 等字段
df['claim_date'] = pd.to_datetime(df['claim_date'])
df = df.sort_values(['policy_id', 'claim_date'])

# 固定长度窗口:过去30天理赔次数
df['claim_count_30d'] = df.groupby('policy_id')['claim_date'].transform(
    lambda x: x.rolling(window='30D', min_periods=1).count()
)

# 事件间隔窗口:相邻理赔间隔天数
df['days_since_last_claim'] = df.groupby('policy_id')['claim_date'].diff().dt.days
时间窗口特征构建流程 原始理赔日志 按保单+时间排序 窗口统计计算 固定长度窗口 滑动窗口 事件间隔窗口 输出:理赔次数/金额/间隔天数特征

4.2 聚合特征

聚合特征通过对理赔记录按某个维度(如保单、客户、车辆)进行分组,计算统计量来刻画群体行为。常用的聚合函数包括:计数、求和、均值、标准差、最大值、最小值、分位数等。

聚合维度 聚合函数 生成特征示例
保单级别 count, sum, mean 保单累计理赔次数、累计赔付金额、平均赔付金额
客户级别 nunique, std, max 客户涉及险种数、理赔金额标准差、单次最大赔付
车辆级别 min, quantile 车辆首次出险时间、理赔金额中位数
地理区域 count, sum 区域报案量、区域总赔付金额
关键技巧:聚合特征容易产生数据泄露。例如,使用全量历史数据计算均值会引入未来信息。正确的做法是:在训练集中,每个样本只使用其时间点之前的聚合统计量。
# 按保单分组,计算截止当前时间之前的聚合特征
def safe_agg(group):
    # 对每个样本,只使用该样本之前的数据
    group = group.sort_values('claim_date')
    group['cum_claim_count'] = range(1, len(group) + 1)
    group['cum_claim_amount'] = group['claim_amount'].cumsum()
    group['avg_claim_amount'] = group['claim_amount'].expanding().mean()
    return group

df = df.groupby('policy_id').apply(safe_agg).reset_index(drop=True)

4.3 比率特征

比率特征通过两个或多个数值字段的比值来消除量纲影响,反映相对关系。在保险精算中,比率特征常用于衡量风险密度、赔付效率等。

比率类型 计算公式 业务含义
赔付率 赔付金额 / 已赚保费 衡量保单盈利能力,>100%表示亏损
案均赔付 总赔付金额 / 理赔次数 反映单次事故严重程度
出险频率 理赔次数 / 保险期间(年) 单位时间内的出险概率
免赔覆盖率 免赔额 / 总赔付金额 客户自付比例,影响理赔意愿
时间密度比 理赔间隔天数 / 保单剩余天数 理赔时间集中度,高值表示近期频繁出险
注意:比率特征的分母不能为零。对于理赔次数为0的保单,案均赔付应填充为0或使用全局均值平滑。建议使用 np.where(denom == 0, 0, num/denom) 进行安全处理。
import numpy as np

# 计算案均赔付,处理分母为0的情况
df['claim_count'] = df['claim_count'].fillna(0)
df['avg_payout'] = np.where(
    df['claim_count'] > 0,
    df['total_claim_amount'] / df['claim_count'],
    0
)

# 计算赔付率(假设已赚保费字段为 earned_premium)
df['loss_ratio'] = np.where(
    df['earned_premium'] > 0,
    df['total_claim_amount'] / df['earned_premium'],
    0
)

4.4 文本特征提取(理赔描述)

理赔描述文本中蕴含大量非结构化信息,如事故原因、责任认定、欺诈线索等。文本特征提取的目标是将这些信息转化为数值向量,供模型使用。

常用的文本特征提取方法包括:

  • 词袋模型(Bag of Words, BoW):统计每个词在文本中出现的次数,忽略词序。适用于高频关键词检测。
  • TF-IDF:考虑词频和逆文档频率,降低常见词的权重,突出特定文档中的关键词。
  • N-gram:提取连续的N个词作为特征,保留局部词序信息。例如,2-gram可捕捉“虚假报案”、“故意碰撞”等短语。
  • 预训练词向量:使用Word2Vec、FastText等模型将词映射为稠密向量,再对文档取平均或加权求和。
  • 规则关键词匹配:基于业务词典,直接标记是否包含“拒赔”、“欺诈”、“酒驾”等敏感词。
方法 维度 优点 缺点 保险场景适用性
词袋模型 高维稀疏 简单、可解释性强 忽略词序和语义 适合关键词统计,如“事故”、“维修”
TF-IDF 高维稀疏 突出重要词,抑制常见词 仍忽略词序 适合区分不同事故类型
N-gram 高维稀疏 保留局部短语信息 维度爆炸,需特征选择 适合“伪造现场”、“虚假理赔”等短语
预训练词向量 低维稠密 语义相似度好,泛化能力强 需要领域微调,可解释性差 适合大规模文本,如理赔报告摘要
规则关键词 低维二值 高精度、高可解释性 依赖专家知识,覆盖不全 适合欺诈检测、拒赔判定
实战建议:在坏样本归因场景中,推荐组合使用“规则关键词 + TF-IDF”。先用规则关键词快速标记高风险样本,再用TF-IDF提取剩余文本中的潜在模式。以下为TF-IDF提取示例:
from sklearn.feature_extraction.text import TfidfVectorizer

# 假设 df['claim_description'] 为理赔描述文本
tfidf = TfidfVectorizer(
    max_features=500,        # 限制最大特征数,避免维度爆炸
    stop_words='english',    # 去除停用词
    ngram_range=(1, 2),      # 使用1-gram和2-gram
    min_df=5,                # 至少在5个文档中出现
    max_df=0.8               # 忽略在80%以上文档中出现的词
)

# 拟合转换
tfidf_matrix = tfidf.fit_transform(df['claim_description'].fillna(''))

# 转换为DataFrame
tfidf_df = pd.DataFrame(
    tfidf_matrix.toarray(),
    columns=tfidf.get_feature_names_out()
)

# 与原数据合并
df = pd.concat([df, tfidf_df], axis=1)
文本特征提取流程(理赔描述) 原始理赔描述文本 文本预处理 分词 → 去停用词 → 词干化/词形还原 规则关键词匹配 TF-IDF / BoW 预训练词向量 输出:二值特征 / 稀疏向量 / 稠密向量
特征工程检查清单:
  • 时间窗口特征是否避免了数据泄露?(使用截止时间前的数据)
  • 聚合特征是否按业务维度正确分组?(保单 vs 客户 vs 车辆)
  • 比率特征的分母是否做了零值保护?
  • 文本特征是否进行了预处理(分词、去停用词)?
  • 特征维度是否可控?(建议使用特征选择或降维)