Eseguire stime con un modello ONNX AutoML in .NET

Questo articolo illustra come usare un modello ONNX (Automated ML) Open Neural Network Exchange (ONNX) per eseguire stime in un'applicazione console .NET Core C# con ML.NET.

ML.NET è un framework di Machine Learning open source multipiattaforma per l'ecosistema .NET che consente di eseguire il training e l'utilizzo di modelli di Machine Learning personalizzati usando un approccio code-first in C# o F# e tramite strumenti a basso codice come Model Builder e l'interfaccia della riga di comando di ML.NET. Il framework è anche estendibile e consente di sfruttare altri framework di Machine Learning diffusi, ad esempio TensorFlow e ONNX.

ONNX è un formato open source per i modelli di intelligenza artificiale. ONNX supporta l'interoperabilità tra framework. Ciò significa che è possibile eseguire il training di un modello in uno dei numerosi framework di Machine Learning più diffusi, ad esempio PyTorch, convertirlo in formato ONNX e utilizzare il modello ONNX in un framework diverso, ad esempio ML.NET. Per altre informazioni, vedere il sito Web ONNX.

Prerequisiti

Creare un'applicazione console C#

In questo esempio si usa il interfaccia della riga di comando di .NET Core per compilare l'applicazione, ma è possibile eseguire le stesse attività usando Visual Studio. Altre informazioni sul interfaccia della riga di comando di .NET Core.

  1. Aprire un terminale e creare una nuova applicazione console C# .NET Core. In questo esempio il nome dell'applicazione è AutoMLONNXConsoleApp . Viene creata una directory con lo stesso nome con il contenuto dell'applicazione.

    dotnet new console -o AutoMLONNXConsoleApp
    
  2. Nel terminale passare alla directory AutoMLONNXConsoleApp.

    cd AutoMLONNXConsoleApp
    

Aggiungere pacchetti software

  1. Installare i Microsoft.ML NuGet , Microsoft.ML.OnnxRuntime e Microsoft.ML.OnnxTransformer usando il interfaccia della riga di comando di .NET Core.

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

    Questi pacchetti contengono le dipendenze necessarie per usare un modello ONNX in un'applicazione .NET. ML.NET un'API che usa il runtime ONNX per le stime.

  2. Aprire il file Program.cs e aggiungere le istruzioni seguenti nella parte using superiore per fare riferimento ai pacchetti appropriati.

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

Aggiungere un riferimento al modello ONNX

Un modo per l'applicazione console per accedere al modello ONNX è aggiungerlo alla directory di output della compilazione. Per altre informazioni sugli elementi comuni di MSBuild, vedere la guida di MSBuild.

Aggiungere un riferimento al file di modello ONNX nell'applicazione

  1. Copiare il modello ONNX nella directory radice AutoMLONNXConsoleApp dell'applicazione.

  2. Aprire il file AutoMLONNXConsoleApp.csproj e aggiungere il contenuto seguente all'interno del Project nodo.

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

    In questo caso, il nome del file di modello ONNX è automl-model.onnx.

  3. Aprire il file Program.cs e aggiungere la riga seguente all'interno della Program classe .

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

Inizializzare MLContext

MainAll'interno del metodo della classe creare una nuova istanza di Program MLContext .

MLContext mlContext = new MLContext();

La classe è un punto di partenza per tutte le ML.NET e l'inizializzazione crea un nuovo ambiente ML.NET che può essere condiviso nel ciclo di vita MLContext mlContext del modello. Concettualmente è simile a DbContext in Entity Framework.

Definire lo schema dei dati del modello

Il modello prevede un formato specifico per i dati di input e output. ML.NET consente di definire il formato dei dati tramite classi. A volte è già possibile conoscere l'aspetto di tale formato. Nei casi in cui non si conosce il formato dei dati, è possibile usare strumenti come Netron per ispezionare il modello ONNX.

Il modello usato in questo esempio usa i dati del set di dati NYC TLC Taxi Trip. Di seguito è riportato un esempio dei dati:

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

Esaminare il modello ONNX (facoltativo)

Usare uno strumento come Netron per esaminare gli input e gli output del modello.

  1. Aprire Netron.

  2. Nella barra dei menu superiore selezionare File > Apri e usare il browser dei file per selezionare il modello.

  3. Verrà aperto il modello. Ad esempio, la struttura del modello automl-model.onnx è simile alla seguente:

    Modello ONNX Netron AutoML

  4. Selezionare l'ultimo nodo nella parte inferiore del grafico ( variable_out1 in questo caso) per visualizzare i metadati del modello. Gli input e gli output sulla barra laterale mostrano gli input, gli output e i tipi di dati previsti del modello. Usare queste informazioni per definire lo schema di input e output del modello.

Definire lo schema di input del modello

Creare una nuova classe denominata OnnxInput con le proprietà seguenti all'interno del file 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; }
}

Ognuna delle proprietà esegue il mapping a una colonna nel set di dati. Le proprietà vengono ulteriormente annotate con attributi.

