Des artefacts aux modèles dans MLflow

L’article suivant explique les différences entre un artefact MLflow et un modèle MLflow, et comment passer de l’un à l’autre. Il explique également comment Azure Machine Learning utilise le concept de modèle MLflow pour simplifier les workflows de déploiement.

Quelle est la différence entre un artefact et un modèle ?

Si vous n’êtes pas familiarisé avec MLflow, vous ne connaissez peut-être pas la différence entre l’enregistrement d’artefacts ou de fichiers, et l’enregistrement de modèles MLflow. Il existe des différences fondamentales entre les deux :

Artefact

Un artefact est un fichier généré (et capturé) à partir de l’exécution ou du travail d’une expérience. Un artefact peut représenter un modèle sérialisé en tant que fichier Pickle, les pondérations d’un modèle PyTorch ou TensorFlow, ou même un fichier texte contenant les coefficients d’une régression linéaire. Certains artefacts peuvent également n’avoir rien à faire avec le modèle lui-même ; ils peuvent à la place contenir des configurations pour exécuter le modèle, des informations de prétraitement ou des échantillons de données, etc. Les artefacts peuvent avoir différents formats.

Vous avez peut-être déjà enregistré des artefacts :

filename = 'model.pkl'
with open(filename, 'wb') as f:
  pickle.dump(model, f)

mlflow.log_artifact(filename)

Modèle

Un modèle dans MLflow est également un artefact. Cependant, nous faisons des hypothèses plus solides sur ce type d’artefact. Ces hypothèses proposent un contrat clair entre les fichiers enregistrés et ce qu’ils signifient. Quand vous enregistrez vos modèles en tant qu’artefacts (de simples fichiers), vous devez savoir ce que signifie chacun de ces fichiers pour le générateur de modèles, afin de savoir comment charger le modèle pour l’inférence. Au contraire, les modèles MLflow peuvent être chargés en utilisant le contrat spécifié au format MLmodel.

Dans Azure Machine Learning, la journalisation des modèles présentent les avantages suivants :

  • Vous pouvez les déployer sur des points de terminaison en temps réel ou par lots sans fournir de script de scoring ni d’environnement.
  • Quand vous déployez des modèles, un fichier Swagger est généré automatiquement pour les déploiements, et la fonctionnalité Tester peut être utilisée dans Azure Machine Learning studio.
  • Vous pouvez utiliser les modèles directement comme entrées de pipeline.
  • Vous pouvez utiliser le tableau de bord IA responsable avec vos modèles.

Vous pouvez enregistrer des modèles en utilisant le SDK MLflow :

import mlflow
mlflow.sklearn.log_model(sklearn_estimator, "classifier")

Le format MLModel

MLflow adopte le format MLModel comme moyen de créer un contrat entre les artefacts et ce qu’ils représentent. Le format MLModel stocke des ressources dans un dossier. Parmi ces ressources, il existe un fichier nommé MLmodel. Celui-ci est la seule référence fiable quant à la façon dont un modèle peut être chargé et utilisé.

La capture d’écran suivante montre le dossier d’un exemple de modèle MLflow dans Azure Machine Learning studio. Le modèle est placé dans un dossier appelé credit_defaults_model. Il n’existe aucune exigence spécifique pour nommer ce dossier. Le dossier contient le fichier MLmodel, parmi d’autres artefacts de modèle.

A screenshot showing assets of a sample MLflow model, including the MLmodel file.

Le code suivant est un exemple de ce à quoi peut ressembler le fichier MLmodel d’un modèle Vision par ordinateur dont l’apprentissage a été effectué avec fastai :

mlModel

artifact_path: classifier
flavors:
  fastai:
    data: model.fastai
    fastai_version: 2.4.1
  python_function:
    data: model.fastai
    env: conda.yaml
    loader_module: mlflow.fastai
    python_version: 3.8.12
