Faça previsões com um modelo AutoML ONNX no .NET

Neste artigo, você aprenderá a usar um modelo ONNX (Open Neural Network Exchange) de ML automatizado (AutoML) para fazer previsões em um aplicativo de console C# .NET Core com ML.NET.

ML.NET é uma estrutura de aprendizado de máquina de código aberto, multiplataforma, para o ecossistema .NET que permite treinar e consumir modelos personalizados de aprendizado de máquina usando uma abordagem code-first em C# ou F#, bem como por meio de ferramentas low-code como o Model Builder e o ML.NET CLI. A estrutura também é extensível e permite que você aproveite outras estruturas populares de aprendizado de máquina, como TensorFlow e ONNX.

ONNX é um formato de código aberto para modelos de IA. O ONNX suporta a interoperabilidade entre frameworks. Isso significa que você pode treinar um modelo em uma das muitas estruturas populares de aprendizado de máquina como o PyTorch, convertê-lo no formato ONNX e consumir o modelo ONNX em uma estrutura diferente, como ML.NET. Para saber mais, visite o site da ONNX.

Pré-requisitos

Criar um aplicativo de console C#

Neste exemplo, você usa a CLI do .NET Core para criar seu aplicativo, mas pode fazer as mesmas tarefas usando o Visual Studio. Saiba mais sobre a CLI do .NET Core.

  1. Abra um terminal e crie um novo aplicativo de console C# .NET Core. Neste exemplo, o nome do aplicativo é AutoMLONNXConsoleApp. Um diretório é criado com esse mesmo nome com o conteúdo do seu aplicativo.

    dotnet new console -o AutoMLONNXConsoleApp
    
  2. No terminal, navegue até o diretório AutoMLONNXConsoleApp .

    cd AutoMLONNXConsoleApp
    

Adicionar pacotes de software

  1. Instale os pacotes NuGet Microsoft.ML, Microsoft.ML.OnnxRuntime e Microsoft.ML.OnnxTransformer usando a CLI do .NET Core.

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

    Esses pacotes contêm as dependências necessárias para usar um modelo ONNX em um aplicativo .NET. ML.NET fornece uma API que usa o tempo de execução ONNX para previsões.

  2. Abra o arquivo Program.cs e adicione as seguintes using instruções na parte superior para fazer referência aos pacotes apropriados.

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

Adicionar uma referência ao modelo ONNX

Uma maneira para o aplicativo de console acessar o modelo ONNX é adicioná-lo ao diretório de saída de compilação. Para saber mais sobre itens comuns do MSBuild, consulte o guia do MSBuild. Se ainda não tiver um modelo, siga este bloco de notas para criar um modelo de exemplo.

Adicione uma referência ao seu arquivo de modelo ONNX em seu aplicativo

  1. Copie seu modelo ONNX para o diretório raiz AutoMLONNXConsoleApp do seu aplicativo.

  2. Abra o arquivo AutoMLONNXConsoleApp.csproj e adicione o seguinte conteúdo dentro do Project nó.

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

    Nesse caso, o nome do arquivo de modelo ONNX é automl-model.onnx.

  3. Abra o arquivo Program.cs e adicione a seguinte linha dentro da Program classe.

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

Inicializar MLContext

Dentro do Main método da sua Program classe, crie uma nova instância do MLContext.

MLContext mlContext = new MLContext();

A MLContext classe é um ponto de partida para todas as operações ML.NET, e a mlContext inicialização cria um novo ambiente de ML.NET que pode ser compartilhado em todo o ciclo de vida do modelo. É semelhante, conceitualmente, ao DbContext no Entity Framework.

Definir o esquema de dados do modelo

Seu modelo espera seus dados de entrada e saída em um formato específico. ML.NET permite-lhe definir o formato dos seus dados através de classes. Às vezes, você já pode saber como é esse formato. Nos casos em que você não sabe o formato de dados, você pode usar ferramentas como Netron para inspecionar seu modelo ONNX.

O modelo usado neste exemplo usa dados do conjunto de dados NYC TLC Taxi Trip. Uma amostra dos dados pode ser vista abaixo:

vendor_id rate_code passenger_count trip_time_in_secs trip_distance payment_type fare_amount
VTS 1 1 1140 3.75 DRFP 15,5
VTS 1 1 480 2.72 DRFP 10,0
VTS 1 1 1680 7.8 CSH 26,5

Inspecione o modelo ONNX (opcional)

Use uma ferramenta como o Netron para inspecionar as entradas e saídas do seu modelo.

  1. Abra o Netron.

  2. Na barra de menu superior, selecione Abrir arquivo > e use o navegador de arquivos para selecionar seu modelo.

  3. O seu modelo abre. Por exemplo, a estrutura do modelo automl-model.onnx tem a seguinte aparência:

    Netron AutoML ONNX Model

  4. Selecione o último nó na parte inferior do gráfico (variable_out1 neste caso) para exibir os metadados do modelo. As entradas e saídas na barra lateral mostram as entradas, saídas e tipos de dados esperados do modelo. Use essas informações para definir o esquema de entrada e saída do seu modelo.

