Déployer un modèle sur Azure Functions

Découvrez comment déployer un modèle Machine Learning ML.NET préentraîné pour effectuer des prédictions sur HTTP par le bais d’un environnement serverless Azure Functions.

Prérequis

Vue d’ensemble de l’exemple Azure Functions

Cet exemple est un une application Azure Functions de déclencheur HTTP C# qui utilise un modèle de classification binaire préentraîné pour catégoriser le sentiment de texte comme positif ou négatif. Azure Functions fournit un moyen simple d’exécuter de petits morceaux de code à grande échelle sur un environnement serverless managé dans le cloud. Vous trouverez le code de cet exemple dans le dépôt dotnet/machinelearning-samples sur GitHub.

Créer un projet Azure Functions

  1. Dans Visual Studio 2022, ouvrez la boîte de dialogue Créer un projet.

  2. Dans la boîte de dialogue « Créer un projet », sélectionnez le modèle de projet Azure Functions.

  3. Dans la zone de texte Nom, tapez « SentimentAnalysisFunctionsApp », puis sélectionnez le bouton Suivant.

  4. Dans la boîte de dialogue « Informations supplémentaires », laissez toutes les valeurs par défaut, puis sélectionnez le bouton Créer.

  5. Installez le package NuGet Microsoft.ML

    1. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur votre projet, puis sélectionnez Gérer les packages NuGet.
    2. Choisissez « nuget.org » comme source du package.
    3. Sélectionnez l’onglet « Parcourir ».
    4. Recherchez Microsoft.ML.
    5. Sélectionnez ce package dans la liste, puis sélectionnez le bouton Installer.
    6. Sélectionnez le bouton OK dans la boîte de dialogue Aperçu des modifications
    7. Sélectionnez le bouton J’accepte dans la boîte de dialogue Acceptation de la licence si vous acceptez les termes du contrat de licence pour les packages de la liste.

    Suivez les mêmes étapes pour installer les packages NuGet Microsoft.Extensions.ML, Microsoft.Extensions.DependencyInjection et Microsoft.Azure.Functions.Extensions.

Ajouter un modèle préentraîné au projet

  1. Créez un répertoire nommé MLModels dans votre projet pour enregistrer votre modèle prégénéré : dans l’Explorateur de solutions, cliquez avec le bouton droit sur votre projet, puis sélectionnez Ajouter > Nouveau dossier. Tapez « MLModels » et appuyez sur Entrée.
  2. Copiez votre modèle prédéfini dans le dossier MLModels.
  3. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur votre fichier de modèle prédéfini et sélectionnez Propriétés. Sous Avancé, définissez la valeur Copier dans le répertoire de sortie sur Copier si plus récent.

Créer une fonction Azure d’analyse des sentiments

Créez une classe pour prédire le sentiment. Ajoutez une nouvelle classe à votre projet :

  1. Dans l’Explorateur de solutions, cliquez avec le bouton de droite sur le projet, puis sélectionnez Ajouter>Nouvelle fonction Azure.

  2. Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Fonction Azure et remplacez la valeur du champ Nom par AnalyzeSentiment.cs. Ensuite, sélectionnez le bouton Ajouter.

  3. Dans la boîte de dialogue Nouvelle fonction Azure, sélectionnez Déclencheur Http et choisissez Anonyme dans la liste déroulante Niveau d’autorisation. Ensuite, sélectionnez le bouton OK.

    Le fichier AnalyzeSentiment.cs s’ouvre dans l’éditeur de code. Ajoutez l’instruction suivante using en haut du fichier AnalyzeSentiment.cs :

    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Microsoft.Extensions.ML;
    using SentimentAnalysisFunctionsApp.DataModels;
    

    Par défaut, la classe AnalyzeSentiment est static. Veillez à supprimer le mot clé static de la définition de classe.

    public class AnalyzeSentiment
    {
    
    }
    

Créer des modèles de données

