Traitement d’images avec des modèles de déploiement par lots
S’APPLIQUE À :Extension Azure ML CLI v2 (actuelle)Kit de développement logiciel (SDK) Python azure-ai-ml v2 (préversion)
Vous pouvez utiliser des déploiements de modèles par lots pour traiter des données tabulaires et aussi tous les autres types de fichiers, comme des images. Ces déploiements sont pris en charge dans les modèles MLflow et personnalisés. Dans cet article, vous découvrez comment déployer un modèle qui classifie des images en fonction de la taxonomie ImageNet.
Prérequis
Un abonnement Azure. Si vous n’avez pas d’abonnement Azure, créez un compte gratuit avant de commencer. Essayez la version gratuite ou payante d’Azure Machine Learning.
Un espace de travail Azure Machine Learning. Pour créer un espace de travail, consultez Gérer les espaces de travail Azure Machine Learning.
Vérifiez que vous disposez des autorisations suivantes dans l’espace de travail Machine Learning :
- Créez ou gérez des points de terminaison et des déploiements par lots : utilisez un rôle propriétaire, contributeur ou personnalisé autorisant
Microsoft.MachineLearningServices/workspaces/batchEndpoints/*
. - Créer des déploiements Azure Resource Manager dans le groupe de ressources de l’espace de travail : utilisez un rôle Propriétaire, Contributeur ou un rôle personnalisé autorisant
Microsoft.Resources/deployments/write
dans le groupe de ressources où l’espace de travail est déployé.
- Créez ou gérez des points de terminaison et des déploiements par lots : utilisez un rôle propriétaire, contributeur ou personnalisé autorisant
Installez le logiciel suivant pour utiliser Machine Learning :
Exécutez la commande suivante pour installer l’interface de ligne de commande Azure et l’extension pour Azure Machine Learning
ml
:az extension add -n ml
Les déploiements de composants de pipeline pour des points de terminaison Batch sont introduits dans la version 2.7 de l’extension
ml
pour l’interface de ligne de commande Azure. Utilisez la commandeaz extension update --name ml
pour obtenir la dernière version.
Se connecter à un espace de travail
L’espace de travail est la ressource de niveau supérieur pour le Machine Learning. Il fournit un emplacement centralisé pour travailler avec tous les artefacts que vous créez lorsque vous utilisez Machine Learning. Dans cette section, vous vous connectez à l’espace de travail dans lequel vous effectuez vos tâches de déploiement.
Dans la commande suivante, entrez les valeurs de votre ID d’abonnement, de votre espace de travail, de votre emplacement et de votre groupe de ressources :
az account set --subscription <subscription>
az configure --defaults workspace=<workspace> group=<resource-group> location=<location>
À propos de cet exemple
Cet article utilise un modèle créé en utilisant TensorFlow avec l’architecture RestNet. Pour plus d’informations, consultez Mappages d’identités dans les réseaux résiduels profonds. Vous pouvez télécharger un exemple de ce modèle. Le modèle a les contraintes suivantes :
- Il fonctionne avec des images de taille 244x244 (tenseurs de
(224, 224, 3)
). - Il nécessite que les entrées soient mises à l’échelle à la plage
[0,1]
.
Les informations de cet article sont basées sur des exemples de code contenus dans le référentiel azureml-examples. Pour exécuter les commandes localement sans devoir copier/coller du code YAML et d’autres fichiers, clonez le référentiel. Changez les répertoires en cli/endpoints/batch/deploy-models/imagenet-classifier si vous utilisez Azure CLI ou en sdk/python/endpoints/batch/deploy-models/imagenet-classifier si vous utilisez le Kit de développement logiciel (SDK) pour Python.
git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/cli/endpoints/batch/deploy-models/imagenet-classifier
Suivre dans les notebooks Jupyter
Vous pouvez suivre cet exemple dans un notebook Jupyter. Dans le dépôt cloné, ouvrez le notebook : imagenet-classifier-batch.ipynb.
Classification d’images avec déploiements par lots
Dans cet exemple, vous découvrez comment déployer un modèle Deep Learning qui peut classifier une image donnée en fonction de la taxonomie d’ImageNet.
Créer le point de terminaison
Créez le point de terminaison qui héberge le modèle :
Spécifiez le nom du point de terminaison.
ENDPOINT_NAME="imagenet-classifier-batch"
Créez le fichier YAML suivant pour définir le point de terminaison de lot, nommé endpoint.yml :
$schema: https://azuremlschemas.azureedge.net/latest/batchEndpoint.schema.json name: imagenet-classifier-batch description: A batch endpoint for performing image classification using a TFHub model ImageNet model. auth_mode: aad_token
Pour créer le point de terminaison, exécutez le code suivant :
az ml batch-endpoint create --file endpoint.yml --name $ENDPOINT_NAME
Inscrire le modèle
Les déploiements de modèles peuvent déployer seulement des modèles inscrits. Vous devez inscrire le modèle. Vous pouvez ignorer cette étape si le modèle que vous essayez de déployer est déjà inscrit.
Téléchargez une copie du modèle.
Inscrire le modèle.
Créer un script de scoring
Créez un script de scoring qui peut lire les images fournies par le déploiement par lots et retourner les scores du modèle.
- La méthode
init
charge le modèle en utilisant le modulekeras
danstensorflow
. - La méthode
run
s’exécute pour chaque mini-lot fourni par le déploiement par lots. - La méthode
run
lit une image du fichier à la fois. - La méthode
run
redimensionne les images aux tailles attendues du modèle. - La méthode
run
redimensionne les images vers le domaine de plage[0,1]
, ce qui est ce que le modèle attend. - Le script retourne les classes et les probabilités associées aux prédictions.
Ce code correspond au fichier code/score-by-file/batch_driver.py :
import os
import numpy as np
import pandas as pd
import tensorflow as tf
from os.path import basename
from PIL import Image
from tensorflow.keras.models import load_model
def init():
global model
global input_width
global input_height
# AZUREML_MODEL_DIR is an environment variable created during deployment
model_path = os.path.join(os.environ["AZUREML_MODEL_DIR"], "model")
# load the model
model = load_model(model_path)
input_width = 244
input_height = 244
def run(mini_batch):
results = []
for image in mini_batch:
data = Image.open(image).resize(
(input_width, input_height)
) # Read and resize the image
data = np.array(data) / 255.0 # Normalize
data_batch = tf.expand_dims(
data, axis=0
) # create a batch of size (1, 244, 244, 3)
# perform inference
pred = model.predict(data_batch)
# Compute probabilities, classes and labels
pred_prob = tf.math.reduce_max(tf.math.softmax(pred, axis=-1)).numpy()
pred_class = tf.math.argmax(pred, axis=-1).numpy()
results.append([basename(image), pred_class[0], pred_prob])
return pd.DataFrame(results)
Conseil
Bien que les images soient fournies dans des mini-lots par le déploiement, ce script de scoring traite une image à la fois. C’est un modèle courant, car une tentative pour charger l’intégralité du lot et l’envoyer au modèle en une seule fois peut entraîner une forte sollicitation de la mémoire sur l’exécuteur de lot (exceptions de mémoire insuffisante).
Dans certains cas, ceci permet d’obtenir un débit élevé dans la tâche de scoring. C’est le cas pour les déploiements par lots sur du matériel GPU quand vous voulez atteindre une utilisation élevée du GPU. Pour obtenir un script de scoring qui tire parti de cette approche, consultez Déploiements à haut débit.
Remarque
Si vous voulez déployer un modèle génératif qui génère des fichiers, découvrez comment créer un script de scoring : Personnaliser les sorties dans les déploiements par lots.
Créer le déploiement
Après avoir créé le script de scoring, créez un déploiement par lots pour celui-ci. Suivez la procédure suivante :
Vérifiez que vous disposez d’un cluster de calcul créé là où vous pouvez créer le déploiement. Dans cet exemple, utilisez un cluster de calcul nommé
gpu-cluster
. Bien que ce ne soit pas obligatoire, l’utilisation de GPU accélère le traitement.Indiquez sur quel environnement exécuter le déploiement. Dans cet exemple, le modèle s’exécute sur
TensorFlow
. Azure Machine Learning a déjà d’un environnement où les logiciels requis sont installés : vous pouvez donc réutiliser cet environnement. Vous devez ajouter quelques dépendances dans un fichier conda.yml.Créez le déploiement.
Pour créer un déploiement sous le point de terminaison créé, créez une configuration
YAML
comme l’exemple suivant. Pour d’autres propriétés, consultez le schéma YAML de point de terminaison de lot complet.$schema: https://azuremlschemas.azureedge.net/latest/modelBatchDeployment.schema.json endpoint_name: imagenet-classifier-batch name: imagenet-classifier-resnetv2 description: A ResNetV2 model architecture for performing ImageNet classification in batch type: model model: azureml:imagenet-classifier@latest compute: azureml:gpu-cluster environment: name: tensorflow212-cuda11-gpu image: mcr.microsoft.com/azureml/curated/tensorflow-2.12-cuda11:latest conda_file: environment/conda.yaml code_configuration: code: code/score-by-file scoring_script: batch_driver.py resources: instance_count: 2 settings: max_concurrency_per_instance: 1 mini_batch_size: 5 output_action: append_row output_file_name: predictions.csv retry_settings: max_retries: 3 timeout: 300 error_threshold: -1 logging_level: info
Créez le déploiement avec la commande suivante :
az ml batch-deployment create --file deployment-by-file.yml --endpoint-name $ENDPOINT_NAME --set-default
Si vous pouvez appeler un déploiement spécifique à l’intérieur d’un point de terminaison, en général, vous allez appeler le point de terminaison lui-même et le laisser décider du déploiement à utiliser. Un tel déploiement est appelé déploiement par défaut.
Cette approche vous permet de changer le déploiement par défaut et de changer le modèle qui sert le déploiement sans changer le contrat avec l’utilisateur appelant le point de terminaison. Utilisez le code suivant pour mettre à jour le déploiement par défaut :
az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
Votre point de terminaison de lot est prêt à être utilisé.
test du déploiement
Pour tester le point de terminaison, utilisez un échantillon de 1 000 images provenant du jeu de données ImageNet d’origine. Les points de terminaison de lot peuvent uniquement traiter les données situées dans le cloud et accessibles à partir de l’espace de travail Azure Machine Learning. Chargez-le dans un magasin de données Azure Machine Learning. Créez une ressource de données qui peut être utilisé pour appeler le point de terminaison pour le scoring.
Remarque
Les points de terminaison de lot acceptent des données qui peuvent être placées dans plusieurs types d’emplacements.
Téléchargez les exemples de données associés.
Créez la ressource de données à partir des données téléchargées.
Créez une définition de ressource de données dans un fichier
YAML
appelé imagenet-sample-unlabeled.yml :$schema: https://azuremlschemas.azureedge.net/latest/data.schema.json name: imagenet-sample-unlabeled description: A sample of 1000 images from the original ImageNet dataset. Download content from https://azuremlexampledata.blob.core.windows.net/data/imagenet-1000.zip. type: uri_folder path: data
Créez la ressource de données.
az ml data create -f imagenet-sample-unlabeled.yml
Quand les données sont chargées et prêtes à être utilisées, appelez le point de terminaison.
JOB_NAME=$(az ml batch-endpoint invoke --name $ENDPOINT_NAME --input azureml:imagenet-sample-unlabeled@latest --query name -o tsv)
Remarque
Si l’utilitaire
jq
n’est pas installé, consultez Télécharger jq.
Conseil
Vous n’indiquez pas le nom du déploiement dans l’opération d’appel. Cela est dû au fait que le point de terminaison achemine automatiquement le travail vers le déploiement par défaut. Comme le point de terminaison n’a qu’un seul déploiement, celui-là est le déploiement par défaut. Vous pouvez cibler un déploiement spécifique en indiquant l’argument/le paramètre deployment_name
.
Un programme de traitement par lots démarre dès que la commande retourne. Vous pouvez surveiller l’état du travail jusqu’à ce qu’il se termine.
Une fois le déploiement terminé, téléchargez les prédictions.
Les prédictions se présentent comme la sortie suivante. Pour la commodité du lecteur, les prédictions sont combinées avec les étiquettes. Pour découvrir comment obtenir cet effet, consultez le notebook associé.
import pandas as pd score = pd.read_csv("named-outputs/score/predictions.csv", header=None, names=['file', 'class', 'probabilities'], sep=' ') score['label'] = score['class'].apply(lambda pred: imagenet_labels[pred]) score
file class probabilities label n02088094_Afghan_hound.JPEG 161 0.994745 Afghan hound n02088238_basset 162 0.999397 basset n02088364_beagle.JPEG 165 0.366914 bluetick n02088466_bloodhound.JPEG 164 0.926464 bloodhound ... ... ... ...
Déploiements à haut débit
Comme mentionné précédemment, le déploiement traite une image à la fois, même quand le déploiement par lots en fournit un lot. Dans la plupart des cas, cette approche est la meilleure. Elle simplifie la façon dont les modèles s’exécutent et évite les éventuels problèmes de mémoire insuffisante. Cependant, dans certains autres cas, vous souhaitez saturer autant que possible le matériel sous-jacent. C’est par exemple le cas des GPU.
Dans ces situations, vous pouvez exécuter l’inférence sur l’ensemble du lot de données. Cette approche implique de charger le jeu complet des images en mémoire et de les envoyer directement au modèle. L’exemple suivant utilise TensorFlow
pour lire le lot d’images et les noter en même temps. Elle utilise également des opérations TensorFlow
pour prétraiter les données. Tout le pipeline s’exécute sur le même appareil utilisé (PROCESSEUR/GPU).
Avertissement
Certains modèles ont une relation non linéaire avec la taille des entrées en termes de consommation de mémoire. Pour éviter des exceptions de mémoire insuffisante, recréez les lots (comme dans cet exemple) ou réduisez la taille des lots créés par le déploiement par lots.
Créez le script de scoring code/score-by-batch/batch_driver.py :
import os import numpy as np import pandas as pd import tensorflow as tf from tensorflow.keras.models import load_model def init(): global model global input_width global input_height # AZUREML_MODEL_DIR is an environment variable created during deployment model_path = os.path.join(os.environ["AZUREML_MODEL_DIR"], "model") # load the model model = load_model(model_path) input_width = 244 input_height = 244 def decode_img(file_path): file = tf.io.read_file(file_path) img = tf.io.decode_jpeg(file, channels=3) img = tf.image.resize(img, [input_width, input_height]) return img / 255.0 def run(mini_batch): images_ds = tf.data.Dataset.from_tensor_slices(mini_batch) images_ds = images_ds.map(decode_img).batch(64) # perform inference pred = model.predict(images_ds) # Compute probabilities, classes and labels pred_prob = tf.math.reduce_max(tf.math.softmax(pred, axis=-1)).numpy() pred_class = tf.math.argmax(pred, axis=-1).numpy() return pd.DataFrame( [mini_batch, pred_prob, pred_class], columns=["file", "probability", "class"] )
- Ce script construit un jeu de données de tenseur à partir du mini-lot envoyé par le déploiement par lots. Ce jeu de données est prétraité pour obtenir les tenseurs attendus pour le modèle à l’aide de l’opération
map
avec la fonctiondecode_img
. - Le jeu de données est remis en lot (16) pour envoyer les données au modèle. Utilisez ce paramètre pour contrôler la quantité d’informations que vous pouvez charger en mémoire et envoyer au modèle à la fois. Si vous travaillez sur un GPU, vous devez ajuster soigneusement ce paramètre pour obtenir l’utilisation maximale du GPU juste avant d’obtenir une exception de mémoire insuffisante.
- Une fois les prédictions calculées, les tenseurs sont convertis en
numpy.ndarray
.
- Ce script construit un jeu de données de tenseur à partir du mini-lot envoyé par le déploiement par lots. Ce jeu de données est prétraité pour obtenir les tenseurs attendus pour le modèle à l’aide de l’opération
Créez le déploiement.
- Pour créer un déploiement sous le point de terminaison créé, créez une configuration
YAML
comme l’exemple suivant. Pour d’autres propriétés, consultez le schéma YAML de point de terminaison de lot complet.
$schema: https://azuremlschemas.azureedge.net/latest/modelBatchDeployment.schema.json endpoint_name: imagenet-classifier-batch name: imagenet-classifier-resnetv2 description: A ResNetV2 model architecture for performing ImageNet classification in batch type: model model: azureml:imagenet-classifier@latest compute: azureml:gpu-cluster environment: name: tensorflow212-cuda11-gpu image: mcr.microsoft.com/azureml/curated/tensorflow-2.12-cuda11:latest conda_file: environment/conda.yaml code_configuration: code: code/score-by-batch scoring_script: batch_driver.py resources: instance_count: 2 tags: device_acceleration: CUDA device_batching: 16 settings: max_concurrency_per_instance: 1 mini_batch_size: 5 output_action: append_row output_file_name: predictions.csv retry_settings: max_retries: 3 timeout: 300 error_threshold: -1 logging_level: info
- Créez le déploiement avec la commande suivante :
az ml batch-deployment create --file deployment-by-batch.yml --endpoint-name $ENDPOINT_NAME --set-default
- Pour créer un déploiement sous le point de terminaison créé, créez une configuration
Vous pouvez utiliser ce nouveau déploiement avec les exemples de données présentés précédemment. Rappelez-vous que pour appeler ce déploiement, vous devez indiquer le nom du déploiement dans la méthode d’appel ou le définir comme déploiement par défaut.
Considérations relatives au traitement des images de modèles MLflow
Les modèles MLflow dans les points de terminaison de lot prennent en charge la lecture d’images en tant que données d’entrée. Étant donné que les déploiements MLflow ne nécessitent pas de script de scoring, tenez compte des considérations suivantes au moment de les utiliser :
- Les fichiers image pris en charge sont les suivants : .png, .jpg, .jpeg, .tiff, .bmp et .gif.
- Les modèles MLflow doivent être prêts à recevoir un
np.ndarray
en entrée, correspondant aux dimensions de l’image d’entrée. Pour prendre en charge plusieurs tailles d’image sur chaque lot, l’exécuteur de lot appelle le modèle MLflow une fois par fichier image. - Il est fortement recommandé que les modèles MLflow incluent une signature. Le cas échéant, elle doit être du type
TensorSpec
. Les entrées sont remodelées pour correspondre à la forme du tenseur si disponible. Si aucune signature n’est disponible, les tenseurs de typenp.uint8
sont déduits. - Pour les modèles qui incluent une signature et doivent gérer des tailles d’images variables, incluez une signature qui peut garantir cela. Ainsi, l’exemple de signature suivant autorise les lots de 3 images chaînées.
import numpy as np
import mlflow
from mlflow.models.signature import ModelSignature
from mlflow.types.schema import Schema, TensorSpec
input_schema = Schema([
TensorSpec(np.dtype(np.uint8), (-1, -1, -1, 3)),
])
signature = ModelSignature(inputs=input_schema)
(...)
mlflow.<flavor>.log_model(..., signature=signature)
Vous pouvez trouver un exemple fonctionnel dans le notebook Jupyter imagenet-classifier-mlflow.ipynb. Pour plus d’informations sur l’utilisation de modèles MLflow dans les déploiements par lots, consultez Utilisation de modèles MLflow dans les déploiements par lots.