Machine Learning in Azure
Tags: azureapril, tutorial, machinelearning, devtips
Published: 2019-04-02 13:05:14

---
title: Machine Learning in Azure
published: true
description: Spin up your own machine learning model and deploy it in Azure.
tags: azureapril, tutorial, machine learning, devtips
series: Azure April
cover_image: https://thepracticaldev.s3.amazonaws.com/i/pblyvmtj4y8bdqisyzey.jpeg
---

*We've selected our favorite tips and tricks created by [Michael Crump](https://twitter.com/mbcrump) and are delivering fresh technical content on Azure all April! Miss a day (Or more)? [Catch up with the series](https://dev.to/t/azureapril).*

*Thank you also to [Luis Quintanilla](https://twitter.com/ljquintanilla) for inspiring this with his work on ML.NET and Azure Functions.*

**Don't have Azure?** [Grab a free subscription](https://azure.microsoft.com/en-us/free?&WT.mc_id=azureapril_devto-blog-cxa). 

---

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](https://azure.microsoft.com/en-us/updates/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](https://docs.microsoft.com/azure/machine-learning/?WT.mc_id=azureapril_devto-blog-cxa)!

## Serverless Machine Learning

This is inspired by [Luis Quintanilla’s article](http://luisquintanilla.me/2018/08/21/serverless-machine-learning-mlnet-azure-functions/) 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](https://dotnet.microsoft.com/learn/machinelearning-ai/ml-dotnet-get-started-tutorial/intro?WT.mc_id=azureapril_devto-blog-cxa). As a prerequisite, you’ll want to install [Azure CLI 2.0](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest&WT.mc_id=https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest&WT.mc_id=azureapril_devto-blog-cxa), [Azure Functions Core Tools](https://docs.microsoft.com/azure/azure-functions/functions-run-local?WT.mc_id=azureapril_devto-blog-cxa) and a recent version of [.NET Core](https://dotnet.microsoft.com/download/dotnet-core/2.2?WT.mc_id=azureapril_devto-blog-cxa).

![iris flower](https://microsoft.github.io/AzureTipsAndTricks/files/iris-machinelearning.png)

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

```
> mkdir demo
> cd demo
```

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
```

Create a data directory under model.

```
> mkdir data
```

Open the [UCI Machine Learning Repository: Iris Data Set](https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data), 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;
        }
```

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

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

        }
    }
```

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
```

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

> [Check out more ML quickstarts and tutorials](https://docs.microsoft.com/azure/machine-learning/?WT.mc_id=azureapril_devto-blog-cxa)!

## Setting up Your Azure Environment Using Cloud Shell

We'll use Azure Cloud Shell which uses the [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest&WT.mc_id=https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest&WT.mc_id=azureapril_devto-blog-cxa) 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](https://shell.azure.com/?WT.mc_id=azureapril_devto-blog-cxa).

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
```

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
```

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
```

## 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
```

You'll see the following:

```
[
  {
    "keyName": "key1",
    "permissions": "Full",
    "value": "YOURKEY"
  },
  {
    "keyName": "key2",
    "permissions": "Full",
    "value": "NONEYOBUSINESS"
  }
]
```

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
```

![model.zip](https://microsoft.github.io/AzureTipsAndTricks/files/blob_model.png)

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](https://microsoft.github.io/AzureTipsAndTricks/files/azurefunction.png)

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

![serverless](https://microsoft.github.io/AzureTipsAndTricks/files/httptrigger.png)

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

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](https://www.getpostman.com/apps) (or a similar REST API tool) and send a `POST` call to 

```
http://localhost:7071/api/Predict with the following body:
```

```
{
 "SepalLength": 3.3,
 "SepalWidth": 1.6,
 "PetalLength": 0.2,
 "PetalWidth": 5.1
}
```

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](https://microsoft.github.io/AzureTipsAndTricks/files/publish.png)

Select `Publish serverless_ai` to deploy your Azure Function app.

![deploying azure function](https://microsoft.github.io/AzureTipsAndTricks/files/test_in_portal.png)

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](https://docs.microsoft.com/azure/machine-learning/?WT.mc_id=azureapril_devto-blog-cxa)!

---
[We'll be posting articles every day in April](https://dev.to/t/azureapril), so stay tuned or jump ahead and check out more tips and tricks [now](http://azuredev.tips).