Registrando modelos MLflow

Este artigo descreve como registrar seus modelos treinados (ou artefatos) como modelos MLflow. Ele explora as diferentes maneiras de personalizar como o MLflow empacota seus modelos e como ele executa esses modelos.

Porquê registar modelos em vez de artefactos?

De artefatos a modelos no MLflow descreve a diferença entre registrar artefatos ou arquivos, em comparação com o registro de modelos MLflow .

Um modelo MLflow também é um artefato. No entanto, esse modelo tem uma estrutura específica que serve como um contrato entre a pessoa que criou o modelo e a pessoa que pretende usá-lo. Este contrato ajuda a construir uma ponte entre os próprios artefatos e seus significados.

O registro em log do modelo tem estas vantagens:

  • Você pode carregar modelos diretamente, para inferência, com mlflow.<flavor>.load_model, e pode usar a predict função
  • As entradas de pipeline podem usar modelos diretamente
  • Você pode implantar modelos sem indicação de um script de pontuação ou um ambiente
  • O Swagger é habilitado automaticamente em pontos de extremidade implantados e o estúdio de Aprendizado de Máquina do Azure pode usar o recurso Teste
  • Você pode usar o painel de IA responsável

Esta seção descreve como usar o conceito do modelo no Azure Machine Learning com MLflow:

Registrando modelos usando o autolog

Você pode usar a funcionalidade de log automático MLflow. O Autolog permite que o MLflow instrua a estrutura em uso para registrar todas as métricas, parâmetros, artefatos e modelos que a estrutura considera relevantes. Por padrão, se o registro automático estiver habilitado, a maioria dos modelos será registrada. Em algumas situações, alguns sabores podem não registrar um modelo. Por exemplo, o sabor PySpark não registra modelos que excedem um determinado tamanho.

Use um ou mlflow.autolog()mlflow.<flavor>.autolog() para ativar o registro automático. Este exemplo usa autolog() para registrar um modelo de classificador treinado com 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)

Gorjeta

Se usar pipelines de Machine Learning, por exemplo , pipelines Scikit-Learn, use a autolog funcionalidade desse tipo de pipeline para registrar modelos. O log do modelo acontece automaticamente quando o fit() método é chamado no objeto de pipeline. O Treinamento e acompanhamento de um classificador XGBoost com o notebook MLflow demonstra como registrar um modelo com pré-processamento, usando pipelines.

Registrando modelos com uma assinatura, ambiente ou amostras personalizados

O método MLflow mlflow.<flavor>.log_model pode registrar modelos manualmente. Esse fluxo de trabalho pode controlar diferentes aspetos do registro em log do modelo.

Use este método quando:

  • Você deseja indicar pacotes pip ou um ambiente conda que diferem daqueles que são detetados automaticamente
  • Você deseja incluir exemplos de entrada
  • Você deseja incluir artefatos específicos no pacote necessário
  • autolog não infere corretamente a sua assinatura. Isso é importante quando você lida com entradas tensoras, onde a assinatura precisa de formas específicas
  • O comportamento de registro automático não cobre seu propósito por algum motivo

Este exemplo de código registra um modelo para um classificador 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 tem a log_models=False configuração. Isso impede o registro automático do modelo MLflow. O registro automático do modelo MLflow acontece mais tarde, como um processo manual
  • Use o infer_signature método para tentar inferir a assinatura diretamente de entradas e saídas
  • O mlflow.utils.environment._mlflow_conda_env método é um método privado no MLflow SDK. Neste exemplo, ele torna o código mais simples, mas use-o com cuidado. Pode mudar no futuro. Como alternativa, você pode gerar a definição YAML manualmente como um dicionário Python.

Registrando modelos com um comportamento diferente no método predict

Ao registrar um modelo com um ou mlflow.autologmlflow.<flavor>.log_model, o sabor do modelo determina como executar a inferência e o que o modelo retorna. O MLflow não impõe nenhum comportamento específico sobre a geração de predict resultados. Em alguns cenários, talvez você queira fazer algum pré-processamento ou pós-processamento antes e depois da execução do modelo.

Nessa situação, implemente pipelines de aprendizado de máquina que se movem diretamente de entradas para saídas. Embora esta implementação seja possível e, por vezes, incentivada a melhorar o desempenho, pode tornar-se difícil de alcançar. Nesses casos, pode ajudar a personalizar como seu modelo lida com a inferência , conforme explicado na próxima seção.

Registrando modelos personalizados

O MLflow suporta muitas estruturas de aprendizado de máquina, incluindo

  • CatBoost
  • FastAI
  • h2o
  • Keras
  • LightGBM
  • MLeap
  • MXNet Glúon
  • ONNX
  • Profeta
  • PyTorch
  • Scikit-Aprender
  • espaCy
  • Faísca MLLib
  • statsmodels
  • TensorFlow
  • XGBoost

No entanto, talvez seja necessário alterar a maneira como um sabor funciona, registrar um modelo não suportado nativamente pelo MLflow ou até mesmo registrar um modelo que usa vários elementos de diferentes estruturas. Nesses casos, talvez seja necessário criar um sabor de modelo personalizado.

Para resolver o problema, o MLflow introduz o pyfunc sabor (a partir de uma função Python). Esse sabor pode registrar qualquer objeto como um modelo, desde que esse objeto satisfaça duas condições:

  • Você implementa o método de método predict , pelo menos
  • O objeto Python herda de mlflow.pyfunc.PythonModel

Gorjeta

Os modelos serializáveis que implementam a API Scikit-learn podem usar o sabor Scikit-learn para registrar o modelo, independentemente de o modelo ter sido construído com o Scikit-learn. Se você puder persistir seu modelo no formato Pickle e o objeto tiver os predict() métodos e predict_proba() (pelo menos), poderá usar mlflow.sklearn.log_model() para registrar o modelo dentro de uma execução MLflow.

Se você criar um wrapper em torno de seu objeto de modelo existente, torna-se mais simples criar um sabor para seu modelo personalizado. O MLflow serializa e empacota para você. Os objetos Python são serializáveis quando o objeto pode ser armazenado no sistema de arquivos como um arquivo, geralmente no formato Pickle. No tempo de execução, o objeto pode se materializar a partir desse arquivo. Isso restaura todos os valores, propriedades e métodos disponíveis quando foi salvo.

Use este método quando:

  • Você pode serializar seu modelo no formato Pickle
  • Você quer manter o estado do modelo, como foi logo após o treinamento
  • Você deseja personalizar como a predict função funciona.

Este exemplo de código encapsula um modelo criado com XGBoost, para fazer com que ele se comporte em uma implementação padrão de sabor XGBoost. Em vez disso, ele retorna as probabilidades em vez das classes:

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 um modelo personalizado na execução:

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)

Gorjeta

Aqui, o infer_signature método usa y_probs para inferir a assinatura. Nossa coluna de destino tem a classe de destino, mas nosso modelo agora retorna as duas probabilidades para cada classe.

Próximos passos