Leveraging Machine Learning with C# and .NET Core: ML.NET in Action

Machine learning (ML) has become a critical component in the development of modern applications. With the increasing demand for intelligent, data-driven applications, software developers need access to powerful and easy-to-use tools to leverage ML capabilities. Enter ML.NET – a cross-platform, open-source machine learning framework developed by Microsoft for C# and F# developers.

Why ML.NET?

ML.NET provides a comprehensive suite of tools that makes it easier for developers to build custom machine learning models using C# or F# without requiring expertise in machine learning. Some advantages of ML.NET include:

  1. Cross-platform support: ML.NET works with .NET Core, making it compatible with various platforms, including Windows, macOS, and Linux.
  2. No ML expertise required: ML.NET's built-in algorithms and easy-to-use APIs enable developers to create ML models without being ML experts.
  3. Integration with popular ML libraries: ML.NET can be extended with TensorFlow, ONNX, and other popular ML libraries, allowing for even more flexibility and power.

Getting Started with ML.NET

To start using ML.NET, you will need to install the ML.NET NuGet package in your .NET Core project. In Visual Studio, you can do this by right-clicking on your project, selecting "Manage NuGet Packages," and then searching for "Microsoft.ML".

Example 1: Sentiment Analysis

In this example, we will create a simple sentiment analysis model using ML.NET. Sentiment analysis is a common NLP (natural language processing) task that involves determining whether a given text is positive or negative.

First, create a new .NET Core Console Application and install the "Microsoft.ML" NuGet package. Next, define two classes for the input and output data schema:

public class SentimentData
{
[LoadColumn(0)] public string SentimentText;
[LoadColumn(1)] [ColumnName("Label")] public bool Sentiment;
}

public class SentimentPrediction : SentimentData
{
[ColumnName("PredictedLabel")] public bool Prediction;
public float Probability;
public float Score;
}

Now, we will create a method to train and evaluate the sentiment analysis model:

private static ITransformer TrainAndEvaluate(MLContext mlContext, IDataView dataView)
{
// Split the data into training and test sets.
var tt = mlContext.Data.TrainTestSplit(dataView);

// Define the pipeline.
var pipeline = mlContext.Transforms.Text.FeaturizeText("Features", nameof(SentimentData.SentimentText))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Concatenate("Features", "Features"))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Concatenate("Features", "Features"))
.Append(mlContext.BinaryClassification.Trainers.SdcaNonCalibrated())
.Append(mlContext.Transforms.CalculateFeatureContribution("Features"))
.Append(mlContext.Transforms.CopyColumns("Score", "Score"))
.Append(mlContext.Transforms.NormalizeMinMax("Score"))
.Append(mlContext.Transforms.Concatenate("Features", "Score"))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Concatenate("Features", "Features"))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Concatenate("Features", "Features"))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.BinaryClassification.Trainers.SdcaNonCalibrated())
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

// Train the model.
var model = pipeline.Fit(tt.TrainSet);

// Evaluate the model.
var predictions = model.Transform(tt.TestSet);
var metrics = mlContext.BinaryClassification.Evaluate(predictions);

Console.WriteLine($"Accuracy: {metrics.Accuracy}");
Console.WriteLine($"AUC: {metrics.AreaUnderRocCurve}");
Console.WriteLine($"F1 Score: {metrics.F1Score}");

return model;
}

Finally, create a method to use the trained model for predictions:

private static void PredictSentiment(MLContext mlContext, ITransformer model)
{
var predictionEngine = mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(model);
var sampleText = new SentimentData { SentimentText = "I love this product!" };
var result = predictionEngine.Predict(sampleText);

Console.WriteLine($"Sentiment: {(result.Prediction ? "Positive" : "Negative")} ({result.Probability:P2})");
}

In the Main method, add the following code to run the example:

csharpCopy codevar mlContext = new MLContext(seed: 0);
var data = mlContext.Data.LoadFromTextFile<SentimentData>("./sentimentdata.csv", separatorChar: ',');
var model = TrainAndEvaluate(mlContext, data);
PredictSentiment(mlContext, model);

Example 2: Image Classification

In this example, we will demonstrate how to use ML.NET to create an image classification model. Image classification is the task of categorizing images into different classes based on their content.

First, create a new .NET Core Console Application and install the "Microsoft.ML" and "Microsoft.ML.ImageAnalytics" NuGet packages. Define two classes for the input and output data schema:

public class ImageData
{
[LoadColumn(0)] public string ImagePath;
[LoadColumn(1)] public string Label;
}

public class ImagePrediction : ImageData
{
public float[] Score;
public string PredictedLabel;
}

Now, create a method to train and evaluate the image classification model:

private static ITransformer TrainAndEvaluate(MLContext mlContext, IDataView dataView)
{
// Split the data into training and test sets.
var tt = mlContext.Data.TrainTestSplit(dataView);

// Define the pipeline.
var pipeline = mlContext.Transforms.Conversion.MapValueToKey("Label")
.Append(mlContext.Transforms.LoadRawImageBytes("ImageBytes", null, nameof(ImageData.ImagePath)))
.Append(mlContext.Transforms.DnnFeaturizeImage("ImageFeatures", m => m.OnnxModel(modelPath), nameof(ImageData.ImageBytes)))
.Append(mlContext.Transforms.NormalizeMinMax("ImageFeatures"))
.Append(mlContext.Transforms.Concatenate("Features", "ImageFeatures"))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Concatenate("Features", "Features"))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Concatenate("Features", "Features"))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Concatenate("Features", "Features"))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.MulticlassClassification.Trainers.SdcaNonCalibrated())
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

// Train the model.
var model = pipeline.Fit(tt.TrainSet);

// Evaluate the model.
var predictions = model.Transform(tt.TestSet);
var metrics = mlContext.MulticlassClassification.Evaluate(predictions);

Console.WriteLine($"Log-loss: {metrics.LogLoss}");
Console.WriteLine($"Per-class Log-loss: {string.Join(", ", metrics.PerClassLogLoss.Select(c => c.ToString("F4")))}");

return model;
}

Next, create a method to use the trained model for predictions:

private static void PredictImage(MLContext mlContext, ITransformer model, string imagePath)
{
var predictionEngine = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model);
var sampleImage = new ImageData { ImagePath = imagePath };
var result = predictionEngine.Predict(sampleImage);

Console.WriteLine($"Predicted Label: {result.PredictedLabel}");
}

In the Main method, add the following code to run the example:

var mlContext = new MLContext(seed: 0);
var data = mlContext.Data.LoadFromTextFile<ImageData>("./image_labels.csv", separatorChar: ',');
var model = TrainAndEvaluate(mlContext, data);
PredictImage(mlContext, model, "./test_image.jpg");

ML.NET provides an accessible and powerful framework for C# and .NET Core developers to leverage machine learning capabilities in their applications. With its ease of use, cross-platform support, and integration with popular ML libraries, ML.NET is a valuable tool for developers looking to incorporate intelligent features into their software. The examples in this article demonstrate just a small fraction of ML.NET's capabilities, and the possibilities are endless for incorporating machine learning into various applications.