Header Ads

Azure Machine Learning: Iris Model Client Application

Today's article is the continuation of my post Azure Machine Learning: Classification Predictive Analysis using Iris Dataset. In this post I shall be demonstrating utilization of azure machine learning model into a client application. I shall be making web base application.


What my web application does is that it consume the iris machine learning model which I had created  in azure machine learning studio. The application will train and predict the provided values into iris classified type i.e. Iris-setosa, Iris-versicolor and Iris-virginica.

Prerequisite

Following are some prerequisites before you proceed further in this tutorial:
  1. Knowledge of my article Azure Machine Learning: Classification Predictive Analysis using Iris Dataset.
  2. Knowledge of Iris dataset
  3. Basic understanding of machine learning concept.
  4. Knowledge of ASP.NET MVC5.
  5. Knowledge of HTML.
  6. Knowledge of JavaScript.
  7. Knowledge of Bootstrap.
  8. Knowledge of Jquery.
  9. Knowledge of C# Programming.
You can download the complete source code for this tutorial or you can follow the step by step discussion below. The sample code is being developed in Microsoft Visual Studio 2015 Enterprise.

Download Link

Let's begin now. 

1)  First we need to convert our azure machine learning model to web service. If you have not created the iris machine learning model previously in azure machine studio, you can follow my article Azure Machine Learning: Classification Predictive Analysis using Iris Dataset otherwise open your machine learning studio and click on the iris dataset machine learning model and create a new copy of it and name it "iris dataset azure ML web service" as shown below i.e.



2) Now, remove the "Evaluate Model" module because we are now creating a web service and we need to remove the evaluation module as shown below i.e.


3) Now click "Run" as shown below to train your model i.e.


4) Click "Predictive Web Service [Recommended]" as shown below to create a web service for the machine learning model i.e.



Notice in above snippet that our iris machine learning model is converted into a module under "Predictive Experiment" tab.

5) Click "Run" button as shown below  to train our model for the web service i.e.



6) Notice a small switch as shown below in the snippet. This switch toggle between your original machine learning model and the web service model i.e.




Notice here that some modules are grayed out in training experiment and some are grayed out in predictive experiment. This is because the grayed out modules tells that they are not being used for example in case of training experiment web service input & web service output modules are not being used while our machine learning model is being evaluated via sample dataset that we have provided and in case of predictive experiment our sample dataset module is grayed out, this means that our web service is not using our sample dataset, we need to train our model with live values via client application.

7) Now, right click "Score Model" module under training experiment and the click "Visualize as shown below, you will see result of our machine learning model according to our provided sample dataset i.e.



8) Let's deploy our web services, so, we can consume it in a client application. Click "Deploy Web Service" as shown below i.e.




In the above snippets, after deploying the web service, you will be navigated to web service section of azure machine learning studio, here you can see your web service API Key that you can consume in your client side application and a configuration tab where you can configure default values of the web service input & output.

9) Now, click "New Web Services Experience" and then click "Consume" as shown below.




In the above snippets, you will see different types of API Keys and code to be consumed in the target client application.

10) Since, I will create web application as a sample application therefore, I will consume the sample consumption code in asp.net mvc5 web application. So for that, create a new asp.net mvc project in visual studio and name it "IrisMLClientApp".

11) Replace "Views\Shared\_Layout.cshtml" file with following code i.e

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />

</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <center>
                <p><strong>Copyright &copy; @DateTime.Now.Year - <a href="http://www.asmak9.com/">Asma's Blog</a>.</strong> All rights reserved.</p>
            </center>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")

    @RenderSection("scripts", required: false)
</body>
</html>

 In the above code we have simply create a simple layout for our application.

12) Now, create new controller, name it "Home" and replace following code in "Controllers\HomeController.cs" i.e.

using IrisMLClientApp.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;

namespace IrisMLClientApp.Controllers
{
    public class HomeController : Controller
    {
        #region Train ML

        //
        // GET: /Home/TrainML
        [AllowAnonymous]
        public ActionResult TrainML()
        {
            return View();
        }

        //
        // POST: /Home/TrainML
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> TrainML(IrisMLViewModel model)
        {
            if (ModelState.IsValid)
            {
                // Info.
                IrisMLResponseViewModel obj = await this.RequestMLModel(model);
            }

            // If we got this far, something failed, redisplay form
            return this.RedirectToAction("TrainMLSuccess");
        }

