ML.ENTITY_FEATURES_AT_TIME 函数

本文档介绍 ML.ENTITY_FEATURES_AT_TIME 函数,此函数可让您在检索特征时对多个实体使用多个截止时间点,因为如果特征包含时间敏感数据,则可能具有时间依赖项。为避免数据泄露,请在训练模型和运行推断时使用时间点功能。

使用此函数可以从多个实体检索多个时间点的特征。例如,您可以检索实体 1 在不晚于三个不同时间点创建的特征,以及检索实体 2 在不晚于另一个不同时间点创建的特征。在检索特征时,可以使用 ML.FEATURES_AT_TIME 函数对所有实体使用相同的截止时间点。

语法

ML.ENTITY_FEATURES_AT_TIME(
  { TABLE feature_table | (feature_query_statement) },
  { TABLE entity_time_table | (entity_time_query_statement) }
  [, num_rows => INT64][, ignore_feature_nulls => BOOL])

参数

ML.ENTITY_FEATURES_AT_TIME 接受以下参数:

  • feature_tableSTRING 值,指定包含特征数据的 BigQuery 表的名称。特征表必须包含以下列:

    • entity_idSTRING 列,包含与特征相关的实体的 ID。
    • 一个或多个特征列。
    • feature_timestampTIMESTAMP 列,标识特征数据的上次更新时间。

    列名称不区分大小写。例如,您可以使用名为 Entity_ID 的列,而不是 entity_id

    特征表必须采用格式,每个特征占一列。

  • feature_query_statementSTRING 值,指定返回特征数据的 GoogleSQL 查询。此查询返回的列必须与 feature_table 相同。如需了解 feature_query_statement 子句支持的 SQL 语法,请参阅 GoogleSQL 查询语法

  • entity_time_tableSTRING 值,指定将实体 ID 映射到特征查找时间的 BigQuery 表的名称。实体时间表必须包含以下列:

    • entity_id:包含实体 ID 的 STRING 列。
    • timeTIMESTAMP 列,标识在为实体 ID 表示的实体选择特征时用作截止时间的时间点。

    列名称不区分大小写。例如,您可以使用名为 Entity_ID 的列,而不是 entity_id

    entity_time_table 标识的表不得大于 100 MB。

  • entity_time_query_statementSTRING 值,指定返回实体时间数据的 GoogleSQL 查询。此查询返回的列必须与 entity_time_table 相同。如需了解 entity_time_query_statement 子句支持的 SQL 语法,请参阅 GoogleSQL 查询语法

  • num_rowsINT64 值,指定对于 entity_time_table 中的每一行要返回的行数。默认值为 1

  • ignore_feature_nullsBOOL 值,指示是否将特征列中的 NULL 值替换为同一实体时间上最接近的前一行中的该特征列值。例如,对于以下特征表和实体时间表:

    特征表

    +-----------+------+------+--------------------------+
    | entity_id | f1   | f2   | feature_timestamp        |
    +-----------+------+------+--------------------------+
    | '2'       | 5.0  | 8.0  | '2022-06-10 09:00:00+00' |
    +-----------+------+------+--------------------------+
    | '2'       | 2.0  | 4.0  | '2022-06-10 12:00:00+00' |
    +-----------+------+------+--------------------------+
    | '2'       | 7.0  | NULL | '2022-06-11 10:00:00+00' |
    +-----------+------+------+--------------------------+
    

    实体时间表

    +-----------+--------------------------+
    | entity_id | time                     |
    +-----------+--------------------------+
    | '2'       | '2022-06-11 10:00:00+00' |
    +-----------+--------------------------+
    

    运行此查询:

    SELECT *
    FROM
      ML.ENTITY_FEATURES_AT_TIME(
        TABLE mydataset.feature_table,
        TABLE mydataset.entity_time_table,
        num_rows => 1,
        ignore_feature_nulls => TRUE);

    产生以下输出,其中实体 ID 2 时间戳为 '2022-06-10 12:00:00+00' 的行中的 f2 值替换了时间戳为 '2022-06-11 10:00:00+00' 的行中的 NULL 值:

    +-----------+------+------+--------------------------+
    | entity_id | f1   | f2   | feature_timestamp        |
    +-----------+------+------+--------------------------+
    | '2'       | 7.0  | 4.0  | '2022-06-11 10:00:00+00' |
    +-----------+------+------+--------------------------+
    

    如果没有可用的替换值(例如,该实体 ID 没有更早的行),则返回 NULL 值。

    默认值为 FALSE

