Erstellen von Vorhersagen mit einem AutoML-ONNX-Modell in .NET

In diesem Artikel erfahren Sie, wie Sie mithilfe eines AutoML-ONNX-Modells (Open Neural Network Exchange) Vorhersagen in einer C#-Konsolenanwendung mit ML.NET erstellen können.

ML.NET ist ein plattformübergreifendes Open-Source-Framework für maschinelles Lernen für das .NET-Ökosystem, das es Ihnen ermöglicht, benutzerdefinierte Machine Learning-Modelle mithilfe eines Code First-Ansatzes in C# oder F# oder mithilfe von Tools mit wenig Code wie Model Builder und der ML.NET CLI zu trainieren und zu verwenden. Das Framework ist erweiterbar und ermöglicht Ihnen die Nutzung anderer beliebter Frameworks für maschinelles Lernen wie TensorFlow und ONNX.

ONNX ist ein Open-Source-Format für KI-Modelle. ONNX unterstützt die Interoperabilität zwischen Frameworks. Das bedeutet, dass Sie ein Modell in einem der vielen beliebten Frameworks für maschinelles Lernen wie PyTorch trainieren, es in das ONNX-Format konvertieren und das ONNX-Modell in einem anderen Framework wie ML.NET verwenden können. Weitere Informationen finden Sie auf der ONNX-Website.

Voraussetzungen

Erstellen einer C#-Konsolenanwendung

In diesem Beispiel verwenden Sie die .NET-CLI, um Ihre Anwendung zu erstellen, aber Sie können dieselben Aufgaben mithilfe von Visual Studio ausführen. Erfahren Sie mehr über die .NET-CLI.

  1. Öffnen Sie ein Terminal, und erstellen Sie eine neue C#.NET-Konsolenanwendung. In diesem Beispiel lautet der Name der Anwendung AutoMLONNXConsoleApp. Es wird ein gleichnamiges Verzeichnis mit dem Inhalt Ihrer Anwendung erstellt.

    dotnet new console -o AutoMLONNXConsoleApp
    
  2. Navigieren Sie im Terminal zum Verzeichnis AutoMLONNXConsoleApp.

    cd AutoMLONNXConsoleApp
    

Hinzufügen von Softwarepaketen

  1. Installieren Sie die NuGet-Pakete Microsoft.ML, Microsoft.ML.OnnxRuntime und Microsoft.ML.OnnxTransformer mithilfe der .NET-CLI.

    dotnet add package Microsoft.ML
    dotnet add package Microsoft.ML.OnnxRuntime
    dotnet add package Microsoft.ML.OnnxTransformer
    

    Diese Pakete enthalten die Abhängigkeiten, die erforderlich sind, um ein ONNX-Modell in einer .NET-Anwendung zu verwenden. ML.NET stellt eine API bereit, die die ONNX-Runtime für Vorhersagen verwendet.

  2. Öffnen Sie die Datei program.cs, und fügen Sie die folgenden using-Anweisungen ganz oben hinzu.

    using System.Linq;
    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms.Onnx;
    

Hinzufügen eines Verweises auf das ONNX-Modell

Eine Möglichkeit für die Konsolenanwendung für den Zugriff auf das ONNX-Modell besteht darin, das ONNX-Modell zum Buildausgabeverzeichnis hinzuzufügen. Wenn Sie noch kein Modell haben, folgen Sie diesem Notebook, um ein Beispielmodell zu erstellen.

Hinzufügen eines Verweises auf Ihre ONNX-Modelldatei in Ihrer Anwendung:

  1. Kopieren Sie Ihr ONNX-Modell in das Stammverzeichnis AutoMLONNXConsoleApp Ihrer Anwendung.

  2. Öffnen Sie die Datei AutoMLONNXConsoleApp.csproj, und fügen Sie den folgenden Inhalt innerhalb des Knotens Project hinzu.

    <ItemGroup>
        <None Include="automl-model.onnx">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
    </ItemGroup>
    

    In diesem Fall lautet der Name der ONNX-Modelldatei automl-model.onnx.

    (Weitere Informationen zu allgemeinen MSBuild-Elementen finden Sie im MSBuild-Leitfaden.)

  3. Öffnen Sie die Datei Program.cs, und fügen Sie die folgende Zeile innerhalb der Klasse Program ein.

    static string ONNX_MODEL_PATH = "automl-model.onnx";
    

Initialisieren von MLContext

Erstellen Sie innerhalb der Main-Methode Ihrer Program-Klasse eine neue Instanz von MLContext.

MLContext mlContext = new MLContext();

Die Klasse MLContext ist ein Startpunkt für alle ML.NET-Vorgänge, und die Initialisierung von mlContext erstellt eine neue ML.NET-Umgebung, die während des gesamten Modelllebenszyklus gemeinsam genutzt werden kann. Die Klasse ähnelt dem Konzept von DbContext in Entity Framework.

Definieren des Modelldatenschemas

