Calcule recursos sob demanda usando funções Python definidas pelo usuário

Este artigo descreve como criar e usar recursos sob demanda no Databricks.

O modelo de aprendizado de máquina para aplicações em tempo real geralmente requer os valores de recurso mais recentes. No exemplo mostrado no diagrama, um recurso para um modelo de recomendação de restaurante é a distância atual do usuário até um restaurante. Esse recurso deve ser calculado “sob demanda” – ou seja, no momento da solicitação de pontuação. Ao receber uma solicitação de pontuação, o modelo procura a localização do restaurante e depois aplica uma função pré-definida para calcular a distância entre a localização atual do usuário e o restaurante. Essa distância é passada como entrada para o modelo, juntamente com outros recursos pré-computados do repositório de recursos.

compute recurso sob demanda fluxo de trabalho

Para usar o recurso sob demanda, seu workspace deve estar habilitado para Unity Catalog e você deve usar o Databricks Runtime 13.3 LTS ML ou acima.

Quais são os recursos sob demanda?

“Sob demanda” refere-se ao recurso cujos valores não são conhecidos antecipadamente, mas são calculados no momento da inferência. No Databricks, você usa UDFs (funções definidas pelo usuário) do Python para especificar como calcular o recurso sob demanda. Essas funções são controladas pelo Unity Catalog e podem ser descobertas por meio do Catalog Explorer.

fluxo de trabalho

Para compute recursos sob demanda, você especifica uma função definida pelo usuário (UDF) Python que descreve como calcular os valores dos recursos.

  • Durante o treinamento, você fornece essa função e suas vinculações de entrada no parâmetro feature_lookups da API create_training_set .

  • Você deve logs o modelo treinado utilizando o método recurso Store log_model. Isso garante que o modelo avalie automaticamente os recursos sob demanda quando for usado para inferência.

  • Para pontuação de lotes, a API score_batch calcula e retorna automaticamente todos os valores de recursos, incluindo recursos sob demanda.

  • Quando você atende um modelo com o modelo de atividade do Databricks, o modelo usa automaticamente a UDF do Python para compute recursos sob demanda para cada solicitação de pontuação.

Crie uma UDF em Python

Você pode criar uma UDF Python em um Notebook ou em Databricks SQL.

Por exemplo, executar o código a seguir em uma célula Notebook cria a UDF example_feature do Python no catálogo main e no esquema default.

%sql
CREATE FUNCTION main.default.example_feature(x INT, y INT)
RETURNS INT
LANGUAGE PYTHON
COMMENT 'add two numbers'
AS $$
def add_numbers(n1: int, n2: int) -> int:
  return n1 + n2

return add_numbers(x, y)
$$

Depois de executar o código, você pode navegar pelo namespace de três níveis no Catalog Explorer para view a definição da função:

função no Catalog Explorer

Para obter mais detalhes sobre a criação de UDFs Python, consulte registrar uma UDF Python no Unity Catalog e o manual da linguagem SQL.

Como lidar com valores de recurso ausentes

Quando um UDF Python depende do resultado de um FeatureLookup, o valor retornado se a pesquisa solicitada key não for encontrada dependerá do ambiente. Ao usar score_batch, o valor retornado é None. Ao usar o serviço on-line, o valor retornado é float("nan").

O código a seguir é um exemplo de como lidar com ambos os casos.

%sql
CREATE OR REPLACE FUNCTION square(x INT)
RETURNS INT
LANGUAGE PYTHON AS
$$
import numpy as np
if x is None or np.isnan(x):
  return 0
return x * x
$$

ensinar um modelo usando recursos sob demanda

Para ensinar o modelo, você usa um FeatureFunction, que é passado para a API create_training_set no parâmetro feature_lookups .

O código de exemplo a seguir usa a UDF main.default.example_feature do Python que foi definida na seção anterior.

# Install databricks-feature-engineering first with:
# %pip install databricks-feature-engineering
# dbutils.library.restartPython()

