4. 特征服务概述:特征工程在实时决策中的角色、特征存储概念、在线与离线特征一致性
在信用额度定价的流式决策场景中,模型推理的时效性直接决定了用户体验与业务风险控制能力。特征工程不再仅仅是离线批处理阶段的“数据加工车间”,而是需要同时支撑离线训练与在线推理的实时基础设施。本章将深入剖析特征工程在实时决策中的核心角色,系统介绍特征存储(Feature Store)的概念,并重点解决在线与离线特征一致性的关键挑战。
4.1 特征工程在实时决策中的角色
传统的特征工程通常以离线批处理方式运行,生成训练数据集后便与模型一同部署。但在流式决策中,特征工程必须从“一次性加工”转变为“持续服务”。其角色体现在以下三个层面:
- 实时特征计算:在毫秒级延迟内,从实时数据流(如交易事件、用户点击、设备指纹)中提取统计量、聚合值、时序特征。
- 特征复用与共享:同一特征(如“过去30天平均消费金额”)在离线训练与在线推理中由同一套逻辑生成,避免重复开发与口径差异。
- 特征生命周期管理:包括特征的注册、版本控制、监控、回滚与废弃,确保模型依赖的特征始终可追溯、可复现。
4.2 特征存储(Feature Store)概念
特征存储是一个专门用于管理、存储、共享和提供特征数据的中央化平台。它解决了传统特征工程中“特征孤岛”与“训练/推理不一致”的痛点。一个完整的特征存储通常包含以下核心组件:
| 组件 | 功能描述 | 在信用额度定价中的示例 |
|---|---|---|
| 特征注册表 | 元数据管理,记录特征名称、类型、来源、版本、创建时间、负责人 | 注册“用户收入等级”、“历史逾期次数”等特征的元数据 |
| 离线特征存储 | 存储历史特征数据,通常基于列式存储(如 Parquet)或数据湖,用于模型训练 | 存储过去3年的用户行为特征,用于训练额度定价模型 |
| 在线特征存储 | 存储最新特征数据,通常基于键值存储(如 Redis、DynamoDB),用于低延迟推理 | 存储用户最新的“近7天消费总额”,供实时额度计算调用 |
| 特征计算引擎 | 定义特征计算逻辑,支持批处理(Spark)与流处理(Flink)两种模式 | 使用 Spark Structured Streaming 计算“滑动窗口平均消费金额” |
| 特征服务 API | 提供统一的特征获取接口,屏蔽底层存储差异 | 模型服务通过 gRPC 调用特征服务,获取用户实时特征向量 |
特征存储的核心价值在于:一次定义,多处使用。特征的计算逻辑在特征注册表中统一定义,离线批处理与在线流处理共享同一份逻辑代码,从根本上消除特征口径不一致的问题。
4.3 在线与离线特征一致性
在线与离线特征一致性是特征存储能否成功落地的关键指标。如果训练时使用的特征分布与推理时不一致,模型性能将显著下降,这种现象被称为训练-推理偏差(Training-Serving Skew)。在信用额度定价中,这种偏差可能导致模型对高风险用户定价过低,或对低风险用户定价过高。
4.3.1 一致性的三个维度
| 维度 | 定义 | 常见问题 | 解决方案 |
|---|---|---|---|
| 逻辑一致性 | 离线与在线使用相同的特征计算逻辑 | 离线使用 Python 脚本,在线使用 Java 实现,结果有细微差异 | 统一特征计算引擎,如 Spark SQL 或 Flink SQL |
| 时间一致性 | 特征的时间窗口对齐,避免数据穿越 | 离线训练使用“截至当日”的数据,在线推理使用了“包含未来”的数据 | 严格的时间点绑定(Point-in-Time Correctness) |
| 数据一致性 | 离线与在线使用相同的数据源与数据版本 | 离线使用清洗后的全量数据,在线使用未清洗的实时数据 | 统一数据管道,实时数据先经过清洗再写入在线存储 |
4.3.2 时间点正确性(Point-in-Time Correctness)
时间点正确性是保证时间一致性的核心原则。它要求:在生成训练样本时,每个样本的特征值必须严格使用该样本对应时间点之前的数据计算,绝不能使用未来的信息。在流式推理中,这一原则天然成立,因为实时特征只能基于已发生的事件计算。但在离线训练中,如果不加注意,很容易因为数据拼接不当而引入未来信息。
4.3.3 一致性保障实践
在 Spark 与特征服务集成中,保障在线与离线特征一致性的最佳实践包括:
- 共享特征定义:使用特征注册表中的统一 SQL 或 Python 函数定义特征逻辑,离线训练与在线推理均引用同一份定义。
- 离线回放(Offline Replay):将实时数据流的历史数据回放到特征计算引擎中,生成与在线存储结构完全一致的离线特征表。
- 一致性校验:定期对离线特征表与在线特征存储中的最新数据进行抽样对比,检查分布差异与数值偏差。
- 特征版本对齐:模型训练时记录所使用的特征版本号,在线推理时加载相同版本的特征逻辑。
4.4 特征服务在信用额度定价中的典型流程
结合上述概念,一个基于特征服务的信用额度定价流式决策流程通常包含以下步骤:
- 步骤1:用户在 App 发起额度调整请求,事件进入 Kafka 实时流。
- 步骤2:Spark Structured Streaming 作业消费事件,调用特征服务 API 获取用户实时特征(如近7天消费、当前负债、收入等级)。
- 步骤3:特征服务从在线特征存储(Redis)中读取最新特征值,若缺失则触发实时计算。
- 步骤4:模型服务接收特征向量,运行定价模型,输出建议额度。
- 步骤5:决策结果写回 Kafka,同时更新在线特征存储中的衍生特征。
- 步骤6:离线管道定期从 Kafka 拉取数据,使用与在线相同的特征逻辑生成训练样本,存入离线特征存储。
mapGroupsWithState 或 flatMapGroupsWithState 算子来管理用户级别的状态特征(如滑动窗口聚合),避免频繁的外部存储调用,同时保证 Exactly-Once 语义。