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

Neste artigo, aprende-se a utilizar um modelo de ML Automatizado (AutoML) Open Neural Network Exchange (ONNX) para fazer previsões numa aplicação de consola C# .NET Core com ML.NET.

ML.NET é um quadro de aprendizagem automática de código aberto, transversal para o ecossistema .NET que permite treinar e consumir modelos de aprendizagem automática personalizados utilizando uma abordagem de código em C# ou F# bem como através de ferramentas de baixo código como Model Builder e o ML.NET CLI. A estrutura também é extensível e permite-lhe alavancar outros quadros populares de aprendizagem automática como o TensorFlow e o ONNX.

O ONNX é um formato de código aberto para modelos de IA. A ONNX suporta a interoperabilidade entre quadros. Isto significa que você pode treinar um modelo em um dos muitos quadros populares de aprendizagem automática como PyTorch, convertê-lo em formato ONNX, e consumir o modelo ONNX em um quadro diferente como ML.NET. Para saber mais, visite o site da ONNX.

Pré-requisitos

Criar uma aplicação de consola C#

Nesta amostra, utiliza o CLI .NET Core para construir a sua aplicação, mas pode fazer as mesmas tarefas utilizando Visual Studio. Saiba mais sobre o CLI .NET Core.

  1. Abra um terminal e crie uma nova aplicação de consola C# .NET Core. Neste exemplo, o nome da aplicação é AutoMLONNXConsoleApp. Um diretório é criado com o mesmo nome com o conteúdo da sua aplicação.

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

    cd AutoMLONNXConsoleApp
    

Adicionar pacotes de software

  1. Instale o Microsoft.ML, Microsoft.ML. OnnxRuntime e Microsoft.ML. Pacotes NuGet OnnxTransformer utilizando o CLI .NET Core.

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

    Estas embalagens contêm as dependências necessárias para utilizar um modelo ONNX numa aplicação .NET. ML.NET fornece uma API que utiliza o tempo de execução ONNX para previsões.

  2. Abra o ficheiro .cs Programa e adicione as seguintes using declarações no topo para fazer referência aos pacotes apropriados.

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

Adicione uma referência ao modelo ONNX

Uma forma de a aplicação da consola aceder ao modelo ONNX é adicioná-la ao diretório de saída de construção. Para saber mais sobre os itens comuns da MSBuild, consulte o guia MSBuild.

Adicione uma referência ao seu ficheiro modelo ONNX na sua aplicação

  1. Copie o seu modelo ONNX para o diretório de raiz autoMLONNXConsoleApp da sua aplicação.

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

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

    Neste caso, o nome do ficheiro modelo ONNX é automl-model.onnx.

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

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

Inicializar O Texto MLContexto

Dentro do Main método da sua Program classe, crie um novo exemplo de MLContext.

MLContext mlContext = new MLContext();

A MLContext classe é um ponto de partida para todas as operações ML.NET, e a inicialização mlContext cria um novo ambiente ML.NET que pode ser partilhado através do ciclo de vida do modelo. É semelhante, conceptualmente, ao DbContext no Quadro de Entidades.

Definir o esquema de dados do modelo

O seu modelo espera os seus dados de entrada e saída num formato específico. ML.NET permite definir o formato dos seus dados através das aulas. Às vezes já se sabe como é o formato. Nos casos em que não conhece o formato de dados, pode utilizar ferramentas como a Netron para inspecionar o seu modelo ONNX.

O modelo utilizado nesta amostra utiliza dados do conjunto de dados da 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 CRD 15,5
VTS 1 1 480 2.72 CRD 10,0
VTS 1 1 1680 7.8 CSH 26,5

Inspecione o modelo ONNX (opcional)

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

  1. Abre o Netron.

  2. Na barra de menu superior, selecione File > Open e use o navegador de ficheiros para selecionar o seu modelo.

  3. O teu modelo abre. Por exemplo, a estrutura do modelo automl.onnx parece o seguinte:

    Netron AutoML ONNX Model

  4. Selecione o último nó na parte inferior do gráfico (variable_out1 neste caso) para visualizar os metadados do modelo. As entradas e saídas na barra lateral mostram-lhe as entradas, saídas e tipos de dados esperados do modelo. Utilize estas 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 ficheiro .cs Programa .

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 mapeia para uma coluna no conjunto de dados. As propriedades são anotadas com atributos.

O ColumnName atributo permite especificar como ML.NET deve referenciar a coluna ao operar nos dados. Por exemplo, embora a TripDistance propriedade siga as convenções de nomeação padrão .NET, o modelo só sabe de uma coluna ou característica conhecida como trip_distance. Para resolver esta discrepância de nomeação, o ColumnName atributo mapeia a TripDistance propriedade a uma coluna ou característica pelo nome trip_distance.

Para valores numéricos, ML.NET funciona apenas em Single tipos de valor. No entanto, o tipo de dados original de algumas das colunas são inteiros. Os OnnxMapType tipos de mapas de atributos entre ONNX e ML.NET.

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

Definir esquema de saída de modelo

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

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

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

Defina um oleoduto de previsão

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

  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 o seu oleoduto. Um IEstimator fornece uma planta das operações, entradas e esquemas de saída do seu oleoduto.

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

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

  4. Um IEstimator apenas define o conjunto de operações a aplicar aos seus dados. O que opera nos seus dados é conhecido como ITransformer. Utilize o Fit método para criar um a partir do seu onnxPredictionPipeline.

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

    O Fit método espera uma IDataView entrada como entrada para realizar as operações. Uma IDataView é uma forma de representar dados em ML.NET utilizando um formato tabular. Dado que neste caso o gasoduto é utilizado apenas para previsões, pode fornecer um vazio IDataView para dar a informação necessária de ITransformer entrada e esquema de saída. O equipado ITransformer é então devolvido para posterior utilização na sua aplicação.

    Dica

    Nesta amostra, o gasoduto é definido e utilizado dentro da mesma aplicação. No entanto, recomenda-se que utilize aplicações separadas para definir e utilizar o seu pipeline para fazer previsões. Em ML.NET os seus oleodutos podem ser serializados e guardados para posterior utilização noutras aplicações de utilizador final .NET. ML.NET suporta vários alvos de implementação, tais como aplicações de desktop, serviços web, aplicações WebAssembly*, entre muitos outros. Para saber mais sobre a poupança de gasodutos, consulte o guia de modelos ML.NET save and load.

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

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

    var onnxPredictionPipeline = GetPredictionPipeline(mlContext);
    

Use o modelo para fazer previsões

Agora que tens um oleoduto, está na altura de o usares para fazer previsões. ML.NET fornece uma API de conveniência para fazer previsões numa única instância de dados chamada PredictionEngine.

  1. Dentro do Main método, crie um PredictionEngine utilizando 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. Utilize o predictionEngine para fazer previsões com base nos novos testInput dados utilizando o Predict método.

    var prediction = onnxPredictionEngine.Predict(testInput);
    
  4. Desemola o resultado da sua previsão para a consola.

    Console.WriteLine($"Predicted Fare: {prediction.PredictedFare.First()}");
    
  5. Utilize o CLI .NET Core para executar a sua aplicação.

    dotnet run
    

    O resultado deve ser semelhante à seguinte saída:

    Predicted Fare: 15.621523
    

Para saber mais sobre fazer previsões em ML.NET, consulte o uso de um modelo para fazer guia de previsões.

Passos seguintes