Entraîner des modèles PyTorch à grande échelle avec Azure Machine Learning

S’APPLIQUE À : Kit de développement logiciel (SDK) Python azure-ai-ml v2 (actuelle)

Dans cet article, vous allez apprendre à entraîner, à optimiser les hyperparamètres et à déployer un modèle PyTorch à l’aide du Kit de développement logiciel (SDK) Python Azure Machine Learning v2.

Vous allez utiliser des exemples de scripts pour classifier des images de poulets et de dindes afin de créer un réseau neuronal de Deep Learning (DNN) d’après le tutoriel d’apprentissage de transfert de PyTorch. L’apprentissage de transfert est une technique qui applique les connaissances acquises lors de la résolution d’un problème à un problème différent, mais connexe. L’apprentissage de transfert permet de raccourcir le processus d’entraînement en demandant moins de données, de temps et de ressources de calcul qu’un entraînement partant de zéro. Pour en savoir plus sur l’apprentissage de transfert, consultez Deep Learning et Machine Learning.

Que vous soyez en train de former un modèle PyTorch d’apprentissage profond ou que vous déposez un modèle existant dans le Cloud, vous pouvez utiliser Azure Machine Learning pour effectuer un scale-out des tâches de formation Open source à l’aide des ressources de calcul de Cloud élastique. Vous pouvez créer, déployer, mettre à jour et surveiller des modèles de niveau production avec Azure Machine Learning.

Prérequis

  • Un abonnement Azure. Si vous n’en avez pas encore, créez un compte gratuit.
  • Exécutez le code de cet article en utilisant une instance de calcul Azure Machine Learning ou dans votre propre notebook Jupyter.
    • Instance de Capacité de calcul Azure Machine Learning (pas de téléchargement ni d’installation nécessaires)
      • Suivez le guide Démarrage rapide : Bien démarrer avec Azure Machine Learning pour créer un serveur de notebooks dédié, préchargé avec le kit SDK et l’exemple de référentiel.
      • Sous l’onglet Exemples de la section Notebooks de votre espace de travail, recherchez un notebook finalisé et développé en accédant à ce répertoire : SDK v2/sdk/python/jobs/single-step/pytorch/train-hyperparameter-tune-deploy-with-pytorch
    • Votre serveur de notebooks Jupyter :

Vous trouverez également une version Jupyter Notebook complète de ce guide dans la page des exemples GitHub.

Avant de pouvoir exécuter le code de cet article pour créer un cluster GPU, vous devez demander une augmentation de quota pour votre espace de travail.

Configuration du travail

Cette section configure le travail pour l’entraînement en chargeant les packages Python requis, en se connectant à un espace de travail, en créant une ressource de calcul pour exécuter un travail de commande et en créant un environnement pour exécuter le travail.

Se connecter à l’espace de travail

Vous devez d’abord vous connecter à votre espace de travail Azure Machine Learning. L’espace de travail est la ressource de premier niveau du service. Il vous fournit un emplacement centralisé dans lequel utiliser tous les artefacts que vous créez quand vous utilisez Azure Machine Learning.

Nous allons utiliser DefaultAzureCredential pour accéder à l’espace de travail. Ces infos de connexion doivent être capables de gérer la plupart des scénarios d’authentification du kit SDK Azure.

Si DefaultAzureCredential ne fonctionne pas pour vous, consultez Package azure.identity ou Configurer l’authentification pour obtenir des informations d’identification plus appropriées.

# Handle to the workspace
from azure.ai.ml import MLClient

# Authentication package
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()

Si vous préférez utiliser un navigateur pour vous connecter et vous authentifier, vous devez supprimer les commentaires dans le code suivant et l’utiliser à la place.

# Handle to the workspace
# from azure.ai.ml import MLClient

# Authentication package
# from azure.identity import InteractiveBrowserCredential
# credential = InteractiveBrowserCredential()

