Modèles dans Unity Catalog, exemple

Cet exemple qui illustre la façon d’utiliser les modèles dans Unity Catalog pour créer une application de Machine Learning qui prévoit la production d’énergie quotidienne d’un parc éolien. Cet exemple indique comment effectuer les opérations suivantes :

  • Suivez et journalisez des modèles avec MLflow.
  • Inscrivez des modèles dans Unity Catalog.
  • Décrivez des modèles et déployez-les pour l’inférence à l’aide d’alias.
  • Intégrez des modèles inscrits avec des applications de production.
  • Recherchez et découvrez des modèles dans Unity Catalog.
  • Supprimez des modèles.

L’article explique comment accomplir ces étapes à l’aide des interfaces utilisateur et API de MLflow Tracking et des modèles dans Unity Catalog.

Spécifications

Vérifiez que vous remplissez toutes les exigences dans Exigences. En outre, les exemples de code de cet article supposent que vous disposez des privilèges suivants :

  • Privilège USE CATALOG sur le catalogue main.
  • Privilèges CREATE MODEL et USE SCHEMA sur le schéma main.default.

Notebook

Tout le code de cet article est fourni dans le notebook suivant.

Modèles dans un exemple de notebook Unity Catalog

Obtenir le notebook

Installer le client Python MLflow

Cet exemple nécessite le client Python MLflow version 2.5.0 ou ultérieure et TensorFlow. Ajoutez les commandes suivantes en haut de votre notebook pour installer ces dépendances.

%pip install --upgrade "mlflow-skinny[databricks]>=2.5.0" tensorflow
dbutils.library.restartPython()

Charger un jeu de données, entraîner un modèle et s’inscrire dans Unity Catalog

Cette section montre comment charger le jeu de données du parc éolien, entraîner un modèle et enregistrer le modèle dans Unity Catalog. L’exécution d’entraînement du modèle et les indicateurs de performance sont suivis dans une exécution d’expérience.

Charger un jeu de données

Le code suivant charge un jeu de données contenant des données météorologiques et des informations sur la production d’énergie d’un parc éolien aux États-Unis. Le jeu de données contient des métriques wind direction, wind speed et air temperature échantillonnées toutes les six heures (à 00:00, 08:00 et 16:00), ainsi qu’une production d’énergie agrégée quotidienne (power) sur plusieurs années.

import pandas as pd
wind_farm_data = pd.read_csv("https://github.com/dbczumar/model-registry-demo-notebook/raw/master/dataset/windfarm_data.csv", index_col=0)

def get_training_data():
  training_data = pd.DataFrame(wind_farm_data["2014-01-01":"2018-01-01"])
  X = training_data.drop(columns="power")
  y = training_data["power"]
  return X, y

def get_validation_data():
  validation_data = pd.DataFrame(wind_farm_data["2018-01-01":"2019-01-01"])
  X = validation_data.drop(columns="power")
  y = validation_data["power"]
  return X, y

def get_weather_and_forecast():
  format_date = lambda pd_date : pd_date.date().strftime("%Y-%m-%d")
  today = pd.Timestamp('today').normalize()
  week_ago = today - pd.Timedelta(days=5)
  week_later = today + pd.Timedelta(days=5)

  past_power_output = pd.DataFrame(wind_farm_data)[format_date(week_ago):format_date(today)]
  weather_and_forecast = pd.DataFrame(wind_farm_data)[format_date(week_ago):format_date(week_later)]
  if len(weather_and_forecast) < 10:
    past_power_output = pd.DataFrame(wind_farm_data).iloc[-10:-5]
    weather_and_forecast = pd.DataFrame(wind_farm_data).iloc[-10:]

  return weather_and_forecast.drop(columns="power"), past_power_output["power"]

Configurer le client MLflow pour accéder aux modèles dans Unity Catalog

Par défaut, le client Python MLflow crée des modèles dans le registre de modèles d’espace de travail sur Azure Databricks. Pour effectuer une mise à niveau vers des modèles dans Unity Catalog, configurez le client pour qu’il puisse accéder aux modèles dans Unity Catalog :

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

Effectuer l’apprentissage d’un modèle et l’inscrire

Le code suivant effectue l'apprentissage d’un réseau neural en utilisant TensorFlow Keras pour prédire la production d’énergie en fonction des caractéristiques météorologiques contenues dans le jeu de données et utilise les API MLflow pour enregistrer le modèle ajusté dans Unity Catalog.

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

MODEL_NAME = "main.default.wind_forecasting"

