DEV Community

Cover image for Machine Learning in Azure
Emily Freeman for Microsoft Azure

Posted on

Machine Learning in Azure

We've selected our favorite tips and tricks created by Michael Crump and are delivering fresh technical content on Azure all April! Miss a day (Or more)? Catch up with the series.

Thank you also to Luis Quintanilla for inspiring this with his work on ML.NET and Azure Functions.

Don't have Azure? Grab a free subscription.


Machine learning can be tricky. Even the name stresses me out. Like... how am I supposed to TEACH a MACHINE?!

Fortunately, Azure is coming up with ways to make it easier for developers to jump into machine learning. ML.NET is the machine learning framework that Microsoft Research made just for .NET developers so you can do everything inside Visual Studio.

When you're ready to deploy your ML.NET algorithm, you can use serverless architecture through Azure Functions. You can think of it as the “Don’t worry about it!” option when you want to get an app up and running but don’t necessarily want to mess around with servers and containers and infrastructure.

Check out more ML quickstarts and tutorials!

Serverless Machine Learning

This is inspired by Luis Quintanilla’s article about using ML.NET with Azure Functions, where he took these two great ideas and combined them.

As you follow this tutorial, you will use ML.NET locally to train your machine learning model. Then you will create an Azure environment with a storage account and an Azure Function to host your machine learning app. The final step is building an app that uses your model.

Let's get started!

Create Your Model

For the ML.NET portion of this quick project, let’s build the iris categorization model from the Getting started in 10 minutes ML.NET tutorial. As a prerequisite, you’ll want to install Azure CLI 2.0, Azure Functions Core Tools and a recent version of .NET Core.

iris flower

Open a command prompt and create a new folder for your ML.NET project.

> mkdir demo
> cd demo
Enter fullscreen mode Exit fullscreen mode

Next, create a new solution as well as a new console project and install the ML.NET package.

> dotnet new solution
> dotnet new console -o model
> dotnet sln add model/model.csproj
> cd model
> dotnet add package Microsoft.ML --version 0.4.0
> dotnet restore
Enter fullscreen mode Exit fullscreen mode

Create a data directory under model.

> mkdir data
Enter fullscreen mode Exit fullscreen mode

Open the UCI Machine Learning Repository: Iris Data Set, copy and paste the data into VS Code, or TextEdit or Notepad, and save it as iris-data.txt in the data directory.

Now it’s time to write some code. Open up your project in Visual Studio Code and create a couple of data structure classes: IrisData.cs and IrisPrediction.cs.

using Microsoft.ML.Runtime.Api;

        public class IrisData
        {
            [Column("0")]
            public float SepalLength;

            [Column("1")]
            public float SepalWidth;

            [Column("2")]
            public float PetalLength;

            [Column("3")]
            public float PetalWidth;

            [Column("4")]
            [ColumnName("Label")]
            public string Label;
        }

        public class IrisPrediction
        {
            [ColumnName("PredictedLabel")]
            public string PredictedLabels;
        }
Enter fullscreen mode Exit fullscreen mode

Add a model class to perform the machine learning training.

using System.Threading.Tasks;
using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Trainers;
using Microsoft.ML.Transforms;

    class Model
    {
        public static async Task<PredictionModel<IrisData, IrisPrediction>> Train(LearningPipeline pipeline, string dataPath, string modelPath)
        {
            // Load Data
            pipeline.Add(new TextLoader(dataPath).CreateFrom<IrisData>(separator: ','));

            // Transform Data
            // Assign numeric values to text in the "Label" column, because
            // only numbers can be processed during model training
            pipeline.Add(new Dictionarizer("Label"));

            // Vectorize Features
            pipeline.Add(new ColumnConcatenator("Features", "SepalLength", "SepalWidth", "PetalLength", "PetalWidth"));

            // Add Learner
            pipeline.Add(new StochasticDualCoordinateAscentClassifier());

            // Convert Label back to text
            pipeline.Add(new PredictedLabelColumnOriginalValueConverter() { PredictedLabelColumn = "PredictedLabel" });

            // Train Model
            var model = pipeline.Train<IrisData, IrisPrediction>();

            // Persist Model
            await model.WriteAsync(modelPath);

            return model;
        }
    }