Obtenez ensuite un descripteur de l’espace de travail en fournissant votre ID d’abonnement, le nom du groupe de ressources et le nom de l’espace de travail. Pour rechercher ces paramètres :

  1. Recherchez le nom de votre espace de travail dans le coin supérieur droit de la barre d’outils Azure Machine Learning studio.
  2. Sélectionnez le nom de votre espace de travail pour afficher votre groupe de ressources et votre ID d’abonnement.
  3. Copiez les valeurs de votre groupe de ressources et de votre ID d’abonnement dans le code.
# Get a handle to the workspace
ml_client = MLClient(
    credential=credential,
    subscription_id="<SUBSCRIPTION_ID>",
    resource_group_name="<RESOURCE_GROUP>",
    workspace_name="<AML_WORKSPACE_NAME>",
)

Le résultat de l’exécution de ce script est un descripteur d’espace de travail qui vous permet de gérer d’autres ressources et travaux.

Remarque

La création de MLClient n’établit pas de connexion du client à l’espace de travail. L’initialisation du client est différée. Elle attend la première fois qu’elle doit effectuer un appel. Dans cet article, cela se produit durant la création du calcul.

Créer une ressource de calcul pour exécuter le travail

Azure Machine Learning a besoin d’une ressource de calcul pour exécuter un travail. La ressource peut être constituée de machines à nœud unique ou à plusieurs nœuds avec un système d’exploitation Linux ou Windows, ou d’une structure de calcul spécifique comme Spark.

Dans l’exemple de script suivant, nous configurons un cluster de calcul Linux. Vous pouvez consulter la page Tarifs d’Azure Machine Learning pour obtenir la liste complète des tailles et des tarifs de machines virtuelles. Dans la mesure où nous avons besoin d’un cluster de GPU pour cet exemple, choisissons un modèle STANDARD_NC6, et créons une infrastructure Capacité de calcul Azure Machine Learning.

from azure.ai.ml.entities import AmlCompute

gpu_compute_target = "gpu-cluster"

try:
    # let's see if the compute target already exists
    gpu_cluster = ml_client.compute.get(gpu_compute_target)
    print(
        f"You already have a cluster named {gpu_compute_target}, we'll reuse it as is."
    )

except Exception:
    print("Creating a new gpu compute target...")

    # Let's create the Azure ML compute object with the intended parameters
    gpu_cluster = AmlCompute(
        # Name assigned to the compute cluster
        name="gpu-cluster",
        # Azure ML Compute is the on-demand VM service
        type="amlcompute",
        # VM Family
        size="STANDARD_NC6s_v3",
        # Minimum running nodes when there is no job running
        min_instances=0,
        # Nodes in cluster
        max_instances=4,
        # How many seconds will the node running after the job termination
        idle_time_before_scale_down=180,
        # Dedicated or LowPriority. The latter is cheaper but there is a chance of job termination
        tier="Dedicated",
    )

    # Now, we pass the object to MLClient's create_or_update method
    gpu_cluster = ml_client.begin_create_or_update(gpu_cluster).result()

print(
    f"AMLCompute with name {gpu_cluster.name} is created, the compute size is {gpu_cluster.size}"
)

Créer un environnement de travail

Pour exécuter un travail Azure Machine Learning, vous avez besoin d’un environnement. Un environnement Azure Machine Learning encapsule les dépendances (telles que le runtime logiciel et les bibliothèques) nécessaires pour exécuter votre script de formation Machine Learning sur votre ressource de calcul. Cet environnement est similaire à un environnement Python sur votre ordinateur local.

Azure Machine Learning vous permet d’utiliser un environnement organisé (ou prêt à l’emploi) ou de créer un environnement personnalisé à l’aide d’une image Docker ou d’une configuration Conda. Dans cet article, vous réutilisez l’environnement organisé Azure Machine Learning AzureML-pytorch-1.9-ubuntu18.04-py37-cuda11-gpu. Utilisez la dernière version de cet environnement à l’aide de la directive @latest.

