This problem is centred around developing an ASP.NET Core MVC Web application that will detect whether a message is a spam or not, based on message content given by the user. To solve this problem, we will build an ML model that takes an input of one column Message, 'Label' column which is what you want to predict, and in this case, is named 'Label', which will tell us the predicted result. To train our model, we will use the
SMS Spam Collection Dataset downloaded from
UCI ML Repository.
As we are classifying the text messages into one of two categories, we will use binary classification for this problem.
Solution
To solve this problem, first, we will build an estimator to define the ML pipeline we want to use. Then we will train this estimator on existing data, and lastly, we'll consume the model in our ASP.NET Core Web Application to predict whether a few examples messages are spam or not.
Prerequsites
Let's start.
Before going to build our Machine Learning model, we need to set up our ASP.NET Core web application.
First, we will create an ASP.NET Core web application and setup the basic data structures that will be used later for Machine Learning model.
- Open Visual Studio and select ASP.NET Core.
- Please enter your project name. I'm going to enter Spam Detection and click on the "Create" button.
- Now, we will select the design pattern that we will be used to develop our project. In my case, I'm going to select the Web Application MVC.
- We have created our ASP.NET Core MVC web application successfully. Now, first of all, we will download the SMS Spam Collection Data Set from UCI ML Repository and transform the data structure according to our requirement.
- After downloading the data, extract the "zip" file.
- We will add a new folder named "Data" and will place the "SMSSpamCollection" dataset file inside this.
- There are two columns inside the dataset file - Lable and Message. In the original dataset, the Lable column is having two values - spam and ham. We will replace spam and ham with True and False respectively. Our data will look like this (Top 5 records from dataset just for view).
- false Go until jurong point, crazy.. Available only in bugis n great world la e buffet... Cine there got amore wat...
- false Ok lar... Joking wif u oni...
- true Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&C's apply 08452810075over18's
- false U dun say so early hor... U c already then say...
- false Nah I don't think he goes to usf, he lives around here though
- Now, we will implement the basic data structure that will be used to build our ML.NET Model. But first, we will install the prerequisite package using "NuGet Package Manger". Open Nuget Manager Console and use "Install-Package Microsoft.ML".
- Now, we will create two new classes inside the Data folder, named "SpamInput" and "SpamPrediction" and both classes will be using "Microsoft.ML.Data".
- Here is our "SpamInput" class snippet.
- public class SpamInput
- {
- [LoadColumn(0)]
- public string Label { get; set; }
- [LoadColumn(1)]
- public string Message { get; set; }
- }
-
And, here is our "SpamPrediction" class snippet.
- public class SpamPrediction
- {
- [ColumnName("PredictedLabel")]
- public string isSpam { get; set; }
- }
- After implementing the basic data strucutres, now we will move to build our ML.NET Model for SMS Spam Detection.
- First of all, we will set up the MLContext which is a catalog of components in ML.NET.
- var mlContext = new MLContext();
- Now, we will specify the schema for spam data and read it into DataView.
- var data = mlContext.Data.LoadFromTextFile<SpamInput>(path: TrainDataPath, hasHeader: true, separatorChar: '\t');
- After specifying the data schema, we will make data process configuration with pipeline data transformations.
- var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("Label", "Label")
- .Append(mlContext.Transforms.Text.FeaturizeText("FeaturesText", new Microsoft.ML.Transforms.Text.TextFeaturizingEstimator.Options {
- WordFeatureExtractor = new Microsoft.ML.Transforms.Text.WordBagEstimator.Options { NgramLength = 2, UseAllLengths = true },
- CharFeatureExtractor = new Microsoft.ML.Transforms.Text.WordBagEstimator.Options { NgramLength = 3, UseAllLengths = false },
- }, "Message"))
- .Append(mlContext.Transforms.CopyColumns("Features", "FeaturesText"))
- .Append(mlContext.Transforms.NormalizeLpNorm("Features", "Features"))
- .AppendCacheCheckpoint(mlContext);
- Now, we will set up a training algorithm that will be used to train our ML.NET Model.
- var trainer = mlContext.MulticlassClassification.Trainers.OneVersusAll
- (mlContext.BinaryClassification.Trainers.AveragedPerceptron(
- labelColumnName: "Label", numberOfIterations: 10, featureColumnName: "Features"), labelColumnName: "Label"
- ).Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
- var trainingPipeline = dataProcessPipeline.Append(trainer);
-
To start training our ML.NET Model, we will fit data into model.
- var model = trainingPipeline.Fit(data);
-
At last but not least, we will predict the message using ML.NET Model.
- var predictor=mlContext.Model.CreatePredictionEngine<SpamInput, SpamPrediction>(model);
- //Predict
- var prediction = predictor.Predict(input);
-
I've created a new class named "SpamDetectionMLModel" inside "ML Model" folder. I've implemented the ML.NET in this class and will use this as an interface.
- Here is the result how "SpamDetectionMLModel" looks like.
- public class SpamDetectionMLModel
- {
- private static string AppPath => Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
- private static string TrainDataPath => Path.Combine(AppPath, "..", "..", "..", "Data", "SMSSpamCollection.csv");
- private MLContext mlContext;
- private ITransformer _model;
- private EstimatorChain<TransformerChain<KeyToValueMappingTransformer>> _trainingPipeline;
- private IDataView _data;
- public SpamDetectionMLModel()
- {
- mlContext = null;
- _model = null;
- _trainingPipeline = null;
- _data = null;
- }
- public void Build()
- {
-
- mlContext = new MLContext();
-
- _data = mlContext.Data.LoadFromTextFile<SpamInput>(path: TrainDataPath, hasHeader: true, separatorChar: '\t');
-
- var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("Label", "Label")
- .Append(mlContext.Transforms.Text.FeaturizeText("FeaturesText", new Microsoft.ML.Transforms.Text.TextFeaturizingEstimator.Options
- {
- WordFeatureExtractor = new Microsoft.ML.Transforms.Text.WordBagEstimator.Options { NgramLength = 2, UseAllLengths = true },
- CharFeatureExtractor = new Microsoft.ML.Transforms.Text.WordBagEstimator.Options { NgramLength = 3, UseAllLengths = false },
- }, "Message"))
- .Append(mlContext.Transforms.CopyColumns("Features", "FeaturesText"))
- .Append(mlContext.Transforms.NormalizeLpNorm("Features", "Features"))
- .AppendCacheCheckpoint(mlContext);
-
- var trainer = mlContext.MulticlassClassification.Trainers.OneVersusAll(mlContext.BinaryClassification.Trainers.AveragedPerceptron(labelColumnName: "Label", numberOfIterations: 10, featureColumnName: "Features"), labelColumnName: "Label")
- .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
- _trainingPipeline = dataProcessPipeline.Append(trainer);
- }
- public void Train()
- {
-
- _model = _trainingPipeline.Fit(_data);
- }
- public SpamPrediction Predict(SpamInput input)
- {
- var predictor=mlContext.Model.CreatePredictionEngine<SpamInput, SpamPrediction>(_model);
- return predictor.Predict(input);
- }
- }
-
After ML.NET Model implementation, now, we will implement and view, that will provide the user interface for consuming our SMS Spam Detection ML.NET Model.
- So first, we will create an empty controller named "SpamDetection" and use the following snippet inside our controller.
- public class SpamDetectionController : Controller
- {
- public IActionResult Predict()
- {
- return View();
- }
- [HttpPost]
- public IActionResult Predict(SpamInput input)
- {
- var model = new SpamDetectionMLModel();
- model.Build();
- model.Train();
- ViewBag.Prediction = model.Predict(input);
- return View();
- }
- }
-
After controller implementation, we will implement our View. Create an empty view named "Predict" inside Views>SpamDetection folder. I've kept it simple.
- @model Spam_Detection.Data.SpamInput
-
- @{
- ViewData["Title"] = "Spam Detection";
- }
-
- <h1>Spam Prediction for Text Messages</h1>
-
- <div class="row">
- <div class="col-md-6">
- <form asp-action="Predict">
- <div asp-validation-summary="ModelOnly" class="text-danger"></div>
- <div class="form-group">
- <label asp-for="Message" class="control-label"></label>
- <textarea asp-for="Message" class="form-control" ></textarea>
- <span asp-validation-for="Message" class="text-danger"></span>
- </div>
- <div class="form-group">
- <input type="submit" value="Predict" class="btn btn-primary" />
- </div>
- </form>
- @if (ViewBag.Prediction != null)
- {
- <h4>Is Spam : @ViewBag.Prediction.isSpam</h4>
- }
- </div>
- </div>
-
- @section Scripts {
- @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
- }
Conclusion
So we have built the solution to our problem.
- We have created ASP.NET Core MVC Web Application template.
- We have downloaded and SMS Spam Collection data set files for training our model.
- We have implemented basic data strucutres for using ML.NET Model.
- We have Build, Trained, and Consumed our ML.NET Model for SMS Spam Detection problem.
- At last we build a user interface that would allow user to enter their message to predict whether the message is spam or not.
- So here is the final look at our solution.
- Now press F5 or select Debug>Start Debuging. Our application will be started.
Demo
Note
In this article, we learned how to develop an ASP.NET Core MVC Web Application for Spam Detection for Text Messages and how to build, train, and consume Spam Detection
ML.NET Machine Learning model in ASP.NET Core application.