Compartilhar via


Tutorial: Prever os preços usando regressão com ML.NET

Este tutorial mostra como criar um modelo de regressão usando do ML.NET para prever os preços, especificamente, as tarifas de táxi de Nova York.

Neste tutorial, você aprenderá a:

  • Preparar e compreender os dados
  • Carregar e transformar os dados
  • Escolher um algoritmo de aprendizado
  • Treinar o modelo
  • Avaliar o modelo
  • Usar o modelo para previsões

Pré-requisitos

  • Visual Studio 2022 com a carga de trabalho "Desenvolvimento de área de trabalho do .NET" instalada.

Criar um aplicativo de console

  1. Crie um Aplicativo de console em C# chamado "TaxiFarePrediction".

  2. Escolha o .NET 6 como a estrutura a ser usada. Selecione o botão Criar.

  3. Crie um diretório chamado Dados em seu projeto para armazenar o conjunto de dados e arquivos de modelo.

  4. Instale o pacote NuGet Microsoft.ML e Microsoft.ML.FastTree:

    Observação

    Este exemplo usa a versão estável mais recente dos pacotes NuGet mencionados, salvo indicação em contrário.

    No Gerenciador de Soluções, clique com o botão direito no projeto e escolha Gerenciar Pacotes NuGet. Escolha "nuget.org" como a origem do pacote, selecione a guia Procurar, pesquise por Microsoft.ML, selecione o pacote na lista e selecione o botão Instalar. Selecione o botão OK na caixa de diálogo Visualizar Alterações e selecione o botão Aceito na caixa de diálogo Aceitação da Licença, se concordar com o termos de licença para os pacotes listados. Faça o mesmo para o pacote NuGet Microsoft.ML.FastTree.

Preparar e compreender os dados

  1. Baixe os conjuntos de dados taxi-fare-train.csv e taxi-fare-test.csv e salve-os na pasta Dados criada na etapa anterior. Esses conjuntos de dados são usados para treinar o modelo de aprendizado de máquina e, em seguida, avaliar a precisão dele. Esses conjuntos de dados são originalmente do Conjunto de dados NYC TLC Taxi Trip.

  2. No Gerenciador de Soluções, clique com o botão direito do mouse em cada um dos arquivos .csv e selecione Propriedades. Em Avançado, altere o valor de Copiar para Diretório de Saída para Copiar se for mais novo.

  3. Abra o conjunto de dados taxi-fare-train.csv e observe os cabeçalhos de coluna na primeira linha. Dê uma olhada em cada uma das colunas. Compreenda os dados e decida quais colunas são recursos e qual é o rótulo.

O label é a coluna que você deseja prever. O Featuresidentificado são as entradas que você atribui ao modelo para prever o Label.

O conjunto de dados fornecido contém as seguintes colunas:

  • vendor_id: o ID do taxista é um recurso.
  • rate_code: o tipo de tarifa da viagem de táxi é um recurso.
  • passenger_count: o número de passageiros na viagem é um recurso.
  • trip_time_in_secs: a quantidade de tempo que a viagem levou. Você deseja prever a tarifa da viagem antes de sua conclusão. Naquele momento, você não sabia quanto tempo a viagem levaria. Portanto, o tempo da viagem não é um recurso e você excluirá essa coluna do modelo.
  • trip_distance: a distância da viagem é um recurso.
  • payment_type: o método de pagamento (dinheiro ou cartão de crédito) é um recurso.
  • fare_amount: a tarifa total de táxi paga é o rótulo.

Criar classes de dados

Crie classes para os dados de entrada e as previsões:

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no projeto e selecione Adicionar>Novo Item.

  2. Na caixa de diálogo Adicionar Novo Item, selecione Classe e altere o campo Nome para TaxiTrip.cs. Em seguida, selecione o botão Adicionar.

  3. Adicione as seguintes diretivas using ao novo arquivo:

    using Microsoft.ML.Data;
    

Remova a definição de classe existente e adicione o seguinte código, que tem duas classes TaxiTrip e TaxiTripFarePrediction, ao arquivo TaxiTrip.cs:

public class TaxiTrip
{
    [LoadColumn(0)]
    public string? VendorId;

    [LoadColumn(1)]
    public string? RateCode;

    [LoadColumn(2)]
    public float PassengerCount;

    [LoadColumn(3)]
    public float TripTime;

    [LoadColumn(4)]
    public float TripDistance;

    [LoadColumn(5)]
    public string? PaymentType;

    [LoadColumn(6)]
    public float FareAmount;
}

public class TaxiTripFarePrediction
{
    [ColumnName("Score")]
    public float FareAmount;
}

TaxiTrip é a classe de dados de entrada e tem definições para cada uma das colunas do conjunto de dados. Use o atributo LoadColumnAttribute para especificar os índices das colunas de origem no conjunto de dados.

A classe TaxiTripFarePrediction representa os resultados previstos. Ela tem um único campo de float, FareAmount, com um atributo ScoreColumnNameAttribute aplicado. No caso da tarefa de regressão, a coluna Pontuação contém valores de rótulo previsto.

Observação

Use o tipo float para representar valores de ponto flutuante nas classes de dados de entrada e previsão.

Definir dados e caminhos de modelo

Adicione as seguintes instruções using adicionais ao início do arquivo Program.cs:

using Microsoft.ML;
using TaxiFarePrediction;

Você precisa criar três campos para conter os caminhos para os arquivos com conjuntos de dados e o arquivo para salvar o modelo:

  • _trainDataPath contém o caminho para o arquivo com o conjunto de dados usado para treinar o modelo.
  • _testDataPath contém o caminho para o arquivo com o conjunto de dados usado para avaliar o modelo.
  • _modelPath contém o caminho para o arquivo em que o modelo treinado está armazenado.

Adicione o seguinte código logo abaixo da seção de usos para especificar esses caminhos e para a variável _textLoader:

string _trainDataPath = Path.Combine(Environment.CurrentDirectory, "Data", "taxi-fare-train.csv");
string _testDataPath = Path.Combine(Environment.CurrentDirectory, "Data", "taxi-fare-test.csv");
string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "Model.zip");

Todas as operações do ML.NET iniciam na classe MLContext. Inicializar mlContext cria um novo ambiente do ML.NET que pode ser compartilhado entre os objetos do fluxo de trabalho de criação de modelo. Ele é semelhante, conceitualmente, a DBContext no Entity Framework.

Inicializar variáveis

Substitua a linha Console.WriteLine("Hello World!") pelo seguinte código para declarar e inicializar a variável mlContext:

MLContext mlContext = new MLContext(seed: 0);

Adicione o seguinte como a próxima linha de código para chamar o método Train:

var model = Train(mlContext, _trainDataPath);

O método Train() executa as seguintes tarefas:

  • Carrega os dados.
  • Extrai e transforma os dados.
  • Treina o modelo.
  • Retorna o modelo.

O método Train treina o modelo. Crie esse método logo abaixo usando o seguinte código:

ITransformer Train(MLContext mlContext, string dataPath)
{

}

Carregar e transformar dados

O ML.NET usa a interface IDataView como uma maneira flexível e eficiente de descrever dados numéricos ou tabulares de texto. O IDataView pode carregar arquivos de texto ou em tempo real (por exemplo, banco de dados SQL ou arquivos de log). Adicione o seguinte código como a primeira linha do método Train():

IDataView dataView = mlContext.Data.LoadFromTextFile<TaxiTrip>(dataPath, hasHeader: true, separatorChar: ',');

Como você deseja prever a tarifa da viagem de táxi, a coluna FareAmount é a Label que você irá prever (a saída do modelo). Use a classe de transformação CopyColumnsEstimator para copiar FareAmount e adicione o seguinte código:

var pipeline = mlContext.Transforms.CopyColumns(outputColumnName: "Label", inputColumnName:"FareAmount")

O algoritmo que treina o modelo requer recursos numéricos, então, é necessário transformar os valores de dados categóricos (VendorId, RateCode e PaymentType) em números (VendorIdEncoded, RateCodeEncoded e PaymentTypeEncoded). Para fazer isso, use a classe de transformação OneHotEncodingTransformer, que atribui valores de chave numérica diferentes para os diferentes valores em cada uma das colunas e adicione o seguinte código:

.Append(mlContext.Transforms.Categorical.OneHotEncoding(outputColumnName: "VendorIdEncoded", inputColumnName:"VendorId"))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(outputColumnName: "RateCodeEncoded", inputColumnName: "RateCode"))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(outputColumnName: "PaymentTypeEncoded", inputColumnName: "PaymentType"))

A última etapa na preparação de dados combina todas as colunas de recursos na coluna Features usando a classe de transformação mlContext.Transforms.Concatenate. Por padrão, um algoritmo de aprendizado processa apenas os recursos da coluna Features. Adicione os códigos a seguir:

.Append(mlContext.Transforms.Concatenate("Features", "VendorIdEncoded", "RateCodeEncoded", "PassengerCount", "TripDistance", "PaymentTypeEncoded"))

Escolher um algoritmo de aprendizado

Esse problema é sobre prever uma tarifa de corrida de táxi em Nova York. À primeira vista, pode parecer que depende simplesmente da distância percorrida. No entanto, os taxistas em Nova York cobram valores variados por outros fatores, como passageiros adicionais ou pagamento por cartão de crédito em vez de dinheiro. Você deseja prever o valor de preço, que é um valor real, com base em outros fatores no conjunto de dados. Para fazer isso, você deve escolher uma tarefa de aprendizado de máquina de regressão.

Acrescente a tarefa de aprendizado de máquina FastTreeRegressionTrainer às definições de transformação de dados adicionando o seguinte como a próxima linha de código em Train():

.Append(mlContext.Regression.Trainers.FastTree());

Treinar o modelo

Ajuste o modelo à dataview do treinamento e retorne o modelo treinado adicionando a seguinte linha de código ao método Train():

var model = pipeline.Fit(dataView);

O método Fit() treina o modelo transformando o conjunto de dados e aplicando o treinamento.

Retorne o modelo treinado com a seguinte linha de código no método Train():

return model;

Avaliar o modelo

Em seguida, avalie o desempenho do modelo com seus dados de teste para garantia de qualidade e validação. Crie o método Evaluate(), logo após Train(), com o código a seguir:

void Evaluate(MLContext mlContext, ITransformer model)
{

}

O método Evaluate executa as seguintes tarefas:

  • Carrega o conjunto de dados de teste.
  • Cria o avaliador de regressão.
  • Avalia o modelo e cria métricas.
  • Exibe as métricas.

Adicione uma chamada ao novo método logo abaixo da chamada do método Train usando o seguinte código:

Evaluate(mlContext, model);

Carregue o conjunto de dados de teste usando o método LoadFromTextFile(). Avalie o modelo usando esse conjunto de dados como uma verificação de qualidade adicionando o seguinte código ao método Evaluate:

IDataView dataView = mlContext.Data.LoadFromTextFile<TaxiTrip>(_testDataPath, hasHeader: true, separatorChar: ',');

Em seguida, transforme os dados Test adicionando o seguinte código a Evaluate():

var predictions = model.Transform(dataView);

O método Transform() faz previsões para testar as linhas de entrada do conjunto de dados.

O método RegressionContext.Evaluate calcula as métricas de qualidade para o PredictionModel usando o conjunto de dados especificado. Ele retorna um objeto RegressionMetrics que contém as métricas gerais computadas pelos avaliadores de regressão.

Para exibi-los a fim de determinar a qualidade do modelo, é preciso primeiro obter as métricas. Adicione o seguinte código ao método Evaluate como a linha seguinte:

var metrics = mlContext.Regression.Evaluate(predictions, "Label", "Score");

Depois que você define a previsão, o método Evaluate() avalia o modelo, que compara os valores previstos com os Labels reais no conjunto de dados de teste e retorna métricas sobre o desempenho do modelo.

Adicione o seguinte código para avaliar o modelo e produzir as métricas de avaliação:

Console.WriteLine();
Console.WriteLine($"*************************************************");
Console.WriteLine($"*       Model quality metrics evaluation         ");
Console.WriteLine($"*------------------------------------------------");

RSquared é outra métrica de avaliação dos modelos de regressão. RSquared aceita valores entre 0 e 1. Quanto mais perto de 1 estiver o valor, melhor o modelo será. Adicione o seguinte código ao método Evaluate para exibir o valor RSquared:

Console.WriteLine($"*       RSquared Score:      {metrics.RSquared:0.##}");

RMS é uma das métricas de avaliação do modelo de regressão. Quanto menor, melhor o modelo. Adicione o seguinte código ao método Evaluate para exibir o valor RMS:

Console.WriteLine($"*       Root Mean Squared Error:      {metrics.RootMeanSquaredError:#.##}");

Usar o modelo para previsões

Crie o método TestSinglePrediction, logo após o método Evaluate, usando o seguinte código:

void TestSinglePrediction(MLContext mlContext, ITransformer model)
{

}

O método TestSinglePrediction executa as seguintes tarefas:

  • Cria um único comentário dos dados de teste.
  • Prevê o valor da tarifa com base nos dados de teste.
  • Combina dados de teste e previsões para relatórios.
  • Exibe os resultados previstos.

Adicione uma chamada ao novo método logo abaixo da chamada do método Evaluate usando o seguinte código:

TestSinglePrediction(mlContext, model);

Use o PredictionEngine para prever a tarifa adicionando o seguinte código a TestSinglePrediction():

var predictionFunction = mlContext.Model.CreatePredictionEngine<TaxiTrip, TaxiTripFarePrediction>(model);

O PredictionEngine é uma API de conveniência, que permite executar uma previsão em uma instância individual de dados. PredictionEngine não é thread-safe. É aceitável usá-lo em ambientes de thread único ou de protótipo. Para aprimorar o desempenho e o acesso thread-safe em ambientes de produção, use o serviço PredictionEnginePool, que cria um ObjectPool de objetos PredictionEngine para uso em todo o aplicativo. Confira este guia sobre como usar o PredictionEnginePool em uma API Web ASP.NET Core.

Observação

A extensão de serviço PredictionEnginePool está atualmente em versão prévia.

Este tutorial usa uma viagem de teste dentro dessa classe. Posteriormente, você pode adicionar outros cenários para fazer experiências com o modelo. Adicione uma corrida de teste à previsão do modelo treinado no método TestSinglePrediction() ao criar uma instância de TaxiTrip:

var taxiTripSample = new TaxiTrip()
{
    VendorId = "VTS",
    RateCode = "1",
    PassengerCount = 1,
    TripTime = 1140,
    TripDistance = 3.75f,
    PaymentType = "CRD",
    FareAmount = 0 // To predict. Actual/Observed = 15.5
};

Em seguida, preveja a tarifa com base em uma única instância dos dados de corrida táxi e passe-a para o PredictionEngine adicionando o seguinte como as próximas linhas do código no método TestSinglePrediction():

var prediction = predictionFunction.Predict(taxiTripSample);

A função Predict() faz uma previsão em uma única instância de dados.

Para exibir a tarifa prevista da corrida especificada, adicione o código a seguir ao método TestSinglePrediction:

Console.WriteLine($"**********************************************************************");
Console.WriteLine($"Predicted fare: {prediction.FareAmount:0.####}, actual fare: 15.5");
Console.WriteLine($"**********************************************************************");

Execute o programa para ver a tarifa de táxi prevista para o seu caso de teste.

Parabéns! Agora você criou com sucesso um modelo de aprendizado de máquina para prever tarifas de táxi, avaliou sua precisão e o usou para fazer previsões. Encontre o código-fonte deste tutorial no repositório do GitHub dotnet/samples.

Próximas etapas

Neste tutorial, você aprendeu a:

  • Preparar e compreender os dados
  • Criar um pipeline de aprendizado
  • Carregar e transformar os dados
  • Escolher um algoritmo de aprendizado
  • Treinar o modelo
  • Avaliar o modelo
  • Usar o modelo para previsões

Avance para o próximo tutorial para saber mais.