2. 特征工程基础:特征分类、存储格式与血缘追踪
在特征回放系统中,特征工程是连接原始数据与模型推理的核心桥梁。本章聚焦于特征的分类体系、存储格式选型以及血缘追踪机制,为后续章节中特征回放的时效性、一致性与可复现性奠定基础。
2.1 特征分类:数值 / 类别 / 文本 / 时序
特征按照数据形态与业务含义可分为四大类,每类在回放场景下的处理逻辑与存储约束各不相同。
| 特征类型 | 典型示例 | 回放关键约束 | 常见预处理 |
|---|---|---|---|
| 数值型 | 用户年龄、商品价格、点击次数 | 需保留原始精度,回放时注意归一化参数一致性 | 标准化、对数变换、分箱 |
| 类别型 | 城市、性别、商品类目 | 回放时需使用同一套编码映射表,避免标签漂移 | Label Encoding、One-Hot、Target Encoding |
| 文本型 | 商品标题、用户评论、搜索 Query | 回放需复现分词与向量化流程,词表版本必须锁定 | 分词、TF-IDF、Embedding |
| 时序型 | 过去7天点击序列、购买间隔 | 回放必须严格对齐时间窗口,防止未来信息泄露 | 滑窗统计、差分、周期性编码 |
实践要点:在特征回放系统中,类别型与文本型特征最容易出现“编码漂移”问题。建议在特征生成时记录编码器版本号或直接存储编码后的 ID,确保回放时映射关系完全一致。
2.2 特征存储格式:Parquet / ORC / Avro
特征回放系统需要频繁读取大规模历史特征数据,存储格式的选择直接影响 I/O 性能与存储成本。以下是三种主流列式与行式存储格式的对比。
| 特性 | Parquet | ORC | Avro |
|---|---|---|---|
| 存储类型 | 列式 | 列式 | 行式 |
| 压缩比 | 高(支持 Snappy / Gzip / Zstd) | 极高(内置轻量级压缩) | 中等(依赖外部编解码器) |
| Schema 演进 | 支持(追加列兼容) | 支持(需谨慎处理) | 原生支持(读写分离 Schema) |
| 谓词下推 | 优秀(统计信息 + 列裁剪) | 优秀(内置索引 + 布隆过滤器) | 较弱(需全量扫描) |
| 适用场景 | 离线分析、特征回放批量读取 | Hive 数仓、大规模聚合查询 | 流式写入、Kafka 消息序列化 |
| 回放系统推荐度 | ★★★★★ | ★★★★☆ | ★★★☆☆ |
选型建议:在特征回放场景中,Parquet 是首选格式。其列式存储特性使得回放时只需读取目标特征列,大幅减少 I/O;配合 Zstd 压缩可在存储与解压速度之间取得良好平衡。ORC 在 Hive 生态中表现更优,Avro 更适合实时特征管道中的序列化传输。
2.3 特征血缘追踪
特征血缘追踪记录了特征从原始数据源到最终特征值的完整变换链路。在特征回放中,血缘信息是定位数据质量问题和复现历史特征的关键。
2.3.1 血缘追踪的核心要素
- 数据源:原始日志表、维表、实时消息队列
- 变换算子:SQL 聚合、UDF 处理、模型 Embedding 提取
- 特征版本:特征生成代码版本、依赖参数版本
- 回放时间戳:特征值对应的业务时间与生成时间
2.3.2 血缘追踪的实现方式
| 实现方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 代码解析 | 解析 SQL / Python 特征脚本,提取数据依赖 | 无需侵入业务代码 | 对动态逻辑解析困难 |
| 元数据注入 | 在特征生成时主动写入血缘元数据 | 准确度高,支持复杂链路 | 需要改造现有特征管道 |
| 日志回放 | 通过特征生成日志逆向还原血缘 | 适合事后排查 | 日志完整性依赖较高 |
常见陷阱:特征血缘追踪中最容易被忽略的是“隐式依赖”——例如特征计算中使用了全局变量、外部配置文件或在线缓存。这些依赖不会出现在 SQL 或代码的显式数据源中,但回放时一旦缺失就会导致特征值不一致。建议在血缘元数据中额外记录“环境依赖”字段。
2.3.3 血缘追踪在回放中的典型应用
- 回放特征验证:通过血缘链路对比回放特征与原始特征是否一致。
- 故障定位:当回放 AUC 出现异常时,沿血缘链路排查是数据源、变换逻辑还是参数问题。
- 特征下线影响分析:通过血缘反向查询哪些模型依赖该特征,评估下线风险。
2.4 本章小结
- 特征按类型分为数值、类别、文本、时序四类,回放时需分别关注归一化一致性、编码映射、词表版本与时间窗口对齐。
- 存储格式推荐 Parquet 作为特征回放的首选,ORC 适用于 Hive 数仓,Avro 更适合实时管道。
- 特征血缘追踪是回放系统可复现性的基石,建议采用元数据注入方式,并记录隐式环境依赖。