Ein Modell erwartet die Eingabe- und Ausgabedaten in einem bestimmten Format. ML.NET ermöglicht es Ihnen, das Format Ihrer Daten über Klassen zu definieren. Manchmal wissen Sie möglicherweise schon, wie dieses Format aussieht. In Fällen, in denen Sie das Datenformat nicht kennen, können Sie Tools wie Netron verwenden, um das ONNX-Modell zu untersuchen.

Das in diesem Beispiel verwendete Modell verwendet Daten aus dem Dataset für NYC TLC-Taxifahrten. Ein Beispiel für die Daten ist in der folgenden Tabelle dargestellt:

vendor_id rate_code passenger_count trip_time_in_secs trip_distance payment_type fare_amount
VTS 1 1 1140 3,75 CRD 15,5
VTS 1 1 480 2.72 CRD 10.0
VTS 1 1 1680 7,8 CSH 26,5

Untersuchen des ONNX-Modells (optional)

Verwenden Sie ein Tool wie Netron, um die Ein- und Ausgaben Ihres Modells zu untersuchen.

  1. Öffnen Sie Netron.

  2. Wählen Sie auf der oberen Menüleiste Datei > Öffnen aus, und verwenden Sie den Dateibrowser, um Ihr Modell auszuwählen.

  3. Ihr Modell wird geöffnet. Die Struktur des Modells automl-model.onnx sieht z. B. wie folgt aus:

    Netron AutoML-ONNX-Modell

  4. Wählen Sie den letzten Knoten am unteren Rand des Graphen aus (in diesem Fall variable_out1), um die Metadaten des Modells anzuzeigen. Die Ein- und Ausgaben auf der Randleiste zeigen Ihnen die erwarteten Eingaben, Ausgaben und Datentypen des Modells. Verwenden Sie diese Informationen, um das Ein- und Ausgabeschema Ihres Modells zu definieren.

Definieren des Modelleingabeschemas

Erstellen Sie eine neue Klasse namens OnnxInput mit den folgenden Eigenschaften innerhalb der Datei Program.cs.

public class OnnxInput
{
    [ColumnName("vendor_id")]
    public string VendorId { get; set; }

    [ColumnName("rate_code"),OnnxMapType(typeof(Int64),typeof(Single))]
    public Int64 RateCode { get; set; }

    [ColumnName("passenger_count"), OnnxMapType(typeof(Int64), typeof(Single))]
    public Int64 PassengerCount { get; set; }

    [ColumnName("trip_time_in_secs"), OnnxMapType(typeof(Int64), typeof(Single))]
    public Int64 TripTimeInSecs { get; set; }

    [ColumnName("trip_distance")]
    public float TripDistance { get; set; }

    [ColumnName("payment_type")]
    public string PaymentType { get; set; }
}

Jede der Eigenschaften wird einer Spalte im Dataset zugeordnet. Die Eigenschaften werden zudem mit Attributen versehen.

Mit dem ColumnName-Attribut können Sie angeben, wie ML.NET auf die Spalte verweisen soll, wenn mit den Daten gearbeitet wird. Obwohl die Eigenschaft TripDistance z. B. den standardmäßigen .NET-Namenskonventionen folgt, kennt das Modell nur eine Spalte oder ein Feature, die bzw. das als trip_distance bekannt ist. Um diese Diskrepanz bei der Benennung zu beheben, ordnet das ColumnName-Attribut die Eigenschaft TripDistance zu einer Spalte oder zu einem Feature namens trip_distance zu.

Bei numerischen Werten arbeitet ML.NET nur mit Single-Werttypen. Der ursprüngliche Datentyp einiger der Spalten sind jedoch ganze Zahlen. Das OnnxMapType-Attribut ordnet Typen zwischen ONNX und ML.NET zu.

Weitere Informationen zu Datenattributen finden Sie im ML.NET-Leitfaden zum Laden von Daten.

Definieren des Modellausgabeschemas

Nachdem die Daten verarbeitet wurden, erzeugen sie eine Ausgabe in einem bestimmten Format. Definieren Sie Ihr Datenausgabeschema. Erstellen Sie eine neue Klasse namens OnnxOutput mit den folgenden Eigenschaften innerhalb der Datei Program.cs.

public class OnnxOutput
{
    [ColumnName("variable_out1")]
    public float[] PredictedFare { get; set; }
}

Ähnlich wie bei OnnxInput verwenden Sie das Attribut ColumnName, um die Ausgabe variable_out1 einem beschreibenderen PredictedFare-Namen zuzuordnen.

Definieren einer Vorhersagepipeline