def train_and_register_keras_model(X, y):
  with mlflow.start_run():
    model = Sequential()
    model.add(Dense(100, input_shape=(X.shape[-1],), activation="relu", name="hidden_layer"))
    model.add(Dense(1))
    model.compile(loss="mse", optimizer="adam")

    model.fit(X, y, epochs=100, batch_size=64, validation_split=.2)
    example_input = X[:10].to_numpy()
    mlflow.tensorflow.log_model(
        model,
        artifact_path="model",
        input_example=example_input,
        registered_model_name=MODEL_NAME
    )
  return model

X_train, y_train = get_training_data()
model = train_and_register_keras_model(X_train, y_train)

Afficher le modèle dans l’interface utilisateur

Vous pouvez afficher et gérer les modèles inscrits et les versions de modèles dans Unity Catalog à l’aide de Catalog Explorer. Recherchez le modèle que vous venez de créer sous le catalogue main et le schéma default.

Page d’un modèle inscrit

Déployer une version de modèle pour une inférence

Les modèles dans Unity Catalog prennent en charge les alias pour les modèles de déploiement. Les alias fournissent des références mutables nommées (par exemple, « Champion » ou « Challenger ») à une version particulière d’un modèle inscrit. Vous pouvez référencer et cibler des versions de modèle à l’aide de ces alias dans les flux de travail d’inférence en aval.

Une fois que vous avez accédé au modèle inscrit dans Catalog Explorer, cliquez sous la colonne Alias pour affecter l’alias « Champion » à la dernière version du modèle, puis appuyez sur « Continuer » pour enregistrer les modifications.

Définir l’alias de modèle inscrit

Charger les versions du modèle à l’aide de l’API

Le composant Modèles MLflow définit des fonctions pour charger des modèles à partir de plusieurs infrastructures de Machine Learning. Par exemple, mlflow.tensorflow.load_model() est utilisé pour charger des modèles TensorFlow enregistrés au format MLflow, et mlflow.sklearn.load_model() pour charger des modèles scikit-learn enregistrés au format MLflow.

Ces fonctions peuvent charger des modèles à partir des modèles dans Unity Catalog.

import mlflow.pyfunc

model_version_uri = "models:/{model_name}/1".format(model_name=MODEL_NAME)

print("Loading registered model version from URI: '{model_uri}'".format(model_uri=model_version_uri))
model_version_1 = mlflow.pyfunc.load_model(model_version_uri)

model_champion_uri = "models:/{model_name}@Champion".format(model_name=MODEL_NAME)

print("Loading registered model version from URI: '{model_uri}'".format(model_uri=model_champion_uri))
champion_model = mlflow.pyfunc.load_model(model_champion_uri)

Prévoir la production d’énergie avec le modèle de champion

Dans cette section, le modèle de champion est utilisé pour évaluer les données de prévisions météorologiques pour le parc éolien. L’application forecast_power() charge la dernière version du modèle de prévision à partir de la phase spécifiée et l’utilise pour prévoir la production d’énergie au cours des cinq prochains jours.

from mlflow.tracking import MlflowClient

def plot(model_name, model_alias, model_version, power_predictions, past_power_output):
  import matplotlib.dates as mdates
  from matplotlib import pyplot as plt
  index = power_predictions.index
  fig = plt.figure(figsize=(11, 7))
  ax = fig.add_subplot(111)
  ax.set_xlabel("Date", size=20, labelpad=20)
  ax.set_ylabel("Power\noutput\n(MW)", size=20, labelpad=60, rotation=0)
  ax.tick_params(axis='both', which='major', labelsize=17)
  ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d'))
  ax.plot(index[:len(past_power_output)], past_power_output, label="True", color="red", alpha=0.5, linewidth=4)
  ax.plot(index, power_predictions.squeeze(), "--", label="Predicted by '%s'\nwith alias '%s' (Version %d)" % (model_name, model_alias, model_version), color="blue", linewidth=3)
  ax.set_ylim(ymin=0, ymax=max(3500, int(max(power_predictions.values) * 1.3)))
  ax.legend(fontsize=14)
  plt.title("Wind farm power output and projections", size=24, pad=20)
  plt.tight_layout()
  display(plt.show())

def forecast_power(model_name, model_alias):
  import pandas as pd
  client = MlflowClient()
  model_version = client.get_model_version_by_alias(model_name, model_alias).version
  model_uri = "models:/{model_name}@{model_alias}".format(model_name=MODEL_NAME, model_alias=model_alias)
  model = mlflow.pyfunc.load_model(model_uri)
  weather_data, past_power_output = get_weather_and_forecast()
  power_predictions = pd.DataFrame(model.predict(weather_data))
  power_predictions.index = pd.to_datetime(weather_data.index)
  print(power_predictions)
  plot(model_name, model_alias, int(model_version), power_predictions, past_power_output)