输出

ML.ENTITY_FEATURES_AT_TIME 返回满足截止时间点条件的输入表行,其中 feature_timestamp 列显示实体时间表的 time 列中的时间戳。

由于您可以指定从同一实体的多个时间点检索特征,因此根据特征和实体时间表中的时间戳以及您指定的 num_rows 值,可能会返回重复的行。例如,如果特征表中实体 ID 1 只有一行,并具有时间戳 2022-06-11 10:00:00+00;同时,实体时间表中实体 ID 1 有两行,并均具有较晚的时间戳。则函数输出会包含两行,并均具有相同的实体 ID 1 特征值。

如果满足以下任一条件:

  • 未在特征表中找到实体时间表中的实体 ID。
  • 特征表中实体 ID 与实体时间表中实体 ID 匹配的行不满足时间点条件。

那么该函数不会返回该实体时间表行的任何输出。

示例

示例 1

此示例展示了如何仅使用在 mydataset.entity_time_table 中标识的时间戳之前创建或更新的特征重新训练模型:

CREATE OR REPLACE
  `mydataset.mymodel` OPTIONS (WARM_START = TRUE)
AS
SELECT * EXCEPT (feature_timestamp, entity_id)
FROM
  ML.ENTITY_FEATURES_AT_TIME(
    TABLE `mydataset.feature_table`,
    TABLE `mydataset.entity_time_table`,
    num_rows => 1,
    ignore_feature_nulls => TRUE);

示例 2

此示例展示了如何根据在 mydataset.entity_time_table 中标识的时间戳之前创建或更新的特征从模型获取预测结果:

SELECT
  *
FROM
  ML.PREDICT(
    MODEL `mydataset.mymodel`,
    (
      SELECT * EXCEPT (feature_timestamp, entity_id)
      FROM
        ML.ENTITY_FEATURES_AT_TIME(
          TABLE `mydataset.feature_table`,
          TABLE `mydataset.entity_time_table`,
          num_rows => 1,
          ignore_feature_nulls => TRUE)
    )
  );

示例 3

这是一个虚构的示例,可用于查看函数的输出:

WITH
  feature_table AS (
    SELECT * FROM UNNEST(
      ARRAY<STRUCT<entity_id STRING, f_1 FLOAT64, f_2 FLOAT64, feature_timestamp TIMESTAMP>>[
        ('id1', 1.0, 1.0, TIMESTAMP '2022-06-10 12:00:00+00'),
        ('id2', 12.0, 24.0, TIMESTAMP '2022-06-11 12:00:00+00'),
        ('id1', 11.0, NULL, TIMESTAMP '2022-06-11 12:00:00+00'),
        ('id1', 6.0, 12.0, TIMESTAMP '2022-06-11 10:00:00+00'),
        ('id2', 2.0, 4.0, TIMESTAMP '2022-06-10 12:00:00+00'),
        ('id2', 7.0, NULL, TIMESTAMP '2022-06-11 10:00:00+00')])
  ),
  entity_time_table AS (
    SELECT * FROM UNNEST(
      ARRAY<STRUCT<entity_id STRING, time TIMESTAMP>>[
        ('id1', TIMESTAMP '2022-06-12 12:00:00+00'),
        ('id2', TIMESTAMP '2022-06-11 10:00:00+00'),
        ('id1', TIMESTAMP '2022-06-10 13:00:00+00')])
  )
SELECT *
FROM
  ML.ENTITY_FEATURES_AT_TIME(
    TABLE feature_table, TABLE entity_time_table, num_rows => 1, ignore_feature_nulls => TRUE);