Registro de modelos de MLflow

En este artículo se describe cómo registrar los modelos entrenados (o artefactos) como modelos de MLflow. Explora las distintas formas de personalizar cómo MLflow empaqueta los modelos y cómo ejecuta esos modelos.

¿Por qué registrar modelos en lugar de artefactos?

De artefactos a modelos en MLflow describe la diferencia entre los artefactos o archivos de registro, en comparación con los modelos de MLflow de registro.

Un modelo en MLflow también es un artefacto. Sin embargo, este modelo tiene una estructura específica que actúa como un contrato entre la persona que creó el modelo y la persona que pretende usarlo. Este contrato crea un puente entre los artefactos y sus significados.

El registro de modelos tiene estas ventajas:

  • Puede cargar directamente los modelos, para la inferencia, con mlflow.<flavor>.load_model y usar la función predict
  • Las entradas de canalización pueden usar modelos directamente
  • Puede implementar modelos sin indicar un script de puntuación o un entorno
  • Swagger se habilita automáticamente en puntos de conexión implementados y Estudio de Azure Machine Learning puede usar la característica Prueba
  • Puede usar el panel de IA responsable

En esta sección se describe cómo usar el concepto del modelo en Azure Machine Learning con MLflow:

Registro de modelos mediante el registro automático

Puede usar la funcionalidad de registro automático de MLflow. El registro automático permite a MLflow indicar al marco que use que registre todas las métricas, parámetros, artefactos y modelos que el marco considera pertinente. De forma predeterminada, si el registro automático está habilitado, la mayoría de los modelos se registran. En algunas situaciones, es posible que algunos tipos no registren un modelo. Por ejemplo, el tipo de PySpark no registra modelos que superen un tamaño determinado.

Use mlflow.autolog() o mlflow.<flavor>.autolog() para activar el registro automático. Este ejemplo, usa autolog() para registrar un modelo clasificador entrenado con XGBoost:

import mlflow
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score

mlflow.autolog()

model = XGBClassifier(use_label_encoder=False, eval_metric="logloss")
model.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=False)

y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)

Sugerencia

Si usa canalizaciones de Machine Learning, por ejemplo, canalizaciones de Scikit-Learn, use la funcionalidad autolog de ese tipo de canalización para registrar modelos. El registro de modelos se produce automáticamente cuando se llama al método fit() en el objeto de canalización. El cuaderno Training and tracking an XGBoost classifier with MLflow (Entrenamiento y seguimiento de un clasificador de XGBoost con MLflow) muestra cómo registrar un modelo con preprocesamiento mediante canalizaciones.

Registro de modelos con firmas, entornos o ejemplos personalizados

El método mlflow.<flavor>.log_model MLflow puede registrar manualmente los modelos. Este flujo de trabajo puede controlar diferentes aspectos del registro de modelos.

Utilice este método cuando:

  • Quiera indicar paquetes PIP o un entorno de Conda que difieran de los que se detectan automáticamente
  • Quiera incluir ejemplos de entrada
  • Quiera incluir artefactos específicos en el paquete necesario
  • autolog no infiera su firma correctamente. Esto es importante con las entradas de tensor, donde la firma necesita formas específicas
  • El comportamiento del registro automático no satisfaga su propósito por algún motivo

El siguiente código de ejemplo registra un modelo para un clasificador de XGBoost:

import mlflow
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
from mlflow.models import infer_signature
from mlflow.utils.environment import _mlflow_conda_env

mlflow.autolog(log_models=False)

model = XGBClassifier(use_label_encoder=False, eval_metric="logloss")
model.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=False)
y_pred = model.predict(X_test)

accuracy = accuracy_score(y_test, y_pred)

# Signature
signature = infer_signature(X_test, y_test)

# Conda environment
custom_env =_mlflow_conda_env(
    additional_conda_deps=None,
    additional_pip_deps=["xgboost==1.5.2"],
    additional_conda_channels=None,
)

# Sample
input_example = X_train.sample(n=1)

# Log the model manually
mlflow.xgboost.log_model(model, 
                         artifact_path="classifier", 
                         conda_env=custom_env,
                         signature=signature,
                         input_example=input_example)

Nota:

  • autolog tiene la configuración de log_models=False. Esto evita el registro automático de modelos de MLflow. El registro automático de modelos de MLflow se produce más adelante, como un proceso manual
  • Use el método infer_signature para intentar deducir la firma directamente desde entradas y salidas
  • mlflow.utils.environment._mlflow_conda_env es un método privado en el SDK de MLflow. En este ejemplo, simplifica el código, pero úselo con precaución, pues podría cambiar en el futuro. Como alternativa, puede generar la definición de YAML manualmente como diccionario de Python.