curated_env_name = "AzureML-pytorch-1.9-ubuntu18.04-py37-cuda11-gpu@latest"

Configurer et soumettre un travail de formation

Dans cette section, nous commençons par présenter les données pour la formation. Nous verrons ensuite comment exécuter un travail de formation à l’aide d’un script de formation que nous avons fourni. Vous apprendrez à générer le travail d’entraînement en configurant la commande pour exécuter le script d’entraînement. Ensuite, vous allez envoyer le travail d’entraînement à exécuter dans Azure Machine Learning.

Obtenir les données d’entraînement

Vous pouvez utiliser le jeu de données de ce fichier compressé. Ce jeu de données se compose de 120 images d’entraînement pour chacune des deux classes (dindes et poules), avec 100 images de validation par classe. Les images sont un sous-ensemble du Jeu de données Open Images v5. Le script de formation pytorch_train.py télécharge et extrait le jeu de données.

Préparer le script d’apprentissage

Dans la section des prérequis, nous avons fourni le script de formation pytorch_train.py. En pratique, vous devez pouvoir prendre n’importe quel script de formation personnalisé en l’état, et l’exécuter avec Azure Machine Learning sans avoir à modifier votre code.

Le script d’entraînement fourni télécharge les données, entraîne un modèle et inscrit le modèle.

Créer le travail d’entraînement

Maintenant que vous disposez de toutes les ressources nécessaires pour exécuter votre travail, il est temps de le générer à l’aide du SDK Python Azure Machine Learning v2. Pour cet exemple, nous créons un command.

Un command Azure Machine Learning est une ressource qui spécifie tous les détails nécessaires pour exécuter votre code d’entraînement dans le cloud. Ces détails incluent les entrées et sorties, le type de matériel à utiliser, le logiciel à installer et la façon d’exécuter votre code. command contient des informations pour exécuter une seule commande.

Configurer la commande

Vous utiliserez le command à usage général pour exécuter le script d’entraînement et effectuer vos tâches souhaitées. Créez un objet command pour spécifier les détails de configuration de votre travail de formation.

from azure.ai.ml import command
from azure.ai.ml import Input

job = command(
    inputs=dict(
        num_epochs=30, learning_rate=0.001, momentum=0.9, output_dir="./outputs"
    ),
    compute=gpu_compute_target,
    environment=curated_env_name,
    code="./src/",  # location of source code
    command="python pytorch_train.py --num_epochs ${{inputs.num_epochs}} --output_dir ${{inputs.output_dir}}",
    experiment_name="pytorch-birds",
    display_name="pytorch-birds-image",
)
  • Les entrées de cette commande incluent le nombre d’époques, le taux d’apprentissage, l’élan et le répertoire de sortie.
  • Pour les valeurs de paramètre :
    1. Fournissez le cluster de calcul gpu_compute_target = "gpu-cluster" que vous avez créé pour exécuter cette commande.
    2. Fournissez l’environnement organisé AzureML-pytorch-1.9-ubuntu18.04-py37-cuda11-gpu que vous avez initialisé.
    3. Si vous n’utilisez pas le notebook finalisé dans le dossier Exemples, spécifiez l’emplacement du fichier pytorch_train.py.
    4. Configurez l’action de ligne de commande elle-même. Dans le cas présent, la commande est python pytorch_train.py. Vous pouvez accéder aux entrées et sorties de la commande via la notation ${{ ... }}.
    5. Configurez les métadonnées telles que le nom d’affichage et le nom de l’expérience, où une expérience est un conteneur pour toutes les itérations effectuées sur un projet spécifique. Tous les travaux soumis sous le même nom d’expérience sont listés les uns à côtés des autres dans Azure Machine Learning Studio.

Envoi du travail

Il est maintenant temps de soumettre le travail à exécuter dans Azure Machine Learning. Cette fois, vous utilisez create_or_update sur ml_client.jobs.

