Pular para o conteúdo principal

Ensinando modelos com tabelas de recursos

Este artigo descreve como o senhor pode treinar modelos usando o recurso engenharia em Unity Catalog ou o espaço de trabalho legado Recurso Store. O senhor deve primeiro criar um treinamento dataset, que define o recurso a ser usado e como join eles. Então, quando o senhor treina um modelo, o modelo retém referências ao recurso.

Quando o senhor treina um modelo usando recurso engenharia em Unity Catalog, pode view a linhagem do modelo no Catalog Explorer. Tabelas e funções que foram usadas para criar o modelo são automaticamente rastreadas e exibidas. Ver recurso governança e linhagem.

Ao usar o modelo para inferência, o senhor pode optar por fazer com que ele recupere valores de recurso do armazenamento de recurso. Os modelos de armazenamento de recurso também são compatíveis com a interfaceMLflow pyfunc, portanto, o senhor pode usar MLflow para realizar a inferência de lotes com tabelas de recurso.

Um modelo pode usar no máximo 50 tabelas e 100 funções para treinamento.

Criar um treinamento dataset

Para selecionar um recurso específico de uma tabela de recursos para o modelo de treinamento, o senhor cria um treinamento dataset usando o FeatureEngineeringClient.create_training_set (para recurso engenharia em Unity Catalog) ou FeatureStoreClient.create_training_set (para recurso workspace Store) API e um objeto chamado FeatureLookup. Um FeatureLookup especifica cada recurso a ser usado no conjunto de treinamento, inclusive o nome da tabela de recursos, o(s) nome(s) do recurso e o(s) key a ser(em) usado(s) ao unir a tabela de recursos com o DataFrame passado para create_training_set. Consulte Recurso Lookup para obter mais informações.

Use o parâmetro feature_names ao criar um FeatureLookup. feature_names recebe um único nome de recurso, uma lista de nomes de recurso ou None para procurar todos os recursos (excluindo a chave primária) na tabela de recursos no momento em que o conjunto de treinamento é criado.

nota

O tipo e a ordem das colunas lookup_key no site DataFrame devem corresponder ao tipo e à ordem da chave primária (excluindo a chave de registro de data e hora) da tabela de recursos de referência.

As colunas de carimbo de data/hora não devem ser usadas como lookup_key.

importante

DATE ou as colunas TIMESTAMP usadas como chave primária devem ser declaradas como chave de série temporal. Se uma tabela de recursos tiver uma coluna key primária DATE ou TIMESTAMP que não seja designada como key de série temporal, as chamadas para create_feature_spec(), create_training_set() e publish_table() retornarão um erro.

Para resolver isso, utilize uma das seguintes abordagens:

  • Declare a coluna como uma coluna de série temporal : Se a coluna representa tempos de eventos ou tempos de observação e você deseja um comportamento de pesquisa pontual, use o parâmetro timeseries_columns ao criar a tabela. Veja Junção de recurso pontual.
  • Alterar o tipo da coluna para STRING : Se a coluna for usada como uma key de pesquisa simples para semântica de correspondência exata (não baseada em tempo), altere o tipo da coluna para STRING para evitar a restrição.

Este artigo inclui exemplos de código para ambas as versões da sintaxe.

Neste exemplo, o DataFrame retornado por trainingSet.load_df contém uma coluna para cada recurso em feature_lookups. Ele preserva todas as colunas do DataFrame fornecido para create_training_set, exceto aquelas excluídas usando exclude_columns.

Python
from databricks.feature_engineering import FeatureEngineeringClient, FeatureLookup

# The model training uses two features from the 'customer_features' feature table and
# a single feature from 'product_features'
feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['total_purchases_30d', 'total_purchases_7d'],
lookup_key='customer_id'
),
FeatureLookup(
table_name='ml.recommender_system.product_features',
feature_names=['category'],
lookup_key='product_id'
)
]

fe = FeatureEngineeringClient()

