diff --git a/docs/machine-learning/how-to-guides/serve-model-serverless-azure-functions-ml-net.md b/docs/machine-learning/how-to-guides/serve-model-serverless-azure-functions-ml-net.md index c04e330f73ba7..0f29f3157d63b 100644 --- a/docs/machine-learning/how-to-guides/serve-model-serverless-azure-functions-ml-net.md +++ b/docs/machine-learning/how-to-guides/serve-model-serverless-azure-functions-ml-net.md @@ -1,28 +1,28 @@ --- -title: Deploy ML.NET Model to Azure Functions +title: "How-To: Deploy ML.NET machine learning model to Azure Functions" description: Serve ML.NET sentiment analysis machine learning model for prediction over the internet using Azure Functions -ms.date: 03/08/2019 -ms.custom: mvc,how-to +ms.date: 04/29/2019 +author: luisquintanilla +ms.author: luquinta +ms.custom: mvc, how-to #Customer intent: As a developer, I want to use my ML.NET Machine Learning model to make predictions through the internet using Azure Functions --- -# How-To: Use ML.NET Model in Azure Functions +# How-To: Deploy ML.NET machine learning model to Azure Functions -This how-to shows how individual predictions can be made using a pre-built ML.NET machine learning model through the internet in a serverless environment such as Azure Functions. - -> [!NOTE] -> This topic refers to ML.NET, which is currently in Preview, and material may be subject to change. For more information, visit [the ML.NET introduction](https://www.microsoft.com/net/learn/apps/machine-learning-and-ai/ml-dotnet). - -This how-to and related sample are currently using **ML.NET version 0.10**. For more information, see the release notes at the [dotnet/machinelearning github repo](https://github.com/dotnet/machinelearning/tree/master/docs/release-notes). +Learn how to deploy a pre-trained ML.NET machine learning model for predictions over HTTP through an Azure Functions serverless environment. ## Prerequisites - [Visual Studio 2017 15.6 or later](https://visualstudio.microsoft.com/downloads/?utm_medium=microsoft&utm_source=docs.microsoft.com&utm_campaign=inline+link&utm_content=download+vs2017) with the ".NET Core cross-platform development" workload and "Azure development" installed. - [Azure Functions Tools](/azure/azure-functions/functions-develop-vs#check-your-tools-version) - Powershell -- Pre-trained model. - - Use the [ML.NET Sentiment Analysis tutorial](../tutorials/sentiment-analysis.md) to build your own model. - - Download this [pre-trained sentiment analysis machine learning model](https://github.com/dotnet/samples/blob/master/machine-learning/models/sentimentanalysis/sentiment_model.zip) +- Pre-trained model + - Use the [ML.NET Sentiment Analysis tutorial](../tutorials/sentiment-analysis.md) to build your own model. + + or + + - Download this [pre-trained sentiment analysis machine learning model](https://github.com/dotnet/samples/blob/master/machine-learning/models/sentimentanalysis/sentiment_model.zip) ## Create Azure Functions Project @@ -53,23 +53,21 @@ Create a class to predict sentiment. Add a new class to your project: The *AnalyzeSentiment.cs* file opens in the code editor. Add the following `using` statement to the top of *GitHubIssueData.cs*: -```csharp -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.ML; -using Microsoft.ML.Core.Data; -using Microsoft.ML.Data; -using MLNETServerless.DataModels; -``` + ```csharp + 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.ML; + using SentimentAnalysisFunctionsApp.DataModels; + ``` -### Create Data Models +## Create Data Models You need to create some classes for your input data and predictions. Add a new class to your project: @@ -82,8 +80,8 @@ You need to create some classes for your input data and predictions. Add a new c using Microsoft.ML.Data; ``` - Remove the existing class definition and add the following code to the SentimentData.cs file: - + Remove the existing class definition and add the following code to the *SentimentData.cs* file: + ```csharp public class SentimentData { @@ -104,42 +102,65 @@ You need to create some classes for your input data and predictions. Add a new c Remove the existing class definition and add the following code to the *SentimentPrediction.cs* file: ```csharp - public class SentimentPrediction + public class SentimentPrediction : SentimentData { [ColumnName("PredictedLabel")] public bool Prediction { get; set; } } ``` -### Add Prediction Logic +`SentimentPrediction` inherits from `SentimentData` which provides access to the original data in the `Text` property as well as the output generated by the model. + +## Load the model into the function + +Insert the following code inside the *AnalyzeSentiment* class: + +```csharp +// Define MLContext +static MLContext _mlContext; + +// Define model +static ITransformer _model; + +// Define model's DataViewSchema +static DataViewSchema _modelSchema; + +// Define PredictionEngine +static PredictionEngine _predictionEngine; + +// AnalyzeSentiment class constructor +static AnalyzeSentiment() +{ + // Create MLContext + _mlContext = new MLContext(); + + // Load Model + _model = _mlContext.Model.Load("MLModels/sentiment_model.zip", out _modelSchema); + + // Create Prediction Engine + _predictionEngine = _mlContext.Model.CreatePredictionEngine(_model); +} +``` + +The constructor contains initialization logic for the [`MLContext`](xref:Microsoft.ML.MLContext), model and [`PredictionEngine`](xref:Microsoft.ML.PredictionEngine%602) so that it can be shared throughout the lifecycle of the function instance. This approach reduces the need to load the model from disk each time the `Run` method executes. + +## Use the model to make predictions Replace the existing implementation of *Run* method in *AnalyzeSentiment* class with the following code: ```csharp public static async Task Run( - [HttpTrigger(AuthorizationLevel.Function,"post", Route = null)] HttpRequest req, - ILogger log) +[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, +ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); - //Create Context - MLContext mlContext = new MLContext(); - - //Load Model - using (var fs = File.OpenRead("MLModels/sentiment_model.zip")) - { - model = mlContext.Model.Load(fs); - } - //Parse HTTP Request Body string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); SentimentData data = JsonConvert.DeserializeObject(requestBody); - - //Create Prediction Engine - PredictionEngine predictionEngine = model.CreatePredictionEngine(mlContext); - + //Make Prediction - SentimentPrediction prediction = predictionEngine.Predict(data); + SentimentPrediction prediction = _predictionEngine.Predict(data); //Convert prediction to string string isToxic = Convert.ToBoolean(prediction.Prediction) ? "Toxic" : "Not Toxic"; @@ -149,6 +170,8 @@ public static async Task Run( } ``` +When the `Run` method executes, the incoming data from the HTTP request is deserialized and used as input for the [`PredictionEngine`](xref:Microsoft.ML.PredictionEngine%602). The [`Predict`](xref:Microsoft.ML.PredictionEngineBase%602.Predict*) method is then called to generate a prediction and return the result to the user. + ## Test Locally Now that everything is set up, it's time to test the application: @@ -156,15 +179,15 @@ Now that everything is set up, it's time to test the application: 1. Run the application 1. Open PowerShell and enter the code into the prompt where PORT is the port your application is running on. Typically the port is 7071. -```powershell -Invoke-RestMethod "http://localhost:/api/AnalyzeSentiment" -Method Post -Body (@{Text="This is a very rude movie"} | ConvertTo-Json) -ContentType "application/json" -``` - -If successful, the output should look similar to the text below: + ```powershell + Invoke-RestMethod "http://localhost:/api/AnalyzeSentiment" -Method Post -Body (@{Text="This is a very rude movie"} | ConvertTo-Json) -ContentType "application/json" + ``` -```powershell -Toxic -``` + If successful, the output should look similar to the text below: + + ```powershell + Toxic + ``` Congratulations! You have successfully served your model to make predictions over the internet using an Azure Function.