Ejemplo de modelos en Unity Catalog

En este ejemplo, se muestra cómo usar Modelos en Unity Catalog para crear una aplicación de aprendizaje automático que prevé la producción diaria de energía de un parque eólico. En el ejemplo se muestra cómo:

  • Seguimiento y registro de modelos con MLflow
  • Registro de modelos en Unity Catalog
  • Descripción de modelos y su implementación para la inferencia usando alias
  • Integración de modelos registrados con aplicaciones de producción
  • Búsqueda y detección de modelos en Unity Catalog
  • Archivado y eliminación de modelos

En el artículo se describe cómo realizar estos pasos mediante el seguimiento de MLflow y Modelos en las API y las interfaces de usuario de Unity Catalog.

Requisitos

Asegúrese de cumplir todos los requisitos de Requisitos. Además, en los ejemplos de código de este artículo se supone que tiene los privilegios siguientes:

  • Privilegio USE CATALOG en el catálogo main.
  • Privilegios CREATE MODEL y USE SCHEMA sobre el esquema main.default.

Notebook

Todo el código de este artículo se proporciona en el cuaderno siguiente.

Modelos en el cuaderno de ejemplos de Unity Catalog

Obtener el cuaderno

Instalación del cliente de Python de MLflow

En este ejemplo se requiere la versión 2.5.0 o posterior del cliente de Python de MLflow y TensorFlow. Agregue los siguientes comandos en la parte superior del cuaderno para instalar estas dependencias.

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

Carga del conjunto de datos, entrenamiento del modelo y registro en Unity Catalog

En esta sección se muestra cómo cargar el conjunto de datos del parque eólico, entrenar un modelo y registrar el modelo en Unity Catalog. Se realiza un seguimiento de la ejecución y las métricas del entrenamiento del modelo en una ejecución de experimento.

Carga del conjunto de datos

El código siguiente carga un conjunto de datos que contiene datos meteorológicos e información de la salida de energía de un granja eólica en los Estados Unidos. El conjunto de datos contiene las características wind direction, wind speed y air temperature muestreadas cada seis horas (una vez a las 00:00, otra a las 08:00 y otra a las 16:00), así como la salida de energía agregada diaria (power), a lo largo de varios años.

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

Configuración del cliente de MLflow para acceder a los modelos de Unity Catalog

De forma predeterminada, el cliente de Python de MLflow crea modelos en el registro de modelos del área de trabajo de Azure Databricks. Para actualizar a modelos en Unity Catalog, configure el cliente para acceder a los modelos en Unity Catalog:

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

Entrenamiento y registro del modelo

El código siguiente entrena una red neuronal mediante TensorFlow Keras para predecir la producción de energía en función de las características meteorológicas del conjunto de datos y usa las API de MLflow para registrar el modelo ajustado en 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)

Visualización del modelo en la interfaz de usuario

Puede establecer, actualizar y quitar alias para modelos en Unity Catalog usando Catalog Explorer. Busque el modelo que acaba de crear en el catálogo main y el esquema default.

Página de modelo registrado

Implementación de una versión de modelo para la inferencia

Los modelos de Unity Catalog admiten alias para la implementación de modelos. Los alias proporcionan referencias mutables con nombre (por ejemplo, "Champion" o "Challenger") a una versión determinada de un modelo registrado. Puede hacer referencia a las versiones del modelo de destino y usar estos alias en flujos de trabajo de inferencia de bajada.

Una vez que haya navegado al modelo registrado en Explorador de catálogo, haga clic en la columna Alias para asignar el alias "Champion" a la versión más reciente del modelo y presione "Continuar" para guardar los cambios.

Establecer el alias del modelo registrado

Carga de versiones del modelo mediante la API

El componente de modelos de MLflow define funciones para cargar modelos desde varios marcos de aprendizaje automático. Por ejemplo, mlflow.tensorflow.load_model() se usa para cargar modelos de TensorFlow que se guardaron en el formato de MLflow, y mlflow.sklearn.load_model() se usa para cargar modelos de scikit-learn guardados en el formato de MLflow.

Estas funciones pueden cargar modelos desde Modelos en 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)

Previsión de la salida de energía con el modelo de campeón

En esta sección, se usa el modelo de campeón para evaluar los datos de previsión meteorológica de la granja eólica. La aplicación forecast_power() carga la versión más reciente del modelo de previsión desde la fase especificada y la usa para pronosticar la producción de energía durante los próximos cinco días.

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

Adición del modelo y las descripciones de las versiones del modelo mediante la API

El código de esta sección muestra cómo puede agregar descripciones de modelo y versión de modelo mediante la API de 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."
)

Creación de una nueva versión del modelo

Las técnicas clásicas de aprendizaje automático también son eficaces para la previsión de energía. El código siguiente entrena un modelo de bosque aleatorio mediante scikit-learn y lo registra en Unity Catalog mediante la función 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
  )

Captura del nuevo número de versión del modelo

En el código siguiente se muestra cómo recuperar el número de versión del modelo más reciente para un nombre de modelo.

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

Adición de una descripción a la nueva versión del modelo

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

Marca de la nueva versión del modelo como Challenger y prueba el modelo

Antes de implementar un modelo para atender el tráfico de producción, se recomienda probarlo en un ejemplo de datos de producción. Anteriormente, usó el alias "Champion" para indicar la versión del modelo que atiende a la mayoría de las cargas de trabajo de producción. El código siguiente asigna el alias "Challenger" a la nueva versión del modelo y evalúa su rendimiento.

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

forecast_power(MODEL_NAME, "Challenger")

Implementación de la nueva versión del modelo como versión del modelo Champion

Después de comprobar que la nueva versión del modelo funciona bien en las pruebas, el código siguiente asigna el alias "Champion" a la nueva versión del modelo y usa exactamente el mismo código de aplicación de la sección Previsión de la producción de energía con el modelo de campeón para generar una previsión de energía.

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

forecast_power(MODEL_NAME, "Champion")

Ahora hay dos versiones de modelo del modelo de previsión: la versión del modelo entrenada en el modelo Keras y la versión entrenada en scikit-learn. Tenga en cuenta que el alias "Challenger" permanece asignado a la nueva versión del modelo scikit-learn, por lo que las cargas de trabajo de bajada destinadas a la versión del modelo "Challenger" siguen ejecutándose correctamente:

Versiones del modelo del producto

Archivado y eliminación de modelos

Cuando ya no se usa una versión del modelo, puede eliminarla. También puede eliminar un modelo registrado completo; esto quita todas las versiones de modelo asociadas. Tenga en cuenta que la eliminación de una versión del modelo borra los alias asignados a la versión del modelo.

Eliminación de la Version 1 mediante la API de MLflow

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

Eliminación del modelo mediante la API de MLflow

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