ml_client.jobs.create_or_update(job)

Une fois exécuté, le travail inscrit un modèle dans votre espace de travail (à la suite de la formation), et génère un lien qui vous permet de voir ce travail dans Azure Machine Learning Studio.

Avertissement

Azure Machine Learning exécute des scripts d’apprentissage en copiant l’intégralité du répertoire source. Si vous avez des données sensibles que vous ne souhaitez pas charger, utilisez un fichier .ignore ou ne l’incluez pas dans le répertoire source.

Ce qui se passe lors de l’exécution

Quand le travail est exécuté, elle passe par les phases suivantes :

  • Préparation : une image docker est créée en fonction de l’environnement défini. L’image est chargée dans le registre de conteneurs de l’espace de travail et mise en cache pour des exécutions ultérieures. Les journaux sont également transmis en continu à l’historique des travaux et peuvent être affichés afin de surveiller la progression. Si un environnement organisé est spécifié, l’image mise en cache sur laquelle repose cet environnement organisé est utilisée.

  • Mise à l’échelle : le cluster tente de monter en puissance si le cluster nécessite plus de nœuds pour l’exécution que la quantité disponible actuellement.

  • En cours d’exécution : tous les scripts dans le dossier de script src sont chargés dans la cible de calcul, les magasins de données sont montés ou copiés, puis le script est exécuté. Les sorties issues de stdout et du dossier ./logs sont transmises en continu à l’historique des travaux et peuvent être utilisées pour surveiller le travail.

Régler les hyperparamètres du modèle

Vous avez formé le modèle avec un ensemble de paramètres. Voyons maintenant si vous pouvez améliorer l’exactitude de votre modèle. Vous pouvez paramétrer et optimiser les hyperparamètres de notre modèle à l’aide des fonctionnalités d’Azure sweep Machine Learning.

Pour paramétrer les hyperparamètres du modèle, définissez l’espace de paramètres dans lequel effectuer une recherche pendant la formation. Pour ce faire, vous devez remplacer certains des paramètres passés au travail de formation par des entrées spéciales du package azure.ml.sweep.

Étant donné que le script d’entraînement utilise un calendrier de taux d’apprentissage pour décomposer le taux d’apprentissage à chaque époque, vous pouvez ajuster le taux d’apprentissage initial et les paramètres de moment.

from azure.ai.ml.sweep import Uniform

# we will reuse the command_job created before. we call it as a function so that we can apply inputs
job_for_sweep = job(
    learning_rate=Uniform(min_value=0.0005, max_value=0.005),
    momentum=Uniform(min_value=0.9, max_value=0.99),
)

Vous allez ensuite configurer le balayage sur le travail de commande, à l’aide de certains paramètres spécifiques au balayage, par exemple la métrique principale à surveiller et l’algorithme d’échantillonnage à utiliser.

Dans le code suivant, nous utilisons l’échantillonnage aléatoire pour essayer différents jeux de configuration d’hyperparamètres dans une tentative d’optimisation de notre métrique principale, best_val_acc.

Nous définissons également une stratégie d’arrêt anticipé, BanditPolicy, pour arrêter les exécutions peu performantes. BanditPolicy met fin à toute exécution qui ne correspond pas au facteur Slack de notre métrique d’évaluation principale. Vous appliquez cette stratégie à chaque époque (dans la mesure où nous signalons notre métrique best_val_acc à chaque époque et que evaluation_interval=1). Notez que nous retardons la première évaluation de la stratégie après les 10 premières époques (delay_evaluation=10).

from azure.ai.ml.sweep import BanditPolicy

sweep_job = job_for_sweep.sweep(
    compute="gpu-cluster",
    sampling_algorithm="random",
    primary_metric="best_val_acc",
    goal="Maximize",
    max_total_trials=8,
    max_concurrent_trials=4,
    early_termination_policy=BanditPolicy(
        slack_factor=0.15, evaluation_interval=1, delay_evaluation=10
    ),
)

