時間點功能聯結

本頁說明如何利用時間點正確性建立一個訓練資料集,準確反映標籤觀察記錄時的特徵值。 這對於防止 數據外洩很重要,因為當您使用特徵值進行模型訓練,而這些特徵值在標籤記錄時不可用,便會發生數據外洩的情況。 這種類型的錯誤可能很難偵測,而且可能會對模型的效能造成負面影響。

時間序列特徵表包含一個時間戳索引鍵列,確保訓練數據集中每列數據都代表該時間戳時的最新已知特徵值。 每當特徵值隨著時間變更時,您應該使用時間序列特徵資料表,例如時間序列資料、事件型資料或時間彙總資料。

下圖顯示時間戳密鑰的使用方式。 針對每個時間戳記錄的功能值是該時間戳之前的最新值,以外框的橙色圓圈表示。 如果未記錄任何值,則特徵值為 null。 如需詳細資訊,請參閱 時間序列功能數據表的運作方式。

特徵值於不同時間抵達。

注意

  • 使用 Databricks Runtime 13.3 LTS 和更新版本時,Unity Catalog 中具有主鍵和時間戳記鍵的任何 Delta 表可作為時間序列特徵表使用。
  • 為了在時間點查詢中表現更佳,Databricks 建議在時間序列表上使用液態叢集(databricks-feature-engineering 0.6.0 及以上版本)。 請參見 使用液體叢集於資料表資料略過
  • 時間點查閱功能有時稱為「時間旅行」。 Databricks 功能存放區中的時間點功能與 Delta Lake time travel 無關。

時間序列功能數據表的運作方式

假設您擁有下列特徵資料表。 此資料取自範例筆記本

資料表包含測量室內的溫度、相對濕度、環境光線和二氧化碳的感應器資料。 基準真實資料表指出房間裡是否有人。 每個資料表都有主鍵 ('room') 和時間戳鍵 ('ts')。 為了簡單起見,只會顯示主鍵 ('0') 單一值的數據。

範例特徵資料表資料

下方圖示說明如何使用時間戳記索引來確保訓練資料集中的時間點的準確性。 使用 AS OF 連接,根據主鍵(未在圖表中顯示)和時間戳記鍵來匹配特徵值。 在訓練集中,AS OF 連接可確保在時間戳記時使用該特徵的最新值。

時間點的運作方式

如圖所示,訓練資料集包括每個感應器在觀測的實地真值時間戳之前的最新特徵值。

如果您建立訓練資料集而不考慮時間戳記,您可能會得到一個具有這些特徵值和觀察到的真實情況的資料列:

溫度 rh 光線 co2 基準真實
15.8 32 212 630 0

然而,這不是訓練的有效觀測,因為 8:52 擷取的 co2 讀數為 630,而此時間是在基準真實的觀測時間 8:50 之後。 未來的數據會「外洩」到定型集,這會損害模型的效能。

需求

  • 針對 Unity Catalog 中的特徵工程:Unity Catalog 用戶端中的特徵工程 (適用於任何版本)。
  • 針對工作區特徵存放區 (舊版):特徵存放區客戶端 v0.3.7 及以上版本。

若要使用時間點功能,您必須使用 timeseries_columns 引數 (對於 Unity Catalog 中的特徵工程) 或 timestamp_keys 引數 (對於工作區特徵存放區) 來指定時間相關的索引鍵。 這表示特徵表的資料列應藉由比對不晚於 timestamps_keys 欄位值的特定主鍵的最新值來連接,而不是透過確切的時間比對來進行連接。

如果您不使用 timeseries_columnstimestamp_keys,而僅將時間序列欄指定為主索引鍵欄,則特徵存放區不會在聯結期間將時間點邏輯套用至時間序列欄。 相反地,其僅會比對具有確切時間比對的資料列,而不是比對時間戳記之前的所有資料列。

在 Unity Catalog 中建立時間序列特徵資料表

在 Unity 統目錄中,任何具有 TIMESERIES 主鍵的表格都是時間序列特徵資料表。 若要建立時間序列功能表,請參閱 在 Unity 目錄中建立功能表。 下列範例說明不同類型的時序表格。

將時間序列表格發佈至線上商店

使用包含時間戳記資料的功能表格時,您必須考慮是否要將時間戳記欄指定為timeseries_column,還是將其視為一般欄位,這取決於您的線上服務需求。

標示有時間序列指定的時間戳記欄

