特征集具体化概念

具体化以源数据为基础计算特征值。 开始时间和结束时间值定义特征窗口。 具体化作业计算此特征窗口中的特征。 具体化后的特征值随后被存储在联机或离线具体化存储中。 数据具体化后,所有特征查询都可以使用具体化存储中的这些值。

如果没有具体化,特征集离线查询将动态地对源应用转换,以便在查询返回值之前计算特征。 该过程在原型制作阶段运行良好。 但是,对于生产环境下的训练和推理操作,应在训练或推理之前具体化特征。 该阶段的具体化能提供更高的可靠性和可。

探索特征具体化

具体化作业 UI 显示离线和联机具体化存储中的数据具体化状态,以及具体化作业列表。

显示功能集具体化作业用户界面的屏幕截图。

在特征窗口中:

  • 顶部的时序图表显示特征窗口期间的数据间隔,以及离线和联机存储的具体化状态。
  • 底部的作业列表显示处理窗口中与所选特征窗口重叠的所有具体化作业。

数据具体化状态和数据间隔

数据间隔是一个时间窗口,功能集在该窗口内将其特征值具体化为以下状态之一:

  • 完成(绿色) - 数据具体化成功
  • 未完成(红色) - 数据间隔中的一个或多个具体化作业被取消或失败
  • 挂起(蓝色) - 数据间隔中的一个或多个具体化作业正在进行中
  • 无(灰色) - 数据间隔中没有提交的具体化作业

特征集运行具体化作业时,会创建或合并数据间隔:

  • 时间线上连续且有相同数据具体化状态的数据间隔会成为一个数据间隔
  • 在一个数据间隔中,当一部分特征数据被再次具体化,并且该部分获得不同的数据具体化状态时,数据间隔会被拆分为多个数据间隔

用户选择特征窗口时可能会在该窗口中看到具有不同数据具体化状态的多个数据间隔。 用户可能会看到时间线上有不相交的多个数据间隔。 例如,前面的快照在离线具体化存储的特征窗口中有 16 个数据间隔

在任何给定时间,特征集最多可以有 2,000 个数据间隔。 特征集达到该限制后,任何具体化作业都不可再运行。 用户必须创建启用了具体化的新特征集版本。 对于新特征集版本,请从头开始具体化离线和联机存储中的特征。

为了避免限制,用户应提前运行回填作业,以填充数据间隔的空白。 该操作会合并数据间隔并减少总数。

数据具体化作业

在运行数据具体化作业之前,请启用特征集级别的离线和/或联机数据具体化。

from azure.ai.ml.entities import (
    MaterializationSettings,
    MaterializationComputeResource,
)

# Turn on both offline and online materialization on the "accounts" featureset.

accounts_fset_config = fs_client._featuresets.get(name="accounts", version="1")

accounts_fset_config.materialization_settings = MaterializationSettings(
    offline_enabled=True,
    online_enabled=True,
    resource=MaterializationComputeResource(instance_type="standard_e8s_v3"),
    spark_configuration={
        "spark.driver.cores": 4,
        "spark.driver.memory": "36g",
        "spark.executor.cores": 4,
        "spark.executor.memory": "36g",
        "spark.executor.instances": 2,
    },
    schedule=None,
)

fs_poller = fs_client.feature_sets.begin_create_or_update(accounts_fset_config)
print(fs_poller.result())

可以将数据具体化作业提交为:

  • 回填作业 - 手动提交的批量具体化作业
  • 重复具体化作业 - 按计划间隔触发的自动具体化作业。

警告

如果禁用了特征集级别的离线和/或联机数据具体化,那么已经在离线和/或联机具体化中具体化的数据将不再可用。 离线和/或联机具体化存储中的数据具体化状态将重置为 None

可以按以下项目提交回填作业:

  • 数据具体化状态
  • 被取消或失败具体化作业的作业 ID

根据数据具体化状态回填数据

用户可以提交以下回填请求:

  • 数据具体化状态值列表 - 未完成、完成或无
  • 特征窗(可选)
from datetime import datetime
from azure.ai.ml.entities import DataAvailabilityStatus

st = datetime(2022, 1, 1, 0, 0, 0, 0)
et = datetime(2023, 6, 30, 0, 0, 0, 0)

