Fazer previsões com um modelo AutoML ONNX no .NET
Neste artigo, será mostrado como usar um modelo de intercâmbio de rede neural (ONNX) aberto do ML (AutoML) para fazer previsões em um aplicativo de console do C# com ML.NET.
O ML.NET é uma estrutura de aprendizado de máquina de código aberto e de plataforma cruzada para o ecossistema do .NET que permite treinar e consumir modelos de aprendizado de máquina personalizados usando uma abordagem de code-first em C# ou F#, ou por meio de ferramentas de pouco código, como o Model Builder e a CLI do ML.NET. A estrutura é extensível e permite aproveitar outras estruturas de aprendizado de máquina populares, como TensorFlow e ONNX.
O ONNX é um formato open-source para modelos de IA. O ONNX é compatível com a interoperabilidade entre estruturas. Isso significa que você pode treinar um modelo em uma das muitas estruturas de aprendizado de máquina populares, como PyTorch, convertê-lo em formato ONNX e consumir o modelo ONNX em uma estrutura diferente, como ML.NET. Para saber mais, visite o site do ONNX.
Pré-requisitos
- SDK do .NET 6 ou posterior
- Editor de texto ou IDE (como o Visual Studio ou Visual Studio Code)
- Modelo ONNX. Para saber como treinar um modelo ONNX AutoML, consulte o seguinte notebook de classificação de marketing bancário.
- Netron (opcional)
Criação de um aplicativo de console em C#
Neste exemplo, é usada a CLI do .NET para compilar o aplicativo, mas é possível fazer as mesmas tarefas usando o Visual Studio. Saiba mais sobre a CLI do .NET.
Abra um terminal e crie um novo aplicativo de console do .NET em C#. Neste exemplo, o nome do aplicativo é
AutoMLONNXConsoleApp
. Um diretório é criado com esse mesmo nome com o conteúdo do aplicativo.dotnet new console -o AutoMLONNXConsoleApp
No terminal, navegue até o diretório AutoMLONNXConsoleApp.
cd AutoMLONNXConsoleApp
Adicionar pacotes de software
Instale os pacotes NuGet Microsoft.ML, Microsoft.ML.OnnxRuntimee Microsoft.ML.OnnxTransformer usando a CLI do .NET.
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. O ML.NET fornece uma API que usa o runtime do ONNX para previsões.
Abra o arquivo Program.cs e adicione as seguintes diretivas
using
na parte superior.using System.Linq; using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms.Onnx;
Adicionar uma referência ao modelo ONNX
Uma maneira do aplicativo de console acessar o modelo ONNX é adicioná-lo ao diretório de saída de compilação. Caso ainda não tenha um modelo, siga este notebook para criar um modelo de exemplo.
Para adicionar uma referência ao arquivo do modelo ONNX em seu aplicativo:
Copie o modelo ONNX para o diretório raiz AutoMLONNXConsoleApp do seu aplicativo.
Abra o arquivo AutoMLONNXConsoleApp.csproj e adicione o conteúdo a seguir dentro do nó
Project
.<ItemGroup> <None Include="automl-model.onnx"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>
Nesse caso, o nome do arquivo do modelo ONNX é automl-model.onnx.
(Para saber mais sobre os itens comuns do MSBuild, consulte o Guia do MSBuild.)
Abra o arquivo Program.cs e adicione as linhas a seguir na classe
Program
.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 classe MLContext
é um ponto de partida para todas as operações do ML.NET e a inicializar o mlContext
cria um ambiente do ML.NET que pode ser compartilhado ao longo do ciclo de vida do modelo. Ele é semelhante, conceitualmente, a DbContext no Entity Framework.
Definir o esquema de dados do modelo
Um modelo espera os dados de entrada e saída em um formato específico. O ML.NET permite definir o formato dos dados por meio de classes. Às vezes, a aparência desse formato pode já ser conhecida. Em casos em que o formato dos dados não é conhecido, é possível usar ferramentas como Netron para inspecionar o modelo ONNX.
O modelo usado neste exemplo usa dados do conjunto de dados do NYC TLC Taxi Trip. Um exemplo dos dados é mostrado na tabela a seguir:
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 |
Inspecionar o modelo ONNX (opcional)
Use uma ferramenta como Netron para inspecionar as entradas e saídas do modelo.
Abra o Netron.
Na barra de menus superior, selecione Arquivo > Abrir e use o navegador de arquivos para selecionar o modelo.
Seu modelo é aberto. Por exemplo, a estrutura do modelo automl-model.onnx é semelhante ao seguinte:
Selecione o último nó na parte inferior do grafo (
variable_out1
, neste caso) para exibir os metadados do modelo. As entradas e saídas na barra lateral mostram as entradas, as saídas e os tipos de dados esperados pelo modelo. Use essas informações para definir o esquema de entrada e saída do modelo.
Definir esquema de entrada de modelo
Crie uma nova classe chamada OnnxInput
com as propriedades a seguir 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 anotadas com mais detalhes com atributos.
O atributo ColumnName
permite especificar como o ML.NET deve referenciar a coluna ao operar com os dados. Por exemplo, embora a propriedade TripDistance
siga as convenções de nomenclatura padrão do .NET, o modelo só conhece uma coluna ou um recurso conhecido como trip_distance
. Para resolver essa discrepância de nomenclatura, o atributo ColumnName
mapeia a propriedade TripDistance
para uma coluna ou recurso de nome trip_distance
.
Para valores numéricos, o ML.NET só opera com tipos de valor Single
. No entanto, o tipo de dados original de algumas colunas são inteiros. O atributo OnnxMapType
mapeia tipos entre o ONNX e o ML.NET.
Para saber mais sobre atributos de dados, consulte o Guia de dados de carga do ML.NET.
Definir o esquema de saída do modelo
Depois que os dados são processados, ele produz uma saída com um determinado formato. Definir o esquema de saída de dados. Crie uma nova classe chamada OnnxOutput
com as propriedades a seguir dentro do arquivo Program.cs.
public class OnnxOutput
{
[ColumnName("variable_out1")]
public float[] PredictedFare { get; set; }
}
Semelhante ao OnnxInput
, use o atributo ColumnName
para mapear a saída variable_out1
para um nome mais descritivo PredictedFare
.
Definir um pipeline de previsão
Um pipeline no ML.NET normalmente é uma série de transformações encadeadas que operam com os dados de entrada para produzir uma saída. Para saber mais sobre transformações de dados, consulte o Guia de transformação de dados do ML.NET.
Criar um novo método chamado
GetPredictionPipeline
dentro da classeProgram
static ITransformer GetPredictionPipeline(MLContext mlContext) { }
Defina o nome das colunas de entrada e saída. Adicione o seguinte código dentro do método
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" };
Definir o pipeline. Um
IEstimator
fornece um blueprint das operações e os esquemas de entrada e de saída do pipeline.var onnxPredictionPipeline = mlContext .Transforms .ApplyOnnxModel( outputColumnNames: outputColumns, inputColumnNames: inputColumns, ONNX_MODEL_PATH);
Nesse caso,
ApplyOnnxModel
é a única transformação no pipeline, que usa os nomes das colunas de entrada e saída, bem como o caminho para o arquivo de modelo ONNX.Um
IEstimator
só define o conjunto de operações a serem aplicadas aos dados. O que opera com os dados é conhecido como umITransformer
. Use o métodoFit
para criar um doonnxPredictionPipeline
.var emptyDv = mlContext.Data.LoadFromEnumerable(new OnnxInput[] {}); return onnxPredictionPipeline.Fit(emptyDv);
O método
Fit
espera umIDataView
como entrada para executar as operações. UmIDataView
é uma maneira de representar dados no ML.NET usando um formato tabular. Como nesse caso o pipeline é usado apenas para previsões, é possível fornecer umIDataView
vazio para fornecerITransformer
, as informações necessárias de esquema de entrada e saída. OITransformer
ajustado é então retornado para uso posterior no aplicativo.Dica
Neste exemplo, o pipeline é definido e usado dentro do mesmo aplicativo. No entanto, é recomendável usar aplicativos separados para definir e usar o pipeline para fazer previsões. No ML.NET, os pipelines podem ser serializados e salvos para uso adicional em outros aplicativos de usuário final do .NET. O ML.NET dá suporte a vários destinos de implantação, como aplicativos de área de trabalho, serviços Web, aplicativos WebAssembly e muito mais. Para saber mais sobre como salvar pipelines, consulte o Guia de modelos treinados para salvar e carregar ML.NET.
Dentro do método
Main
, chame o métodoGetPredictionPipeline
com os parâmetros necessários.var onnxPredictionPipeline = GetPredictionPipeline(mlContext);
Usar o modelo para fazer previsões
Agora que já tem um pipeline, é hora de usá-lo para fazer previsões. O ML.NET fornece uma API de conveniência para fazer previsões em uma única instância de dados chamada PredictionEngine
.
Dentro do método
Main
, crie umPredictionEngine
usando o métodoCreatePredictionEngine
.var onnxPredictionEngine = mlContext.Model.CreatePredictionEngine<OnnxInput, OnnxOutput>(onnxPredictionPipeline);
Criar um banco de dados de teste.
var testInput = new OnnxInput { VendorId = "CMT", RateCode = 1, PassengerCount = 1, TripTimeInSecs = 1271, TripDistance = 3.8f, PaymentType = "CRD" };
Use o
predictionEngine
para fazer previsões com base nos novostestInput
dados usando o métodoPredict
.var prediction = onnxPredictionEngine.Predict(testInput);
Gere o resultado de sua previsão para o console.
Console.WriteLine($"Predicted Fare: {prediction.PredictedFare.First()}");
Use a CLI do .NET para executar o aplicativo.
dotnet run
O resultado deve ser semelhante à saída a seguir:
Predicted Fare: 15.621523
Para saber mais sobre como fazer previsões no ML.NET, confira Usar um modelo para fazer previsões.