當您需要訓練資料集的時間點正確性,並想要在線上應用程式中查詢特定時間戳記的最新特徵值時,請使用 timeseries_column 。 時間序列特徵資料表必須有一個時間戳記鍵,而且不能有任何分割區資料行。 時間戳記索引鍵資料行必須是 TimestampTypeDateType

Databricks 建議時間序列特徵資料表不得擁有超過兩個主索引鍵資料行,以確保高效能寫入和查詢。

FeatureEngineering用戶端API

fe = FeatureEngineeringClient()

# Create a time series table for point-in-time joins
fe.create_table(
    name="catalog.schema.user_behavior_features",
    primary_keys=["user_id", "event_timestamp"],
    timeseries_columns="event_timestamp",  # Enables point-in-time logic
    df=features_df # DataFrame must contain primary keys and time series columns
)

SQL API

-- Create table with time series constraint for point-in-time joins
CREATE TABLE catalog.schema.user_behavior_features (
    user_id STRING NOT NULL,
    event_timestamp TIMESTAMP NOT NULL,  -- part of primary key and designated as TIMESERIES
    purchase_amount DOUBLE,
    page_views_last_hour INT,
    CONSTRAINT pk_user_behavior PRIMARY KEY (user_id, event_timestamp TIMESERIES)
) USING DELTA
TBLPROPERTIES (
    'delta.enableChangeDataFeed' = 'true'
);

這很重要

若特徵表的主鍵是DATETIMESTAMP欄位,且未以timeseries_columns宣告為時間序列欄位,則無法使用此表格與create_feature_spec()create_training_set()publish_table()配合。 這些 API 要求所有 DATETIMESTAMP 主鍵欄位都宣告為時間序列欄位。

如果你的使用情境需要以日期或時間戳值作為純查詢鍵(語意精確匹配,沒有時間點邏輯),請將欄位類型改為STRING

更新時間序列特徵資料表

與一般特徵資料表不同,將特徵寫入時間序列特徵資料表時,您的 DataFrame 必須提供特徵資料表的所有特徵值。 此條件約束可減少時間序列特徵資料表中時間戳記之間的特徵值的稀疏性。

Unity Catalog 中的特徵工程

fe = FeatureEngineeringClient()
# daily_users_batch_df DataFrame contains the following columns:
# - user_id
# - ts
# - purchases_30d
# - is_free_trial_active
fe.write_table(
  "ml.ads_team.user_features",
  daily_users_batch_df,
  mode="merge"
)

工作區特徵存放區用戶端 v0.13.4 及以上版本

fs = FeatureStoreClient()
# daily_users_batch_df DataFrame contains the following columns:
# - user_id
# - ts
# - purchases_30d
# - is_free_trial_active
fs.write_table(
  "ads_team.user_features",
  daily_users_batch_df,
  mode="merge"
)

支援串流寫入時間序列特徵資料表。

使用時間序列特徵資料表建立訓練集

若要對時間序列功能資料表中的特徵值執行時間點查閱,您必須在 功能的 timestamp_lookup_key中指定 FeatureLookup ,指出包含要查閱時間序列特徵之時間戳的 DataFrame 資料行名稱。 Databricks 功能存放區會在 DataFrame 的 timestamp_lookup_key 列中指定的時間戳之前擷取最新的特徵值,且其主鍵(不包括時間戳索引鍵)符合 DataFrame 的 lookup_key 列中的值,如果不存在此類特徵值,則使用 null

Unity Catalog 中的特徵工程

feature_lookups = [
  FeatureLookup(
    table_name="ml.ads_team.user_features",
    feature_names=["purchases_30d", "is_free_trial_active"],
    lookup_key="u_id",
    timestamp_lookup_key="ad_impression_ts"
  ),
  FeatureLookup(
    table_name="ml.ads_team.ad_features",
    feature_names=["sports_relevance", "food_relevance"],
    lookup_key="ad_id",
  )
]

# raw_clickstream DataFrame contains the following columns:
# - u_id
# - ad_id
# - ad_impression_ts
training_set = fe.create_training_set(
  df=raw_clickstream,
  feature_lookups=feature_lookups,
  exclude_columns=["u_id", "ad_id", "ad_impression_ts"],
  label="did_click",
)
training_df = training_set.load_df()

提示

若要在啟用 Photon 時獲得更快的查詢效能,請將 use_spark_native_join=True 傳遞至 FeatureEngineeringClient.create_training_set。 這需要 databricks-feature-engineering 版本 0.6.0 或更新的版本。

工作區特徵庫