Vous devez créer des classes pour vos données d’entrée et prévisions. Ajoutez une nouvelle classe à votre projet :

  1. Créez un répertoire nommé DataModels dans votre projet pour enregistrer vos modèles de données : dans l’Explorateur de solutions, cliquez avec le bouton droit sur votre projet et sélectionnez Ajouter > Nouveau dossier. Tapez « DataModels » et appuyez sur Entrée.

  2. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le répertoire DataModels, puis sélectionnez Ajouter > Classe.

  3. Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Classe, puis remplacez la valeur du champ Nom par SentimentData.cs. Ensuite, sélectionnez le bouton Ajouter.

    Le fichier SentimentData.cs s’ouvre dans l’éditeur de code. Ajoutez l’instruction using suivante en haut du fichier SentimentData.cs :

    using Microsoft.ML.Data;
    

    Supprimez la définition de classe existante et ajoutez le code suivant au fichier SentimentData.cs :

    public class SentimentData
    {
        [LoadColumn(0)]
        public string SentimentText;
    
        [LoadColumn(1)]
        [ColumnName("Label")]
        public bool Sentiment;
    }
    
  4. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le répertoire DataModels, puis sélectionnez Ajouter > Classe.

  5. Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Classe et remplacez la valeur du champ Nom par SentimentPrediction.cs. Ensuite, sélectionnez le bouton Ajouter. Le fichier SentimentPrediction.cs s’ouvre dans l’éditeur de code. Ajoutez l’instruction using suivante en haut du fichier SentimentPrediction.cs :

    using Microsoft.ML.Data;
    

    Supprimez la définition de classe existante et ajoutez le code suivant au fichier SentimentPrediction.cs :

    public class SentimentPrediction : SentimentData
    {
    
        [ColumnName("PredictedLabel")]
        public bool Prediction { get; set; }
    
        public float Probability { get; set; }
    
        public float Score { get; set; }
    }
    

    SentimentPrediction hérite de SentimentData, qui fournit l’accès aux données d’origine dans la propriété SentimentText ainsi que la sortie générée par le modèle.

Inscrire le service PredictionEnginePool

Pour effectuer une prédiction unique, vous devez créer un PredictionEngine. PredictionEngine n’est pas thread-safe. En outre, vous devez créer une instance de celui-ci partout où il est nécessaire dans votre application. À mesure que votre application croît, ce processus peut devenir non gérable. Pour améliorer les performances et la sécurité des threads, utilisez une combinaison d’injection de dépendances et du service PredictionEnginePool, qui crée un ObjectPool d’objets PredictionEngine à utiliser dans votre application.

Pour plus d’informations, voir Injection de dépendances.

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter>Classe.

  2. Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Classe et définissez la valeur du champ Nom sur Startup.cs. Ensuite, sélectionnez le bouton Ajouter.

  3. Ajoutez les instructions using suivantes en haut du fichier Startup.cs :

    using Microsoft.Azure.Functions.Extensions.DependencyInjection;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.ML;
    using SentimentAnalysisFunctionsApp;
    using SentimentAnalysisFunctionsApp.DataModels;
    using System.IO;
    using System;
    
  4. Supprimez le code sous les instructions using et ajoutez le code suivant :

    [assembly: FunctionsStartup(typeof(Startup))]
    namespace SentimentAnalysisFunctionsApp
    {
        public class Startup : FunctionsStartup
        {
    
        }
    }
    
  5. Définissez des variables pour stocker l’environnement dans lequel l’application s’exécute et le chemin du fichier où se trouve le modèle à l’intérieur de la classe Startup

    private readonly string _environment;
    private readonly string _modelPath;
    
  6. En dessous de cela, créez un constructeur pour définir les valeurs des variables _environment et _modelPath. Lorsque l’application s’exécute localement, l’environnement par défaut est Développement.

    public Startup()
    {
        _environment = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT");
    
        if (_environment == "Development")
        {
            _modelPath = Path.Combine("MLModels", "sentiment_model.zip");
        }
        else
        {
            string deploymentPath = @"D:\home\site\wwwroot\";
            _modelPath = Path.Combine(deploymentPath, "MLModels", "sentiment_model.zip");
        }
    }
    
  7. Ensuite, ajoutez une nouvelle méthode appelée Configure pour inscrire le service PredictionEnginePool sous le constructeur.

    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddPredictionEnginePool<SentimentData, SentimentPrediction>()
            .FromFile(modelName: "SentimentAnalysisModel", filePath: _modelPath, watchForChanges: true);
    }
    