from databricks.feature_engineering import FeatureEngineeringClient
from databricks.feature_engineering import FeatureFunction, FeatureLookup
from sklearn import linear_model

fe = FeatureEngineeringClient()

features = [
  # The feature 'on_demand_feature' is computed as the sum of the the input value 'new_source_input'
  # and the pre-materialized feature 'materialized_feature_value'.
  # - 'new_source_input' must be included in base_df and also provided at inference time.
  #   - For batch inference, it must be included in the DataFrame passed to 'FeatureEngineeringClient.score_batch'.
  #   - For real-time inference, it must be included in the request.
  # - 'materialized_feature_value' is looked up from a feature table.

  FeatureFunction(
      udf_name="main.default.example_feature",    # UDF must be in Unity Catalog so uses a three-level namespace
      input_bindings={
        "x": "new_source_input",
        "y": "materialized_feature_value"
      },
      output_name="on_demand_feature",
  ),
  # retrieve the prematerialized feature
  FeatureLookup(
    table_name = 'main.default.table',
    feature_names = ['materialized_feature_value'],
    lookup_key = 'id'
  )
]

# base_df includes the columns 'id', 'new_source_input', and 'label'
training_set = fe.create_training_set(
  df=base_df,
  feature_lookups=features,
  label='label',
  exclude_columns=['id', 'new_source_input', 'materialized_feature_value']     # drop the columns not used for training
)

# The training set contains the columns 'on_demand_feature' and 'label'.
training_df = training_set.load_df().toPandas()

# training_df columns ['materialized_feature_value', 'label']
X_train = training_df.drop(['label'], axis=1)
y_train = training_df.label

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

logs o modelo e registra-o no Catálogo do Unity

Pacote de modelos com metadados de recursos podem ser registrados no Unity Catalog. As tabelas de recursos usadas para criar o modelo devem ser armazenadas no Unity Catalog.

Para garantir que o modelo avalie automaticamente os recursos sob demanda quando for usado para inferência, você deve configurar o URI do registro e, em seguida, logs o modelo em log, da seguinte forma:

import mlflow
mlflow.set_registry_uri("databricks-uc")

fe.log_model(
    model=model,
    artifact_path="main.default.model",
    flavor=mlflow.sklearn,
    training_set=training_set,
    registered_model_name="main.default.recommender_model"
)

Se a UDF do Python que define os recursos sob demanda importar qualquer pacote do Python, você deverá especificar esses pacotes usando o argumento extra_pip_requirements. Por exemplo:

import mlflow
mlflow.set_registry_uri("databricks-uc")

fe.log_model(
    model=model,
    artifact_path="model",
    flavor=mlflow.sklearn,
    training_set=training_set,
    registered_model_name="main.default.recommender_model",
    extra_pip_requirements=["scikit-learn==1.20.3"]
)

Limitação

O recurso sob demanda pode gerar todos os tipos de dados suportados pelo repositório de recursos, exceto MapType e ArrayType.

Exemplos Notebook : recurso sob demanda

O Notebook a seguir mostra um exemplo de como ensinar e pontuar um modelo que utiliza um recurso sob demanda.

Notebook básico de demonstração de recursos sob demanda

Abra o bloco de anotações em outra guia

O site Notebook a seguir mostra um exemplo de um modelo de recomendação de restaurante. A localização do restaurante é pesquisada em uma tabela on-line do Databricks. A localização atual do usuário é enviada como parte da solicitação de pontuação. O modelo usa um recurso sob demanda para compute o tempo real de distância do usuário até o restaurante. Essa distância é então usada como entrada para o modelo.

Recurso de recomendação de restaurante sob demanda usando demonstração de tabelas on-line Notebook

Abra o bloco de anotações em outra guia

O site Notebook a seguir mostra o mesmo modelo de recomendação de restaurante usando um armazenamento on-line de terceiros. A localização do restaurante é pesquisada em uma tabela de recurso pré-materializada publicada no DynamoDB.

Recurso de recomendação de restaurante sob demanda usando a demonstração do DynamoDB Notebook

Abra o bloco de anotações em outra guia