# Create a training set using training DataFrame and features from Feature Store
# The training DataFrame must contain all lookup keys from the set of feature lookups,
# in this case 'customer_id' and 'product_id'. It must also contain all labels used
# for training, in this case 'rating'.
training_set = fe.create_training_set(
df=training_df,
feature_lookups=feature_lookups,
label='rating',
exclude_columns=['customer_id', 'product_id']
)

training_df = training_set.load_df()

Criar um TrainingSet quando a chave de pesquisa não corresponder à chave primária

Use o argumento lookup_key em FeatureLookup para o nome da coluna no conjunto de treinamento. create_training_set executa um join ordenado entre as colunas do conjunto de treinamento especificado no argumento lookup_key usando a ordem em que a chave primária foi especificada quando a tabela de recursos foi criada.

Neste exemplo, recommender_system.customer_features tem a seguinte chave primária: customer_id, dt.

A tabela de recursos recommender_system.product_features tem o endereço primário key product_id.

Se o training_df tiver as seguintes colunas:

  • cid
  • transaction_dt
  • product_id
  • rating

O código a seguir criará as pesquisas de recurso corretas para o site TrainingSet:

Python
feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['total_purchases_30d', 'total_purchases_7d'],
lookup_key=['cid', 'transaction_dt']
),
FeatureLookup(
table_name='ml.recommender_system.product_features',
feature_names=['category'],
lookup_key='product_id'
)
]

Quando create_training_set é chamado, ele cria um treinamento dataset executando um left join, unindo as tabelas recommender_system.customer_features e training_df usando a chave (customer_id,dt) correspondente a (cid,transaction_dt), conforme mostrado no código a seguir:

Python
customer_features_df = spark.sql("SELECT * FROM ml.recommender_system.customer_features")
product_features_df = spark.sql("SELECT * FROM ml.recommender_system.product_features")

training_df.join(
customer_features_df,
on=[training_df.cid == customer_features_df.customer_id,
training_df.transaction_dt == customer_features_df.dt],
how="left"
).join(
product_features_df,
on="product_id",
how="left"
)

Criar um TrainingSet contendo dois recursos com o mesmo nome de tabelas de recursos diferentes

Use o argumento opcional output_name no FeatureLookup. O nome fornecido é usado no lugar do nome do recurso no DataFrame retornado por TrainingSet.load_df. Por exemplo, com o código a seguir, o DataFrame retornado por training_set.load_df inclui as colunas customer_height e product_height.

Python
feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['height'],
lookup_key='customer_id',
output_name='customer_height',
),
FeatureLookup(
table_name='ml.recommender_system.product_features',
feature_names=['height'],
lookup_key='product_id',
output_name='product_height'
),
]

fe = FeatureEngineeringClient()

with mlflow.start_run():
training_set = fe.create_training_set(
df=df,
feature_lookups=feature_lookups,
label='rating',
exclude_columns=['customer_id']
)
training_df = training_set.load_df()

Criar um TrainingSet usando o mesmo recurso várias vezes

Para criar um TrainingSet usando o mesmo recurso unido por uma chave de pesquisa diferente, use vários FeatureLookups. Use um output_name exclusivo para cada saída FeatureLookup.

Python
feature_lookups = [
FeatureLookup(
table_name='ml.taxi_data.zip_features',
feature_names=['temperature'],
lookup_key=['pickup_zip'],
output_name='pickup_temp'
),
FeatureLookup(
table_name='ml.taxi_data.zip_features',
feature_names=['temperature'],
lookup_key=['dropoff_zip'],
output_name='dropoff_temp'
)
]

Criar um TrainingSet para o modelo não supervisionado de aprendizado de máquina

Defina label=None ao criar um TrainingSet para modelos de aprendizado não supervisionado. Por exemplo, o seguinte TrainingSet pode ser usado para agrupar diferentes clientes em grupos com base em seus interesses:

Python
feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['interests'],
lookup_key='customer_id',
),
]

fe = FeatureEngineeringClient()
with mlflow.start_run():
training_set = fe.create_training_set(
df=df,
feature_lookups=feature_lookups,
label=None,
exclude_columns=['customer_id']
)