Enter fullscreen mode Exit fullscreen mode

Place your logic inside the Program.cs file to run through the process:

    class Program
    {
        static void Main(string[] args)
        {
            string dataPath = "/Users/mbcrump/Documents/demo/model/data/iris-data.txt";

            string modelPath = "/Users/mbcrump/Documents/demo/model/model.zip";

            var model = Model.Train(new LearningPipeline(), dataPath, modelPath).Result;

            // Test data for prediction
            var prediction = model.Predict(new IrisData()
            {
                SepalLength = 3.3f,
                SepalWidth = 1.6f,
                PetalLength = 0.2f,
                PetalWidth = 5.1f
            });

            Console.WriteLine($"Predicted flower type is: {prediction.PredictedLabels}");

        }
    }
Enter fullscreen mode Exit fullscreen mode

Run the model project to create a new model.zip file in your root directory. Below is the results that I got.

Michaels-MacBook-Pro:model mbcrump$ dotnet run
Automatically adding a MinMax normalization transform, use 'norm=Warn' or 'norm=No' to turn this behavior off.
Using 4 threads to train.
Automatically choosing a check frequency of 4.
Auto-tuning parameters: maxIterations = 9996.
Auto-tuning parameters: L2 = 2.668802E-05.
Auto-tuning parameters: L1Threshold (L1/L2) = 0.
Using best model from iteration 500.
Not training a calibrator because it is not needed.
Predicted flower type is: Iris-virginica
Enter fullscreen mode Exit fullscreen mode

Congratulations! You’ve trained a machine learning model with ML.NET that categorizes irises.

Check out more ML quickstarts and tutorials!

Setting up Your Azure Environment Using Cloud Shell

We'll use Azure Cloud Shell which uses the Azure CLI to set up our Azure environment. The easiest way to do this is to sign in to your Azure portal account and click on the cloud shell icon shown below to open a bash shell or go to shell.azure.com.

Once logged in, create a new resource group for this project in the bash shell (and replace mlnetdemo as well as the location with one of your own).

$ az group create --name mlnetdemo --location westus
Enter fullscreen mode Exit fullscreen mode

Add storage to this resource group.

NOTE: You'll have to change the name below to something unique

$ az storage account create --name mlnetdemostorage --location westus --resource-group mlnetdemo --sku Standard_LRS
Enter fullscreen mode Exit fullscreen mode

Create your Azure Function and configure it to use the beta runtime which supports .NET Core.

NOTE: You'll have to change the name below to something unique.

$ az functionapp create --name mlnetdemoazfunction1 --storage-account mlnetdemostorage1 --consumption-plan-location westus --resource-group mlnetdemo
$ az functionapp config appsettings set --name mlnetdemoazfunction1 --resource-group mlnetdemo --settings FUNCTIONS_EXTENSION_VERSION=beta
Enter fullscreen mode Exit fullscreen mode

Deploying Your Machine Learning Model

To get your model up to the server, you will need to get the keys to your storage account. Use the following command in the bash window to get it.

$ az storage account keys list --account-name mlnetdemostorage1 --resource-group mlnetdemo
Enter fullscreen mode Exit fullscreen mode

You'll see the following:

[
  {
    "keyName": "key1",
    "permissions": "Full",
    "value": "YOURKEY"
  },
  {
    "keyName": "key2",
    "permissions": "Full",
    "value": "NONEYOBUSINESS"
  }
]
Enter fullscreen mode Exit fullscreen mode

Use the following command to create a new directory called models to put your model in using your account key (this can be found in the navigation window under Settings | Access keys).

$ az storage container create --name models --account-key YOURKEY --account-name mlnetdemostorage1
Enter fullscreen mode Exit fullscreen mode

model.zip

