Skip to content

PhasonMatrix/CSnakesFlowerClassifier

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CSnakes Flower Classifier

Demo project to show integration of Python Machine Learning functionality in a C# desktop application.

This is a flower image classifier with five classes, trained on the Kaggle data set which you can download yourself if you want to try running the training. You can also modify this code to work for any image classification experiments you might want to try.

The Classifier model is a standard Convolutional Neural Network. This is not intended to demonstrate a good or accurate solution, just the ability to run Python ML in C#. The model tends to over-fit on this data set. Go ahead and use this project as a basis for experimenting with different model architectures, hyper-parameter tuning or other data sets.

Inference

Inference screenshot

Training

Training screenshot

Technologies, Frameworks and Libraries

  • 🐍 CSnakes - Python environment integrated into a C# project
  • 💻 Avalonia UI - Cross-platform UI Framework for .NET
  • 🔥 PyTorch - Machine Learning, Artificial Neural Networks
  • 🖼️ SkiaSharp - .NET wrapper for the Skia image library
  • 📈 LiveCharts2 - Data visualisation

C# <--> Python data passing

Simple/Primitive variables

In the UnitTest project you can find some code in CommunicationTests.cs and py_communication_test.py that demonstrates passing string and integers between C# and Python. For more info on conversion of data types between languages see the CSnakes User Guide.

Strings:

def greetings(name: str) -> str:
    return f"Hello, {name}!"
string name = "Fred";
var pyCommunicationTestModule = _env.PyCommunicationTest();
string greetingResult = pyCommunicationTestModule.Greetings(name);
Assert.Equal("Hello, Fred!", greetingResult);

Integers:

def add(a: int, b: int) -> int:
    return a + b
long a = 5;
long b = 7;
var pyCommunicationTestModule = _env.PyCommunicationTest();
long addResult = pyCommunicationTestModule.Add(a, b);
Assert.Equal(12, addResult);

Large data with bytes

For large amounts of data like image pixels it can be very slow to use Python types like list[int] and list[float]. It is faster and more efficient to use bytes. You can also use the Buffer Protocol when working with NumPy arrays. For more info see the CSnakes User Guide

def pass_bytes(data: bytes) -> bytes:
    # do something to the bytes. increment each byte by 1
    result_byte_array = bytearray(len(data))
    for i in range(len(data)):
        result_byte_array[i] = data[i] + 1

    return bytes(result_byte_array)
byte[] data = new byte[] { 1, 2, 3, 4, 5 };
var pyCommunicationTestModule = _env.PyCommunicationTest();
byte[] result = pyCommunicationTestModule.PassBytes(data);
Assert.Equal(new byte[] { 2, 3, 4, 5, 6 }, result);

Log streaming

Data can be streamed back to the C# caller while Python is performing a long-running function. This is achieved using a Python Generator

def train_and_save(training_data_dir:str, model_file_name:str) -> Generator[str, int, bool]:
    ... long-running process
    # use yield keyword to send value back to caller
    yield f"Epoch: {epoch+1} of {epochs}"
IGeneratorIterator<string, long, bool> messageGenerator = train.TrainAndSave(trainingDataDir, modelFileName);
foreach (string message in messageGenerator)
{
    Debug.WriteLine($"{DateTime.Now} : {message}");
    _env.Logger?.LogInformation(message);
}

Running

Things you need to know before you start.

  1. First time run will be SLOW. The Python interpreter is not included in this source code. The CSnakes library will automatically download and install Python 3.12 on the first run, set up a virtual environment and PIP install packages listed in requirements.txt. Yes, at run-time, not build-time. Be patient, the application may look like it has hung.
var builder = Host.CreateApplicationBuilder(Array.Empty<string>());
builder.Services
        .WithPython()
        .WithHome(pythonHomePath)
        .FromRedistributable(RedistributablePythonVersion.Python3_12)  // downloads Python interpreter
        .WithVirtualEnvironment(Path.Combine(pythonHomePath, ".venv")) // creates a virtual environment
        .WithPipInstaller();                                           // pip install -r requirements.txt
  1. Note that the line of code that saves the trained model is commented out. Uncomment it when you're ready to save for real.
    # save the trained model
    #torch.save(model.state_dict(), model_save_path) # TODO: uncomment this line to save the model
  1. Requirements
  • Cross-platform. Developed and tested on Windows but should work on Linux and Mac.
  • .NET 9.0 SDK.
  • Supports GPU Inference and Training, but assumes you have CUDA 12.9 installed. Will automatically fall back to CPU if you don't.

About

Demo - Python ML in C# project

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published