4. 特征工程入门:特征分类与构造

特征工程是数据产品从“可用”走向“好用”的关键环节。在分群评分沙盘中,原始数据往往无法直接用于模型训练,必须经过分类识别、清洗转换和衍生构造,才能成为真正有预测能力的特征。本章从特征分类出发,系统讲解数值型、类别型、时序型特征的处理逻辑,并给出常用的特征构造与衍生方法。

4.1 特征三大分类

根据数据本身的测量尺度和业务含义,特征通常分为三类:数值型、类别型和时序型。不同类型对应不同的预处理和编码策略。

特征类型 定义 典型示例 常见问题
数值型 连续或离散的定量测量值,可进行算术运算 年龄、收入、交易金额、点击次数 量纲差异、异常值、长尾分布
类别型 有限个离散取值,表示所属分组或标签 性别、城市、职业、会员等级 基数过高、顺序编码误导、缺失类别
时序型 带有时间顺序的观测值,依赖前后关系 登录时间、购买日期、行为序列 时间窗口选择、周期性、非对齐采样
实践建议:在分群评分场景中,数值型特征通常直接进入距离计算或树模型分裂;类别型特征需要先做编码(如独热、目标编码);时序型特征则必须提取统计量(如最近30天均值)后才能参与建模。

4.2 特征构造与衍生方法

特征构造是从原始数据中主动创建新特征的过程,目的是暴露数据中隐藏的模式。以下列出三类最常用的构造方法。

4.2.1 数值型特征衍生

  • 多项式组合:对两个或多个数值特征做乘、除、平方、交叉乘积,例如 收入 / 年龄、消费金额²。
  • 分箱离散化:将连续值按等距、等频或业务阈值切分为有序类别,例如年龄分箱为 [0-18, 19-35, 36-55, 56+]。
  • 统计聚合:在分组内计算均值、标准差、最大值、最小值、变异系数等,例如“用户过去7天平均订单金额”。
  • 比率与占比:构造分子/分母形式的指标,如“信用卡使用率 = 信用卡消费 / 总消费”。

4.2.2 类别型特征编码

编码方法 适用场景 优点 缺点
独热编码 低基数类别(< 20 个取值) 无顺序假设,模型可解释 维度爆炸,稀疏矩阵
标签编码 有序类别(如等级、学历) 保留顺序信息,节省内存 误导模型认为数值有等差关系
目标编码 高基数类别(城市、商品ID) 压缩维度,直接关联目标 易过拟合,需交叉验证平滑
频次编码 类别分布极不均匀 简单稳定,反映流行度 丢失类别语义

4.2.3 时序型特征提取

  • 滑动窗口统计:在固定时间窗口内计算均值、总和、趋势斜率,例如“最近30天登录天数”。
  • 时间戳分解:从日期时间中提取年、月、日、星期几、是否为节假日、是否为工作日。
  • 间隔与周期:计算相邻事件的时间间隔、距当前时间的距离、周期性编码(如正弦/余弦变换)。
  • 序列聚合:对行为序列做计数、去重计数、最长连续天数、模式匹配等。
案例:在信用卡评分沙盘中,原始数据只有“交易时间”和“交易金额”。通过时序特征衍生,可以构造出“近7天交易笔数”“近30天交易总额”“交易时间间隔标准差”“周末交易占比”等强预测特征,显著提升分群区分度。

4.3 特征构造流程总览

下图展示了从原始数据到可用特征集的完整构造流程,包含分类识别、清洗转换、衍生构造和筛选评估四个阶段。

特征构造流程总览 原始数据 特征分类识别 清洗与转换 特征衍生与构造 数值型:多项式 · 分箱 · 统计聚合 · 比率 类别型:独热 · 标签 · 目标 · 频次编码 时序型:滑动窗口 · 时间分解 · 间隔 · 序列聚合 特征筛选与评估 可用特征集

4.4 实战:从原始交易表构造评分特征

以下代码演示如何从一张原始交易记录表出发,通过特征工程构造出可用于分群评分的特征集。示例使用 Python 风格伪代码,核心逻辑可直接迁移到 Spark、SQL 或 Pandas 环境。

# 原始数据:交易记录表 transactions
# 字段:user_id, trans_date, trans_amount, merchant_type

# 1. 数值型特征衍生
df['amount_log'] = np.log1p(df['trans_amount'])                     # 对数变换
df['amount_per_day'] = df['trans_amount'] / df['days_since_reg']    # 比率特征
df['amount_bin'] = pd.cut(df['trans_amount'], bins=[0,100,500,2000,1e6], labels=['低','中','高','超高'])

# 2. 类别型特征编码(目标编码示例)
target_mean = df.groupby('merchant_type')['target'].mean()
df['merchant_target_enc'] = df['merchant_type'].map(target_mean)

# 3. 时序型特征提取
df['trans_year'] = df['trans_date'].dt.year
df['trans_month'] = df['trans_date'].dt.month
df['trans_weekday'] = df['trans_date'].dt.weekday

# 滑动窗口:每个用户最近30天交易笔数
df['last30d_count'] = df.sort_values('trans_date') \
    .groupby('user_id')['trans_date'] \
    .rolling(window='30D', on='trans_date') \
    .count() \
    .reset_index(level=0, drop=True)

# 4. 聚合特征:用户级汇总
user_features = df.groupby('user_id').agg(
    total_amount=('trans_amount', 'sum'),
    avg_amount=('trans_amount', 'mean'),
    trans_count=('trans_date', 'count'),
    unique_merchant=('merchant_type', 'nunique'),
    last_trans_days=('trans_date', lambda x: (pd.Timestamp.today() - x.max()).days)
).reset_index()
避坑提醒:特征构造时务必注意数据泄露问题。滑动窗口统计只能使用历史数据,不能包含未来信息;目标编码必须在训练集内进行交叉验证平滑,避免直接使用全量目标均值。

4.5 特征构造的常见陷阱与应对

陷阱 表现 应对策略
数据泄露 特征使用了未来信息,模型在线上失效 严格按时间切分训练/验证集;滑动窗口只使用历史窗口
维度灾难 独热编码后特征数量暴增,模型过拟合 使用目标编码、嵌入或特征选择降维
缺失值传播 衍生特征因原始缺失而大量为空 提前填充或标记缺失;使用树模型天然处理缺失
特征冗余 高度相关的特征降低模型稳定性 计算相关性矩阵,保留代表性特征或做PCA
核心原则:特征构造不是越多越好。在分群评分沙盘中,优先保证每个特征都有清晰的业务含义和可解释性,再通过交叉验证评估其增量贡献。一个干净、可解释的50维特征集,往往优于混乱的500维特征集。