Tutoriel : Déployer un modèle de classification d’image pré-entraîné sur Azure Functions avec PyTorch

Dans cet article, vous allez découvrir comment utiliser Python, PyTorch et Azure Functions pour charger un modèle préentraîné en vue de classifier une image en fonction de son contenu. Comme vous effectuez tout le travail localement et que vous ne créez aucune ressource Azure dans le cloud, aucun coût n’est à prévoir pour effectuer ce tutoriel.

  • Initialisez un environnement local pour le développement de fonctions Azure en Python.
  • Importez un modèle Machine Learning PyTorch préentraîné dans une application de fonction.
  • Créez une API HTTP serverless pour classifier une image comme l’une des 1 000 classes ImageNet.
  • Consommez l’API à partir d’une application web.

Prérequis

Vérification du prérequis

  1. Dans un terminal ou une fenêtre de commande, exécutez func --version pour vérifier que la version d’Azure Functions Core Tools est bien 2.7.1846 ou ultérieure.
  2. Exécutez python --version (Linux/MacOS) ou py --version (Windows) pour vérifier que votre version de Python est bien 3.7.x.

Cloner le dépôt du tutoriel

  1. Dans un fenêtre de terminal ou de commande, clonez le dépôt suivant en utilisant Git :

    git clone https://github.com/Azure-Samples/functions-python-pytorch-tutorial.git
    
  2. Accédez au dossier et examinez son contenu.

    cd functions-python-pytorch-tutorial
    
    • start est votre dossier de travail pour le tutoriel.
    • end est le résultat final et l’implémentation complète à titre de référence.
    • resources contient le modèle Machine Learning et les bibliothèques de helpers.
    • frontend est un site web qui appelle l’application de fonction.

Créer et activer un environnement virtuel Python

Accédez au dossier start, et exécutez les commandes suivantes pour créer et activer un environnement virtuel nommé .venv.

cd start
python -m venv .venv
source .venv/bin/activate

Si Python n’a pas installé le package venv sur votre distribution Linux, exécutez la commande suivante :

sudo apt-get install python3-venv

Vous devez exécuter toutes les commandes suivantes dans cet environnement virtuel activé. (Pour quitter l’environnement virtuel, exécutez deactivate.)

Créer un projet de fonctions local

Dans Azure Functions, un projet de fonction est un conteneur pour une ou plusieurs fonctions individuelles qui répond chacune à un déclencheur spécifique. Toutes les fonctions d’un projet partagent les mêmes configurations locales et d’hébergement. Dans cette section, vous créez un projet de fonction qui contient une seule fonction réutilisable nommée classify, qui fournit un point de terminaison HTTP. Vous y ajoutez du code spécifique dans une section ultérieure.

  1. Dans le dossier start, utilisez Azure Functions Core Tools pour initialiser une application de fonction Python :

    func init --worker-runtime python
    

    Après l’initialisation, le dossier start contient différents fichiers pour le projet, dont des fichiers de configuration nommés local.settings.json et host.json. Comme local.settings.json peut contenir des secrets téléchargés depuis Azure, le fichier est exclu par défaut du contrôle de code source dans le fichier .gitignore.

    Conseil

    Comme un projet de fonction est lié à un runtime spécifique, toutes les fonctions du projet doivent être écrites dans le même langage.

  2. Ajoutez une fonction à votre projet avec la commande suivante, où l’argument --name est le nom unique de votre fonction et où l’argument --template spécifie le déclencheur de la fonction. func new crée un sous-dossier correspondant au nom de la fonction qui contient un fichier de code approprié au langage choisi du projet et un fichier de configuration nommé function.json.

    func new --name classify --template "HTTP trigger"
    

    Cette commande crée un dossier correspondant au nom de la fonction, classify. Dans ce dossier se trouvent deux fichiers : __init__.py, qui contient le code de la fonction, et function.json, qui décrit le déclencheur de la fonction, et ses liaisons d’entrée et de sortie. Si vous souhaitez en savoir plus sur le contenu de ces fichiers, veuillez consulter la rubrique Modèle de programmation dans le guide du développeur Python.