poller = fs_client.feature_sets.begin_backfill(
    name="transactions",
    version="1",
    feature_window_start_time=st,
    feature_window_end_time=et,
    data_status=[DataAvailabilityStatus.NONE],
)
print(poller.result().job_ids)

提交回填请求后,将为匹配数据具体化状态(未完成、完成或无)的每个数据间隔创建一个新的具体化作业。 此外,相关数据间隔必须位于规定的特征窗口中。 如果数据间隔的数据具体化状态为 Pending,则不会提交该间隔的具体化作业。

回填请求中的特征窗口开始时间和结束时间都是可选项:

  • 如果未提供特征窗口开始时间,则将采用第一个数据具体化状态不为 None数据间隔开始时间。
  • 如果未提供特征窗口结束时间,则将采用第一个数据具体化状态不为 None数据间隔结束时间。

注意

如果没有给特征集提交回填或重复作业,则第一个回填作业必须提交特征窗口的开始和结束时间。

此示例包含以下当前数据间隔和具体化状态值:

开始时间 结束时间 数据具体化状态
2023-04-01T04:00:00.000 2023-04-02T04:00:00.000 None
2023-04-02T04:00:00.000 2023-04-03T04:00:00.000 Incomplete
2023-04-03T04:00:00.000 2023-04-04T04:00:00.000 None
2023-04-04T04:00:00.000 2023-04-05T04:00:00.000 Complete
2023-04-05T04:00:00.000 2023-04-06T04:00:00.000 None

此回填请求具有以下值:

  • 数据具体化 data_status=[DataAvailabilityStatus.Complete, DataAvailabilityStatus.Incomplete]
  • 特征窗口开始 = 2023-04-02T12:00:00.000
  • 特征窗口结束 = 2023-04-04T12:00:00.000