Maintenant, vous pouvez soumettre ce travail comme avant. Cette fois, vous exécutez un travail de balayage qui balaie votre travail de formation.

returned_sweep_job = ml_client.create_or_update(sweep_job)

# stream the output and wait until the job is finished
ml_client.jobs.stream(returned_sweep_job.name)

# refresh the latest status of the job after streaming
returned_sweep_job = ml_client.jobs.get(name=returned_sweep_job.name)

Vous pouvez effectuer le monitoring du travail à l’aide du lien d’interface utilisateur Studio présenté durant l’exécution du travail.

Trouver le meilleur modèle

Une fois toutes les exécutions terminées, vous pouvez trouver l’exécution qui a produit le modèle avec la plus grande précision.

from azure.ai.ml.entities import Model

if returned_sweep_job.status == "Completed":

    # First let us get the run which gave us the best result
    best_run = returned_sweep_job.properties["best_child_run_id"]

    # lets get the model from this run
    model = Model(
        # the script stores the model as "outputs"
        path="azureml://jobs/{}/outputs/artifacts/paths/outputs/".format(best_run),
        name="run-model-example",
        description="Model created from run.",
        type="custom_model",
    )

else:
    print(
        "Sweep job status: {}. Please wait until it completes".format(
            returned_sweep_job.status
        )
    )

Déployer le modèle en tant que point de terminaison en ligne

Vous pouvez maintenant déployer votre moteur en tant que point de terminaison en ligne, c’est-à-dire en tant que service web dans le cloud Azure.

Pour déployer un service Machine Learning Service, vous avez généralement besoin des éléments suivants :

  • Les ressources de modèle que vous souhaitez déployer. Ces ressources incluent le fichier et les métadonnées du modèle que vous avez déjà inscrits dans votre travail d’entraînement.
  • Du code à exécuter en tant que service. Le code exécute le modèle lors d’une requête d’entrée donnée (script d’entrée). Ce script d’entrée reçoit les données envoyées à un service web déployé, puis les passe au modèle. Une fois que le modèle a traité les données, le script retourne la réponse du modèle au client. Le script est propre à votre modèle et doit comprendre les données que le modèle attend et retourne. Lorsque vous utilisez un modèle MLFlow, Azure Machine Learning crée automatiquement ce script pour vous.

Pour plus d’informations sur le déploiement, consultez Déployer et noter un modèle Machine Learning avec un point de terminaison en ligne managé à l’aide du Kit de développement logiciel (SDK) Python v2.

Créer un point de terminaison en ligne

Pour commencer à déployer votre modèle, vous devez créer votre point de terminaison en ligne. Le nom du point de terminaison doit être unique dans toute la région Azure. Dans le cadre de cet article, vous allez créer un nom unique à l’aide d’un UUID (identificateur unique universel).

import uuid

# Creating a unique name for the endpoint
online_endpoint_name = "aci-birds-endpoint-" + str(uuid.uuid4())[:8]
from azure.ai.ml.entities import ManagedOnlineEndpoint

# create an online endpoint
endpoint = ManagedOnlineEndpoint(
    name=online_endpoint_name,
    description="Classify turkey/chickens using transfer learning with PyTorch",
    auth_mode="key",
    tags={"data": "birds", "method": "transfer learning", "framework": "pytorch"},
)

endpoint = ml_client.begin_create_or_update(endpoint).result()

print(f"Endpoint {endpoint.name} provisioning state: {endpoint.provisioning_state}")

Une fois le point de terminaison créé, vous pouvez le récupérer comme suit :

endpoint = ml_client.online_endpoints.get(name=online_endpoint_name)

print(
    f'Endpint "{endpoint.name}" with provisioning state "{endpoint.provisioning_state}" is retrieved'
)