Registro de modelos con un comportamiento diferente en el método predict

Al registrar un modelo con mlflow.autolog o mlflow.<flavor>.log_model, el tipo de modelo determina cómo ejecutar la inferencia y lo que devuelve el modelo. MLflow no impone ningún comportamiento específico para la generación de resultados de predict. En algunos escenarios, puede que desee realizar preprocesamiento o procesamiento posterior antes y después de que se ejecute el modelo.

En esta situación, implemente canalizaciones de aprendizaje automático que se mueven directamente de entradas a salidas. Aunque esta implementación es posible y, a veces, se recomienda para mejorar el rendimiento, podría resultar difícil lograrla. En esos casos, puede ser útil personalizar cómo controla el modelo las inferencias como se explica en la sección siguiente.

Registro de modelos personalizados

MLflow admite muchos marcos de aprendizaje automático, como los siguientes:

  • CatBoost
  • FastAI
  • h2o
  • Keras
  • LightGBM
  • MLeap
  • MXNet Gluon
  • ONNX
  • Prophet
  • PyTorch
  • Scikit-Learn
  • spaCy
  • Spark MLLib
  • statsmodels
  • TensorFlow
  • XGBoost

Sin embargo, puede que deba cambiar la forma en que funciona un tipo, registrar un modelo no compatible de forma nativa con MLflow o incluso registrar un modelo que use varios elementos de diferentes marcos. En esos casos, podría ser necesario crear un tipo de modelo personalizado.

Para resolver el problema, MLflow presenta el tipo pyfunc (a partir de una función de Python). Este tipo puede registrar cualquier objeto como modelo, siempre que ese objeto cumpla dos condiciones:

  • Que usted implemente, al menos, el método predict
  • Que el objeto de Python se herede de mlflow.pyfunc.PythonModel

Sugerencia

Los modelos serializables que implementan la API Scikit-learn pueden usar el tipo Scikit-learn para registrar el modelo, independientemente de si el modelo se creó con Scikit-learn o no. Si puede conservar el modelo en formato pickle y el objeto tiene los métodos predict() y predict_proba() (como mínimo), puede usar mlflow.sklearn.log_model() para registrar el modelo dentro de una ejecución de MLflow.

Si crea un contenedor para el objeto de modelo existente, es más sencillo crear un tipo para el modelo personalizado. MLflow lo serializa y lo empaqueta automáticamente. Los objetos de Python son serializables cuando se pueden almacenar en el sistema de archivos como un archivo, generalmente con el formato pickle. En tiempo de ejecución, el objeto puede materializarse desde ese archivo. Esto restaura todos los valores, propiedades y métodos disponibles cuando se guardó.

Utilice este método cuando:

  • Pueda serializar el modelo en formato pickle
  • Pueda conservar el estado del modelo, ya que fue justo después del entrenamiento
  • Quiera personalizar cómo opera la función predict.

Este ejemplo de código encapsula un modelo creado con XGBoost, para que se comporte de forma distinta a la implementación predeterminada del tipo XGBoost. En su lugar, devuelve las probabilidades en lugar de las clases:

from mlflow.pyfunc import PythonModel, PythonModelContext

class ModelWrapper(PythonModel):
    def __init__(self, model):
        self._model = model

    def predict(self, context: PythonModelContext, data):
        # You don't have to keep the semantic meaning of `predict`. You can use here model.recommend(), model.forecast(), etc
        return self._model.predict_proba(data)

    # You can even add extra functions if you need to. Since the model is serialized,
    # all of them will be available when you load your model back.
    def predict_batch(self, data):
        pass

Registre un modelo personalizado en la ejecución:

import mlflow
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
from mlflow.models import infer_signature

mlflow.xgboost.autolog(log_models=False)

model = XGBClassifier(use_label_encoder=False, eval_metric="logloss")
model.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=False)
y_probs = model.predict_proba(X_test)

accuracy = accuracy_score(y_test, y_probs.argmax(axis=1))
mlflow.log_metric("accuracy", accuracy)

signature = infer_signature(X_test, y_probs)
mlflow.pyfunc.log_model("classifier", 
                        python_model=ModelWrapper(model),
                        signature=signature)

Sugerencia

Aquí, el método infer_signature usa y_probs para deducir la firma. La columna de destino tiene la clase de destino, pero el modelo ahora devuelve las dos probabilidades de cada clase.

Pasos siguientes