创建以下具体化作业:

  • 作业 1:进程特征窗口 [2023-04-02T12:00:00.000, 2023-04-03T04:00:00.000
  • 作业 2:进程特征窗口 [2023-04-04T04:00:00.000, 2023-04-04T12:00:00.000

如果两个作业都成功完成,新的数据间隔和具体化状态值将变为:

开始时间 结束时间 数据具体化状态
2023-04-01T04:00:00.000 2023-04-02T04:00:00.000 None
2023-04-02T04:00:00.000 2023-04-02T12:00:00.000 Incomplete
2023-04-02T12:00:00.000 2023-04-03T04:00:00.000 Complete
2023-04-03T04:00:00.000 2023-04-04T04:00:00.000 None
2023-04-04T04:00:00.000 2023-04-05T04:00:00.000 Complete
2023-04-05T04:00:00.000 2023-04-06T04:00:00.000 None

2023-04-02创建了一个新的数据间隔,因为当天的一半现在有不同的具体化状态:Complete。 尽管 2023-04-04 的半天运行了新的具体化作业,但由于具体化状态没有变化,所以数据间隔没有变化(拆分)。

如果用户仅对数据具体化 data_status=[DataAvailabilityStatus.Complete, DataAvailabilityStatus.Incomplete] 发出回填请求,而不设置特征窗口开始和结束时间,请求会使用本节前面提到的参数默认值创建以下作业:

  • 作业 1:进程特征窗口 [2023-04-02T04:00:00.000, 2023-04-03T04:00:00.000
  • 作业 2:进程特征窗口 [2023-04-04T04:00:00.000, 2023-04-05T04:00:00.000

对比最新请求作业的特征窗口,以及上一示例中所示的请求作业。

按作业 ID 回填数据

也可以使用作业 ID 创建回填请求。 这种方法可以方便地重试失败或被取消的具体化作业。 首先,找到要重试作业的 ID:

  • 导航到特征集的“具体化作业”用户界面
  • 选择具有“失败状态”值的特定作业“显示名称
  • 在作业“概述”页面中,找到“名称”属性下的相关作业 ID 值,以 Featurestore-Materialization- 开头。

poller = fs_client.feature_sets.begin_backfill(
    name="transactions",
    version=version,
    job_id="<JOB_ID_OF_FAILED_MATERIALIZATION_JOB>",
)
print(poller.result().job_ids)

可以使用失败或被取消具体化作业的 ID 提交回填作业。 在这种情况下,失败或被取消的原始具体化作业的特征窗口数据状态应为 Incomplete。 如果不满足此条件,则按 ID 的回填作业会导致用户错误。 例如,失败的具体化作业可能有一个特征窗口开始时间值 2023-04-01T04:00:00.000,以及结束时间值 2023-04-09T04:00:00.000。 仅当 2023-04-01T04:00:00.0002023-04-09T04:00:00.000 时间范围内任意点的数据状态均为 Incomplete 时,使用失败作业 ID 提交的回填作业才会成功。

指南和最佳做法

设置适当的 source_delay 和重复计划

源数据的 source_delay 属性表示数据生成事件时间与消耗就绪数据的获取时间之间的延迟。 由于上游数据管道的延迟,在 t 时间发生的事件会在 t + x 时间到达源数据表中。 x 值是源延迟。

显示 source_delay 概念的插图。

为了设置合适,重复具体化作业计划会考虑延迟。 重复作业为 [schedule_trigger_time - source_delay - schedule_interval, schedule_trigger_time - source_delay) 时间窗口生成特征。

materialization_settings:
  schedule:
    type: recurrence
    interval: 1
    frequency: Day
    start_time: "2023-04-15T04:00:00.000"

此示例中的日常作业从 2023 年 4 月 15 日开始于凌晨 4 点触发。 根据 source_delay 设置,2023 年 5 月 1 日运行的作业在不同的时间窗口中生成特征:

  • source_delay=0 在窗口 [2023-04-30T04:00:00.000, 2023-05-01T04:00:00.000) 期间生成特征值
  • source_delay=2hours 在窗口 [2023-04-30T02:00:00.000, 2023-05-01T02:00:00.000) 期间生成特征值
  • source_delay=4hours 在窗口 [2023-04-30T00:00:00.000, 2023-05-01T00:00:00.000) 期间生成特征值

更新具体化存储

在更新存储在联机或离线具体化存储中的特征之前,该特征存储中的所有特征集都需要禁用相应的离线和/或联机具体化。 如果某些特征启用了具体化,则更新操作将失败为 UserError

如果禁用特征集上的离线和/或联机具体化,则将重置离线和/或联机具体化存储中的数据具体化状态。 重置会导致已具体化的数据不可用。 如果之后启用特征集上的离线和/或联机具体化,用户必须重新提交具体化作业。

联机数据启动

仅当提交的离线具体化作业成功完成时,才能用联机数据启动。 如果一开始只启用了特征集脱机具体化,之后才启用联机具体化,那么:

  • 联机存储数据的默认数据具体化状态为 None

  • 提交第一个联机具体化作业时,离线存储中具体化状态为 Complete 的数据将用于计算联机特征。 这称为联机数据启动。 联机数据启动可节省计算成本,因为它重复使用离线具体化存储中已经计算过的特征。此表汇总了会引起联机数据启动的数据间隔中的离线和联机数据状态值:

    开始时间 结束时间 离线数据状态 联机数据状态 联机数据启动
    2023-04-01T04:00:00.000 2023-04-02T04:00:00.000 None None
    2023-04-02T04:00:00.000 2023-04-03T04:00:00.000 Incomplete None
    2023-04-03T04:00:00.000 2023-04-04T04:00:00.000 Pending None 没有提交具体化作业
    2023-04-04T04:00:00.000 2023-04-05T04:00:00.000 Complete None

解决源数据错误和修改

某些方案在数据具体化后会因错误或其他缘由修改源数据。 在这些情况下,为跨越多个数据间隔的特定特征窗口刷新特征数据可以解决错误或过时的功能数据。 在特征窗口中提交解决错误或过时特征数据的具体化请求,数据状态为 NoneCompleteIncomplete

应仅在特征窗口不包含任何数据状态为 Pending 的数据间隔时,才提交特征数据刷新的具体化请求。

填补空白

在具体化存储中,具体化数据可能由于以下原因而存在空白:

  • 从未为特征窗口提交过具体化作业
  • 为特征窗口提交的具体化作业失败或被取消

在这种情况下,请在特征窗口中为 data_status=[DataAvailabilityStatus.NONE,DataAvailabilityStatus.Incomplete] 提交具体化请求,以填补空白。 单个具体化请求就能填充特征窗口中的所有空白。

后续步骤