Definir esquema de entrada de modelo

Crie uma nova classe chamada OnnxInput com as seguintes propriedades dentro do arquivo 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; }
}

Cada uma das propriedades é mapeada para uma coluna no conjunto de dados. As propriedades são ainda anotadas com atributos.

O ColumnName atributo permite especificar como ML.NET deve fazer referência à coluna ao operar nos dados. Por exemplo, embora a TripDistance propriedade siga convenções de nomenclatura padrão do .NET, o modelo só conhece uma coluna ou recurso conhecido como trip_distance. Para resolver essa discrepância de nomenclatura, o atributo mapeia ColumnName a TripDistance propriedade para uma coluna ou recurso pelo nome trip_distance.

Para valores numéricos, ML.NET opera apenas em tipos de Single valor. No entanto, o tipo de dados original de algumas das colunas são inteiros. O OnnxMapType atributo mapeia tipos entre ONNX e ML.NET.

Para saber mais sobre atributos de dados, consulte o guia ML.NET carregar dados.

Definir esquema de saída do modelo

Uma vez que os dados são processados, ele produz uma saída de um determinado formato. Defina seu esquema de saída de dados. Crie uma nova classe chamada OnnxOutput com as seguintes propriedades dentro do arquivo Program.cs .

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

Semelhante ao OnnxInput, use o ColumnName atributo para mapear a variable_out1 saída para um nome PredictedFaremais descritivo.

Definir um pipeline de previsão

Um pipeline em ML.NET é normalmente uma série de transformações encadeadas que operam nos dados de entrada para produzir uma saída. Para saber mais sobre transformações de dados, consulte o ML.NET guia de transformação de dados.

  1. Criar um novo método chamado GetPredictionPipeline dentro da Program classe

    static ITransformer GetPredictionPipeline(MLContext mlContext)
    {
    
    }
    
  2. Defina o nome das colunas de entrada e saída. Adicione o seguinte código dentro do GetPredictionPipeline método.

    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. Defina seu pipeline. Um IEstimator fornece um esquema das operações, entrada e saída do seu pipeline.

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

    Nesse caso, é a única transformação no pipeline, que recebe os nomes das colunas de entrada e saída, ApplyOnnxModel bem como o caminho para o arquivo de modelo ONNX.

  4. Um IEstimator define apenas o conjunto de operações a serem aplicadas aos seus dados. O que opera em seus dados é conhecido como ITransformer. Use o Fit método para criar um a partir do seu onnxPredictionPipelinearquivo .

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

    O Fit método espera uma IDataView entrada as para executar as operações. An IDataView é uma maneira de representar dados em ML.NET usando um formato tabular. Como neste caso o pipeline é usado apenas para previsões, você pode fornecer um vazio IDataView para fornecer as informações necessárias do ITransformer esquema de entrada e saída. O encaixe ITransformer é então devolvido para posterior utilização na sua aplicação.

    Gorjeta

    Neste exemplo, o pipeline é definido e usado dentro do mesmo aplicativo. No entanto, é recomendável usar aplicativos separados para definir e usar seu pipeline para fazer previsões. Além ML.NET seus pipelines podem ser serializados e salvos para uso posterior em outros aplicativos de usuário final .NET. ML.NET suporta vários destinos de implantação, como aplicativos de desktop, serviços Web, aplicativos WebAssembly* e muito mais. Para saber mais sobre como salvar pipelines, consulte o guia ML.NET salvar e carregar modelos treinados.

    *WebAssembly só é suportado no .NET Core 5 ou superior

  5. Dentro do Main método, chame o GetPredictionPipeline método com os parâmetros necessários.

    var onnxPredictionPipeline = GetPredictionPipeline(mlContext);
    

Use o modelo para fazer previsões

Agora que você tem um pipeline, é hora de usá-lo para fazer previsões. ML.NET fornece uma API conveniente para fazer previsões em uma única instância de dados chamada PredictionEngine.

  1. Dentro do Main método, crie um PredictionEngine usando o CreatePredictionEngine método.

    var onnxPredictionEngine = mlContext.Model.CreatePredictionEngine<OnnxInput, OnnxOutput>(onnxPredictionPipeline);
    
  2. Crie uma entrada de dados de teste.

    var testInput = new OnnxInput
    {
        VendorId = "CMT",
        RateCode = 1,
        PassengerCount = 1,
        TripTimeInSecs = 1271,
        TripDistance = 3.8f,
        PaymentType = "CRD"
    };
    
  3. Use o para fazer previsões com base nos novos testInput dados usando o predictionEnginePredict método.

    var prediction = onnxPredictionEngine.Predict(testInput);
    
  4. Envie o resultado da sua previsão para o console.

    Console.WriteLine($"Predicted Fare: {prediction.PredictedFare.First()}");
    
  5. Use a CLI do .NET Core para executar seu aplicativo.

    dotnet run
    

    O resultado deve ser semelhante à seguinte saída:

    Predicted Fare: 15.621523
    

Para saber mais sobre como fazer previsões no ML.NET, consulte o guia Usar um modelo para fazer previsões.

Próximos passos