model_uuid: e694c68eba484299976b06ab9058f636
run_id: e13da8ac-b1e6-45d4-a9b2-6a0a5cfac537
signature:
  inputs: '[{"type": "tensor",
             "tensor-spec": 
                 {"dtype": "uint8", "shape": [-1, 300, 300, 3]}
           }]'
  outputs: '[{"type": "tensor", 
              "tensor-spec": 
                 {"dtype": "float32", "shape": [-1,2]}
            }]'

Saveurs des modèles

Compte tenu du grand nombre de frameworks d’apprentissage automatique disponibles, MLflow a introduit le concept de saveur comme moyen de fournir un contrat unique fonctionnant dans tous les frameworks d’apprentissage automatique. Une saveur indique ce à quoi il faut s’attendre pour un modèle donné créé avec un framework spécifique. Par exemple, TensorFlow a sa propre saveur, qui spécifie comment un modèle TensorFlow devrait être conservé et chargé. Étant donné que chaque saveur de modèle indique comment conserver et charger celui-ci pour un framework donné, le format MLModel n’impose pas un même mécanisme de sérialisation que tous les modèles doivent prendre en charge. Cette décision permet à chaque saveur d’utiliser les méthodes produisant les meilleures performances ou la meilleure prise en charge en fonction de leurs meilleures pratiques, sans compromettre la compatibilité avec la norme MLModel.

Le code suivant est un exemple de section flavors pour un modèle fastai.

flavors:
  fastai:
    data: model.fastai
    fastai_version: 2.4.1
  python_function:
    data: model.fastai
    env: conda.yaml
    loader_module: mlflow.fastai
    python_version: 3.8.12

Signature de modèle

Une signature de modèle dans MLflow est une partie importante de la spécification du modèle, car elle sert de contrat de données entre le modèle et le serveur qui exécute le modèle. Une signature de modèle est également importante pour analyser et appliquer les types d’entrée d’un modèle au moment du déploiement. Si une signature est disponible, MLflow applique les types d’entrée quand les données sont soumises à votre modèle. Pour plus d’informations, consultez Application d’une signature MLflow.

Les signatures sont indiquées quand les modèles sont enregistrés, et elles sont conservées dans la section signature du fichier MLmodel. La fonctionnalité d’enregistrement automatique dans MLflow infère automatiquement les signatures de la façon la plus efficace possible. Cependant, vous devrez peut-être enregistrer les modèles manuellement si les signatures inférées ne sont pas celles dont vous avez besoin. Pour plus d’informations, consultez Comment enregistrer des modèles avec des signatures.

Il existe deux types de signatures :

  • Signature basée sur des colonnes : cette signature fonctionne sur des données tabulaires. Pour les modèles avec ce type de signature, MLflow fournit des objets pandas.DataFrame comme entrées.
  • Signature basée sur Tensor : cette signature fonctionne sur des tableaux multidimensionnels ou des tenseurs. Pour les modèles avec cette signature, MLflow fournit numpy.ndarray en guise d’entrées (ou un dictionnaire de numpy.ndarray dans le cas de tenseurs nommés).

L’exemple suivant correspond à un modèle de vision par ordinateur dont l’apprentissage a été effectué avec fastai. Ce modèle reçoit un lot d’images représentées comme des tenseurs de forme (300, 300, 3) avec la représentation RVB de celles-ci (entiers non signés). Le modèle génère des lots de prédictions (probabilités) pour deux classes.

mlModel

signature:
  inputs: '[{"type": "tensor",
             "tensor-spec": 
                 {"dtype": "uint8", "shape": [-1, 300, 300, 3]}
           }]'
  outputs: '[{"type": "tensor", 
              "tensor-spec": 
                 {"dtype": "float32", "shape": [-1,2]}
            }]'

Conseil

Azure Machine Learning génère un fichier Swagger pour un déploiement d’un modèle MLflow avec une signature disponible. Il est ainsi plus facile de tester les déploiements en utilisant Azure Machine Learning studio.

Environnement de modèle

