es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo guardar más metadatos en un modelo de MLFlow?

Estoy intentando guardar un modelo en MLFlow, pero como tengo un pipeline personalizado de predicción para recuperar datos, necesito guardar metadatos adicionales en el modelo.

Intenté usar mi clase de firma personalizada, que hace correctamente el trabajo y guarda el modelo con los metadatos adicionales en el archivo MLModel (formato YAML). Pero cuando quiero cargar el modelo del registro de MLFlow, la firma no es fácilmente accesible.

También intenté guardar un diccionario adicional en la función log_model, pero lo guarda en el archivo conda.yaml:

¿Debería crear mi propio sabor? ¿O mi propia herencia de Modelo? He visto aquí que PyFuncModel recibe alguna clase de metadatos y una implementación para resolver esto, pero no sé dónde debería pasar mis propias implementaciones a PyFuncModel en un script de experimento. Aquí hay un ejemplo mínimo:

import mlflow
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression

metadata_dic = {"metadata1": "value1", "metadata2": "value2"}

X = np.array([[-2, -1, 0, 1, 2, 1],[-2, -1, 0, 1, 2, 1]]).T
y = np.array([0, 0, 1, 1, 1, 0])

X = pd.DataFrame(X, columns=["X1", "X2"])
y = pd.DataFrame(y, columns=["y"])


model = LogisticRegression()
model.fit(X, y)

mlflow.sklearn.log_model(model, "model")
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Parece que tu enfoque de utilizar una clase de firma personalizada o guardar un diccionario de metadatos como argumento para la función log_model debería funcionar. El problema de no poder acceder fácilmente a la firma al cargar desde el registro de MLFlow podría deberse a que la función log_model no guarda la firma de una manera compatible con la forma en que mlflow.sklearn.load_model lo espera.

    Un enfoque que podrías tomar es crear tu propio sabor de modelo personalizado que extienda mlflow.pyfunc.PythonModel o mlflow.pyfunc.PyFuncModel. Puedes definir tu propia clase de metadatos como una subclase de mlflow.pyfunc.model.PythonModelMetadata y sobrescribir el método load_context para cargar los metadatos y retornar un objeto de contexto personalizado que contenga tanto el modelo como los metadatos. Aquí hay un ejemplo de cómo podrías modificar tu código para usar un sabor personalizado:

    from mlflow.pyfunc import PythonModel, PythonModelContext, PythonModelMetadata
    
    class MyMetadata(PythonModelMetadata):
        def __init__(self, metadata1, metadata2):
            self.metadata1 = metadata1
            self.metadata2 = metadata2
    
    class MyPyFuncModel(PythonModel):
        FLAVOR_NAME = "my-pyfunc"
        METADATA = MyMetadata
        PREDICT_INPUT_SCHEMA = None
        PREDICT_OUTPUT_SCHEMA = None
    
        def __init__(self, model, metadata):
            self.model = model
            self.metadata = metadata
    
        def predict(self, context, inputs):
            # Use custom logic to retrieve features
            features = get_custom_features(inputs)
            return self.model.predict(features)
    
        @staticmethod
        def load_context(context):
            metadata = MyMetadata.from_dict(context.artifacts["model.yaml"]["metadata"])
            model = YourModelLoadingLogic(context.artifacts["model"])
            return PythonModelContext(MyPyFuncModel(model, metadata))
    
    metadata_dic = {"metadata1": "valor1", "metadata2": "valor2"}
    
    X = np.array([[-2, -1, 0, 1, 2, 1],[-2, -1, 0, 1, 2, 1]]).T
    y = np.array([0, 0, 1, 1, 1, 0])
    
    X = pd.DataFrame(X, columns=["X1", "X2"])
    y = pd.DataFrame(y, columns=["y"])
    
    model = LogisticRegression()
    model.fit(X, y)
    
    mlflow.pyfunc.log_model(
        artifact_path="model",
        python_model=MyPyFuncModel(model, MyMetadata(**metadata_dic)),
        signature=None,
        registered_model_name="mi-modelo-registrado",
        conda_env=None,
        code_path=None,
    )
    

    Aquí, definimos una nueva clase MyPyFuncModel que extiende mlflow.pyfunc.PythonModel. Establecemos el FLAVOR_NAME como “my-pyfunc” para diferenciarlo del sabor predeterminado “python_function”, y configuramos el atributo METADATA como MyMetadata para especificar nuestra clase de metadatos personalizados. También definimos el método predict para manejar nuestra lógica personalizada de recuperación de características.

    En el método load_context, cargamos los metadatos del archivo “model.yaml” (que se genera automáticamente por MLFlow al usar la función log_model) y utilizamos nuestra propia lógica para cargar el objeto del modelo. Luego, retornamos un objeto PythonModelContext que contiene tanto el modelo como los metadatos.

    Para registrar nuestro modelo utilizando este nuevo sabor, usamos la función mlflow.pyfunc.log_model en lugar de mlflow.sklearn.log_model. Le pasamos una instancia de nuestra clase MyPyFuncModel, junto con una instancia de MyMetadata inicializada con nuestro diccionario de metadatos.

    Al cargar el modelo desde el registro, podemos utilizar mlflow.pyfunc.load_model junto con el nombre de nuestro sabor personalizado (“my-pyfunc”) para recuperar una instancia de nuestra clase MyPyFuncModel, que contiene tanto el modelo como los metadatos. A partir de ahí, podemos acceder fácilmente a los metadatos y utilizarlos según sea necesario.

Comments are closed.