4. 特征工程与Feature Store

在推荐、风控、实时定价等在线场景中,模型推理往往需要在几十毫秒内拿到一组特征。如果每次请求都临时去业务库做多表关联、聚合和编码,延迟和一致性都难以保证。Vertex AI Feature Store 的核心价值,就是把“特征计算”和“特征读取”解耦:离线侧用 BigQuery 或 Dataflow 批量/流式写入特征值,在线侧通过一个低延迟的在线存储(在线特征服务)按实体主键读取最新特征,训练与推理共用同一份特征定义,从而避免训练/服务偏差(training-serving skew)。

一、Feature Store 的关键对象与数据模型

理解 Feature Store,先要理解它的四层对象:特征组(FeatureGroup)、特征(Feature)、特征值(FeatureValue)和实体(Entity)。特征组是特征的容器,通常对应一张 BigQuery 源表或一个特征视图;特征是最小可读取单元,例如 user_avg_order_amount_7d;实体是主键,例如 user_id、item_id;特征值则是“实体 + 特征 + 时间戳 + 值”的记录。在线读取时,系统按实体主键定位记录,返回该实体最新的特征值。

Vertex AI Feature Store 支持两种注册方式:一是基于 BigQuery 源表直接注册特征组,适合已有离线特征表的团队;二是基于特征视图(FeatureView),把 BigQuery 或 Bigtable 中的数据同步到在线存储。前者偏“离线为主、在线按需同步”,后者更适合需要持续低延迟在线服务的场景。选择哪种方式,取决于特征的更新频率、在线 QPS 和一致性要求。

Vertex AI Feature Store 在线特征服务链路 离线特征计算 BigQuery 聚合 / Dataflow 流式 user_id, ts, feature_value Feature Store 注册 FeatureGroup(特征组) FeatureView(特征视图) 在线特征存储 低延迟 KV 存储 按 entity_id 索引最新值 写入 同步 在线读取 API readFeatureValues(entity_id) 返回最新特征值 + 时间戳 毫秒级读取 在线推理服务 请求:user_id / item_id 拼接特征 → 模型打分 请求特征 返回特征 关键点:离线与在线共用同一份特征定义;在线存储只保留每个实体的最新值;读取按 entity_id 定位,避免全表扫描。 一致性保障:写入时携带事件时间戳,在线读取返回最新值,训练侧按时间点回溯,减少训练/服务偏差。

二、从 BigQuery 到在线服务:一次完整的特征注册

假设我们要为电商推荐模型提供用户侧特征。离线侧在 BigQuery 中已有一张按天更新的表 proj.ds.user_features_daily,字段包括 user_id、event_date、avg_order_amount_7d、order_cnt_30d、last_login_days。接下来做三件事。

第一步,创建特征组。特征组绑定 BigQuery 源表,并指定实体列 user_id 和时间列 event_date。这一步只是“登记”,不会复制数据。示例命令如下:

gcloud ai feature-groups create user_features \
  --region=us-central1 \
  --source-bigquery-uri=bq://proj.ds.user_features_daily \
  --entity-id-columns=user_id \
  --feature-columns=avg_order_amount_7d,order_cnt_30d,last_login_days

第二步,创建特征视图并同步到在线存储。特征视图决定哪些特征进入在线服务,以及同步策略。若特征每天更新一次,可用批量同步;若要求分钟级新鲜度,可配置持续同步。同步时系统按 user_id 聚合,保留每个实体的最新时间戳记录。

gcloud ai feature-views create user_features_online \
  --region=us-central1 \
  --feature-group=user_features \
  --sync-config=cron:"0 2 * * *"

第三步,在线读取。推理服务通过 Feature Store 的在线读取接口,传入 user_id 列表,一次取回多个实体的特征。返回结果包含特征值和时间戳,便于在日志中核对新鲜度。典型调用如下:

response = client.read_feature_values(
    entity_type="user",
    entity_ids=["u_1001", "u_1002"],
    feature_view="projects/proj/locations/us-central1/featureOnlineStores/fs/featureViews/user_features_online"
)
# 返回: {"u_1001": {"avg_order_amount_7d": 268.5, "order_cnt_30d": 12, ...}}

三、低延迟与一致性:工程上真正要盯住的指标

Feature Store 的在线读取延迟通常在个位数毫秒到几十毫秒之间,但实际表现取决于三个因素:实体基数、单次请求的实体数量和在线存储的预热程度。如果一次请求携带上千个实体,读取会退化为批量扫描,延迟明显上升。工程上建议单次请求控制在几十到几百个实体,并对高频实体做本地缓存。

一致性方面,要区分“特征新鲜度”和“训练/服务一致性”。新鲜度由同步频率决定:每天同步一次,在线特征最多滞后 24 小时;持续同步可做到分钟级。训练/服务一致性则要求训练样本使用与在线读取相同的特征定义和时间语义。常见做法是:训练时按样本时间点回溯特征值,在线时读取最新值,并在特征视图中统一时间列含义。

实践建议:先用小规模实体(如 1 万用户)验证在线读取延迟和命中率,再逐步扩大。监控指标至少包括 P95 读取延迟、特征缺失率、同步延迟和在线存储容量。

四、可复用性:让特征成为团队资产

Feature Store 的“可复用”体现在三个层面。第一,定义复用:同一特征组可被多个模型、多个特征视图引用,避免每个团队重复写 SQL。第二,权限复用:通过 IAM 控制谁能注册、谁能读取,特征成为受治理的数据资产。第三,血缘复用:从 BigQuery 源表到特征视图再到在线服务,链路可追溯,出问题时能快速定位是计算错误还是同步延迟。

一个常见的落地节奏是:先选 1~2 个高价值场景(如首页推荐、风控评分)接入,把用户、物品两类核心特征注册进来;稳定后再扩展到更多实体和特征组。不要一开始就追求“全量特征上架”,那会带来治理成本和同步压力。特征工程的重点始终是:在线能低延迟取到、离线能一致复现、团队能安全复用。