A Code-Based Introduction to AI For .Net Programmers
If you are new to AI but want to get a grasp of the fundamentals and some terminology, going through some code may be the easiest way to do it. Thanks to the ONNX Runtime and Microsoft DirectML, the code is easy-to-implement, succinct, and digestible for those of us .Net folks.
Terminology
The Console Application
This application requires only two NuGet packages:
Program.cs
Stripped of error handling and user messaging, the main program is very basic, mostly just dealing with files. It creates an instance of the ImageClassifier class, makes it do the grunt work, and finally prints the top guess returned by the model.
var imagePath = args[0]; //the image file
var modelPath = "resnet50.onnx"; //the ONNX model
var labelsPath = "labels.txt"; //the list of labels the ONNX model was trained on
var classifier = new ImageClassifier(modelPath, labelsPath);
var result = classifier.Predict(imagePath);
Console.WriteLine($"This is most likely: {result}");
ImageClassifier.cs
There are three methods in this class: the constructor, the Predict method used in program.cs, and a method that converts the image to a tensor.
Constructor
public ImageClassifier(string modelPath, string labelsPath)
{
var options = new SessionOptions();
options.AppendExecutionProvider_DML(0);
_session = new InferenceSession(modelPath, options);
_classLabels = File.ReadAllLines(labelsPath);
}
The constructor creates an ONNX Runtime inference session for the model, and we tell it via the session options to use the DirectML execution provider with a 0 as the parameter, which specifies the primary GPU as the hardware we want to run it on.
Recommended by LinkedIn
Remember how AI is basically lots of work with numbers? What better hardware to do that with than a GPU, which excels at crunching numbers. (Well, OK, better would be an NPU, a neural processing unit, now in some machines, which is dedicated hardware for this math geekery, but it is not supported in this particular version of the DirectML EP.)
Finally it reads in the list of labels that ResNet50 was trained on that will be used later when we get the result.
Predict function
public string Predict(string imagePath)
{
var inputTensor = PreprocessImage(imagePath);
// Run inference
var inputs = new List<NamedOnnxValue>
{
NamedOnnxValue.CreateFromTensor("image_tensor", inputTensor)
};
using IDisposableReadOnlyCollection<DisposableNamedOnnxValue> results = _session.Run(inputs);
// Get the output and convert it to an array of probabilities
var output = results.First().AsTensor<float>().ToArray();
// Find the index of the maximum probability
int maxIndex = output.ToList().IndexOf(output.Max());
// Map the index to a label
return _classLabels[maxIndex];
}
This is where the magic happens, in three parts:
PreprocessImage function
private DenseTensor<float> PreprocessImage(string imagePath)
{
const int targetWidth = 224;
const int targetHeight = 224;
var tensor = new DenseTensor<float>(new[] { 1, 3, targetHeight, targetWidth });
using var image = Image.Load<Rgb24>(imagePath);
image.Mutate(x => x.Resize(targetWidth, targetHeight));
for (int y = 0; y < targetHeight; y++)
{
for (int x = 0; x < targetWidth; x++)
{
var pixel = image[x, y];
tensor[0, 0, y, x] = pixel.R / 255.0f;
tensor[0, 1, y, x] = pixel.G / 255.0f;
tensor[0, 2, y, x] = pixel.B / 255.0f;
}
}
return tensor;
}
One of the requirements for using the ResNet50 model is that input images need to be 224x224 (yes, that tiny!). This method resizes the input image to that size and then generates a tensor based on the RGB values of each of those pixels.
Tensors have always sounded mysterious and inscrutable, but you can clearly see here it's just the image in numerical form.
There you have it
Let's recap with one more example:
The application:
I'm in that spot you mentioned where you could have used this, very useful!
By the way, if you want a source for models, check out Hugging Face for downloadable models, especially Microsoft's DirectML AI Hub collection, and the GitHub Model Catalog for models you can run in the cloud via Azure AI. https://huggingface.co/microsoft/dml-ai-hub-models https://github.com/marketplace/models The code is available at https://github.com/jonathankhootek/ResnetTest