        //
        // GET: /Home/TrainMLSuccess
        [AllowAnonymous]
        public ActionResult TrainMLSuccess()
        {
            return View();
        }

        #endregion

        #region Predict

        //
        // GET: /Home/Predict
        [AllowAnonymous]
        public ActionResult Predict()
        {
            return View();
        }

        //
        // POST: /Home/Predict
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Predict(IrisMLViewModel model)
        {
            // Initialization.
            IrisMLResponseViewModel obj = new IrisMLResponseViewModel();

            if (ModelState.IsValid)
            {
                // Info.
                obj = await this.RequestMLModel(model);
            }

            // If we got this far, something failed, redisplay form
            return this.RedirectToAction("PredictionResult", obj);
        }

        //
        // GET: /Home/PredictionResult
        [AllowAnonymous]
        public ActionResult PredictionResult(IrisMLResponseViewModel input)
        {
            // Initialization
            PredictionResultViewModel result = new PredictionResultViewModel();

            // Switch
            switch (input.Class_Type_Predicted)
            {
                case "1": result.Class_Name = "Iris-setosa";
                    break;

                case "2":
                    result.Class_Name = "Iris-versicolor";
                    break;

                case "3":
                    result.Class_Name = "Iris-virginica";
                    break;

                default: result.Class_Name = "Iris-setosa";
                    break;
            }

            return View(result);
        }

        #endregion

        #region Helpers

        #region Request ML model method

        public async Task<IrisMLResponseViewModel> RequestMLModel(IrisMLViewModel input)
        {
            // Initialization.
            IrisMLResponseViewModel obj = new IrisMLResponseViewModel();

            try
            {
                using (var client = new HttpClient())
                {
                    var scoreRequest = new
                    {
                        Inputs = new Dictionary<string, List<Dictionary<string, string>>>() {
                        {
                            "input1",
                            new List<Dictionary<string, string>>(){new Dictionary<string, string>(){
                                            {
                                                "Sepal-Length", input.Sepal_Length
                                            },
                                            {
                                                "Sepal-Width", input.Sepal_Width
                                            },
                                            {
                                                "Petal-Length", input.Petal_Length
                                            },
                                            {
                                                "Petal-width", input.Petal_Width
                                            },
                                            {
                                                "Class", input.Class_Name
                                            },
                                            {
                                                "Class-Type", input.Class_Type
                                            },
                                }
                            }
                        },
                    },
                        GlobalParameters = new Dictionary<string, string>()
                        {
                        }
                    };

                    const string apiKey = "your-apikey"; // Replace this with the API key for the web service
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
                    client.BaseAddress = new Uri("your-uri");

                    // WARNING: The 'await' statement below can result in a deadlock
                    // if you are calling this code from the UI thread of an ASP.Net application.
                    // One way to address this would be to call ConfigureAwait(false)
                    // so that the execution does not attempt to resume on the original context.
                    // For instance, replace code such as:
                    //      result = await DoSomeTask()
                    // with the following:
                    //      result = await DoSomeTask().ConfigureAwait(false)

                    HttpResponseMessage response = await client.PostAsJsonAsync("", scoreRequest).ConfigureAwait(false);

                    if (response.IsSuccessStatusCode)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        string[] data = result.Split(':');
                        obj.Class_Type_Predicted = data[12].Split('}')[0].Split('\"')[1];;
                        Console.WriteLine("Result: {0}", result);
                    }
                    else
                    {
                        Console.WriteLine(string.Format("The request failed with status code: {0}", response.StatusCode));

                        // Print the headers - they include the requert ID and the timestamp,
                        // which are useful for debugging the failure
                        Console.WriteLine(response.Headers.ToString());

                        string responseContent = await response.Content.ReadAsStringAsync();
                        Console.WriteLine(responseContent);
                    }
                }
            }
            catch (Exception ex)
            {
                // Info
                Console.Write(ex);
            }

            // Info.
            return obj;
        }

        #endregion

        #endregion
    }
}

