Bereitstellen des Modells für Azure Functions

Erfahren Sie, wie Sie ein vorab trainiertes ML.NET-Modell für maschinelles Lernen für Vorhersagen über HTTP in einer serverlosen Azure Functions-Umgebung bereitstellen.

Voraussetzungen

Übersicht über das Azure Functions-Beispiel

Dieses Beispiel ist eine Azure Functions-Anwendung mit einem C#-HTTP-Trigger, die ein vortrainiertes binäres Klassifizierungsmodell verwendet, um die Stimmung von Text als positiv oder negativ zu kategorisieren. Azure Functions bietet eine einfache Möglichkeit, kleine Codeabschnitte in einer verwalteten serverlosen Umgebung in der Cloud auszuführen. Den Code für dieses Beispiel finden Sie im Repository dotnet/machinelearning-samples auf GitHub.

Erstellen eines Azure Functions-Projekts

  1. Öffnen Sie in Visual Studio 2022 das Dialogfeld Neues Projekt erstellen.

  2. Wählen Sie im Dialogfeld „Neues Projekt erstellen“ die Projektvorlage Azure Functions aus.

  3. Geben Sie „SentimentAnalysisFunctionsApp“ im Textfeld Name ein, und wählen Sie die Schaltfläche Weiter aus.

  4. Übernehmen Sie im Dialogfeld „Weitere Informationen“ alle Standardwerte, und wählen Sie die Schaltfläche Erstellen aus.

  5. Installieren Sie das NuGet-Paket Microsoft.ML.

    1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie NuGet-Pakete verwalten aus.
    2. Wählen Sie als Paketquelle „nuget.org“ aus.
    3. Wählen Sie die Registerkarte „Durchsuchen“ aus.
    4. Suchen Sie nach Microsoft.ML.
    5. Wählen Sie das Paket in der Liste aus, und klicken Sie auf die Schaltfläche Installieren.
    6. Klicken Sie im Dialogfeld Vorschau der Änderungen auf die Schaltfläche OK.
    7. Wählen Sie die Schaltfläche Ich stimme zu im Dialogfeld Zustimmung zur Lizenz, wenn Sie mit den Lizenzbedingungen für die aufgeführten Pakete einverstanden sind.

    Führen Sie die gleichen Schritte aus, um die NuGet-Pakete Microsoft.Extensions.ML, Microsoft.Extensions.DependencyInjection und Microsoft.Azure.Functions.Extensions zu installieren.

Hinzufügen des vorab trainierten Modells zum Projekt

  1. Erstellen Sie in Ihrem Projekt ein Verzeichnis mit dem Namen MLModels, um Ihr vorgefertigtes Modell zu speichern: Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf Ihr Projekt, und wählen Sie Hinzufügen > Neuer Ordner aus. Geben Sie „MLModels“ ein, und drücken Sie die EINGABETASTE.
  2. Kopieren Sie Ihr vorbereitetes Modell in den MLModels-Ordner.
  3. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf Ihr vorbereitetes Modell, und wählen Sie Eigenschaften aus. Ändern Sie unter Erweitert den Wert von In Ausgabeverzeichnis kopieren in Kopieren, wenn neuer.

Erstellen einer Azure-Funktion zur Standpunktanalyse

Erstellen Sie eine Klasse, um den Standpunkt vorherzusagen. Fügen Sie dem Projekt eine neue Klasse hinzu:

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie dann Hinzufügen>Neue Azure-Funktion aus.

  2. Wählen Sie im Dialogfeld Neues Element hinzufügen die Option Azure-Funktion aus, und ändern Sie das Feld Name in AnalyzeSentiment.cs. Wählen Sie dann die Schaltfläche Hinzufügen aus.

  3. Wählen Sie im Dialogfeld Neue Azure-Funktion die Option Http-Trigger und dann in der Dropdownliste für die Autorisierungsebene Anonym aus. Wählen Sie dann die Schaltfläche OK aus.

    Die Datei AnalyzeSentiment.cs wird im Code-Editor geöffnet. Fügen Sie oben in AnalyzeSentiment.cs die folgendeusing-Direktive hinzu:

    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;
    

    Standardmäßig ist die AnalyzeSentiment-Klasse static. Entfernen Sie das static -Schlüsselwort aus der Klassendefinition.

    public class AnalyzeSentiment
    {
    
    }
    