ColumnNameL'attributo consente di specificare ML.NET deve fare riferimento alla colonna quando si opera sui dati. Ad esempio, anche se la proprietà segue le convenzioni di TripDistance denominazione .NET standard, il modello conosce solo una colonna o una funzionalità nota come trip_distance . Per risolvere questa discrepanza di denominazione, l'attributo esegue il mapping della proprietà ColumnName a una colonna o a una funzionalità con il nome TripDistance trip_distance .

Per i valori numerici, ML.NET opera solo sui Single tipi di valore. Tuttavia, il tipo di dati originale di alcune colonne è integer. OnnxMapTypeL'attributo esegue il mapping dei tipi tra ONNX e ML.NET.

Per altre informazioni sugli attributi dei dati, vedere la guida ML.NET caricamento dati.

Definire lo schema di output del modello

Dopo l'elaborazione, i dati producono un output di un determinato formato. Definire lo schema di output dei dati. Creare una nuova classe denominata OnnxOutput con le proprietà seguenti all'interno del file Program.cs.

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

Analogamente a OnnxInput , usare ColumnName l'attributo per eseguire il mapping variable_out1 dell'output a un nome più PredictedFare descrittivo.

Definire una pipeline di stima

Una pipeline in ML.NET è in genere una serie di trasformazioni concatenate che operano sui dati di input per produrre un output. Per altre informazioni sulle trasformazioni dei dati, vedere la guida ML.NET di trasformazione dei dati.

  1. Creare un nuovo metodo denominato GetPredictionPipeline all'interno della Program classe

    static ITransformer GetPredictionPipeline(MLContext mlContext)
    {
    
    }
    
  2. Definire il nome delle colonne di input e di output. Aggiungere il codice seguente all'interno del metodo GetPredictionPipeline.

    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. Definire la pipeline. Fornisce un progetto delle operazioni, degli schemi di input e IEstimator di output della pipeline.

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

    In questo caso, è l'unica trasformazione nella pipeline, che accetta i nomi delle colonne di input e di output, nonché il percorso del file di modello ApplyOnnxModel ONNX.

  4. Un IEstimator oggetto definisce solo il set di operazioni da applicare ai dati. Ciò che opera sui dati è noto come ITransformer . Usare il Fit metodo per crearne uno da onnxPredictionPipeline .

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

    Il Fit metodo prevede un oggetto come input su cui eseguire le IDataView operazioni. Un IDataView è un modo per rappresentare i dati in ML.NET usando un formato tabulare. Poiché in questo caso la pipeline viene usata solo per le stime, è possibile fornire un vuoto per fornire le IDataView informazioni necessarie sullo schema di input e ITransformer output. L'oggetto ITransformer adattato viene quindi restituito per un ulteriore uso nell'applicazione.

    Suggerimento

    In questo esempio la pipeline viene definita e usata all'interno della stessa applicazione. È tuttavia consigliabile usare applicazioni separate per definire e usare la pipeline per eseguire stime. In ML.NET le pipeline possono essere serializzate e salvate per un ulteriore uso in altre applicazioni dell'utente finale .NET. ML.NET supporta varie destinazioni di distribuzione, ad esempio applicazioni desktop, servizi Web, applicazioni WebAssembly* e molte altre. Per altre informazioni sul salvataggio delle pipeline, vedere la guida salvare ML.NET e caricare modelli con training.

    *WebAssembly è supportato solo in .NET Core 5 o versione successiva

  5. MainAll'interno del metodo chiamare il metodo con i parametri GetPredictionPipeline obbligatori.

    var onnxPredictionPipeline = GetPredictionPipeline(mlContext);
    

Usare il modello per effettuare previsioni

Ora che è disponibile una pipeline, è possibile usarla per eseguire stime. ML.NET un'API per l'esecuzione di stime su una singola istanza di dati denominata PredictionEngine .

  1. MainAll'interno del metodo creare un oggetto usando il metodo PredictionEngine CreatePredictionEngine .

    var onnxPredictionEngine = mlContext.Model.CreatePredictionEngine<OnnxInput, OnnxOutput>(onnxPredictionPipeline);
    
  2. Creare un input di dati di test.

    var testInput = new OnnxInput
    {
        VendorId = "CMT",
        RateCode = 1,
        PassengerCount = 1,
        TripTimeInSecs = 1271,
        TripDistance = 3.8f,
        PaymentType = "CRD"
    };
    
  3. Utilizzare predictionEngine l'oggetto per eseguire stime basate sui nuovi testInput dati utilizzando il metodo Predict .

    var prediction = onnxPredictionEngine.Predict(testInput);
    
  4. Visualizzare il risultato della stima nella console.

    Console.WriteLine($"Predicted Fare: {prediction.PredictedFare.First()}");
    
  5. Usare il interfaccia della riga di comando di .NET Core per eseguire l'applicazione.

    dotnet run
    

    Il risultato dovrebbe essere simile all'output seguente:

    Predicted Fare: 15.621523
    

Per altre informazioni sull'esecuzione di stime in ML.NET, vedere la guida Usare un modello per eseguire stime.

Passaggi successivi