Aller au contenu principal

Calcul de fonctionnalités à la demande

Dans Databricks, les fonctionnalités à la demande sont calculées au moment de l'inférence à l'aide de fonctions Python définies par l'utilisateur (UDF). Utilisez-les lorsque les valeurs des fonctionnalités ne sont pas connues à l'avance et dépendent des entrées au moment de la requête.

Pour utiliser les fonctionnalités à la demande, votre Workspace doit être activé pour Unity Catalog et vous devez utiliser Databricks Runtime 13,3 LTS ML ou supérieur.

Que sont les fonctionnalités à la demande ?

« À la demande » fait référence aux fonctionnalités dont les valeurs ne sont pas connues à l'avance, mais sont calculées au moment de l'inférence. Dans Databricks, vous utilisez les fonctions définies par l'utilisateur Python (UDF) pour spécifier comment calculer les fonctionnalités à la demande. Ces fonctions sont régies par Unity Catalog et découvrables via l'Explorateur de catalogues.

Workflow

Pour calculer des fonctionnalités à la demande, vous spécifiez une fonction définie par l'utilisateur (UDF) Python qui décrit comment calculer les valeurs de la fonctionnalité.

  • Pendant l'entraînement, vous fournissez cette fonction et ses liaisons d'entrée dans le paramètre feature_lookups de l'API create_training_set.
  • Vous devez enregistrer le modèle entraîné à l'aide de la méthode du Magasin de fonctionnalités log_model. Cela garantit que le modèle évalue automatiquement les fonctionnalités à la demande lorsqu'il est utilisé pour l'inférence.
  • Pour le score par lots, l'API score_batch calcule et renvoie automatiquement toutes les valeurs de fonctionnalités, y compris les fonctionnalités à la demande.
  • Lorsque vous servez un modèle avec Model Serving, le modèle utilise automatiquement la fonction Python UDF pour calculer des caractéristiques à la demande pour chaque requête de scoring.

Créer une UDF Python

Vous pouvez créer une UDF Python en utilisant du code SQL ou Python. Les exemples suivants créent une UDF Python dans le catalogue main et le schéma default.

Pour utiliser Python, vous devez d'abord installer le package databricks-sdk[openai]. Utilisez %pip install comme suit :

Python
%pip install unitycatalog-ai[databricks]
dbutils.library.restartPython()

Ensuite, utilisez un code similaire au suivant pour créer une UDF Python :

from unitycatalog.ai.core.databricks import DatabricksFunctionClient

client = DatabricksFunctionClient()

CATALOG = "main"
SCHEMA = "default"

def add_numbers(number_1: float, number_2: float) -> float:
"""
A function that accepts two floating point numbers, adds them,
and returns the resulting sum as a float.

Args:
number_1 (float): The first of the two numbers to add.
number_2 (float): The second of the two numbers to add.

Returns:
float: The sum of the two input numbers.
"""
return number_1 + number_2

function_info = client.create_python_function(
func=add_numbers,
catalog=CATALOG,
schema=SCHEMA,
replace=True
)

Après avoir exécuté le code, vous pouvez naviguer dans l'espace de noms à trois niveaux dans l'Explorateur de catalogues pour afficher la définition de la fonction :

fonction dans Catalog Explorer

Pour plus de détails sur la création d'UDF Python, consultez Enregistrer une UDF Python dans Unity Catalog et le manuel du langage SQL.

Comment gérer les valeurs de fonctionnalité manquantes

Lorsqu’une UDF Python dépend du résultat d’un FeatureLookup, la valeur renvoyée si la clé de recherche demandée n’est pas trouvée dépend de l’environnement. Lorsque vous utilisez score_batch, la valeur renvoyée est None. Lorsque vous utilisez le service en ligne, la valeur renvoyée est float("nan").

Le code suivant est un exemple de la façon de gérer les deux cas.

%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
$$

Entraîner un modèle à l'aide de fonctionnalités à la demande

Pour entraîner le modèle, vous utilisez un FeatureFunction, qui est transmis à l’API create_training_set dans le paramètre feature_lookups.

L'exemple de code suivant utilise l'UDF Python main.default.example_feature qui a été défini dans la section précédente.

Python
# 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 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)

Spécifier les valeurs default

Pour spécifier les valeurs default des fonctionnalités, utilisez le parameter default_values dans le FeatureLookup.

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

Si les colonnes de features sont renommées en utilisant le parameter rename_outputs, default_values doit utiliser les noms de features renommées.

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
}
)

Enregistrer le modèle et l'inscrire dans Unity Catalog

Les modèles packagés avec des métadonnées de fonctionnalités peuvent être enregistrés dans Unity Catalog. Les tables de fonctionnalités utilisées pour créer le modèle doivent être stockées dans Unity Catalog.

Pour vous assurer que le modèle évalue automatiquement les fonctionnalités à la demande lorsqu'il est utilisé pour l'inférence, vous devez définir l'URI du registre, puis journaliser le modèle, comme suit :

Python
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"
)

Si l’UDF Python qui définit les fonctionnalités à la demande importe des packages Python, vous devez spécifier ces packages à l’aide de l’argument extra_pip_requirements. Par exemple :

Python
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"]
)

Limitations

  • Pour les Endpoints de Feature Serving, tous les types de données pris en charge par le Magasin de fonctionnalités sont pris en charge en tant que types de sortie des fonctions de fonctionnalité, à l'exception de ArrayType, MapType et StructType. StructType n'est pas non plus pris en charge en tant que type d'entrée de fonction de fonctionnalité.
  • Pour les versions databricks-feature-engineering inférieures à 0.14.0, les autorisations Unity Catalog suivantes sont requises pour utiliser une fonction définie par l'utilisateur (UDF) afin de créer un ensemble d'entraînement ou pour créer un endpoint Feature Serving.
    • USE CATALOG privilège sur le catalogue system
    • USE SCHEMA privilège sur le schéma system.information_schema

Exemples de Notebook : fonctionnalités à la demande

Le notebook suivant montre un exemple de la façon d'entraîner et de noter un modèle qui utilise une fonctionnalité à la demande.

Notebook de démonstration des fonctionnalités de base à la demande

Le Notebook suivant présente un exemple de modèle de recommandation de restaurant. L'emplacement du restaurant est recherché dans une table en ligne Databricks. La position actuelle de l’utilisateur est envoyée dans le cadre de la demande de scoring. Le modèle utilise une fonctionnalité à la demande pour calculer la distance en temps réel entre l'utilisateur et le restaurant. Cette distance est ensuite utilisée comme entrée pour le modèle.

Notebook de démonstration des fonctionnalités de recommandation de restaurant à la demande utilisant des tables en ligne