Partilhar via


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

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

Neste tutorial, você aprenderá a:

  • Preparar e compreender os dados
  • Carregue e transforme os dados
  • Escolha um algoritmo de aprendizagem
  • Treinar o modelo
  • Avaliar o modelo
  • Use o modelo para previsões

Pré-requisitos

Criar um aplicativo de console

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

  2. Escolha .NET 8 como a estrutura a ser usada. Clique no botão Criar.

  3. Crie um diretório chamado Data em seu projeto para armazenar o conjunto de dados e os 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 do mouse no projeto e selecione Gerenciar pacotes NuGet. Escolha "nuget.org" como a origem do pacote, selecione o separador Explorar, procure por o Microsoft.ML, selecione o pacote na lista e selecione Instalar. Selecione o botão OK na caixa de diálogo Pré-visualizar Alterações e, em seguida, selecione o botão Aceito na caixa de diálogo Aceitação de Licença se concordar com os termos de licença para os pacotes listados. Faça o mesmo para o pacote Microsoft.ML.FastTree NuGet.

Preparar e compreender os dados

  1. Transfira os conjuntos de dados taxi-fare-train.csv e taxi-fare-test.csv e guarde-os na pasta Data que criou no passo anterior. Usamos esses conjuntos de dados para treinar o modelo de aprendizado de máquina e, em seguida, avaliar a precisão do modelo. 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 o Diretório de Saída para Copiar semais recente.

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

A label é a coluna que você deseja prever. As Featuresidentificadas são as entradas que você dá ao modelo para prever o Label.

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

  • vendor_id: O ID do vendedor de táxi é um recurso.
  • rate_code: O tipo de tarifa da corrida de táxi é um atributo.
  • passenger_count: O número de passageiros na viagem é uma característica.
  • trip_time_in_secs: A quantidade de tempo que a viagem levou. Você quer prever a tarifa da viagem antes que a viagem seja concluída. Nesse momento, você não sabe quanto tempo a viagem levaria. Assim, o tempo de viagem não é um recurso e você excluirá esta coluna do modelo.
  • trip_distance: A distância da viagem é uma característica.
  • payment_type: O método de pagamento (dinheiro ou cartão de crédito) é uma funcionalidade.
  • fare_amount: A tarifa total de táxi paga é a etiqueta.

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 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. Tem um único campo flutuante, FareAmount, com um atributo ScoreColumnNameAttribute aplicado. No caso da tarefa de regressão, a coluna Pontuação contém valores de rótulo previstos.

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 diretivas using adicionais à parte superior do arquivo Program.cs:

using Microsoft.ML;
using TaxiFarePrediction;

Você precisa criar três campos para manter 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 onde o modelo treinado está armazenado.

Adicione o seguinte código logo abaixo da seção usings 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 ML.NET são iniciadas na classe MLContext . Inicializar mlContext cria um novo ambiente de ML.NET que pode ser compartilhado entre os objetos de fluxo de trabalho de criação de modelo. É semelhante, conceitualmente, ao DBContext no Entity Framework.

Inicializar variáveis

Substitua a linha Console.WriteLine("Hello World!") pelo código a seguir 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

ML.NET usa a interface IDataView como uma maneira flexível e eficiente de descrever dados numéricos ou tabulares de texto. 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 FareAmounte adicione o seguinte código:

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

O algoritmo que treina o modelo requer recursos de numéricos, então você tem que transformar os dados categóricos (VendorId, RateCodee PaymentType) valores em números (VendorIdEncoded, RateCodeEncodede PaymentTypeEncoded). Para fazer isso, use a classe de transformação OneHotEncodingTransformer, que atribui diferentes valores de chave numérica aos 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 características na coluna Características usando a classe de transformação mlContext.Transforms.Concatenate. Por padrão, um algoritmo de aprendizagem processa apenas características da coluna Características. Adicione o seguinte código:

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

Escolha um algoritmo de aprendizagem

Este problema é sobre a previsão de uma tarifa de viagem de táxi em Nova York. À primeira vista, pode parecer depender simplesmente da distância percorrida. No entanto, os vendedores de táxi em Nova York cobram valores variáveis por outros fatores, como passageiros adicionais ou pagar com cartão de crédito em vez de dinheiro. Você deseja prever o valor do preço, que é um valor real, com base nos outros fatores do conjunto de dados. Para fazer isso, tu escolhes uma tarefa de aprendizagem 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 no Train():

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

Treinar o modelo

Ajuste o modelo ao conjunto de dados de treino dataview e devolva o modelo treinado adicionando a seguinte linha de código no método Train():

var model = pipeline.Fit(dataView);

O método Fit() treina seu 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 os dados de teste para garantia de qualidade e validação. Crie o método Evaluate(), logo após Train(), com o seguinte código:

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 de 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 no método Evaluate:

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

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

var predictions = model.Transform(dataView);

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

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 calculadas pelos avaliadores de regressão.

Para exibi-los e determinar a qualidade do modelo, você precisa obter as métricas primeiro. Adicione o seguinte código como a próxima linha no método Evaluate:

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

Depois de definir 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 leva valores entre 0 e 1. Quanto mais próximo o seu valor estiver de 1, melhor será o modelo. 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 mais baixo, 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:0.##}");

Use 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 comentário único dos dados de teste.
  • Prevê o valor da tarifa com base nos dados do 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 de método Evaluate, usando o seguinte código:

TestSinglePrediction(mlContext, model);

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

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

O PredictionEngine é uma API de conveniência, que permite executar uma previsão em uma única instância de dados. PredictionEngine não é seguro para threads. É aceitável usar em ambientes single-threaded ou de protótipos. Para melhorar o desempenho e a segurança de threads em ambientes de produção, use o serviço PredictionEnginePool, que cria uma ObjectPool de objetos PredictionEngine para uso em todo o aplicativo. Consulte este guia sobre como usar PredictionEnginePool em umASP.NET Core Web API .

Observação

PredictionEnginePool extensão de serviço está atualmente em versão preliminar.

Este tutorial usa uma viagem de teste dentro desta classe. Mais tarde, você pode adicionar outros cenários para experimentar o modelo. Adicione uma viagem para testar a previsão de custo do modelo treinado no método TestSinglePrediction() criando 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 da viagem de táxi e passe-a para o PredictionEngine adicionando o seguinte como as próximas linhas de 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 viagem especificada, adicione o seguinte código 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ê construiu com sucesso um modelo de aprendizado de máquina para prever tarifas de viagens de táxi, avaliou sua precisão e o usou para fazer previsões. Você pode encontrar o código-fonte deste tutorial no dotnet/samples repositório GitHub.

Próximos passos

Neste tutorial, você aprendeu como:

  • Preparar e compreender os dados
  • Criar um pipeline de aprendizagem
  • Carregue e transforme os dados
  • Escolha um algoritmo de aprendizagem
  • Treinar o modelo
  • Avaliar o modelo
  • Use o modelo para previsões

Avance para o próximo tutorial para saber mais.