À haut niveau, ce code initialise automatiquement les objets et services pour une utilisation ultérieure à la demande de l’application, ce qui évite d’avoir à le faire manuellement.

Les modèles Machine Learning ne sont pas statiques. À mesure que de nouvelles données de formation deviennent disponibles, le modèle est réentraîné et redéployé. Pour obtenir la dernière version du modèle dans votre application, vous pouvez redémarrer ou redéployer votre application. Toutefois, cela entraîne un temps d’arrêt de l’application. Le service PredictionEnginePool fournit un mécanisme pour recharger un modèle mis à jour sans redémarrer ou redéployer votre application.

Définissez le paramètre watchForChanges sur true et PredictionEnginePool démarre un FileSystemWatcher qui écoute les notifications de modification du système de fichiers et déclenche des événements en cas de modification du fichier. Cela invite le PredictionEnginePool à recharger automatiquement le modèle.

Le modèle est identifié par le paramètre modelName afin que plusieurs modèles par application puissent être rechargés en cas de modification.

Conseil

Vous pouvez également utiliser la méthode FromUri lors de l’utilisation de modèles stockés à distance. Au lieu de surveiller les événements de modification de fichiers, FromUri interroge l’emplacement distant pour les modifications. L’intervalle d’interrogation est de 5 minutes par défaut. Vous pouvez augmenter ou diminuer l’intervalle d’interrogation en fonction des exigences de votre application. Dans l’exemple de code ci-dessous, le PredictionEnginePool sonde le modèle stocké au niveau de l’URI spécifié chaque minute.

builder.Services.AddPredictionEnginePool<SentimentData, SentimentPrediction>()
  .FromUri(
      modelName: "SentimentAnalysisModel",
      uri:"https://github.com/dotnet/samples/raw/main/machine-learning/models/sentimentanalysis/sentiment_model.zip",
      period: TimeSpan.FromMinutes(1));

Charger le modèle dans la fonction

Insérez le code suivant à l’intérieur de la classe AnalyzeSentiment :

public AnalyzeSentiment(PredictionEnginePool<SentimentData, SentimentPrediction> predictionEnginePool)
{
    _predictionEnginePool = predictionEnginePool;
}

Ce code affecte le PredictionEnginePool en le passant au constructeur de la fonction, obtenu par injection de dépendances.

Utiliser le modèle pour élaborer des prédictions

Remplacez l’implémentation existante de la méthode Run dans la classe AnalyzeSentiment par le code suivant :

public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
    ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    // Parse HTTP Request Body
    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    SentimentData data = JsonConvert.DeserializeObject<SentimentData>(requestBody);

    //Make Prediction
    SentimentPrediction prediction = _predictionEnginePool.Predict(modelName: "SentimentAnalysisModel", example: data);

    //Convert prediction to string
    string sentiment = Convert.ToBoolean(prediction.Prediction) ? "Positive" : "Negative";

    //Return Prediction
    return new OkObjectResult(sentiment);
}

Quand la méthode Run s’exécute, les données entrantes issues de la requête HTTP sont désérialisées et utilisées comme entrée pour le PredictionEnginePool. La méthode Predict est ensuite appelée pour effectuer des prédictions à l’aide du SentimentAnalysisModel inscrit dans la classe Startup, et retourne les résultats à l’utilisateur en cas de réussite.

Tester les topologies localement

Maintenant que tout est configuré, il est temps de tester l’application :

  1. Exécution de l'application

  2. Ouvrez PowerShell et entrez le code dans l’invite, où PORT est le port sur lequel s’exécute votre application, en règle générale 7071.

    Invoke-RestMethod "http://localhost:<PORT>/api/AnalyzeSentiment" -Method Post -Body (@{SentimentText="This is a very bad steak"} | ConvertTo-Json) -ContentType "application/json"
    

    En cas de réussite, la sortie devrait se présenter ainsi :

    Negative
    

Félicitations ! Vous avez réussi à alimenter votre modèle de façon à effectuer des prédictions sur Internet à l’aide d’une fonction Azure.

Étapes suivantes