In the above code, I have created actions for the respective pages in which I have consumed our machine learning model web service. Following piece of code will train & predict result base on the iris machine learning model. The provided values are real time values. So, if the pattern value does not exist for a particular class the machine learning model will result output score same as the input, but, if some values exist for a particular class, the machine learning model will try predicting the input result.

        #region Request ML model method

        public async Task<IrisMLResponseViewModel> RequestMLModel(IrisMLViewModel input)
        {
            // Initialization.
            IrisMLResponseViewModel obj = new IrisMLResponseViewModel();

            try
            {
                using (var client = new HttpClient())
                {
                    var scoreRequest = new
                    {
                        Inputs = new Dictionary<string, List<Dictionary<string, string>>>() {
                        {
                            "input1",
                            new List<Dictionary<string, string>>(){new Dictionary<string, string>(){
                                            {
                                                "Sepal-Length", input.Sepal_Length
                                            },
                                            {
                                                "Sepal-Width", input.Sepal_Width
                                            },
                                            {
                                                "Petal-Length", input.Petal_Length
                                            },
                                            {
                                                "Petal-width", input.Petal_Width
                                            },
                                            {
                                                "Class", input.Class_Name
                                            },
                                            {
                                                "Class-Type", input.Class_Type
                                            },
                                }
                            }
                        },
                    },
                        GlobalParameters = new Dictionary<string, string>()
                        {
                        }
                    };

                    const string apiKey = "your-apikey"; // Replace this with the API key for the web service
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
                    client.BaseAddress = new Uri("your-uri");

                    // WARNING: The 'await' statement below can result in a deadlock
                    // if you are calling this code from the UI thread of an ASP.Net application.
                    // One way to address this would be to call ConfigureAwait(false)
                    // so that the execution does not attempt to resume on the original context.
                    // For instance, replace code such as:
                    //      result = await DoSomeTask()
                    // with the following:
                    //      result = await DoSomeTask().ConfigureAwait(false)

                    HttpResponseMessage response = await client.PostAsJsonAsync("", scoreRequest).ConfigureAwait(false);

                    if (response.IsSuccessStatusCode)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        string[] data = result.Split(':');
                        obj.Class_Type_Predicted = data[12].Split('}')[0].Split('\"')[1];;
                        Console.WriteLine("Result: {0}", result);
                    }
                    else
                    {
                        Console.WriteLine(string.Format("The request failed with status code: {0}", response.StatusCode));

                        // Print the headers - they include the requert ID and the timestamp,
                        // which are useful for debugging the failure
                        Console.WriteLine(response.Headers.ToString());

                        string responseContent = await response.Content.ReadAsStringAsync();
                        Console.WriteLine(responseContent);
                    }
                }
            }
            catch (Exception ex)
            {
                // Info
                Console.Write(ex);
            }

            // Info.
            return obj;
        }

        #endregion

Replace your target model "API Key" & "URI" path in the above code.

13) Now create "Models\HomeViewModels.cs" file and replace following code in it i.e.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace IrisMLClientApp.Models
{
    public class IrisMLViewModel
    {
        [Required]
        [Display(Name = "Sepal-Length")]
        public string Sepal_Length { get; set; }

        [Required]
        [Display(Name = "Sepal-Width")]
        public string Sepal_Width { get; set; }

        [Required]
        [Display(Name = "Petal-Length")]
        public string Petal_Length { get; set; }

        [Required]
        [Display(Name = "Petal-Width")]
        public string Petal_Width { get; set; }

        [Required]
        [Display(Name = "Class Name")]
        public string Class_Name { get; set; }

        [Required]
        [Display(Name = "Class-Type")]
        public string Class_Type { get; set; }
    }

    public class IrisMLResponseViewModel
    {
        [Display(Name = "Class-Type")]
        public string Class_Type_Predicted { get; set; }
    }

    public class PredictionResultViewModel
    {
        [Display(Name = "Class Name")]
        public string Class_Name { get; set; }
    }
}

In the above code, I have created the target view models in order to map the input and output values.

14) Create target page files for actions under "Views" i.e. "TrainML.cshtml, TrainMLSuccess.cshtml, Predict.cshtml & PredictionResult.cshtml" and replace following code in them i.e.

TrainML.cshtml