feature_lookups = [
  FeatureLookup(
    table_name="ads_team.user_features",
    feature_names=["purchases_30d", "is_free_trial_active"],
    lookup_key="u_id",
    timestamp_lookup_key="ad_impression_ts"
  ),
  FeatureLookup(
    table_name="ads_team.ad_features",
    feature_names=["sports_relevance", "food_relevance"],
    lookup_key="ad_id",
  )
]

# raw_clickstream DataFrame contains the following columns:
# - u_id
# - ad_id
# - ad_impression_ts
training_set = fs.create_training_set(
  df=raw_clickstream,
  feature_lookups=feature_lookups,
  exclude_columns=["u_id", "ad_id", "ad_impression_ts"],
  label="did_click",
)
training_df = training_set.load_df()

時間序列特徵資料表上的任何 FeatureLookup 都必須是時間點查詢,因此它必須指定要在 DataFrame 中使用的 timestamp_lookup_key 資料行。 時間點查詢不會略過時間序列特徵資料表中具有 null 特徵值的資料列。

設定歷程記錄特徵值的使用時間限制

使用特徵存放區用戶端 v0.13.0 或更高版本,或 Unity Catalog 用戶端中的任何版本的特徵工程,您可以從訓練集中排除具有較舊時間戳記的特徵值。 若要這樣做,請使用 lookback_window 中的參數 FeatureLookup

lookback_window 的資料類型必須是 datetime.timedelta,且預設值為 None (不論年齡為何,都會使用所有特徵值)。

例如,下列程式碼會排除任何超過 7 天的特徵值:

Unity Catalog 中的特徵工程

from datetime import timedelta

feature_lookups = [
  FeatureLookup(
    table_name="ml.ads_team.user_features",
    feature_names=["purchases_30d", "is_free_trial_active"],
    lookup_key="u_id",
    timestamp_lookup_key="ad_impression_ts",
    lookback_window=timedelta(days=7)
  )
]

工作區特徵庫

from datetime import timedelta

feature_lookups = [
  FeatureLookup(
    table_name="ads_team.user_features",
    feature_names=["purchases_30d", "is_free_trial_active"],
    lookup_key="u_id",
    timestamp_lookup_key="ad_impression_ts",
    lookback_window=timedelta(days=7)
  )
]

當您使用上述 create_training_set 呼叫 FeatureLookup 時,其會自動執行時間點聯結,並排除超過 7 天的特徵值。

回顧視窗會在訓練和批次推斷期間套用。 在線推理過程中,無論回溯窗口如何,皆會使用最新的特徵值。

使用時間序列特徵資料表為模型評分

當您對經由時間序列特徵資料表訓練的模型進行評分時,Databricks 特徵存放區會使用與模型在訓練過程中封裝的中繼資料進行時間點查詢,以擷取適當的特徵。 您提供給 FeatureEngineeringClient.score_batch 的 DataFrame(用於 Unity Catalog 中的特徵工程)或 FeatureStoreClient.score_batch(用於工作區特徵存放區)必須包含一個名為 DataType 的時間戳記資料行,其名稱需與提供給 timestamp_lookup_keyFeatureLookupFeatureEngineeringClient.create_training_setFeatureStoreClient.create_training_set 相同。

提示

若要在啟用 Photon 時獲得更快的查詢效能,請將 use_spark_native_join=True 傳遞至 FeatureEngineeringClient.score_batch。 這需要 databricks-feature-engineering 版本 0.6.0 或更新的版本。

將時間序列特徵上傳至線上儲存庫

您可以使用 FeatureEngineeringClient.publish_table (用於 Unity Catalog 的特徵工程) 或 FeatureStoreClient.publish_table (用於工作區特徵商店) 將時間序列特徵資料表發佈至線上商店。 Databricks 特徵存放區會將特徵資料表中每個主索引鍵的最新特徵值快照發佈至線上存放區。 線上商店支援主索引鍵查詢,但不支援特定時間查詢。

筆記本範例:時間序列特徵資料表

這些示例筆記本說明時間序列特徵資料表的特定時間點查詢。

在已啟用 Unity Catalog 的工作區中使用此筆記本。

時間序列特徵資料表範例筆記本 (Unity Catalog )

取得筆記本

在此提供的筆記本專為未針對 Unity Catalog 啟用的工作區而設計。 它使用工作區功能儲存庫。

時間序列特徵資料表範例筆記本 (未針對 Unity Catalog 啟用工作區)

取得筆記本