forecast_power(MODEL_NAME, "Champion")

Ajouter un modèle et des descriptions de version de celui-ci à l’aide de l’API

Le code de cette section montre comment ajouter des descriptions de modèles et de versions de modèle à l’aide de l’API MLflow.

client = MlflowClient()
client.update_registered_model(
  name=MODEL_NAME,
  description="This model forecasts the power output of a wind farm based on weather data. The weather data consists of three features: wind speed, wind direction, and air temperature."
)

client.update_model_version(
  name=MODEL_NAME,
  version=1,
  description="This model version was built using TensorFlow Keras. It is a feed-forward neural network with one hidden layer."
)

Créer une nouvelle version du modèle

Les techniques de Machine Learning classiques sont également efficaces pour la prévision de l’alimentation. Le code suivant effectue l'apprentissage d’un modèle de forêt aléatoire à l’aide de scikit-learn, et l’inscrit dans Unity Catalog en utilisant la fonction mlflow.sklearn.log_model().

import mlflow.sklearn
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

with mlflow.start_run():
  n_estimators = 300
  mlflow.log_param("n_estimators", n_estimators)

  rand_forest = RandomForestRegressor(n_estimators=n_estimators)
  rand_forest.fit(X_train, y_train)

  val_x, val_y = get_validation_data()
  mse = mean_squared_error(rand_forest.predict(val_x), val_y)
  print("Validation MSE: %d" % mse)
  mlflow.log_metric("mse", mse)

  example_input = val_x.iloc[[0]]

  # Specify the `registered_model_name` parameter of the `mlflow.sklearn.log_model()`
  # function to register the model to <UC>. This automatically
  # creates a new model version
  mlflow.sklearn.log_model(
    sk_model=rand_forest,
    artifact_path="sklearn-model",
    input_example=example_input,
    registered_model_name=MODEL_NAME
  )

Récupérer le nouveau numéro de version du modèle

Le code suivant montre comment récupérer le dernier numéro de version du modèle pour un nom de modèle.

client = MlflowClient()
model_version_infos = client.search_model_versions("name = '%s'" % MODEL_NAME)
new_model_version = max([model_version_info.version for model_version_info in model_version_infos])

Ajouter une description à la nouvelle version du modèle

client.update_model_version(
  name=MODEL_NAME,
  version=new_model_version,
  description="This model version is a random forest containing 100 decision trees that was trained in scikit-learn."
)

Marquer la nouvelle version du modèle comme Challenger et tester le modèle

Avant de déployer un modèle pour traiter le trafic de production, il est recommandé de le tester sur un échantillon de données de production. Auparavant, vous utilisiez l’alias « Champion » pour désigner la version du modèle servant la majorité des charges de travail de production. Le code suivant assigne l’alias « Challenger » à la nouvelle version du modèle et évalue ses performances.

client.set_registered_model_alias(
  name=MODEL_NAME,
  alias="Challenger",
  version=new_model_version
)

forecast_power(MODEL_NAME, "Challenger")

Déployer la nouvelle version du modèle en tant que version du modèle Champion

Après avoir vérifié que la nouvelle version du modèle fonctionne correctement lors des tests, le code suivant assigne l’alias « Champion » à la nouvelle version du modèle et utilise exactement le même code d’application que celui décrit dans la section Prévoir la production d’énergie avec le modèle de champion pour produire une prévision d’alimentation.

client.set_registered_model_alias(
  name=MODEL_NAME,
  alias="Champion",
  version=new_model_version
)

forecast_power(MODEL_NAME, "Champion")

Il existe désormais deux versions du modèle de prévision : celle dont l’apprentissage a été effectué dans le modèle Keras, et celle dont l’apprentissage a été effectué dans scikit-learn. Notez que l’alias « Challenger » reste affecté à la nouvelle version du modèle scikit-learn, de sorte que toutes les charges de travail en aval qui ciblent la version du modèle « Challenger » continuent de s’exécuter correctement :

Versions du modèle de produit

Supprimer des modèles

Quand une version du modèle n’est plus utilisée, vous pouvez la supprimer. Vous pouvez également supprimer un modèle inscrit tout entier, ce qui a pour effet de supprimer toutes les versions du modèle associées. Notez que la suppression d’une version de modèle efface tous les alias attribués à la version du modèle.

Supprimer la Version 1 à l’aide de l’API MLflow

client.delete_model_version(
   name=MODEL_NAME,
   version=1,
)

Supprimer le modèle à l’aide de l’API MLflow

client = MlflowClient()
client.delete_registered_model(name=MODEL_NAME)