Pular para o conteúdo principal

Usar recurso para treinar modelos

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.

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 a 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()

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.