training_df = training_set.load_df()

Criar um TrainingSet ao usar o site view como uma tabela de recurso

Para usar o view como uma tabela de recurso, o senhor deve usar a versão 0.7.0 do databricks-feature-engineering ou o acima, que está integrado ao Databricks Runtime 16.0 ML.

O view deve ser um simples SELECT view da tabela Delta de origem. Um SELECT view simples é definido como um view criado a partir de uma única tabela Delta em Unity Catalog que pode ser usada como uma tabela de recurso e cuja chave primária é selecionada sem cláusulas join, GROUP BY ou DISTINCT. As palavras-chave aceitáveis na instrução SQL são SELECT, FROM, WHERE, ORDER BY, LIMIT e OFFSET.

No exemplo a seguir, ml.recommender_system.customer_table tem chave primária cid e dt, em que dt é uma coluna de série temporal. O exemplo pressupõe que o dataframe training_df tenha as colunas cid, dt e label:

Python
from databricks.feature_engineering import FeatureEngineeringClient, FeatureLookup

customer_features_df = spark.sql("CREATE OR REPLACE VIEW ml.recommender_system.customer_features AS SELECT cid, dt, pid, rating FROM ml.recommender_system.customer_table WHERE rating > 3")

feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['pid', 'rating'],
lookup_key=['cid'],
timestamp_lookup_key='dt'
),
]

fe = FeatureEngineeringClient()

training_set = fe.create_training_set(
df=training_df,
feature_lookups=feature_lookups,
label='label'
)

training_df = training_set.load_df()

Crie um conjunto de treinamento com valores de default

Ao criar um treinamento dataset, é possível especificar valores de default para recurso para lidar com casos em que o recurso Store não possui um valor de recurso computacional para um ID.

Para especificar valores de default, utilize o parâmetro default_values no arquivo FeatureLookup.

O exemplo a seguir demonstra como especificar valores de default para um conjunto de recursos:

Python
feature_lookups = [
FeatureLookup(
table_name="ml.recommender_system.customer_features",
feature_names=[
"membership_tier",
"age",
"page_views_count_30days",
],
lookup_key="customer_id",
default_values={
"age": 18,
"membership_tier": "bronze"
},
),
]

Se as colunas de recurso forem renomeadas usando o parâmetro " rename_outputs ", o comando " default_values " deverá utilizar os nomes renomeados dos recursos.

Python
FeatureLookup(
table_name = 'main.default.table',
feature_names = ['materialized_feature_value'],
lookup_key = 'id',
rename_outputs={"materialized_feature_value": "feature_value"},
default_values={
"feature_value": 0
}
)

Treinar modelos e realizar inferência de lotes com tabelas de recursos

Quando o senhor treina um modelo usando recurso do recurso Store, o modelo retém referências ao recurso. Ao usar o modelo para inferência, o senhor pode optar por fazer com que ele recupere valores de recurso do recurso Store. O senhor deve fornecer o key(s) principal (is) do recurso usado no modelo. O modelo recupera o recurso necessário do recurso Store em seu site workspace. Em seguida, ele junta os valores do recurso conforme necessário durante a pontuação.

Para dar suporte à pesquisa de recurso no momento da inferência:

  • O senhor deve log o modelo usando o método log_model de FeatureEngineeringClient (para recurso engenharia em Unity Catalog) ou FeatureStoreClient (para recurso workspace Store).

  • O senhor deve usar o DataFrame retornado por TrainingSet.load_df para treinar o modelo. Se o senhor modificar esse DataFrame de alguma forma antes de usá-lo para treinar o modelo, as modificações não serão aplicadas quando o modelo for usado para inferência. Isso diminui o desempenho do modelo.

  • O tipo de modelo deve ter um python_flavor correspondente no MLflow. O MLflow é compatível com a maioria das estruturas de treinamento de modelos Python, incluindo:

    • scikit-learn
    • Keras
    • PyTorch
    • SparkML
    • LightGBM
    • XGBoost
    • TensorFlow Keras (usando o site python_flavor mlflow.keras)
  • Modelos pyfunc personalizados do MLflow