Exécuter la fonction localement

  1. Démarrez la fonction en démarrant l’hôte du runtime Azure Functions local dans le dossier start :

    func start
    
  2. Une fois que le point de terminaison classify apparaît dans la sortie, accédez à l’URL http://localhost:7071/api/classify?name=Azure. Le message « Hello Azure ! » devrait apparaître dans la sortie.

  3. Utilisez Ctrl-C pour arrêter l’hôte.

Importer le modèle PyTorch et ajouter le code d’assistance

Pour modifier la fonction classify en vue de classifier une image en fonction de son contenu, utilisez un modèle ResNet préentraîné. Le modèle préentraîné, fourni par PyTorch, classifie une image comme faisant partie de l’une des 1 000 classes ImageNet. Vous ajoutez ensuite du code helper et des dépendances à votre projet.

  1. Dans le dossier start, exécutez la commande suivante pour copier le code de prédiction et les étiquettes dans le dossier classify.

    cp ../resources/predict.py classify
    cp ../resources/labels.txt classify
    
  2. Vérifiez que le dossier classify contient les fichiers nommés predict.py et labels.txt. Si ce n’est pas le cas, vérifiez que vous avez exécuté la commande dans le dossier start.

  3. Ouvrez start/requirements.txt dans un éditeur de texte et ajoutez les dépendances exigées par le code d’assistance, qui doit ressembler à ceci :

    azure-functions
    requests
    -f https://download.pytorch.org/whl/torch_stable.html
    torch==1.13.0+cpu
    torchvision==0.14.0+cpu
    

    Conseil

    Les versions de torch et torchvision doivent correspondre aux valeurs répertoriées dans la table de versions du référentiel de vision PyTorch.

  4. Enregistrez requirements.txt, puis exécutez la commande suivante à partir du dossier start pour installer les dépendances.

    pip install --no-cache-dir -r requirements.txt
    

L’installation peut prendre quelques minutes, pendant lesquelles vous pouvez modifier la fonction dans la section suivante.

Conseil

Sur Windows, vous pouvez rencontrer l’erreur « Impossible d’installer les packages en raison d’une erreur EnvironmentError : [errno 2]. Pas de fichier ou de répertoire correspondant : », suivi d’un long chemin vers un fichier, comme sharded_mutable_dense_hashtable.cpython-37.pyc. En général, cette erreur se produit parce que la profondeur du chemin du dossier devient trop longue. Dans ce cas, définissez la clé de Registre HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem@LongPathsEnabled sur 1 pour activer les chemins longs. Vous pouvez également vérifier où votre interpréteur Python est installé. Si cet emplacement a un chemin long, essayez en le réinstallant dans un dossier avec un chemin plus court.

