Eseguire stime con un modello ONNX AutoML in .NET

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

ML.NET è un framework open source multipiattaforma e multipiattaforma per l'ecosistema .NET che consente di eseguire il training e l'uso di modelli di Machine Learning personalizzati usando un approccio code-first in C# o F# e 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 più 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 usare 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 l'interfaccia della riga di comando di .NET Core per compilare l'applicazione, ma è possibile eseguire le stesse attività usando Visual Studio. Altre informazioni sull'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. Una directory viene creata 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 pacchetti NuGet Microsoft.ML, Microsoft.ML.OnnxRuntime e Microsoft.ML.OnnxTransformer usando l'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 fornisce un'API che usa il runtime ONNX per le stime.

  2. Aprire il file Program.cs e aggiungere le istruzioni seguenti using nella parte 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 consentire all'applicazione console di accedere al modello ONNX consiste nell'aggiungerlo alla directory di output di compilazione. Per altre informazioni sugli elementi comuni di MSBuild, vedere la guida a MSBuild. Se non si ha già un modello, seguire questo notebook per creare un modello di esempio.

Aggiungere un riferimento al file del 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 del 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

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

MLContext mlContext = new MLContext();

La MLContext classe è un punto di partenza per tutte le operazioni ML.NET e l'inizializzazione mlContext crea un nuovo ambiente ML.NET che può essere condiviso nel ciclo di vita del modello. È simile, concettualmente, 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 potresti già sapere che aspetto ha questo formato. Nei casi in cui non si conosce il formato dei dati, è possibile usare strumenti come Netron per controllare 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 di 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 in alto selezionare File > Apri e usare il browser file per selezionare il modello.

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

    Netron AutoML ONNX Model

  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.

L'attributo ColumnName consente di specificare come ML.NET deve fare riferimento alla colonna quando si opera sui dati. Ad esempio, anche se la TripDistance proprietà segue convenzioni di 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 ColumnName mapping della TripDistance proprietà a una colonna o a una funzionalità in base al nome trip_distance.

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

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

Definire lo schema di output del modello

Una volta elaborati i dati, genera 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 l'attributo per eseguire il ColumnName mapping dell'output variable_out1 a un nome PredictedFarepiù descrittivo.

Definire una pipeline di stima

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

  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 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. Un oggetto IEstimator fornisce un progetto di operazioni, input e schemi di output della pipeline.

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

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

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

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

    Il Fit metodo prevede che un oggetto IDataView come input esegua le 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 valore vuoto IDataView per fornire le ITransformer informazioni necessarie sullo schema di input e output. L'oggetto montato viene quindi restituito ITransformer 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 uso aggiuntivo in altre applicazioni degli utenti finali .NET. ML.NET supporta diverse destinazioni di distribuzione, ad esempio applicazioni desktop, servizi Web, applicazioni WebAssembly* e molti altri ancora. Per altre informazioni sul salvataggio delle pipeline, vedere la guida ML.NET salvare e caricare i modelli sottoposti a training.

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

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

    var onnxPredictionPipeline = GetPredictionPipeline(mlContext);
    

Usare il modello per effettuare previsioni

Ora che si dispone di una pipeline, è possibile usarla per eseguire stime. ML.NET fornisce un'API utile per eseguire stime su una singola istanza di dati denominata PredictionEngine.

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

    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. predictionEngine Usare per eseguire stime in base ai nuovi testInput dati usando il Predict metodo .

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

    Console.WriteLine($"Predicted Fare: {prediction.PredictedFare.First()}");
    
  5. Usare l'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 sull'uso di un modello per eseguire stime.

Passaggi successivi