@model IrisMLClientApp.Models.IrisMLViewModel
@{
    ViewBag.Title = "Iris Machine Learning Model Client Application";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("TrainML", "Home", FormMethod.Post, new { @id = "trainMLFormId", @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    HtmlHelper.UnobtrusiveJavaScriptEnabled = false;

    <h4>Train Iris Machine Learning Model</h4>
    <hr />

    <div class="form-group">
        @Html.LabelFor(m => m.Sepal_Length, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Sepal_Length, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Sepal_Length, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Sepal_Width, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Sepal_Width, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Sepal_Width, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Petal_Length, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Petal_Length, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Petal_Length, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Petal_Width, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Petal_Width, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Petal_Width, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Class_Name, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Class_Name, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Class_Name, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Class_Type, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Class_Type, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Class_Type, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Train" />
            <a href="@Url.Action("Predict", "Home")" class="btn btn-default">Predict</a>
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/custom-validator")
}

TrainMLSuccess.cshtml


@{
    ViewBag.Title = "Iris Machine Learning Model Client Application";
}

<h2>@ViewBag.Title.</h2>

<br/>
<br />
<p class="alert-success"><b>Your machine learning model has been successfully trained.</b></p>

<div class="col-md-10">
    <a href="@Url.Action("TrainML", "Home")" class="btn btn-default">Back</a>
</div>
<br />
<br />

Predict.cshtml



@model IrisMLClientApp.Models.IrisMLViewModel
@{
    ViewBag.Title = "Iris Machine Learning Model Client Application";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("Predict", "Home", FormMethod.Post, new { @id = "trainMLFormId", @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    HtmlHelper.UnobtrusiveJavaScriptEnabled = false;

    <h4>Predict Iris Machine Learning Model</h4>
    <hr />

    <div class="form-group">
        @Html.LabelFor(m => m.Sepal_Length, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Sepal_Length, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Sepal_Length, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Sepal_Width, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Sepal_Width, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Sepal_Width, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Petal_Length, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Petal_Length, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Petal_Length, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Petal_Width, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Petal_Width, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Petal_Width, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Class_Name, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Class_Name, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Class_Name, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Class_Type, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Class_Type, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Class_Type, "", new { @class = "text-danger  " })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Predict" />
            <a href="@Url.Action("TrainML", "Home")" class="btn btn-default">Train</a>
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/custom-validator")
}

PredictionResult.cshtml


@model IrisMLClientApp.Models.PredictionResultViewModel
@{
    ViewBag.Title = "Iris Machine Learning Model Client Application";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("Predict", "Home", FormMethod.Post, new { @id = "trainMLFormId", @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    HtmlHelper.UnobtrusiveJavaScriptEnabled = false;

    <h4>Prediction Result</h4>
    <hr />

    <div class="form-group">
        @Html.LabelFor(m => m.Class_Name, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Class_Name, new { @class = "form-control", @readonly = "readonly" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <a href="@Url.Action("Predict", "Home")" class="btn btn-default">Back</a>
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/custom-validator")
}

15) Now execute the project and train & predict the test values i.e.





Conclusion

In this article, you will learn to convert your machine learning model created in Microsoft azure machine learning studio to a predictive web service model. You will also learn to deploy the  web service from the azure machine learning studio. Finally you will learn to consume the deployed web service into your target application. You will also learn to create sample asp.net mvc5 base web application in order to consume the machine learning model created in azure machine learning studio and you will learn to perform real time training & prediction of input values to your machine learning model.

6 comments:

  1. It's a wonderful post and very helpful, thanks for all this information. You are including better information regarding this topic in an effective way.Thank you so much.

    Allergy Medicines
    Ayurvedic Medicine For Immunity
    Hyperpigmentation cream
    Viral Fever Medicines
    It's a wonderful post and very helpful, thanks for all this information. You are including better information regarding this topic in an effective way.Thank you so much.

    Allergy Medicines
    Ayurvedic Medicine For Immunity
    Hyperpigmentation cream
    Viral Fever Medicines

    ReplyDelete
  2. This blog is having the general information. Got a creative work and this is very different one.We have to
    develop our creativity mind.This blog helps for this. Thank you for this blog. This is very interesting and useful...
    SEO Company in India
    SEO Company in chennai

    Digital Marketing Company in Chennai
    Digital Marketing Company in India

    ReplyDelete
  3. very nice blog this course very useful to us this gives the big opportunity to us i like this information very much.

    Data Warehousing Training in chennai

    ReplyDelete