Maschinelles Lernen in .NET
.NET, Python und KI, Teil 2
Der Artikel „Effizienter Brückenschlag“ aus der dotnetpro-Ausgabe 2/2026 [1] hat bereits im Überblick dargestellt, wie KI-Modelle und Python-Code in .NET-Anwendungen integriert werden können. In diesem Beitrag fokussieren wir vertieft auf den Vergleich der Einsatzmöglichkeiten von ML.NET, Scikit-Learn und ONNX aus Sicht der .NET-Entwickler. Wir zeigen den typischen Workflow und gehen auf Performance, Interoperabilität sowie Werkzeuge ein. Ein einfaches C#-Beispiel demonstriert das Training eines kleinen Modells mit ML.NET und den Export nach ONNX.
ML.NET ist ein Open-Source-Framework für Machine Learning (ML) auf dem .NET-Ökosystem. Es ermöglicht .NET-Entwicklern, Modelle direkt in C# zu trainieren und in .NET-Anwendungen einzusetzen. ML.NET umfasst ein API-Set (NuGet-Pakete), den Visual-Studio-Model Builder und ein CLI-Tool (dotnet-ml). Scikit-Learn ist hingegen eine etablierte Python-Bibliothek für maschinelles Lernen, optimiert für Statistik, Klassifikation, Regression und Clustering. Es stellt aktuelle Algorithmen bereit und ist unter einer BSD-Lizenz veröffentlicht. ONNX (Open Neural Network Exchange) ist weder Bibliothek noch Framework, sondern ein offenes Modellformat zur Repräsentation von ML- und Deep-Learning-Modellen. Durch ONNX können Modelle zwischen verschiedenen Umgebungen ausgetauscht und mit optimierten Laufzeiten (ONNX Runtime) ausgeführt werden. Wichtige Merkmale sind in Tabelle 1 gegenübergestellt.
Tabelle 1: Maschinelles Lernen in .NET umsetzen
| ML.NET | Scikit-Learn | Scikit-Learn | |
| Sprache | C#, .NET | Python | Modell-Format (.onnx), Bindings für C#, Python und andere |
| Typischer Einsatz | ML in .NET-Apps | Forschung, Prototyping, wissenschaftliches Machine Learning | Modell-Austausch und -Inferenz über Framework-Grenzen hinweg |
| Training | Direkt in ML.NET (.NET-Algorithmen)
| Direkt in Python (NumPy/SciPy-Backend) | Nicht selbst für Training – Training in PyTorch/TF et cetera, dann Export ins ONNX-Format |
| Inferenz | In ML.NET-App (CPU/ GPU) oder via ONNX | In Python (Batch-orientiert); eher nicht zielführend für Einzelvorhersagen | Performant durch ONNX Runtime (CPU/GPU) |
| Interoperabilität | Exportierbar nach ONNX; begrenzte direkte Python-Integration | Kann über sklearn-onnx konvertiert werden | Plattformübergreifende Laufzeitumgebung; Modelltausch zwischen ML.NET, Python, C++, Java et cetera (ONNX-Runtime) |
| Ökosystem/Reife | Relativ jung, stark von Microsoft vorangetrieben; wachsend | Sehr reif, weit verbreitet, große Community | Wachsende offene Spezifikation, breite Unterstützung durch Industrie und Community |
| Performance | Nutzt .NET-Parallelisierung, GPU (via ONNX/DirectML) | Gut für mittlere Datenmengen, aber Python-Overhead bei Einzelvorhersage | Optimierte Inferenz (State-of-the-Art-C++-Engine), oft schneller als Scikit-Learn |
Praxis-Workflow: Training, Export, Inferenz
In einer typischen .NET-ML-Pipeline trainiert man zunächst ein Modell (zum Beispiel mit ML.NET oder einer Python-Bibliothek) und exportiert es dann ins ONNX-Format, um es in verschiedenen Umgebungen auszuführen. ONNX ist primär ein Bereitstellungsformat – das eigentliche Training erfolgt in Frameworks wie TensorFlow, PyTorch oder auch ML.NET. Anschließend kann das Modell in .NET via ML.NET oder ONNX Runtime geladen und für Vorhersagen eingesetzt werden. Ein vereinfachter Workflow ist in Bild 1 dargestellt.
Workflow zum Erstellen einer ML-Pipeline: Vom Training bis zur Nutzung in .NET-Apps (Bild 1)
AutorDieser Ablauf entspricht dem häufig empfohlenen Verfahren: Ein Modell wird in der gewählten Umgebung trainiert, dann exportiert, validiert und schließlich in einer Produktivanwendung konsumiert. Zum Beispiel kann ML.NET ein Modell trainieren und speichern. Später lädt man die ONNX-Datei in eine .NET-App und führt die Inferenz durch. Die ONNX-Runtime kann dabei Hardwarebeschleunigung nutzen, das heißt, das Modell kann optimiert werden und auf CPU, GPU oder anderen Beschleunigern ausgeführt werden, ohne das ursprüngliche Trainings-Framework zur Laufzeit zu benötigen.
Beispiel: Modelltraining mit ML.NET und ONNX-Export
Nachfolgend ein minimales C#-Beispiel, welches ein Regressionsmodell auf synthetischen Daten trainiert und dann ins ONNX-Format exportiert.
using Microsoft.ML;
using Microsoft.ML.Data;
using System.IO;
// Trainings- und Vorhersagedaten-Klassen
public class HousingData
{
public float Size;
public float[] HistoricalPrices;
public float CurrentPrice;
}
public class HousingPrediction
{
[ColumnName("Score")]
public float PredictedPrice;
}
var mlContext = new MLContext();
// Beispielhafte Trainingsdaten
var data = new[]
{
new HousingData { Size = 600, HistoricalPrices = new[] {100000f,125000f,122000f}, CurrentPrice = 170000f },
new HousingData { Size = 1000, HistoricalPrices = new[] {200000f,250000f,230000f}, CurrentPrice = 225000f },
new HousingData { Size = 800, HistoricalPrices = new[] {126000f,130000f,200000f}, CurrentPrice = 195000f }
};
var trainingData = mlContext.Data.LoadFromEnumerable(data);
// Pipeline: Features zusammenfügen und trainieren (SDCA-Regression)
var pipeline = mlContext.Transforms.Concatenate("Features", nameof(HousingData.Size), nameof(HousingData.HistoricalPrices))
.Append(mlContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Regression.Trainers.Sdca(labelColumnName: "CurrentPrice", featureColumnName: "Features"));
var model = pipeline.Fit(trainingData);
// Modell lokal speichern (optional)
mlContext.Model.Save(model, trainingData.Schema, "model.zip");
// Modell nach ONNX exportieren
using var fs = File.Create("model.onnx");
mlContext.Model.ConvertToOnnx(model, trainingData, fs);Im Beispiel wird zunächst aus den Properties Size und HistoricalPrices eine Feature-Vektor-Kombination erstellt, normalisiert und ein lineares Regressionsmodell (SDCA) trainiert (Bild 2).
Nutzung der Daten zum Training des Modells (Bild 2)
AutorDer Zusammenhang wird in diesen Fall gut durch eine gerade (lineare Einfachregression) ausgedrückt. Mittels des Modelltrainings werden gute Parameter für die Linie gefunden, welche die Gerade so durch die Datenpunkte legen, dass diese im Durchschnitt einen minimalen Abstand zu diesen aufweist (Bild 3).
Zusammenhang zwischen Wohnfläche (Größe) und Preis bei Wohnhäusern (Bild 3)
AutorLineares Regressionsmodell (SDCA):
Ein lineares Regressionsmodell beschreibt den Zusammenhang zwischen Eingabemerkmalen (Features) und einer Zielgröße durch eine gewichtete Summe. Ziel ist es, die Gewichte so zu bestimmen, dass die Vorhersage möglichst nah an den tatsächlichen Werten liegt. SDCA (Stochastic Dual Coordinate Ascent) ist ein effizientes Optimierungsverfahren, das speziell für große Datensätze geeignet ist. Es passt die Modellparameter iterativ an, indem es zufällig ausgewählte Trainingsbeispiele verarbeitet und so schnell zu einer guten Lösung konvergiert. In ML.NET wird SDCA häufig für Regression und Klassifikation eingesetzt, da es eine gute Balance aus Geschwindigkeit und Genauigkeit bietet.
Für lineare Zusammenhänge gibt es auch die Möglichkeit, die Gerade exakt zu errechnen (Methode der kleinsten Quadrate), was bedeutet, keinen Algorithmus auf der Basis von ML zu nutzen. ML kommt jedoch aufgrund seines „lernenden“ Vorgehens in der Regel auch dann zu einer (guten) Lösung, wenn der Zusammenhang komplexer ist (mehrere Variablen), eine große Anzahl von Datensätze zu verarbeiten sind und der Zusammenhang nicht linear ist.
Zurück zum Quellcode: Anschließend erfolgt mit ConvertToOnnx(...) der Export in eine Datei model.onnx. Diese ONNX-Datei kann dann in einer beliebigen Umgebung mit einem ONNX-fähigen Runner (zum Beispiel ML.NET mittels ApplyOnnxModel oder das eigenständige ONNX-Runtime-NuGet-Paket) geladen und verwendet werden.
Einsatz des ONNX-Modells in .NET
Zum Konsumieren eines ONNX-Modells in einer neuen .NET-Anwendung installiert man das Paket Microsoft.ML.OnnxTransformer und erstellt beispielsweise folgenden Transformer:
var onnxEstimator = mlContext.Transforms.ApplyOnnxModel("model.onnx");
// Das erzeugt einen Inferenz-Estimator, der später gefittet wird:
var onnxTransformer = onnxEstimator.Fit(trainingData);
// Auf neuen Daten kann dann Transform bzw. CreatePredictionEngine angewendet werden.Hier bedeuten:
- Estimator (onnxEstimator) beschreibt, was getan werden soll (hier: ONNX-Modell anwenden).
- Fit(...): initialisiert/erstellt daraus ein lauffähiges Objekt auf Basis der Datenstruktur.
- Transformer (onnxTransformer) ist das fertige Objekt, das tatsächlich Vorhersagen durchführen kann.
Auf diese Weise wird das ONNX-Modell in die ML.NET-Pipeline eingebettet.
Leistung und Interoperabilität
Sehen wir uns wichtige Eigenschaften in diesem Zusammenhang an:
- Performance: ONNX Runtime ist eine optimierte Inferenz-Engine für ML- und DNN-Modelle. Sie führt ONNX-Modelle in nativer Geschwindigkeit aus und nutzt dabei Hardware-Beschleunigung (zum Beispiel CPU-Vektorbefehle, GPU, Tensor Cores) automatisch. Scikit-Learn selbst ist auf Batch-Vorhersagen ausgelegt und weniger für Einzel- beziehungsweise niedrige Latenz optimiert. ML.NET kann dank .NET-Multithreading ebenfalls gute CPU-Leistung bieten; für Deep-Learning-Modelle greift ML.NET intern auf ONNX Runtime zurück, um GPU/CPU-Beschleunigung zu nutzen.
- Interoperabilität: ML.NET-Modelle lassen sich ins ONNX-Format exportieren, um in anderen Sprachen deployt zu werden. Umgekehrt können in Scikit-Learn trainierte Modelle konvertiert und mit ONNX Runtime in .NET geladen werden. ONNX unterstützt zahlreiche Frameworks (Keras, PyTorch, Scikit-Learn et cetera). Das vereinfacht den Austausch: Einmal exportiert, kann ein ONNX-Modell auf Windows-, Linux- oder Embedded-Geräten mit derselben Logik laufen, unabhängig vom originalen Trainings-Framework.
Nicht alle ML.NET-Algorithmen sind vollständig ONNX-kompatibel. Vor dem Export sollte man prüfen, ob der eingesetzte Trainer, zum Beispiel einige Matrix-Faktorisierer oder Meta-Transformer, ONNX unterstützt.
Zusammenfassung
ML.NET bietet .NET-Entwicklern einen vertrauten Weg zu ML, während Scikit-Learn die breite Python-Community bedient. ONNX steht für den datenaustauschübergreifenden Anwendungsfall. Es ermöglicht, Modelle zwischen diesen Welten portabel zu machen. Für .NET-Projekte empfiehlt sich eine hybride Strategie: Trainieren oder Prototyping in Scikit-Learn/Python, Export nach ONNX, dann Einbindung in .NET über ML.NET oder ONNX Runtime für eine performante, plattformübergreifende Inferenz.
[1] Veikko Krypczyk, Effizienter Brückenschlag, dotnetpro 2/2026, Seite 40 ff.