Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
APPLIES TO :
Extension Azure ML CLI v2 (actuelle)
Kit de développement logiciel (SDK) Python azure-ai-ml v2 (préversion)
Les points de terminaison par lots peuvent être utilisés pour déployer des modèles coûteux, tels que des modèles de langage, sur des données textuelles. Dans ce didacticiel, vous apprendrez à déployer un modèle qui peut effectuer un résumé textuel de longues séquences de texte à l’aide d’un modèle depuis HuggingFace. Il montre également comment effectuer une optimisation de l’inférence à l’aide des bibliothèques HuggingFace optimum et accelerate.
À propos de cet exemple
Le modèle avec lequel nous allons travailler a été construit à l’aide des transformateurs de bibliothèque populaires de HuggingFace avec un modèle préentraîné de Facebook avec l’architecture BART. Il a été introduit dans le document BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation. Ce modèle présente les contraintes suivantes qu’il faut garder à l’esprit pour le déploiement :
- Il peut fonctionner avec des séquences allant jusqu’à 1 024 jetons.
- Il est formé pour résumer le texte en anglais.
- Nous allons utiliser Torch comme back-end.
L’exemple de cet article est basé sur des extraits de code contenus dans le référentiel azureml-examples. Pour exécuter les commandes localement sans avoir à copier ou à coller des fichiers YAML et autres, utilisez les commandes suivantes pour cloner le référentiel et accéder au dossier de votre langage de programmation :
git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/cli
Les fichiers de cet exemple se situent dans :
cd endpoints/batch/deploy-models/huggingface-text-summarization
Suivre dans les notebooks Jupyter
Vous pouvez suivre cet exemple dans un Jupyter Notebook. Dans le dépôt cloné, ouvrez le notebook : text-summarization-batch.ipynb.
Prérequis
Un abonnement Azure. Si vous n’avez pas d’abonnement Azure, créez un compte gratuit avant de commencer.
Un espace de travail Azure Machine Learning. Pour créer un espace de travail, consultez Gérer les espaces de travail Azure Machine Learning.
Les autorisations suivantes dans l’espace de travail Azure Machine Learning :
- Pour la création ou la gestion des déploiements et des points de terminaison de lot : utilisez un rôle Propriétaire, Contributeur, ou un rôle personnalisé auquel les autorisations
Microsoft.MachineLearningServices/workspaces/batchEndpoints/*ont été accordées. - Pour la création de 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é auquel l’autorisation
Microsoft.Resources/deployments/writea été accordée dans le groupe de ressources où l’espace de travail est déployé.
- Pour la création ou la gestion des déploiements et des points de terminaison de lot : utilisez un rôle Propriétaire, Contributeur, ou un rôle personnalisé auquel les autorisations
L’interface CLI Azure Machine Learning ou le kit SDK Azure Machine Learning pour Python :
Exécutez la commande suivante pour installer Azure CLI et l’
mlextension pour Azure Machine Learning :az extension add -n mlLes déploiements de composants de pipeline pour les points de terminaison de lot sont introduits dans la version 2.7 de l’extension
mlpour Azure CLI. Utilisez la commandeaz extension update --name mlpour obtenir la dernière version.
Se connecter à un espace de travail
L’espace de travail est la ressource de niveau supérieur du service Azure Machine Learning. Il fournit un emplacement centralisé dans lequel utiliser tous les artefacts que vous créez quand vous utilisez Azure 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, saisissez votre ID d’abonnement, le nom de l’espace de travail, le nom du groupe de ressources et l’emplacement :
az account set --subscription <subscription>
az configure --defaults workspace=<workspace> group=<resource-group> location=<location>
Inscription du modèle
En raison de la taille du modèle, elle n’est pas incluse dans ce référentiel. Vous pouvez plutôt télécharger une copie depuis le hub du modèle HuggingFace. Vous avez besoin des packages transformers et torch installés dans l’environnement que vous utilisez.
%pip install transformers torch
Utilisez le code suivant pour télécharger le modèle dans un dossier model :
from transformers import pipeline
model = pipeline("summarization", model="facebook/bart-large-cnn")
model_local_path = 'model'
summarizer.save_pretrained(model_local_path)
Nous pouvons maintenant inscrire ce modèle dans le registre Azure Machine Learning :
MODEL_NAME='bart-text-summarization'
az ml model create --name $MODEL_NAME --path "model"
Création du point de terminaison
Nous allons créer un point de terminaison de lot nommé text-summarization-batch où déployer le modèle HuggingFace pour exécuter une synthèse de texte sur des fichiers texte en anglais.
Choisissez le nom du point de terminaison. Le nom du point de terminaison figure dans l’URI associé à celui-ci. De ce fait, les noms de point de terminaison de traitement par lots doivent être uniques au sein d’une région Azure. Par exemple, il ne peut y avoir qu’un seul point de terminaison de traitement par lots avec le nom
mybatchendpointdanswestus2.Configurer votre point de terminaison de traitement par lots
Le fichier YAML suivant définit un point de terminaison de lot :
endpoint.yml
$schema: https://azuremlschemas.azureedge.net/latest/batchEndpoint.schema.json name: text-summarization-batch description: A batch endpoint for summarizing text using a HuggingFace transformer model. auth_mode: aad_tokenCréez le point de terminaison :
Création du déploiement
Créons le déploiement qui héberge le modèle :
Vous devez créer un script de scoring qui peut lire les fichiers CSV fournis par le déploiement par lots et retourner les scores du modèle avec le résumé. Le script suivant exécute ces actions :
- Indique une fonction
initqui détecte la configuration matérielle (CPU ou GPU) et charge le modèle en conséquence. Le modèle et le générateur de jetons sont chargés dans des variables globales. Nous n’utilisons pas d’objetpipelinede HuggingFace pour tenir compte de la limitation des longueurs de séquence du modèle que nous utilisons actuellement. - Notez que nous effectuons des optimisations de modèles pour améliorer les performances à l’aide des bibliothèques
optimumetaccelerate. Si le modèle ou le matériel ne le prend pas en charge, nous exécutons le déploiement sans ces optimisations. - Indique une fonction
runexécutée pour chaque mini-lot fourni par le déploiement par lots. - La fonction
runlit l’intégralité du lot à l’aide de la bibliothèquedatasets. Le texte que vous devez résumer est situé sur la colonnetext. - La méthode
runitère sur chacune des lignes du texte et exécute la prédiction. Étant donné qu’il s’agit d’un modèle très coûteux, l’exécution de la prédiction sur des fichiers entiers entraîne une exception de type mémoire insuffisante. Notez que le modèle n’est pas exécuté avec l’objetpipelineà partir detransformers. Cela permet de tenir compte de longues séquences de texte et de la limitation de 1 024 jetons dans le modèle sous-jacent que vous utilisez. - Il retourne le résumé du texte fourni.
code/batch_driver.py
import os import time import torch import subprocess import mlflow from pprint import pprint from transformers import AutoTokenizer, BartForConditionalGeneration from optimum.bettertransformer import BetterTransformer from datasets import load_dataset def init(): global model global tokenizer global device cuda_available = torch.cuda.is_available() device = "cuda" if cuda_available else "cpu" if cuda_available: print(f"[INFO] CUDA version: {torch.version.cuda}") print(f"[INFO] ID of current CUDA device: {torch.cuda.current_device()}") print("[INFO] nvidia-smi output:") pprint( subprocess.run(["nvidia-smi"], stdout=subprocess.PIPE).stdout.decode( "utf-8" ) ) else: print( "[WARN] CUDA acceleration is not available. This model takes hours to run on medium size data." ) # AZUREML_MODEL_DIR is an environment variable created during deployment model_path = os.path.join(os.environ["AZUREML_MODEL_DIR"], "model") # load the tokenizer tokenizer = AutoTokenizer.from_pretrained( model_path, truncation=True, max_length=1024 ) # Load the model try: model = BartForConditionalGeneration.from_pretrained( model_path, device_map="auto" ) except Exception as e: print( f"[ERROR] Error happened when loading the model on GPU or the default device. Error: {e}" ) print("[INFO] Trying on CPU.") model = BartForConditionalGeneration.from_pretrained(model_path) device = "cpu" # Optimize the model if device != "cpu": try: model = BetterTransformer.transform(model, keep_original_model=False) print("[INFO] BetterTransformer loaded.") except Exception as e: print( f"[ERROR] Error when converting to BetterTransformer. An unoptimized version of the model will be used.\n\t> {e}" ) mlflow.log_param("device", device) mlflow.log_param("model", type(model).__name__) def run(mini_batch): resultList = [] print(f"[INFO] Reading new mini-batch of {len(mini_batch)} file(s).") ds = load_dataset("csv", data_files={"score": mini_batch}) start_time = time.perf_counter() for idx, text in enumerate(ds["score"]["text"]): # perform inference inputs = tokenizer.batch_encode_plus( [text], truncation=True, padding=True, max_length=1024, return_tensors="pt" ) input_ids = inputs["input_ids"].to(device) summary_ids = model.generate( input_ids, max_length=130, min_length=30, do_sample=False ) summaries = tokenizer.batch_decode( summary_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False ) # Get results: resultList.append(summaries[0]) rps = idx / (time.perf_counter() - start_time + 00000.1) print("Rows per second:", rps) mlflow.log_metric("rows_per_second", rps) return resultListConseil
Bien que les fichiers soient fournis dans des mini-lots par le déploiement, ce script de scoring traite un fichier à la fois. Il s’agit d’un modèle courant lorsque vous traitez de modèles coûteux (comme les transformateurs), car la tentative de charger l’ensemble du lot et de l’envoyer au modèle à la fois peut entraîner une sollicitation élevée de la mémoire sur l’exécuteur de lot (exceptions OOM).
- Indique une fonction
Nous devons indiquer sur quel environnement nous allons réaliser le déploiement. Dans notre cas, notre modèle s’exécute sur
Torchet nécessite les bibliothèquestransformers,accelerateetoptimumde HuggingFace. Azure Machine Learning a déjà un environnement qui prend en charge Torch et les GPU. Nous allons simplement ajouter quelques dépendances dans unconda.yamlfichier.environment/torch200-conda.yaml
name: huggingface-env channels: - conda-forge dependencies: - python=3.8.5 - pip - pip: - torch==2.0 - transformers - accelerate - optimum - datasets - mlflow - azureml-mlflow - azureml-core - azureml-dataset-runtime[fuse]Nous pouvons utiliser le fichier conda mentionné précédemment comme suit :
La définition d’environnement est incluse dans le fichier de déploiement.
deployment.yml
compute: azureml:gpu-cluster environment: name: torch200-transformers-gpu image: mcr.microsoft.com/azureml/openmpi4.1.0-cuda11.8-cudnn8-ubuntu22.04:latestImportant
L’environnement
torch200-transformers-gpuque nous avons créé nécessite un matériel compatible CUDA 11.8 pour exécuter Torch 2.0 et Ubuntu 20.04. Si votre appareil GPU ne prend pas en charge cette version de CUDA, vous pouvez vérifier l’autre environnement condatorch113-conda.yaml(également disponible sur le dépôt), qui exécute Torch 1.3 sur Ubuntu 18.04 avec CUDA 10.1. Toutefois, l’accélération à l’aide desoptimumetacceleratebibliothèques n’est pas prise en charge sur cette configuration.Chaque déploiement s’exécute sur des clusters de calcul. Ils prennent en charge les clusters de calcul Azure Machine Learning (AmlCompute) ou les clusters Kubernetes. Dans cet exemple, étant donné que notre modèle peut tirer parti de l’accélération GPU, nous utilisons un cluster GPU.
az ml compute create -n gpu-cluster --type amlcompute --size STANDARD_NV6 --min-instances 0 --max-instances 2Remarque
Vous n’êtes pas facturé pour le calcul à ce stade, car le cluster reste à zéro nœud jusqu’à ce qu’un point de terminaison de lot soit appelé et qu’un travail de scoring par lots soit envoyé. Apprenez-en davantage sur la gestion et l’optimisation des coûts pour AmlCompute.
Créons à présent le déploiement.
Pour créer un nouveau déploiement sous le point de terminaison créé, créez une configuration
YAMLcomme suit. Pour obtenir des propriétés supplémentaires, vous pouvez vérifier le schéma YAML du point de terminaison de lot complet.deployment.yml
$schema: https://azuremlschemas.azureedge.net/latest/modelBatchDeployment.schema.json endpoint_name: text-summarization-batch name: text-summarization-optimum description: A text summarization deployment implemented with HuggingFace and BART architecture with GPU optimization using Optimum. type: model model: azureml:bart-text-summarization@latest compute: azureml:gpu-cluster environment: name: torch200-transformers-gpu image: mcr.microsoft.com/azureml/openmpi4.1.0-cuda11.8-cudnn8-ubuntu22.04:latest conda_file: environment/torch200-conda.yaml code_configuration: code: code scoring_script: batch_driver.py resources: instance_count: 2 settings: max_concurrency_per_instance: 1 mini_batch_size: 1 output_action: append_row output_file_name: predictions.csv retry_settings: max_retries: 1 timeout: 3000 error_threshold: -1 logging_level: infoEnsuite, créez le déploiement avec la commande suivante :
az ml batch-deployment create --file deployment.yml --endpoint-name $ENDPOINT_NAME --set-defaultImportant
Vous remarquerez dans ce déploiement une valeur élevée de
timeoutdans le paramètreretry_settings. La raison est liée à la nature du modèle que nous exécutons. Il s’agit d’un modèle très coûteux et d’une inférence sur une seule ligne peut prendre jusqu’à 60 secondes. Letimeoutparamètre contrôle la durée pendant laquelle le déploiement batch doit attendre que le script de scoring termine le traitement de chaque mini-lot. Étant donné que notre modèle exécute des prédictions ligne par ligne, le traitement d’un fichier long peut prendre du temps. Notez également que le nombre de fichiers par lot est défini sur 1 (mini_batch_size=1). C’est là encore lié à la nature du travail que nous faisons. Le traitement d’un fichier à la fois par lot est assez coûteux pour le justifier. Vous remarquerez qu'il s'agit d'un schéma dans le traitement du langage naturel.Bien que vous puissiez appeler un déploiement spécifique à l’intérieur d’un point de terminaison, vous voulez en général appeler le point de terminaison lui-même et le laisser décider du déploiement à utiliser. Ce déploiement s’appelle le déploiement « par défaut ». Cela vous donne la possibilité de modifier le déploiement par défaut et donc de modifier le modèle qui sert le déploiement sans modifier le contrat avec l’utilisateur appelant le point de terminaison. Utilisez l’instruction suivante pour mettre à jour le déploiement par défaut :
À ce stade, notre point de terminaison par lots est prêt à être utilisé.
Test du déploiement
Pour tester notre point de terminaison, nous allons utiliser un exemple de jeu de données BillSum : A Corpus for Automatic Summarization of US Legislation. Cet exemple est inclus dans le dépôt dans le dossier data. Notez que les données sont au format CSV et que le contenu à résumer se trouve sous la colonne text (ce qui est attendu par le modèle).
Appelons le point de terminaison :
JOB_NAME=$(az ml batch-endpoint invoke --name $ENDPOINT_NAME --input data --input-type uri_folder --query name -o tsv)Remarque
L’utilitaire
jqne sera pas forcément installé sur chaque installation. Vous pouvez obtenir plus d’instructions sur ce lien.Conseil
Notez qu’en indiquant un chemin local comme entrée, les données sont chargées dans le compte de stockage par défaut d’Azure Machine Learning.
Un programme de traitement par lots est démarré dès que la commande retourne son résultat. Vous pouvez surveiller l’état du travail jusqu’à ce qu’il se termine :
Une fois le déploiement terminé, nous pouvons télécharger les prédictions :
Considérations relatives au déploiement de modèles qui traitent du texte
Comme mentionné dans certaines des notes de ce didacticiel, le traitement du texte peut avoir certaines particularités qui nécessitent une configuration spécifique pour les déploiements par lots. Prenez en compte les points suivants lors de la conception du déploiement par lots :
- Certains modèles NLP peuvent être très coûteux en termes de mémoire et de temps de calcul. Si c’est le cas, envisagez de réduire le nombre de fichiers inclus sur chaque mini-lot. Dans l’exemple précédent, le nombre a été pris au minimum, 1 fichier par lot. Bien que ce ne soit peut-être pas votre cas, prenez en compte le nombre de fichiers que votre modèle peut noter à chaque fois. N’oubliez pas que la relation entre la taille de l’entrée et l’empreinte mémoire de votre modèle peut ne pas être linéaire pour les modèles Deep Learning.
- Si votre modèle ne peut même pas gérer un fichier à la fois (comme dans cet exemple), envisagez de lire les données d’entrée dans des lignes/blocs. Implémentez le traitement par lots au niveau des lignes si vous devez obtenir un débit ou une utilisation matérielle plus élevée.
- Définissez la valeur
timeoutde votre déploiement en accord avec le coût de votre modèle et la quantité de données que vous prévoyez de traiter. N’oubliez pas quetimeoutindique le délai d’attente pendant lequel le déploiement par lots attend que votre script de scoring s’exécute pour un lot donné. Si votre lot comporte de nombreux fichiers, ou des fichiers avec de nombreuses lignes, cela aura un impact sur la valeur appropriée de ce paramètre.
Considérations relatives aux modèles MLflow qui traitent du texte
Les mêmes considérations mentionnées précédemment s’appliquent aux modèles MLflow. Toutefois, étant donné que vous n’êtes pas obligé de fournir un script de scoring pour votre déploiement de modèle MLflow, certaines des recommandations mentionnées peuvent nécessiter une approche différente.
- Les modèles MLflow dans les points de terminaison Batch prennent en charge la lecture des données tabulaires en tant que données d’entrée, qui peuvent contenir de longues séquences de texte. Pour plus d’informations, consultez les types de fichiers pris en charge.
- Les déploiements par lots appellent la fonction de prédiction de votre modèle MLflow avec le contenu d’un fichier entier en tant que trame de données Pandas. Si vos données d’entrée contiennent de nombreuses lignes, il est probable que l’exécution d’un modèle complexe (comme celui présenté dans ce tutoriel) entraîne une exception de mémoire insuffisante. Si c’est votre cas, vous pouvez envisager ce qui suit :
- Personnalisez la façon dont votre modèle exécute des prédictions et implémentez le traitement par lots. Pour savoir comment personnaliser l’inférence du modèle MLflow, consultez Journaliser des modèles personnalisés.
- Créez un script de scoring et chargez votre modèle à l’aide de
mlflow.<flavor>.load_model(). Pour plus d’informations, consultez Utilisation de modèles MLflow avec un script de scoring.