Since we are using Cloud Shell, it will be easier to use the Azure Portal for this step. You can also use the Azure CLI if you wish.

Browse to your version of the mlnetdemo resource group and drill down to your storage resource that you created earlier. Go into the blobs and you see the new folder models subdirectory.

Upload the model.zip here which can be found on your hard drive.

Identify Irises Like a Robot

Note: Make sure you have the Azure Workload installed to see this template.

azure workload

Create a new project using the Azure Functions project template called serverless_ai.

serverless

When prompted, select the Http trigger option and connect it to your Azure storage account for the project (mlnetdemostorage1 for this post).

Then complete the following steps:

  • Use NuGet to add the Microsoft.ML package to your project.
  • Copy the IrisData.cs and IrisPrediction.cs files from your model project to the serverless_ai project.

You’ll need them both again.

Change the name of the Http trigger class Function1 to Predict and copy in the following code:

using Newtonsoft.Json;
using Microsoft.ML;

namespace serverless_ai
{
    public static class Predict
    {
        [FunctionName("Predict")]
        public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req,
        [Blob("models/model.zip", FileAccess.Read, Connection = "AzureWebJobsStorage")] Stream serializedModel,
        TraceWriter log)
        {
            if (typeof(Microsoft.ML.Runtime.Data.LoadTransform) == null ||
                typeof(Microsoft.ML.Runtime.Learners.LinearClassificationTrainer) == null ||
                typeof(Microsoft.ML.Runtime.Internal.CpuMath.SseUtils) == null ||
                typeof(Microsoft.ML.Runtime.FastTree.FastTree) == null)
            {
                log.Error("Error loading ML.NET");
                return new StatusCodeResult(500);
            }

            //Read incoming request body
            string requestBody = new StreamReader(req.Body).ReadToEnd();

            log.Info(requestBody);

            //Bind request body to IrisData object
            IrisData data = JsonConvert.DeserializeObject<IrisData>(requestBody);

            //Load prediction model
            var model = PredictionModel.ReadAsync<IrisData, IrisPrediction>(serializedModel).Result;

            //Make prediction
            IrisPrediction prediction = model.Predict(data);

            //Return prediction
            return (IActionResult)new OkObjectResult(prediction.PredictedLabels);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

These lines use your model to evaluate new iris data to make a prediction. Your app is ready for testing.

Test Locally Before Deploying

To test the Azure Function app on your local machine, check your local.settings.json file to make sure that AzureWebJobsStorage has a value associated with it.

This is how your local app will find your uploaded model on your Azure storage account. If this has a value (and it should if you bound the project to your account when you created it), you can just F5 the serverless_ai project in order to run it.

Now open up Postman (or a similar REST API tool) and send a POST call to

http://localhost:7071/api/Predict with the following body:
Enter fullscreen mode Exit fullscreen mode
{
 "SepalLength": 3.3,
 "SepalWidth": 1.6,
 "PetalLength": 0.2,
 "PetalWidth": 5.1
}
Enter fullscreen mode Exit fullscreen mode

If all is well, the categorizer will return Iris-verginica.

To Deploy Skynet

… or whatever AI you are deploying from Visual Studio, go to your build settings in the toolbar.

deploy

Select Publish serverless_ai to deploy your Azure Function app.

deploying azure function

To test the app deployment in the Azure Portal, select you Azure Function app under mlnetdemo (or however you named it) and then pick the Predict function under that. Use the Test panel to the right of the screen to see your deployed app in action.

This will place your iris categorizer out on Azure for other people to try. Congratulations! You are now able to deploy artificial intelligences to the cloud.

Want more machine learning on Azure? Check out our ML quickstarts and tutorials!


We'll be posting articles every day in April, so stay tuned or jump ahead and check out more tips and tricks now.

Top comments (1)

Collapse
 
shaijut profile image
Shaiju T

Hi Can you answer my question. I am planning to participate in a Azure Hackathon. So I have idea to detect social distancing using phone camera in real time. Is there a way to do this using Azure Custom Vision AI OR is there some other Azure services for this purpose ?