將模型部署到 Azure Functions
瞭解如何透過 Azure Functions 無伺服器環境部署預先定型 ML.NET 機器學習模型,以透過 HTTP 進行預測。
必要條件
- 已安裝 .NET 桌面開發和 Azure 開發工作負載的 Visual Studio 2022。 當您選取此工作負載時,會自動安裝 .NET SDK。
- Azure Functions Tools
- PowerShell
- 預先定型的模型。 下載此 預先定型的情感分析機器學習模型,或使用 ML.NET 情感分析教學課程 來建置您自己的模型。
Azure Functions 範例概觀
此範例是 C# HTTP 觸發程序 Azure Functions 應用程式,該應用程式會使用預先定型的二進位分類模型,將文字的情感分類為正面或負面。 Azure Functions 可讓您輕鬆地在雲端的受控無伺服器環境中大規模執行小段程式碼。 您可以在 GitHub 的 dotnet/machinelearning-samples repository 找到此範例的程式碼。
建立 Azure Functions 專案
在 Visual Studio 2022 中,開啟 [建立新專案] 對話方塊。
在 [建立新專案] 對話方塊中,選取 [Azure Functions] 專案範本。
在 [名稱] 文本框中,輸入 “SentimentAnalysisFunctionsApp”,然後選取 [下一步]。
在 [其他資訊] 對話框中,保留所有預設值不變,然後選取 [建立]。
安裝 Microsoft.ML NuGet 套件
- 在 [方案總管] 中,於您的專案上按一下滑鼠右鍵,然後選取 [管理 NuGet 套件]。
- 選擇「nuget.org」作為套件來源。
- 選取 [瀏覽] 索引標籤。
- 搜尋 Microsoft.ML。
- 在清單中選取該套件,然後選取 安裝。
- 選取 [預覽變更] 對話方塊上的 [確定] 按鈕
- 如果您同意所列套件的授權條款,請在 [授權接受] 對話方塊上選取 [我接受] 按鈕。
請遵循相同的步驟來安裝 Microsoft.Extensions.ML、Microsoft.Extensions.DependencyInjection 和 Microsoft.Azure.Functions.Extensions NuGet 套件。
將預先定型的模型新增至專案
- 在專案中建立名為 MLModels 的目錄以儲存預建模型:在方案總管中,右鍵點擊您的專案,然後選取 [新增 > 新資料夾]。 輸入 「MLModels」,然後選取 [Enter。
- 將預先建置的模型複製到 MLModels 資料夾。
- 在 [方案總管] 中,右鍵點擊您的預先建置模型檔案,然後選取 屬性。 在 [進階] 底下,將 [複製到輸出目錄] 的值變更為 [有更新時才複製]。
建立 Azure Function 來分析情感
建立用來預測情緒的類別。 將新類別新增至專案:
在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增]>[新增 Azure 函式...]。
在 [新增項目] 對話方塊中,選取 [Azure Function],然後將 [名稱] 欄位變更為 AnalyzeSentiment.cs。 然後,選取 [新增]。
在 [新增 Azure 函式] 對話方塊中,選取 [HTTP 觸發程序],然後從 [授權層級] 下拉式清單中選擇 [匿名]。 然後,選取 [確定]。
AnalyzeSentiment.cs 檔案隨即在程式碼編輯器中開啟。 將下列
using
指示詞新增至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;
根據預設,
AnalyzeSentiment
類別為static
。 請務必從類別定義移除static
關鍵字。public class AnalyzeSentiment { }
建立資料模型
您必須為輸入資料和預測建立一些類別。 將新類別新增至專案:
在專案中建立名為 DataModels 的目錄以儲存您的資料模型:在方案總管中,以滑鼠右鍵按一下您的專案,然後選取 [新增 > 資料夾]。 輸入「DataModels」,然後選取 ,按下 Enter。
在方案總管中,以滑鼠右鍵按一下 DataModels 目錄,然後選取 [新增 > 類別]。
在 [新增項目] 對話方塊中,選取 [類別],然後將 [名稱] 欄位變更為 SentimentData.cs。 然後,選擇 新增。
SentimentData.cs 檔案隨即在程式碼編輯器中開啟。 將下列
using
指示詞新增至SentimentData.cs頂端:using Microsoft.ML.Data;
移除現有的類別定義,然後將下列程式碼新增至 SentimentData.cs 檔案:
public class SentimentData { [LoadColumn(0)] public string SentimentText; [LoadColumn(1)] [ColumnName("Label")] public bool Sentiment; }
在方案總管中,以滑鼠右鍵按一下 DataModels 目錄,然後選取 [新增 > 類別]。
在 [加入新項目] 對話方塊中,選取 [類別],然後將 [名稱] 欄位變更為 SentimentPrediction.cs。 然後,選取 新增。 SentimentPrediction.cs 檔案隨即在程式碼編輯器中開啟。 將下列
using
指示詞新增至SentimentPrediction.cs頂端:using Microsoft.ML.Data;
移除現有的類別定義,然後將下列程式碼新增至 SentimentPrediction.cs 檔案:
public class SentimentPrediction : SentimentData { [ColumnName("PredictedLabel")] public bool Prediction { get; set; } public float Probability { get; set; } public float Score { get; set; } }
SentimentPrediction
會從SentimentData
繼承,後者會在SentimentText
屬性中提供原始資料的存取,以及由模型產生的輸出。
登錄 PredictionEnginePool 服務
若要進行單一預測,您必須建立 PredictionEngine
。
PredictionEngine
不是安全執行緒。 此外,您必須在應用程式內有需要的任何地方建立其執行個體。 隨著應用程式成長,此程序可能會變得無法管理。 為了提升效能和執行緒安全性,請合併使用相依性插入與 PredictionEnginePool
服務,以建立 ObjectPool
物件的 PredictionEngine
供整個應用程式使用。
如果您想要深入了解相依性插入,下列連結提供詳細資訊。
在 [方案總管] 中,於專案上按一下滑鼠右鍵,然後選取 [新增]>[類別]。
在 [新增項目] 對話方塊中,選取 [類別],然後將 [名稱] 欄位變更為 Startup.cs。 然後,選取 新增。
將下列
using
指示詞新增至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;
移除 指示詞下方
using
的現有程序代碼,並新增下列程序代碼:[assembly: FunctionsStartup(typeof(Startup))] namespace SentimentAnalysisFunctionsApp { public class Startup : FunctionsStartup { } }
定義變數來儲存應用程式執行所在的環境,以及模型位於
Startup
類別內的檔案路徑private readonly string _environment; private readonly string _modelPath;
請在其下方建立建構函式來設定
_environment
和_modelPath
變數的值。 當應用程式在本機執行時,預設環境為「開發」。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"); } }
然後,新增名為
Configure
的新方法,以在建構函式下方註冊PredictionEnginePool
服務。public override void Configure(IFunctionsHostBuilder builder) { builder.Services.AddPredictionEnginePool<SentimentData, SentimentPrediction>() .FromFile(modelName: "SentimentAnalysisModel", filePath: _modelPath, watchForChanges: true); }
概括而言,此程式碼會在應用程式要求時自動初始化物件和服務以供稍後使用,而不必手動執行。
機器學習模型不是靜態的。 當新的定型資料可供使用時,模型會重新定型並重新部署。 將最新版本的模型放入應用程式的方法之一,就是重新啟動或重新部署您的應用程式。 不過,這會導致應用程式停機。 此 PredictionEnginePool
服務提供一種機制來重新載入更新後的模型,而不需重新啟動或重新部署您的應用程式。
將 watchForChanges
參數設定為 true
,並 PredictionEnginePool
啟動接聽檔案系統變更通知的 FileSystemWatcher
,然後在檔案發生變更時引發事件。 這會提示 PredictionEnginePool
自動重新載入模型。
模型是由 modelName
參數所識別,讓每個應用程式可以在變更時重新載入多個模型。
提示
或者,您可以在使用遠端儲存的模型時使用 FromUri
方法。
FromUri
不會監看檔案變更事件,而是輪詢遠端位置是否有變更。 輪詢間隔預設為 5 分鐘。 您可以根據應用程式的需求增加或減少輪詢間隔。 在下列程式碼範例中,PredictionEnginePool
會每隔一分鐘輪詢儲存在指定 URI 的模型。
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));
將模型載入函式
將下列程式碼插入 AnalyzeSentiment 類別:
public AnalyzeSentiment(PredictionEnginePool<SentimentData, SentimentPrediction> predictionEnginePool)
{
_predictionEnginePool = predictionEnginePool;
}
此程式碼會透過將 PredictionEnginePool
傳遞到您透過相依性插入所取得的函式建構函式來指派它。
使用模型來進行預測
使用下列程式碼取代 AnalyzeSentiment 類別中 Run 方法的現有實作:
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);
}
Run
方法執行時,來自 HTTP 請求的傳入資料會還原序列化,並用來作為 PredictionEnginePool
的輸入。 接著會呼叫 Predict
方法,以使用在 SentimentAnalysisModel
類別中註冊的 Startup
進行預測,並在成功時將結果傳回給使用者。
在本機進行測試
一切都設定好後,就可以開始測試應用程式:
執行應用程式
開啟 Powershell 並在提示字元中輸入下列程式碼,其中 PORT 是正在執行您應用程式的連接埠。 一般來說,連接埠是 7071。
Invoke-RestMethod "http://localhost:<PORT>/api/AnalyzeSentiment" -Method Post -Body (@{SentimentText="This is a very bad steak"} | ConvertTo-Json) -ContentType "application/json"
如果成功,輸出看起來應該類似下列文字:
Negative
恭喜! 您已成功提供您的模型,以使用 Azure Function 在網際網路上進行預測。