Problem
This problem is centered around developing an ASP.NET Core MVC Web application that will predict the presence of heart disease based on 14 attributes i.e age, sex, and cp etc. given by the user. To solve this problem, we will build an ML model that takes an input of 14 columns of data from the user, 13 are featured columns (also called independent variables) plus the 'Label' column which is what you want to predict, and in this case, is named 'num', which will tell us the predicted result. Here is the Traning Data downloaded from UCI ML Repository
Solution
To solve this problem, first, we will create an ASP.NET Core MVC Web application, then we will install prerequisite packages from NuGet manager, and then we will build an ML model for Heart Disease Prediction. Thereafter, we will train the model on existing data, and lastly, we'll consume the model in our ASP.NET Core application to predict if the heart disease is present for given data by the user.
Prerequisites
- Visual Studio (I'm using VS2019)
- .NET Core 2.1 or > 2.1 SDK
- Basic understanding of ASP.NET MVC or ASP.NET Core MVC
Let's Start!
- Open Visual Studio (I'm using 2019), click on "Create New Project" and select ASP.NET Core.
- On the configuration of the new project window, select your project name and click on "Create".
- Select Web Application (Model-View-Controller).
- Open NuGet Package Manager Console and install the following packages.
- Install-Package Microsoft.ML
- Install-Package Microsoft.ML.FastTree
- After package installation, right-click on the project and add new folders to make the project look good.
- First, we need to define the data's structure mapped to the datasets to load (HeartTraining.tsv ) with a TextLoader. Create a folder name DataStructures inside ML Model folder and add the following data structure classes that will be used in Machine Learning model. Create two new classes name HeartData.cs and HeartPrediction.cs and add the following snippets one by one.
using Microsoft.ML.Data;
namespace Heart_Disease_Prediction.ML_Model.DataStructures
{
public class HeartData
{
[LoadColumn(0)]
public float Age { get; set; }
[LoadColumn(1)]
public float Sex { get; set; }
[LoadColumn(2)]
public float Cp { get; set; }
[LoadColumn(3)]
public float TrestBps { get; set; }
[LoadColumn(4)]
public float Chol { get; set; }
[LoadColumn(5)]
public float Fbs { get; set; }
[LoadColumn(6)]
public float RestEcg { get; set; }
[LoadColumn(7)]
public float Thalac { get; set; }
[LoadColumn(8)]
public float Exang { get; set; }
[LoadColumn(9)]
public float OldPeak { get; set; }
[LoadColumn(10)]
public float Slope { get; set; }
[LoadColumn(11)]
public float Ca { get; set; }
[LoadColumn(12)]
public float Thal { get; set; }
[LoadColumn(13)]
public bool Label { get; set; }
}
}
- Now, we need a class that will be used to show the heart disease prediction from the model.
using Microsoft.ML.Data;
namespace Heart_Disease_Prediction.ML_Model.DataStructures
{
public class HeartPrediction
{
// ColumnName attribute is used to change the column name from
// its default value, which is the name of the field.
[ColumnName("PredictedLabel")]
public bool Prediction;
// No need to specify ColumnName attribute, because the field
// name "Probability" is the column name we want.
public float Probability;
public float Score;
}
}
- After creating a data structure, now we will build our ML.NET model. I've created a new class named MLModel. You need to create a new folder named Data inside ML Model folder and add the following data files that will be used to train our Machine Learning model. You can download them from here.
- Create a new class named MLModel.cs and insert the following code into that.
using Heart_Disease_Prediction.ML_Model.DataStructures;
using Microsoft.ML;
using System.IO;
using System.Linq;
namespace Heart_Disease_Prediction.ML_Model
{
public class MLModel
{
private readonly MLContext mlContext;
private ITransformer trainedModel = null;
private static string BaseDatasetsRelativePath = @"../../../ML Model/Data";
private static string TrainDataRelativePath = $"{BaseDatasetsRelativePath}/HeartTraining.csv";
private static string TrainDataPath = GetAbsolutePath(TrainDataRelativePath);
public MLModel()
{
mlContext = new MLContext();
}
public void Build()
{
// STEP 1: Common data loading configuration
var trainingDataView = mlContext.Data.LoadFromTextFile<HeartData>(TrainDataPath, hasHeader: true, separatorChar: ';');
// STEP 2: Concatenate the features and set the training algorithm
var pipeline = mlContext.Transforms.Concatenate("Features", "Age", "Sex", "Cp", "TrestBps", "Chol", "Fbs", "RestEcg", "Thalac", "Exang", "OldPeak", "Slope", "Ca", "Thal") .Append(mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Label", featureColumnName: "Features"));
trainedModel = pipeline.Fit(trainingDataView);
}
public HeartPrediction Consume(HeartData input)
{
var predictionEngine = mlContext.Model.CreatePredictionEngine<HeartData, HeartPrediction>(trainedModel);
return predictionEngine.Predict(input);
}
private static string GetAbsolutePath(string relativePath)
{
FileInfo _dataRoot = new FileInfo(typeof(Program).Assembly.Location);
string assemblyFolderPath = _dataRoot.Directory.FullName;
string fullPath = Path.Combine(assemblyFolderPath, relativePath);
return fullPath;
}
}
}
- In the above-given snippet, first, we have created an Estimator by concatenating the features into single 'features' column. Then, we chose our trainer/algorithm (I selected FastTree) to train the model with it.
- To train the model, we have implemented in the Fit() method from the Estimator object. Note: The ML.NET works with data with a lazy loading approach.
- After all this, your project would look like this.
- Now, we need to add controller and views for user interaction. Make an empty controller named HeartDisease and insert the following snippet.
using Microsoft.AspNetCore.Mvc;
using Heart_Disease_Prediction.ML_Model.DataStructures;
using Heart_Disease_Prediction.ML_Model;
namespace Heart_Disease_Prediction.Controllers
{
public class HeartDiseaseController : Controller
{
[HttpGet]
public IActionResult Predict()
{
return View();
}
[HttpPost]
public IActionResult Predict(HeartData input)
{
var model = new MLModel();
model.Build();
var result = model.Consume(input);
ViewBag.HeartPrediction = result;
return View();
}
}
}
- Now, we will create a view named Prediction inside HeartDisease folder under Views folder. Paste the following snippet into that.
@model Heart_Disease_Prediction.ML_Model.DataStructures.HeartData
@{
ViewData["Title"] = "Heart Disease Prediction";
}
<h1>Heart Disease Prediction in ASP.NET Core using ML.NET</h1>
<hr />
<div class="row">
<form asp-action="Predict" class="col-md-8">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="row">
<div class="col-md-4">
<div class="row">
<div class="form-group col-md-6">
<label asp-for="Age" class="control-label"></label>
<input asp-for="Age" class="form-control" />
<span asp-validation-for="Age" class="text-danger"></span>
</div>
<div class="form-group col-md-6">
<label asp-for="Sex" class="control-label"></label>
<select asp-for="Sex" class="form-control">
<option value="1">Male</option>
<option value="0">Female</option>
</select>
<span asp-validation-for="Sex" class="text-danger"></span>
</div>
</div>
<!-- Remaining input fields -->
</div>
</div>
<div class="col-md-4">
<!-- Prediction results display -->
@if (ViewBag.HeartPrediction != null)
{
<h4>Prediction: @ViewBag.HeartPrediction.Prediction</h4>
<h4>Probability: @ViewBag.HeartPrediction.Probability</h4>
<h4>Score: @ViewBag.HeartPrediction.Score</h4>
}
</div>
</form>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
- Now, all our implementation has been completed so let us try to build the application and run. You will see the following output screen.
- Enter your data and click on the Predict button. The Heart Disease Prediction will be shown.
Demo
Note. In this article, we learned how to develop an ASP.NET Core MVC Web Application for Heart Disease Prediction and how to train, evaluate, and consume Heart Disease Prediction Machine Learning model in ASP.NET Core application.
For more information about dataset attributes description please checkout UCI ML Repository.
You can download the demo project from my GitHub repository heart disease prediction.