Mettre à jour la fonction pour effectuer des prédictions

  1. Ouvrez le fichier classify/__init__.py dans un éditeur de texte et ajoutez les lignes suivantes après les instructions import existantes pour importer la bibliothèque JSON standard et les assistances predict :

    import logging
    import azure.functions as func
    import json
    
    # Import helper script
    from .predict import predict_image_from_url
    
  2. Remplacez tout le contenu de la fonction main par le code suivant :

    def main(req: func.HttpRequest) -> func.HttpResponse:
        image_url = req.params.get('img')
        logging.info('Image URL received: ' + image_url)
    
        results = predict_image_from_url(image_url)
    
        headers = {
            "Content-type": "application/json",
            "Access-Control-Allow-Origin": "*"
        }
    
        return func.HttpResponse(json.dumps(results), headers = headers)
    

    Cette fonction reçoit une URL d’image dans un paramètre de chaîne de requête nommé img. Elle appelle ensuite predict_image_from_url à partir de la bibliothèque de helpers pour télécharger et classifier l’image en utilisant le modèle PyTorch. La fonction retourne ensuite une réponse HTTP avec les résultats.

    Important

    Comme ce point de terminaison HTTP est appelé par une page web hébergée sur un autre domaine, la réponse comprend un en-tête Access-Control-Allow-Origin pour satisfaire aux exigences CORS (Cross-Origin Resource Sharing) du navigateur.

    Dans une application de production, remplacez * par l’origine spécifique de la page web pour renforcer la sécurité.

  3. Enregistrez vos modifications puis, en supposant que l’installation des dépendances est terminée, redémarrez l’hôte de fonction local avec func start. Veillez à exécuter l’hôte dans le dossier start avec l’environnement virtuel activé. Sinon, l’hôte démarrera, mais vous verrez des erreurs lors de l’appel de la fonction.

    func start
    
  4. Dans un navigateur, ouvrez l’URL suivante pour appeler la fonction avec l’URL d’une image de bouvier bernois, puis vérifiez que le code JSON retourné classifie l’image comme représentant un bouvier bernois.

    http://localhost:7071/api/classify?img=https://raw.githubusercontent.com/Azure-Samples/functions-python-pytorch-tutorial/master/resources/assets/Bernese-Mountain-Dog-Temperament-long.jpg
    
  5. Conservez l’hôte en cours d’exécution, car vous allez l’utiliser à l’étape suivante.

Exécuter le front-end de l’application web locale pour tester la fonction

Pour tester l’appel du point de terminaison de fonction à partir d’une autre application web, il existe une application simple dans le dossier frontend du référentiel.

  1. Ouvrez un nouveau terminal ou une invite de commandes, puis activez l’environnement virtuel (comme décrit précédemment sous Créer et activer un environnement virtuel Python).

  2. Accédez au dossier frontend du référentiel.

  3. Démarrez un serveur HTTP avec Python :

    python -m http.server
    
  4. Dans un navigateur, accédez à localhost:8000, puis entrez une des URL de photo suivantes dans la zone de texte ou utilisez l’URL de n’importe quelle image accessible publiquement.

    • https://raw.githubusercontent.com/Azure-Samples/functions-python-pytorch-tutorial/master/resources/assets/Bernese-Mountain-Dog-Temperament-long.jpg
    • https://github.com/Azure-Samples/functions-python-pytorch-tutorial/blob/master/resources/assets/bald-eagle.jpg?raw=true
    • https://raw.githubusercontent.com/Azure-Samples/functions-python-pytorch-tutorial/master/resources/assets/penguin.jpg
  5. Sélectionnez Submit (Envoyer) pour appeler le point de terminaison de la fonction afin de classifier l’image.

    Capture d’écran du projet terminé

    Si le navigateur signale une erreur quand vous envoyez l’URL de l’image, vérifiez le terminal dans lequel vous exécutez l’application de fonction. Si vous voyez une erreur comme « Aucun module "PIL" trouvé », c’est que vous avez peut-être démarré l’application de fonction dans le dossier start sans activer au préalable l’environnement virtuel que vous avez créé précédemment. Si vous voyez encore des erreurs, réexécutez pip install -r requirements.txt avec l’environnement virtuel activé et regardez s’il y a des erreurs.

Nettoyer les ressources

Comme l’intégralité de ce tutoriel s’exécute localement sur votre machine, il n’y a pas de ressources ni de services Azure à nettoyer.

Étapes suivantes

Dans ce tutoriel, vous avez vu comment créer et personnaliser un point de terminaison d’API HTTP avec Azure Functions pour classifier des images à l’aide d’un modèle PyTorch. Vous avez également découvert comment appeler l’API depuis une application web. Vous pouvez utiliser les techniques de ce tutoriel pour élaborer des API plus complexes, qui s’exécutent sur le modèle de calcul serverless fourni par Azure Functions.

Voir aussi :