在 .NET 中使用 AutoML ONNX 模型進行預測

在本文中,您將了解如何在 C# .NET Core 主控台應用程式中,使用自動化 ML (AutoML) Open Neural Network Exchange (ONNX) 模型搭配 ML.NET 進行預測。

ML.NET 是 .NET 生態系統的開放原始碼、跨平台機器學習架構,可讓您使用 C# 或 F# 的 Code-First 方法,並透過像是 Model BuilderML.NET CLI 的低程式碼工具,以定型和取用自訂機器學習模型。 此架構也可擴充,可讓您利用其他熱門的機器學習架構,例如 TensorFlow 和 ONNX。

ONNX 是 AI 模型的開放原始碼格式。 ONNX 支援架構間的互通性。 這表示您可以在其中一個熱門的機器學習架構 (例如 PyTorch) 中定型模型、將它轉換成 ONNX 格式,然後在 ML.NET 等不同的架構中取用 ONNX 模型。 若要深入了解,請前往 ONNX 網站

必要條件

建立 C# 主控台應用程式

在此範例中,您使用 .NET Core CLI 來組建應用程式,但也可以使用 Visual Studio 這樣做。 深入了解 .NET Core CLI

  1. 開啟終端,建立新的 C# .NET Core 主控台應用程式。 在此範例中,應用程式的名稱為 AutoMLONNXConsoleApp。 將會以該名稱建立目錄,目錄中有應用程式的內容。

    dotnet new console -o AutoMLONNXConsoleApp
    
  2. 在終端中,瀏覽至 AutoMLONNXConsoleApp 目錄。

    cd AutoMLONNXConsoleApp
    

新增軟體套件

  1. 使用 .NET Core CLI 安裝 Microsoft.MLMicrosoft.ML.OnnxRuntimeMicrosoft.ML.OnnxTransformer NuGet 封裝。

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

    這些封裝中有在 .NET 應用程式中使用 ONNX 模型所需的相依性。 ML.NET 提供一個使用 ONNX 執行階段進行預測的 API。

  2. 開啟 Program.cs 檔案,在頂端加入下列 using 陳述式來參考適當的封裝。

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

新增 ONNX 模型的參考

將 ONNX 模型新增至組建輸出目錄,即可供主控台應用程式存取。 若要深入了解 MSBuild 的一般項目,請參閱 MSBuild 指南。 如果您還沒有模型,請參考此筆記本來建立範例模型。

在應用程式中新增 ONNX 模型檔案的參考

  1. 將 ONNX 模型複製到應用程式的 AutoMLONNXConsoleApp 根目錄。

  2. 開啟 AutoMLONNXConsoleApp.csproj 檔案,在 Project 節點內新增下列內容。

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

    在此案例中,ONNX 模型檔的名稱為 automl-model.onnx

  3. 開啟 Program.cs 檔案,在 Program 類別內新增下列這一行。

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

初始化 MLContext

Program 類別的 Main 方法內,建立 MLContext 的新執行個體。

MLContext mlContext = new MLContext();

MLContext 類別是所有 ML.NET 作業的起點,初始化 mlContext 會建立新的 ML.NET 環境,供整個模型生命週期共用。 在概念上類似於 Entity Framework 中的 DbContext。

定義模型資料結構描述

模型需要特定格式的輸入和輸出資料。 ML.NET 可讓您透過類別來定義資料的格式。 您有時可能已知道該格式的樣子。 如果不知道資料格式,您可以使用 Netron 之類的工具來檢查 ONNX 模型。

此範例所用的模型使用「NYC TLC 計程車車程」資料集的資料。 以下是資料範例:

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

檢查 ONNX 模型 (選擇性)

使用 Netron 之類的工具來檢查模型的輸入和輸出。

  1. 開啟 Netron。

  2. 在頂端功能表列,選取 [檔案] > [開啟],然後使用檔案瀏覽器選取您的模型。

  3. 模型隨即開啟。 例如,automl-model.onnx 模型的結構如下所示:

    Netron AutoML ONNX Model

  4. 選取圖表底部的最後一個節點 (此案例中的 variable_out1),以顯示模型的中繼資料。 提要欄位上的輸入和輸出顯示模型預期的輸入、輸出和資料類型。 使用此資訊來定義模型的輸入和輸出結構描述。

定義模型輸入結構描述

在 Program.cs 檔案內,使用下列屬性建立名為 OnnxInput 的新類別。

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; }
}