Les conditions requises pour l’exécution du modèle sont spécifiées dans le fichier conda.yaml. MLflow peut détecter automatiquement les dépendances ou bien vous pouvez les indiquer manuellement en appelant la méthode mlflow.<flavor>.log_model(). Cette dernière peut être pratique si les bibliothèques incluses dans votre environnement ne sont pas celles que vous avez prévu d’utiliser.

Le code suivant est un exemple d’environnement utilisé pour un modèle créé avec le framework fastai :

conda.yaml

channels:
- conda-forge
dependencies:
- python=3.8.5
- pip
- pip:
  - mlflow
  - astunparse==1.6.3
  - cffi==1.15.0
  - configparser==3.7.4
  - defusedxml==0.7.1
  - fastai==2.4.1
  - google-api-core==2.7.1
  - ipython==8.2.0
  - psutil==5.9.0
name: mlflow-env

Remarque

Quelle est la différence entre un environnement MLflow et un environnement Azure Machine Learning ?

Alors qu’un environnement MLflow fonctionne au niveau du modèle, un environnement Azure Machine Learning fonctionne au niveau de l’espace de travail (pour les environnements inscrits) ou des travaux/déploiements (pour les environnements anonymes). Lorsque vous déployez des modèles MLflow dans Azure Machine Learning, l’environnement du modèle est généré et utilisé pour le déploiement. Vous pouvez aussi remplacer ce comportement avec Azure Machine Learning CLI v2 et déployer des modèles MLflow en utilisant un environnement Azure Machine Learning spécifique.

Fonction predict

Tous les modèles MLflow contiennent une fonction predict. Cette fonction est appelée lors du déploiement d’un modèle en utilisant une expérience de déploiement sans code. Ce que la fonction predict retourne (par exemple des classes, des probabilités ou une prédiction) dépend du framework (c’est-à-dire de la saveur) utilisée pour l’apprentissage. Lisez la documentation sur chaque saveur pour savoir ce que la fonction retourne.

Dans des cas identiques, il peut être nécessaire de personnaliser cette fonction predict pour modifier la façon dont l’inférence est effectuée. Dans ce cas, vous devez enregistrer les modèles ayant un comportement différent dans la méthode predict ou enregistrer la saveur d’un modèle personnalisé.

Workflows pour le chargement de modèles MLflow

Vous pouvez charger des modèles qui ont été créés en tant que modèles MLflow depuis plusieurs emplacements, notamment :

  • directement depuis l’exécution où les modèles ont été enregistrés
  • depuis le système de fichiers où les modèles sont enregistrés
  • depuis le registre de modèles où les modèles sont inscrits.

MLflow offre un moyen cohérent de charger ces modèles, quel que soit leur emplacement.

Deux workflows sont disponibles pour le chargement des modèles :

  • Recharger le même objet et les mêmes types que ceux enregistrés : vous pouvez charger des modèles en utilisant le SDK MLflow et obtenir une instance du modèle avec des types appartenant à la bibliothèque d’apprentissage. Par exemple, un modèle ONNX retourne un ModelProto tandis qu’un modèle d’arbre de décision dont l’apprentissage a été effectué avec scikit-learn retourne un objet DecisionTreeClassifier. Utilisez mlflow.<flavor>.load_model() pour recharger le même objet et les mêmes types de modèle que ceux qui ont été enregistrés.

  • Recharger un modèle pour l’inférence en cours d’exécution : vous pouvez charger des modèles en utilisant le SDK MLflow et obtenir un wrapper où MLflow garantit la présence d’une fonction predict. Quelle que soit la saveur que vous utilisez, chaque modèle MLflow a une fonction predict. En outre, MLflow garantit que cette fonction peut être appelée en utilisant des arguments de type pandas.DataFrame, numpy.ndarray ou dict[string, numpyndarray] (en fonction de la signature du modèle). MLflow gère la conversion de type vers le type d’entrée attendu par le modèle. Utilisez mlflow.pyfunc.load_model() afin de recharger un modèle pour l’inférence en cours d’exécution.