Journalisation de modèles MLflow
Cet article explique comment consigner vos modèles entraînés (ou artefacts) en tant que modèles MLflow. Il explore les différentes façons de personnaliser la façon dont MLflow empaquette vos modèles et comment il exécute ces modèles.
Pourquoi journaliser des modèles au lieu d’artefacts ?
Les artefacts et les modèles dans MLflow décrivent la différence entre les artefacts de journalisation ou les fichiers, par rapport à la journalisation des modèles MLflow.
Un modèle MLflow est également un artefact. Toutefois, ce modèle a une structure spécifique qui sert de contrat entre la personne qui a créé le modèle et la personne qui a l’intention de l’utiliser. Ce contrat permet de créer un pont entre les artefacts eux-mêmes et leurs significations.
La journalisation des modèles présente les avantages suivants :
- Vous pouvez charger directement des modèles, pour l’inférence avec
mlflow.<flavor>.load_model
, et vous pouvez utiliser la fonctionpredict
- Les entrées de pipeline peuvent utiliser directement des modèles
- Vous pouvez déployer des modèles sans indication d’un script de scoring ou d’un environnement
- Swagger est automatiquement activé dans les points de terminaison déployés, et Azure Machine Learning Studio peut utiliser la fonctionnalité de test
- Vous pouvez utiliser le tableau de bord d’IA responsable
Cette section explique comment utiliser le concept du modèle dans Azure Machine Learning avec MLflow :
Journalisation des modèles à l’aide de la journalisation automatique
Vous pouvez utiliser la fonctionnalité de journal automatique MLflow. La journalisation automatique permet à MLflow d’indiquer à l’infrastructure en cours d’utilisation de journaliser toutes les métriques, paramètres, artefacts et modèles considérés par l’infrastructure comme pertinents. Par défaut, si la journalisation automatique est activée, la plupart des modèles sont enregistrés. Dans certaines situations, certaines saveurs peuvent ne pas journaliser un modèle. Par exemple, la saveur PySpark ne journalise pas les modèles qui dépassent une certaine taille.
Utilisez mlflow.autolog()
ou mlflow.<flavor>.autolog()
pour activer la journalisation automatique. Cet exemple utilise autolog()
pour journaliser un modèle classifieur entraîné avec 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)
Conseil
Si vous utilisez des pipelines Machine Learning, par exemple des pipelines Scikit-Learn, utilisez les fonctionnalités autolog
de cette saveur de pipeline pour journaliser les modèles. La journalisation des modèles se produit automatiquement lorsque la méthode fit()
est appelée sur l’objet de pipeline. L’entraînement et suivi d’un classifieur XGBoost avec le notebook de MLflow montre comment journaliser un modèle avec prétraitement à l’aide de pipelines.
Journalisation des modèles avec une signature, un environnement ou des exemples personnalisés
La méthode mlflow.<flavor>.log_model
MLflow peut journaliser manuellement les modèles. Ce flux de travail peut contrôler différents aspects de la journalisation des modèles.
Utilisez cette méthode dans les cas suivants :
- Vous souhaitez indiquer des packages pip ou un environnement conda qui diffèrent de ceux qui sont automatiquement détectés
- Vous souhaitez inclure des exemples d’entrée
- Vous souhaitez inclure des artefacts spécifiques dans le package nécessaire
autolog
ne déduit pas correctement votre signature. Cela est important lorsque vous traitez des entrées de capteur, où la signature a besoin de formes spécifiques- Le comportement de journal automatique ne couvre pas votre objectif pour une raison quelconque
Cet exemple de code journalise un modèle pour un classifieur 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)
Remarque
autolog
a la configurationlog_models=False
. Cela empêche la journalisation automatique des modèles MLflow. La journalisation automatique des modèles MLflow se produit ultérieurement, en tant que processus manuel- Cela utilise la méthode
infer_signature
pour essayer de déduire directement la signature des entrées et des sorties. - La méthode
mlflow.utils.environment._mlflow_conda_env
est une méthode privée dans le (SDK) MLflow. Dans cet exemple, il simplifie le code, mais l’utilise avec précaution. Cela pourrait changer à l'avenir. En guise d’alternative, vous pouvez générer manuellement la définition YAML en tant que dictionnaire Python.
Journalisation des modèles avec un comportement différent dans la méthode predict
Lors de la journalisation d’un modèle avec mlflow.autolog
ou mlflow.<flavor>.log_model
, la saveur du modèle détermine comment exécuter l’inférence et ce que le modèle retourne. MLflow n’applique aucun comportement spécifique concernant la génération de résultats predict
. Dans certains scénarios, il se peut que vous souhaitiez effectuer un traitement antérieur ou postérieur avant et après l’exécution de votre modèle.
Dans ce cas, implémentez des pipelines Machine Learning qui passent directement des entrées aux sorties. Bien que cette implémentation soit possible et parfois encouragée à améliorer les performances, il peut devenir difficile d’atteindre. Dans ces cas, il peut aider à personnaliser la façon dont votre modèle gère l’inférence, comme expliqué dans la section suivante.
Journalisation des modèles personnalisés
MLflow prend en charge de nombreuses infrastructures Machine Learning, notamment
- CatBoost
- FastAI
- h2o
- Keras
- LightGBM
- MLeap
- MXNet Gluon
- ONNX
- Prophet
- PyTorch
- Scikit-Learn
- spaCy
- Spark MLLib
- statsmodels
- TensorFlow
- XGBoost
Toutefois, vous pouvez avoir besoin de modifier la façon dont une saveur fonctionne, de journaliser un modèle non pris en charge en mode natif par MLflow ou même journaliser un modèle qui utilise plusieurs éléments à partir de différents infrastructures. Dans ces cas, il peut être nécessaire de créer une saveur de modèle personnalisée.
Pour résoudre le problème, MLflow introduit la saveur pyfunc
(à partir d’une fonction Python). Cette saveur peut consigner n’importe quel objet en tant que modèle, tant que cet objet satisfait à deux conditions :
- Vous implémentez la méthode
predict
(au moins) - L’objet Python hérite de
mlflow.pyfunc.PythonModel
Conseil
Les modèles sérialisables qui implémentent l’API Scikit-learn peuvent utiliser la saveur Scikit-learn pour journaliser le modèle, quel que soit le modèle créé avec Scikit-learn. Si vous pouvez conserver votre modèle au format Pickle et que l’objet a les méthodes predict()
et predict_proba()
(au moins), vous pouvez utiliser mlflow.sklearn.log_model()
pour enregistrer le modèle à l’intérieur d’une exécution MLflow.
Si vous créez un wrapper autour de votre objet de modèle existant, il devient le plus simple de créer une saveur pour votre modèle personnalisé. MLflow sérialise et les packages pour vous. Les objets Python sont sérialisables lorsque l’objet peut être stocké dans le système de fichiers en tant que fichier généralement au format Pickle. Au moment de l’exécution, l’objet peut matérialiser à partir de ce fichier. Cela restaure toutes les valeurs, propriétés et méthodes disponibles lors de son enregistrement.
Utilisez cette méthode dans les cas suivants :
- Vous pouvez sérialiser votre modèle au format Pickle
- Vous souhaitez conserver l’état du modèle, tel qu’il était juste après l’entraînement
- Vous souhaitez personnaliser le fonctionnement de la fonction
predict
.
Cet exemple de code encapsule un modèle créé avec XGBoost pour qu’il se comporte différemment de l’implémentation par défaut de la saveur XGBoost. Au lieu de cela, elle retourne les probabilités au lieu des 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
Journaliser un modèle personnalisé dans l’exécution :
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)
Conseil
Ici, la méthode infer_signature
utilise y_probs
pour déduire la signature. Notre colonne cible a la classe cible, mais notre modèle retourne maintenant les deux probabilités pour chaque classe.