Distribuire un modello in Funzioni di Azure
Informazioni su come distribuire un modello di Machine Learning ML.NET con training preliminare per le previsioni su HTTP tramite un ambiente serverless di Funzioni di Azure.
Prerequisiti
- Visual Studio 2022 con i carichi di lavoro Sviluppo di desktop .NET e Sviluppo di Azure installati. .NET 6 SDK viene installato automaticamente quando si seleziona questo carico di lavoro.
- Strumenti di Funzioni di Azure
- PowerShell
- Modello con training preliminare. Scaricare questo modello di Machine Learning di analisi del sentiment con training preliminare o usare l'esercitazione ML.NET analisi del sentiment per creare un modello personalizzato.
Panoramica dell'esempio di Funzioni di Azure
Questo esempio è un'applicazione di Funzioni di Azure trigger HTTP C# che usa un modello di classificazione binaria con training preliminare per classificare il sentiment del testo come positivo o negativo. Funzioni di Azure offre un modo semplice per eseguire piccole parti di codice su larga scala in un ambiente serverless gestito nel cloud. Il codice per questo esempio è disponibile nel repository dotnet/machinelearning-samples in GitHub.
Creare un progetto di Funzioni di Azure
In Visual Studio 2022 aprire la finestra di dialogo Crea un nuovo progetto.
Nella finestra di dialogo "Crea un nuovo progetto" selezionare il modello di progetto Funzioni di Azure.
Nella casella di testo Nome digitare "SentimentAnalysisFunctionsApp" e selezionare il pulsante Avanti.
Nella finestra di dialogo "Informazioni aggiuntive" lasciare invariate tutte le impostazioni predefinite e selezionare il pulsante Crea.
Installare il pacchetto NuGet Microsoft.ML
- In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e selezionare Gestisci pacchetti NuGet.
- Scegliere "nuget.org" come origine pacchetto.
- Selezionare la scheda “Sfoglia”.
- Cercare Microsoft.ML.
- Selezionare il pacchetto nell'elenco e selezionare il pulsante Installa.
- Selezionare il pulsante OK nella finestra di dialogo Anteprima modifiche
- Selezionare il pulsante Accetto nella finestra di dialogo Accettazione licenza se si accettano le condizioni di licenza per i pacchetti elencati.
Seguire la stessa procedura per installare i pacchetti NuGet di Microsoft.Extensions.ML, Microsoft.Extensions.DependencyMakection e Microsoft.Azure.Functions.Extensions.
Aggiungere il modello con training preliminare al progetto
- Creare una directory denominata MLModels nel progetto per salvare il modello di pre-compilazione: in Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi > Nuova cartella. Digitare "MLModels" e premere INVIO.
- Copiare il modello predefinito nella cartella MLModels.
- In Esplora soluzioni fare clic con il pulsante destro del mouse sul file del modello predefinito e scegliere Proprietà. In Avanzate impostare il valore di Copia nella directory di output su Copia se più recente.
Creare la funzione di Azure per analizzare il sentiment
Creare una classe per prevedere il sentiment. Aggiungere una nuova classe al progetto:
In Esplora soluzioni, fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>Nuova funzione Azure.
Nella finestra di dialogo Aggiungi nuovo elemento selezionare Funzione di Azure e impostare il campo Nome su AnalyzeSentiment.cs. Selezionare quindi il pulsante Aggiungi.
Nella finestra di dialogo Nuova funzione di Azure selezionare trigger HTTP e scegliere anonimo nell'elenco a discesa Livello di autorizzazione. Fare quindi clic su OK.
Il file AnalyzeSentiment.cs verrà aperto nell'editor del codice. Aggiungere la direttiva seguente
using
all'inizio di 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;
Per impostazione predefinita, la classe
AnalyzeSentiment
èstatic
. Assicurarsi di rimuovere la parola chiavestatic
dalla definizione della classe.public class AnalyzeSentiment { }
Creare i modelli di dati
È necessario creare alcune classi per i dati di input e le stime. Aggiungere una nuova classe al progetto:
Creare una directory denominata DataModels nel progetto per salvare i modelli di dati: in Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi > Nuova cartella. Digitare "DataModels" e premere INVIO.
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla directory DataModels e quindi scegliere Aggiungi > Classe.
Nella finestra di dialogo Aggiungi nuovo elemento selezionare Classe e impostare il campo Nome su SentimentData.cs. Selezionare quindi il pulsante Aggiungi.
Il file SentimentData.cs verrà aperto nell'editor del codice. Aggiungere la direttiva seguente
using
all'inizio di SentimentData.cs:using Microsoft.ML.Data;
Rimuovere la definizione di classe esistente e aggiungere il codice seguente al file SentimentData.cs:
public class SentimentData { [LoadColumn(0)] public string SentimentText; [LoadColumn(1)] [ColumnName("Label")] public bool Sentiment; }
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla directory DataModels e quindi scegliere Aggiungi > Classe.
Nella finestra di dialogo Aggiungi nuovo elemento selezionare Classe e impostare il campo Nome su SentimentPrediction.cs. Selezionare quindi il pulsante Aggiungi. Il file SentimentPrediction.cs verrà aperto nell'editor del codice. Aggiungere la direttiva seguente
using
all'inizio di SentimentPrediction.cs:using Microsoft.ML.Data;
Rimuovere la definizione di classe esistente e aggiungere il codice seguente al file SentimentPrediction.cs:
public class SentimentPrediction : SentimentData { [ColumnName("PredictedLabel")] public bool Prediction { get; set; } public float Probability { get; set; } public float Score { get; set; } }
SentimentPrediction
eredita daSentimentData
che consente l'accesso ai dati originali nella proprietàSentimentText
e all'output generato dal modello.
Registrare il servizio PredictionEnginePool
Per eseguire una singola stima, è necessario creare un oggetto PredictionEngine
. PredictionEngine
non è thread-safe. Inoltre, è necessario crearne un'istanza ovunque sia necessaria all'interno dell'applicazione. Man mano che l'applicazione cresce, la gestione di questo processo può rivelarsi difficile. Per migliorare le prestazioni e la sicurezza dei thread, usare una combinazione di inserimento delle dipendenze e del servizio PredictionEnginePool
, che crea un ObjectPool
di oggetti PredictionEngine
da usare in tutta l'applicazione.
Il collegamento seguente fornisce ulteriori informazioni sull'inserimento delle dipendenze.
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>Classe.
Nella finestra di dialogo Aggiungi nuovo elemento selezionare Classe e modificare il campo Nome in Startup.cs. Selezionare quindi il pulsante Aggiungi.
Aggiungere le direttive seguenti
using
all'inizio di 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;
Rimuovere il codice esistente sotto le
using
direttive e aggiungere il codice seguente:[assembly: FunctionsStartup(typeof(Startup))] namespace SentimentAnalysisFunctionsApp { public class Startup : FunctionsStartup { } }
Definire le variabili per archiviare l'ambiente in cui l'app è in esecuzione e il percorso del file in cui si trova il modello all'interno della classe
Startup
private readonly string _environment; private readonly string _modelPath;
Di seguito, creare un costruttore per impostare i valori delle variabili
_environment
e_modelPath
. Quando l'applicazione è in esecuzione in locale, l'ambiente predefinito è Sviluppo.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"); } }
Aggiungere quindi un nuovo metodo denominato
Configure
per registrare il servizioPredictionEnginePool
sotto il costruttore.public override void Configure(IFunctionsHostBuilder builder) { builder.Services.AddPredictionEnginePool<SentimentData, SentimentPrediction>() .FromFile(modelName: "SentimentAnalysisModel", filePath: _modelPath, watchForChanges: true); }
A livello generale, questo codice inizializza automaticamente gli oggetti e i servizi per usarli in un secondo momento quando richiesto dall'applicazione anziché dover eseguire manualmente questa operazione.
I modelli di Machine Learning non sono statici. Man mano che diventano disponibili nuovi dati di training, il modello viene nuovamente sottoposto a training e ridistribuito. Un modo per ottenere la versione più recente del modello nell'applicazione consiste nel riavviare o ridistribuire l'applicazione. Tuttavia, ciò comporta tempi di inattività dell'applicazione. Il servizio PredictionEnginePool
fornisce un meccanismo per ricaricare un modello aggiornato senza riavviare o ridistribuire l'applicazione.
Impostare il parametro watchForChanges
su true
, e PredictionEnginePool
avvia FileSystemWatcher
in ascolto delle notifiche di modifica del file system e genera eventi quando viene apportata una modifica al file. In questo modo viene richiesto a PredictionEnginePool
di ricaricare automaticamente il modello.
Il modello viene identificato dal parametro modelName
in modo che sia possibile ricaricare più di un modello per applicazione al momento della modifica.
Suggerimento
In alternativa, è possibile usare il metodo FromUri
quando si usano i modelli archiviati in modalità remota. Invece di cercare gli eventi modificati dei file, FromUri
esegue il polling della posizione remota per individuare le modifiche. Per impostazione predefinita, l'intervallo di polling è 5 minuti. È possibile aumentare o ridurre l'intervallo di polling in base ai requisiti dell'applicazione. Nell'esempio di codice seguente, PredictionEnginePool
esegue il polling del modello archiviato all'URI specificato ogni minuto.
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));
Caricare il modello nella funzione
Inserire il codice seguente all'interno della classe AnalyzeSentiment:
public AnalyzeSentiment(PredictionEnginePool<SentimentData, SentimentPrediction> predictionEnginePool)
{
_predictionEnginePool = predictionEnginePool;
}
Questo codice assegna PredictionEnginePool
passandolo al costruttore della funzione ottenuto tramite l'inserimento delle dipendenze.
Usare il modello per effettuare previsioni
Sostituire l'implementazione esistente del metodo Run nella classe AnalyzeSentiment con il codice seguente:
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);
}
Quando il metodo Run
viene eseguito, i dati in ingresso dalla richiesta HTTP vengono deserializzati e usati come input per PredictionEnginePool
. Il metodo Predict
viene quindi chiamato per eseguire stime usando l’oggetto SentimentAnalysisModel
registrato nella classe Startup
e restituisce i risultati all'utente, se ha esito positivo.
Test in locale
Dopo aver completato la configurazione, è possibile testare l'applicazione:
Eseguire l'applicazione
Aprire PowerShell e immettere il codice nel prompt, dove PORT è la porta su cui l'applicazione è in esecuzione. La porta è in genere la 7071.
Invoke-RestMethod "http://localhost:<PORT>/api/AnalyzeSentiment" -Method Post -Body (@{SentimentText="This is a very bad steak"} | ConvertTo-Json) -ContentType "application/json"
In caso di esito positivo, l'output sarà simile al testo seguente:
Negative
Complimenti. È stato creato il modello per eseguire previsioni tramite Internet usando una funzione di Azure.