Python
# Train model
import mlflow
from sklearn import linear_model

feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['total_purchases_30d'],
lookup_key='customer_id',
),
FeatureLookup(
table_name='ml.recommender_system.product_features',
feature_names=['category'],
lookup_key='product_id'
)
]

fe = FeatureEngineeringClient()

with mlflow.start_run():

# df has columns ['customer_id', 'product_id', 'rating']
training_set = fe.create_training_set(
df=df,
feature_lookups=feature_lookups,
label='rating',
exclude_columns=['customer_id', 'product_id']
)

training_df = training_set.load_df().toPandas()

# "training_df" columns ['total_purchases_30d', 'category', 'rating']
X_train = training_df.drop(['rating'], axis=1)
y_train = training_df.rating

model = linear_model.LinearRegression().fit(X_train, y_train)

fe.log_model(
model=model,
artifact_path="recommendation_model",
flavor=mlflow.sklearn,
training_set=training_set,
registered_model_name="recommendation_model"
)

# Batch inference

# If the model at model_uri is packaged with the features, the FeatureStoreClient.score_batch()
# call automatically retrieves the required features from Feature Store before scoring the model.
# The DataFrame returned by score_batch() augments batch_df with
# columns containing the feature values and a column containing model predictions.

fe = FeatureEngineeringClient()

# batch_df has columns 'customer_id' and 'product_id'
predictions = fe.score_batch(
model_uri=model_uri,
df=batch_df
)

# The 'predictions' DataFrame has these columns:
# 'customer_id', 'product_id', 'total_purchases_30d', 'category', 'prediction'

Usar valores de recurso personalizados ao pontuar um pacote de modelos com metadados de recurso

Em default, um pacote de modelos com metadados de recurso procura o recurso nas tabelas de recurso na inferência. Para usar valores de recurso personalizados para a pontuação, inclua-os no DataFrame passado para FeatureEngineeringClient.score_batch (para recurso engenharia em Unity Catalog) ou FeatureStoreClient.score_batch (para recurso workspace Store).

Por exemplo, suponha que o senhor pacote um modelo com esses dois recursos:

Python
feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['account_creation_date', 'num_lifetime_purchases'],
lookup_key='customer_id',
),
]

Na inferência, o senhor pode fornecer valores personalizados para o recurso account_creation_date chamando score_batch em um DataFrame que inclua uma coluna chamada account_creation_date. Nesse caso, o site API procura apenas o recurso num_lifetime_purchases do recurso Store e usa os valores de coluna account_creation_date personalizados fornecidos para a pontuação do modelo.

Python
# batch_df has columns ['customer_id', 'account_creation_date']
predictions = fe.score_batch(
model_uri='models:/ban_prediction_model/1',
df=batch_df
)

Treinar e pontuar um modelo usando uma combinação de recurso Store recurso e dados residentes fora do recurso Store

O senhor pode treinar um modelo usando uma combinação de recurso Store recurso e dados de fora do recurso Store. Quando o senhor empacota o modelo com metadados de recurso, o modelo recupera os valores de recurso do recurso Store para inferência.

Para treinar um modelo, inclua os dados extras como colunas no DataFrame passadas para FeatureEngineeringClient.create_training_set (para recurso engenharia em Unity Catalog) ou FeatureStoreClient.create_training_set (para recurso workspace Store). Este exemplo usa o recurso total_purchases_30d do recurso Store e a coluna externa browser.

Python
feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['total_purchases_30d'],
lookup_key='customer_id',
),
]

fe = FeatureEngineeringClient()

# df has columns ['customer_id', 'browser', 'rating']
training_set = fe.create_training_set(
df=df,
feature_lookups=feature_lookups,
label='rating',
exclude_columns=['customer_id'] # 'browser' is not excluded
)

Na inferência, o DataFrame usado em FeatureStoreClient.score_batch deve incluir a coluna browser.