Erstellen von Datenmodellen

Sie müssen einige Klassen für die Eingabedaten und Vorhersagen erstellen. Fügen Sie dem Projekt eine neue Klasse hinzu:

  1. Erstellen Sie ein Verzeichnis mit dem Namen DataModels in Ihrem Projekt, um Ihre Datenmodelle zu speichern: Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie Hinzufügen > Neuer Ordner aus. Geben Sie „DataModels“ ein, und drücken Sie die EINGABETASTE.

  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das DataModels-Verzeichnis, und wählen Sie Hinzufügen > Klasse aus.

  3. Wählen Sie im Dialogfeld Neues Element hinzufügen die Option Klasse aus, und ändern Sie das Feld Name in SentimentData.cs. Wählen Sie dann die Schaltfläche Hinzufügen aus.

    Die Datei SentimentData.cs wird im Code-Editor geöffnet. Fügen Sie am Anfang der Datei SentimentData.cs die folgende using-Direktive hinzu:

    using Microsoft.ML.Data;
    

    Entfernen Sie die vorhandene Klassendefinition, und fügen Sie den folgenden Code der Datei SentimentData.cs hinzu:

    public class SentimentData
    {
        [LoadColumn(0)]
        public string SentimentText;
    
        [LoadColumn(1)]
        [ColumnName("Label")]
        public bool Sentiment;
    }
    
  4. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das DataModels-Verzeichnis, und wählen Sie Hinzufügen > Klasse aus.

  5. Wählen Sie im Dialogfeld Neues Element hinzufügen die Option Klasse aus, und ändern Sie das Feld Name in SentimentPrediction.cs. Wählen Sie dann die Schaltfläche Hinzufügen aus. Die Datei SentimentPrediction.cs wird im Code-Editor geöffnet. Fügen Sie oben in SentimentPrediction.cs die folgendeusing-Direktive hinzu:

    using Microsoft.ML.Data;
    

    Entfernen Sie die vorhandene Klassendefinition, und fügen Sie den folgenden Code der Datei SentimentPrediction.cs hinzu:

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

    SentimentPrediction erbt von SentimentData, was den Zugriff auf die Originaldaten in der SentimentText-Eigenschaft sowie auf die vom Modell generierte Ausgabe ermöglicht.

Registrieren des PredictionEnginePool-Diensts

Um eine einzelne Vorhersage zu treffen, müssen Sie eine PredictionEngine erstellen. PredictionEngine ist nicht threadsicher. Außerdem müssen Sie eine Instanz davon überall dort erstellen, wo diese in Ihrer Anwendung erforderlich ist. Wenn die Anwendung wächst, kann dieser Prozess ggf. nicht mehr verwaltet werden. Um eine bessere Leistung und Threadsicherheit zu erzielen, verwenden Sie eine Kombination aus Abhängigkeitsinjektion (Dependency Injection, DI) und dem PredictionEnginePool-Dienst, der einen ObjectPool aus PredictionEngine-Objekten für die Verwendung in Ihrer gesamten Anwendung erstellt.

Unter dem folgenden Link finden Sie weitere Informationen zur Abhängigkeitsinjektion.

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und klicken Sie auf Hinzufügen>Klasse.

  2. Wählen Sie im Dialogfeld Neues Element hinzufügen die Option Klasse aus, und ändern Sie das Feld Name in Startup.cs. Wählen Sie dann die Schaltfläche Hinzufügen aus.

  3. Fügen Sie oben in Startup.cs die folgenden using-Direktiven hinzu:

    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. Entfernen Sie den vorhandenen Code unter den using-Direktiven und fügen Sie den folgenden Code hinzu:

    [assembly: FunctionsStartup(typeof(Startup))]
    namespace SentimentAnalysisFunctionsApp
    {
        public class Startup : FunctionsStartup
        {
    
        }
    }
    
  5. Definieren Sie Variablen zum Speichern der Umgebung, in der die App ausgeführt wird, und des Dateipfads, in dem sich das Modell in der Startup-Klasse befindet.

    private readonly string _environment;
    private readonly string _modelPath;
    
  6. Erstellen darunter einen Konstruktor, um die Werte der Variablen _environment und _modelPath festzulegen. Wenn die Anwendung lokal ausgeführt wird, ist die Standardumgebung Development (Entwicklung).

    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. Fügen Sie dann eine neue Methode namens Configure hinzu, um den PredictionEnginePool Dienst unter dem Konstruktor zu registrieren.

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