每個屬性各對應到資料集的一個資料行。 屬性 (Property) 由屬性 (Attribute) 進一步標註。

ColumnName 屬性可讓您指定 ML.NET 在操作資料時,應該如何參考資料行。 例如,雖然 TripDistance 屬性遵循標準的 .NET 命名慣例,但模型只知道一個稱為 trip_distance 的資料行或功能。 為了解決此命名差異,ColumnName 屬性 (attribute) 將 TripDistance 屬性 (Property) 對應至名為 trip_distance 的資料行或功能。

對於數值,ML.NET 只操作 Single 實值型別。 不過,某些資料行的原始資料類型是整數。 OnnxMapType 屬性會在 ONNX 和 ML.NET 之間對應型別。

若要深入了解資料屬性,請參閱 ML.NET 載入資料指南

定義模型輸出結構描述

處理資料後會產生特定格式的輸出。 定義資料輸出結構描述。 在 Program.cs 檔案內,使用下列屬性建立名為 OnnxOutput 的新類別。

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

類似於 OnnxInput,請使用 ColumnName 屬性,將 variable_out1 輸出對應至更具描述性的名稱 PredictedFare

定義預測管線

ML.NET 中的管線通常是一系列的連鎖轉換,可操作輸入資料來產生輸出。 若要深入了解資料轉換,請參閱 ML.NET 資料轉換指南

  1. Program 類別內建立名為 GetPredictionPipeline 的新方法

    static ITransformer GetPredictionPipeline(MLContext mlContext)
    {
    
    }
    
  2. 定義輸入和輸出資料行的名稱。 將下列程式碼新增至 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. 定義管線。 IEstimator 提供管線的作業、輸入和輸出結構描述的藍圖。

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

    在此案例中,ApplyOnnxModel 是管線中唯一的轉換,接受輸入和輸出資料行的名稱,以及 ONNX 模型檔的路徑。

  4. IEstimator 只定義要套用至資料的一組作業。 真正操作資料的是 ITransformer。 使用 Fit 方法從 onnxPredictionPipeline 建立這一項。

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

    Fit 方法需要 IDataView 作為要操作的輸入。 IDataView 是在 ML.NET 中使用表格式來表示資料的一種方法。 因為在此案例中,管線只用於預測,您可以提供空白 IDataView,為 ITransformer 提供必要的輸入和輸出結構描述資訊。 然後會傳回填好的 ITransformer,供您的應用程式進一步使用。

    提示

    在此範例中,管線是在相同的應用程式中定義和使用。 不過,建議您使用個別的應用程式來定義和使用管線,以進行預測。 在 ML.NET 中可以序列化並儲存管線,以進一步用於其他 .NET 使用者應用程式中。 ML.NET 支援各種部署目標,例如桌面應用程式、Web 服務、WebAssembly 應用程式* 等等。 若要深入了解儲存管線,請參閱 ML.NET 儲存和載入定型的模型指南

    *僅 .NET Core 5 或更新版本才支援 WebAssembly

  5. Main 方法中,使用必要參數來呼叫 GetPredictionPipeline 方法。

    var onnxPredictionPipeline = GetPredictionPipeline(mlContext);
    

使用模型來進行預測

您已有管線,現在可以用來進行預測。 ML.NET 提供一個方便的 API,可在名為 PredictionEngine 的單一資料執行個體上進行預測。

  1. Main 方法中,使用 CreatePredictionEngine 方法建立 PredictionEngine

    var onnxPredictionEngine = mlContext.Model.CreatePredictionEngine<OnnxInput, OnnxOutput>(onnxPredictionPipeline);
    
  2. 建立測試資料輸入。

    var testInput = new OnnxInput
    {
        VendorId = "CMT",
        RateCode = 1,
        PassengerCount = 1,
        TripTimeInSecs = 1271,
        TripDistance = 3.8f,
        PaymentType = "CRD"
    };
    
  3. 使用 predictionEngine,根據新的 testInput 資料,利用 Predict 方法進行預測。

    var prediction = onnxPredictionEngine.Predict(testInput);
    
  4. 將預測結果輸出至主控台。

    Console.WriteLine($"Predicted Fare: {prediction.PredictedFare.First()}");
    
  5. 使用 .NET Core CLI 來執行應用程式。

    dotnet run
    

    結果看起來應該類似下列輸出:

    Predicted Fare: 15.621523
    

若要深入了解在 ML.NET 中進行預測,請參閱使用模型進行預測指南

下一步