Python
# At inference, 'browser' must be provided
# batch_df has columns ['customer_id', 'browser']
predictions = fe.score_batch(
model_uri=model_uri,
df=batch_df
)

Carregar modelos e realizar inferência de lotes usando MLflow

Após um modelo ter sido registrado usando o método log_model de FeatureEngineeringClient (para recurso engenharia em Unity Catalog) ou FeatureStoreClient (para recurso workspace Store), MLflow pode ser usado na inferência. mlflow.pyfunc.predict recupera valores de recurso do recurso Store e também junta quaisquer valores fornecidos no momento da inferência. O senhor deve fornecer o key(s) principal (is) do recurso usado no modelo.

nota

A inferência de lotes com MLflow requer MLflow versão 2.11 e acima. Não há suporte para modelos que usam tabelas de recurso de série temporal. Para fazer inferência de lotes com tabelas de recurso de séries temporais, use score_batch. Consulte Treinar modelos e realizar inferência de lotes com tabelas de recursos.

Python
# Train model
import mlflow
from sklearn import linear_model

feature_lookups = [
FeatureLookup(
table_name='ml.recommender_system.customer_features',
feature_names=['total_purchases_30d'],
lookup_key='customer_id',
),
FeatureLookup(
table_name='ml.recommender_system.product_features',
feature_names=['category'],
lookup_key='product_id'
)
]

fe = FeatureEngineeringClient()

with mlflow.start_run():

# df has columns ['customer_id', 'product_id', 'rating']
training_set = fe.create_training_set(
df=df,
feature_lookups=feature_lookups,
label='rating',
exclude_columns=['customer_id', 'product_id']
)

training_df = training_set.load_df().toPandas()

# "training_df" columns ['total_purchases_30d', 'category', 'rating']
X_train = training_df.drop(['rating'], axis=1)
y_train = training_df.rating

model = linear_model.LinearRegression().fit(X_train, y_train)

fe.log_model(
model=model,
artifact_path="recommendation_model",
flavor=mlflow.sklearn,
training_set=training_set,
registered_model_name="recommendation_model",
#refers to the default value of "result_type" if not provided at inference
params={"result_type":"double"},
)

# Batch inference with MLflow

# NOTE: the result_type parameter can only be used if a default value
# is provided in log_model. This is automatically done for all models
# logged using Databricks Runtime for ML 15.0 or above.
# For earlier Databricks Runtime versions, use set_result as shown below.

# batch_df has columns 'customer_id' and 'product_id'
model = mlflow.pyfunc.load_model(model_version_uri)

# If result_type parameter is provided in log_model
predictions = model.predict(df, {"result_type":"double"})

# If result_type parameter is NOT provided in log_model
model._model_impl.set_result_type("double")
predictions = model.predict(df)

Lidar com valores de recurso ausentes

Quando uma pesquisa inexistente key é passada para o modelo para previsão, o valor do recurso buscado por FeatureLookup é NaN.

Solução de problemas

Mensagem de erro: Could not find lookup key columns ... required by FeatureLookups.

ou

Mensagem de erro: Unable to join feature table '...' because timestamp lookup key '...' not found in DataFrame.

A chamada create_training_set falhou porque uma key primária ou key de carimbo de data/hora está faltando no DataFrame de treinamento. O DataFrame de treinamento deve conter todas as chaves de pesquisa e chaves de pesquisa de carimbo de data/hora do conjunto de pesquisas de recurso.

Exemplo de notebook

O Notebook básico mostra como criar uma tabela de recursos, usá-la para treinar um modelo e executar lotes de pontuação usando a pesquisa automática de recursos. Ele também mostra a interface de usuário do recurso engenharia, que o senhor pode usar para pesquisar recursos e entender como os recursos são criados e usados.

Recurso básico de engenharia em Unity Catalog exemplo Notebook

Abrir notebook em uma nova aba

O Notebook de exemplo de táxi ilustra o processo de criação de recursos, atualizando-os e usando-os para treinamento de modelos e inferência de lotes.

recurso engenharia in Unity Catalog taxi example Notebook

Abrir notebook em uma nova aba