Auf hoher Ebene initialisiert dieser Code die Objekte und Dienste bei Anforderung automatisch für eine spätere Verwendung, sodass dies nicht manuell durchgeführt werden muss.

Machine Learning-Modelle sind nicht statisch. Wenn neue Trainingsdaten verfügbar werden, wird das Modell erneut trainiert und erneut bereitgestellt. Eine Möglichkeit, die neueste Version des Modells in Ihre Anwendung zu integrieren, besteht in der erneuten Bereitstellung der gesamten Anwendung. Dies führt jedoch zu Ausfallzeiten der Anwendung. Der PredictionEnginePool-Dienst bietet einen Mechanismus zum Nachladen eines aktualisierten Modells, ohne dass Ihre Anwendung neu gestartet oder neu bereitgestellt werden muss.

Legen Sie den watchForChanges-Parameter auf true fest. Der PredictionEnginePool startet dann einen FileSystemWatcher, der auf Änderungsbenachrichtigungen des Dateisystems lauscht und Ereignisse auslöst, wenn die Datei geändert wird. Dadurch wird der PredictionEnginePool aufgefordert, das Modell automatisch erneut zu laden.

Das Modell wird durch den Parameter modelName identifiziert, sodass bei der Änderung mehrere Modelle pro Anwendung erneut geladen werden können.

Tipp

Alternativ können Sie beim Arbeiten mit Modellen, die remote gespeichert sind, die FromUri-Methode verwenden. Anstatt auf Dateiänderungsereignisse zu warten, fragt FromUri den Remotespeicherort nach Änderungen ab. Das Abruf Intervall beträgt standardmäßig 5 Minuten. Sie können das Abrufintervall basierend auf den Anforderungen Ihrer Anwendung vergrößern oder verkleinern. Im folgenden Codebeispiel fragt der PredictionEnginePool das am angegebenen URI gespeicherte Modell jede Minute ab.

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));

Laden des Modells in die Funktion

Fügen Sie den folgenden Code in die AnalyzeSentiment-Klasse ein:

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

Mit diesem Code wird die PredictionEnginePool durch Übergabe an den Konstruktor der Funktion zugewiesen, den Sie über die Abhängigkeitsinjektion erhalten.

Verwenden des Modells für Vorhersagen

Ersetzen Sie die vorhandene Implementierung der Run-Methode in der AnalyzeSentiment-Klasse durch den folgenden Code:

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);
}

Wenn die Methode Run ausgeführt wird, werden die eingehenden Daten aus der HTTP-Anforderung deserialisiert und als Eingabe für den PredictionEnginePool verwendet. Anschließend wird die Predict-Methode aufgerufen, um mithilfe des in der Startup-Klasse registrierten SentimentAnalysisModel Vorhersagen zu treffen und bei Erfolg die Ergebnisse an den Benutzer zurückzugeben.

Lokales Testen

Nachdem alles eingerichtet ist, ist es Zeit, die Anwendung zu testen:

  1. Ausführen der Anwendung

  2. Öffnen Sie PowerShell, und geben Sie den Code in der Eingabeaufforderung ein, wobei PORT der Port ist, auf dem Ihre Anwendung ausgeführt wird. In der Regel ist es Port 7071.

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

    Bei erfolgreicher Ausführung sollte die Ausgabe dem folgenden Text ähneln:

    Negative
    

Herzlichen Glückwunsch! Sie haben Ihr Modell erfolgreich bereitgestellt, um mit einer Azure-Funktion Vorhersagen über das Internet zu treffen.

Nächste Schritte