Eine Pipeline in ML.NET ist typischerweise eine Reihe von verketteten Transformationen, die mit den Eingabedaten arbeiten, um eine Ausgabe zu erzeugen. Weitere Informationen zu Datentransformationen finden Sie im ML.NET-Leitfaden zur Datentransformation.

  1. Erstellen einer neuen Methode namens GetPredictionPipeline innerhalb der Klasse Program

    static ITransformer GetPredictionPipeline(MLContext mlContext)
    {
    
    }
    
  2. Definieren Sie den Namen der Ein- und Ausgabespalten. Fügen Sie der GetPredictionPipeline-Methode den folgenden Code hinzu.

    var inputColumns = new string []
    {
        "vendor_id", "rate_code", "passenger_count", "trip_time_in_secs", "trip_distance", "payment_type"
    };
    
    var outputColumns = new string [] { "variable_out1" };
    
  3. Definieren Sie Ihre Pipeline. Ein IEstimator bietet eine Blaupause der Vorgänge sowie die Ein- und Ausgabeschemas Ihrer Pipeline.

    var onnxPredictionPipeline =
        mlContext
            .Transforms
            .ApplyOnnxModel(
                outputColumnNames: outputColumns,
                inputColumnNames: inputColumns,
                ONNX_MODEL_PATH);
    

    In diesem Fall ist ApplyOnnxModel die einzige Transformation in der Pipeline, die die Namen der Ein- und Ausgabespalten sowie den Pfad zur ONNX-Modelldatei übernimmt.

  4. Ein IEstimator definiert nur den Satz von Vorgängen, der auf Ihre Daten angewendet werden soll. Was mit Ihren Daten arbeitet, wird als ITransformer bezeichnet. Verwenden Sie die Fit-Methode, um eine aus Ihrer onnxPredictionPipeline zu erstellen.

    var emptyDv = mlContext.Data.LoadFromEnumerable(new OnnxInput[] {});
    
    return onnxPredictionPipeline.Fit(emptyDv);
    

    Die Fit-Methode erwartet ein IDataView als Eingabe, um die Vorgänge für auszuführen. Ein IDataView ist eine Möglichkeit, Daten in ML.NET mithilfe eines Tabellenformats darzustellen. Da in diesem Fall die Pipeline nur für Vorhersagen verwendet wird, können Sie ein leeres IDataView bereitstellen, um dem ITransformer die erforderlichen Informationen zum Ein- und Ausgabeschema zu geben. Das angepasste ITransformer wird dann zur weiteren Verwendung in Ihrer Anwendung zurückgegeben.

    Tipp

    In diesem Beispiel wird die Pipeline innerhalb derselben Anwendung definiert und verwendet. Es wird jedoch empfohlen, dass Sie separate Anwendungen zur Definition und Verwendung Ihrer Pipeline für Vorhersagen verwenden. In ML.NET können Ihre Pipelines serialisiert und zur weiteren Verwendung in anderen .NET-Endbenutzeranwendungen gespeichert werden. ML.NET unterstützt verschiedene Bereitstellungsziele wie Desktopanwendungen, Webdienste, WebAssembly-Anwendungen und viele andere. Weitere Informationen zum Speichern von Pipelines finden Sie im ML.NET-Leitfaden zum Speichern und Laden von trainierten Modellen.

  5. Rufen Sie innerhalb der Main-Methode die GetPredictionPipeline-Methode mit den erforderlichen Parametern auf.

    var onnxPredictionPipeline = GetPredictionPipeline(mlContext);
    

Verwenden des Modells für Vorhersagen

Nachdem Sie jetzt über eine Pipeline verfügen, ist es an der Zeit, diese für Vorhersagen zu verwenden. ML.NET stellt eine praktische API für die Erstellung von Vorhersagen für eine einzelne Dateninstanz namens PredictionEngine zur Verfügung.

  1. Erstellen Sie innerhalb der Main-Methode eine PredictionEngine mithilfe der CreatePredictionEngine-Methode.

    var onnxPredictionEngine = mlContext.Model.CreatePredictionEngine<OnnxInput, OnnxOutput>(onnxPredictionPipeline);
    
  2. Erstellen Sie eine Testdateneingabe.

    var testInput = new OnnxInput
    {
        VendorId = "CMT",
        RateCode = 1,
        PassengerCount = 1,
        TripTimeInSecs = 1271,
        TripDistance = 3.8f,
        PaymentType = "CRD"
    };
    
  3. Verwenden Sie die predictionEngine, um Vorhersagen auf der Grundlage der neuen testInput-Daten mithilfe der Predict-Methode zu treffen.

    var prediction = onnxPredictionEngine.Predict(testInput);
    
  4. Geben Sie das Ergebnis Ihrer Vorhersage in der Konsole aus.

    Console.WriteLine($"Predicted Fare: {prediction.PredictedFare.First()}");
    
  5. Verwenden Sie die .NET-CLI zur Ausführung Ihrer Anwendung.

    dotnet run
    

    Das Ergebnis sollte so ähnlich wie die folgende Ausgabe aussehen:

    Predicted Fare: 15.621523
    

Weitere Informationen zur Erstellung von Vorhersagen in ML.NET finden Sie unter Verwenden eines Modells für Vorhersagen.

Nächste Schritte