Déployer le modèle sur le point de terminaison

Vous pouvez désormais déployer le modèle avec le script d’entrée. Un point de terminaison peut avoir plusieurs déploiements. À l’aide de règles, le point de terminaison peut ensuite diriger le trafic vers ces déploiements.

Dans le code suivant, vous allez créer un déploiement unique qui gère 100 % du trafic entrant. Nous avons spécifié un nom de couleur arbitraire aci-blue pour le déploiement. Vous pouvez également utiliser n’importe quel autre nom tel que aci-green ou aci-red pour le déploiement.

Code permettant de déployer le modèle sur le point de terminaison :

  • Déploie la meilleure version du modèle que vous avez inscrit plus tôt.
  • Permet d’affecter un score au modèle à l’aide du fichier score.py.
  • Utilise l’environnement organisé (que vous avez spécifié plus tôt) pour effectuer l’inférence.
from azure.ai.ml.entities import (
    ManagedOnlineDeployment,
    Model,
    Environment,
    CodeConfiguration,
)

online_deployment_name = "aci-blue"

# create an online deployment.
blue_deployment = ManagedOnlineDeployment(
    name=online_deployment_name,
    endpoint_name=online_endpoint_name,
    model=model,
    environment=curated_env_name,
    code_configuration=CodeConfiguration(code="./score/", scoring_script="score.py"),
    instance_type="Standard_NC6s_v3",
    instance_count=1,
)

blue_deployment = ml_client.begin_create_or_update(blue_deployment).result()

Notes

Attendez-vous à ce que ce déploiement prenne un peu de temps.

Tester le modèle déployé

Une fois que vous avez déployé le modèle sur le point de terminaison, vous pouvez prédire la sortie du modèle déployé à l’aide de la méthode invoke sur le point de terminaison.

Pour tester le point de terminaison, utilisons un exemple d’image pour la prédiction. Nous allons tout d’abord afficher l’image.

# install pillow if PIL cannot imported
%pip install pillow
import json
from PIL import Image
import matplotlib.pyplot as plt

%matplotlib inline
plt.imshow(Image.open("test_img.jpg"))

Créez une fonction pour mettre en forme et redimensionner l’image.

# install torch and torchvision if needed
%pip install torch
%pip install torchvision

import torch
from torchvision import transforms


def preprocess(image_file):
    """Preprocess the input image."""
    data_transforms = transforms.Compose(
        [
            transforms.Resize(256),
            transforms.CenterCrop(224),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
        ]
    )

    image = Image.open(image_file)
    image = data_transforms(image).float()
    image = torch.tensor(image)
    image = image.unsqueeze(0)
    return image.numpy()

Mettez en forme l’image et convertissez-la en fichier JSON.

image_data = preprocess("test_img.jpg")
input_data = json.dumps({"data": image_data.tolist()})
with open("request.json", "w") as outfile:
    outfile.write(input_data)

Vous pouvez ensuite appeler le point de terminaison avec ce fichier JSON et imprimer le résultat.

# test the blue deployment
result = ml_client.online_endpoints.invoke(
    endpoint_name=online_endpoint_name,
    request_file="request.json",
    deployment_name=online_deployment_name,
)

print(result)

Nettoyer les ressources

Si vous n’avez plus besoin du point de terminaison, supprimez-le pour cesser d’utiliser la ressource. Vérifiez qu’aucun autre déploiement n’utilise le point de terminaison avant de le supprimer.

ml_client.online_endpoints.begin_delete(name=online_endpoint_name)

Notes

Attendez-vous à ce que ce nettoyage prenne un peu de temps.

Étapes suivantes

Dans cet article, vous avez entraîné et inscrit un réseau neuronal de Deep Learning à l’aide de PyTorch sur Azure Machine Learning. Vous avez également déployé le modèle sur un point de terminaison en ligne. Consultez ces autres articles pour en savoir plus sur Azure Machine Learning.