Share via


Tutorial: Predicción de precios mediante regresión con ML.NET

En este tutorial se muestra cómo compilar un modelo de regresión con ML.NET para predecir precios, en concreto, las tarifas de taxi de Nueva York.

En este tutorial aprenderá a:

  • Preparar y entender los datos
  • Cargar y transformar los datos
  • Elegir un algoritmo de aprendizaje
  • Entrenar el modelo
  • Evaluar el modelo
  • Usar el modelo para las predicciones

Requisitos previos

Creación de una aplicación de consola

  1. Cree una aplicación de consola en C# llamada "TaxiFarePrediction".

  2. Seleccione .NET 6 como marco de trabajo que va a usarse. Haga clic en el botón Crear.

  3. Cree un directorio denominado Datos en el proyecto para almacenar el conjunto de datos y los archivos de modelo.

  4. Instale los paquetes NuGet Microsoft.ML y Microsoft.ML.FastTree:

    Nota

    En este ejemplo se usa la versión estable más reciente de los paquetes NuGet mencionados, a menos que se indique lo contrario.

    En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Administrar paquetes NuGet. Elija "nuget.org" como origen del paquete, seleccione la pestaña Examinar, busque Microsoft.ML, seleccione el paquete en la lista y seleccione el botón Instalar. Seleccione el botón Aceptar en el cuadro de diálogo Vista previa de cambios y, a continuación, seleccione el botón Acepto del cuadro de diálogo Aceptación de la licencia en caso de que esté de acuerdo con los términos de licencia de los paquetes mostrados. Haga lo mismo con el paquete NuGet Microsoft.ML.FastTree.

Preparar y entender los datos

  1. Descargue los conjuntos de datos taxi-fare-train.csv y taxi-fare-test.csv y guárdelos en la carpeta Datos que ha creado en el paso anterior. Usaremos estos conjuntos de datos para entrenar el modelo de aprendizaje automático y, después, evaluar su precisión. Estos conjuntos de datos proceden originalmente del conjunto de datos NYC TLC Taxi Trip.

  2. En el Explorador de soluciones, haga clic con el botón derecho en cada uno de los archivos .csv y seleccione Propiedades. En Avanzadas, cambie el valor de Copiar en el directorio de salida por Copiar si es posterior.

  3. Abra el conjunto de datos taxi-fare-train.csv y consulte los encabezados de columna de la primera fila. Eche un vistazo a cada una de las columnas. Estudie los datos y decida qué columnas son características y cuál es la etiqueta.

label es la columna que quiere predecir. Las Features identificadas son las entradas que proporciona al modelo para predecir la Label.

El conjunto de datos proporcionado contiene las columnas siguientes:

  • vendor_id: el identificador del taxista es una característica.
  • rate_code: el tipo de tarifa del viaje en taxi es una característica.
  • passenger_count: el número de pasajeros en el recorrido es una característica.
  • trip_time_in_secs: la cantidad de tiempo que tardó el viaje. Por ejemplo, si quiere calcular la tarifa del viaje antes de que termine y aún no conoce la duración del viaje, el tiempo del viaje no es una característica, por lo que deberá excluir esta columna del modelo.
  • trip_distance: la distancia del viaje es una característica.
  • payment_type: el método de pago (efectivo o tarjeta de crédito) es una característica.
  • fare_amount: la tarifa de taxi total pagada es la etiqueta.

Crear clases de datos

Cree clases para los datos de entrada y las predicciones:

  1. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y, a continuación, seleccione Agregar>Nuevo elemento.

  2. En el cuadro de diálogo Agregar nuevo elemento, seleccione Clase y cambie el campo Nombre a TaxiTrip.cs. A continuación, seleccione el botón Agregar.

  3. Agregue las siguientes directivas using al nuevo archivo:

    using Microsoft.ML.Data;
    

Quite la definición de clase existente y agregue el código siguiente, que tiene dos clases TaxiTrip y TaxiTripFarePrediction, al archivo 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 es la clase de datos de entrada y tiene definiciones para cada una de las columnas del conjunto de datos. Use el atributo LoadColumnAttribute para especificar los índices de las columnas de origen en el conjunto de datos.

La clase TaxiTripFarePrediction representa los resultados predichos. Tiene un único campo flotante, FareAmount, con un atributo ScoreColumnNameAttribute aplicado. En el caso de la tarea de regresión, la columna Score contiene valores de etiqueta predichos.

Nota

Use el tipo float para representar los valores de punto flotante en las clases de entrada y predicción de datos.

Definir rutas de acceso de datos y modelos

Agregue las siguientes instrucciones using adicionales a la parte superior del archivo Program.cs:

using Microsoft.ML;
using TaxiFarePrediction;

Deberá crear tres campos que contengan las rutas de acceso a los archivos con los conjuntos de datos y el archivo para guardar el modelo:

  • _trainDataPath contiene la ruta de acceso al archivo con el conjunto de datos utilizado para entrenar el modelo.
  • _testDataPath contiene la ruta de acceso al archivo con el conjunto de datos utilizado para evaluar el modelo.
  • _modelPath contiene la ruta de acceso al archivo en el que se almacena el modelo entrenado.

Agregue el código siguiente justo debajo de la sección usings para especificar esas rutas de acceso y para la variable _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 las operaciones de ML.NET se inician en la clase MLContext. La inicialización de mlContext crea un entorno de ML.NET que se puede compartir entre los objetos del flujo de trabajo de creación de modelos. Como concepto, se parece a DBContext en Entity Framework.

Inicialización de variables

Reemplace la línea Console.WriteLine("Hello World!") por el siguiente código para declarar e inicializar la variable mlContext:

MLContext mlContext = new MLContext(seed: 0);

Agregue lo siguiente como la siguiente línea de código para llamar al método Train:

var model = Train(mlContext, _trainDataPath);

El método Train() ejecuta las tareas siguientes:

  • Carga los datos.
  • Extrae y transforma los datos.
  • Entrena el modelo.
  • Devuelve el modelo.

El método Train entrena el modelo. Cree ese método justo debajo mediante el código siguiente:

ITransformer Train(MLContext mlContext, string dataPath)
{

}

Cargar y transformar datos

ML.NET usa la interfaz IDataView como una forma flexible y eficaz de describir datos tabulares de texto o numéricos. IDataView puede cargar archivos de texto o en tiempo real (por ejemplo, una base de datos SQL o archivos de registro). Agregue el código siguiente a la primera línea del método Train():

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

Como quiere predecir la tarifa de carreras de taxi, la columna FareAmount es la Label que va a predecir (la salida del modelo). Para ello, use la clase de transformación CopyColumnsEstimator para copiar FareAmount y agregue el código siguiente:

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

El algoritmo que entrena el modelo requiere características numéricas, por lo que debe transformar los datos de categorías (VendorId, RateCode y PaymentType) en números (VendorIdEncoded, RateCodeEncoded y PaymentTypeEncoded). Para ello, use la clase de transformación OneHotEncodingTransformer, que asigna diferentes valores de clave numéricos a los distintos valores de cada una de las columnas y agregue el código siguiente:

.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"))

En el último paso para la preparación de los datos, se combinan todas las columnas de característica en la columna Características mediante la clase de transformación mlContext.Transforms.Concatenate. De forma predeterminada, un algoritmo de aprendizaje solo procesa las características de la columna Features. Agregue el código siguiente:

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

Elegir un algoritmo de aprendizaje

Este problema consiste en predecir la tarifa de una carrera de taxi en la ciudad de Nueva York. A primera vista, puede parecer que simplemente depende de la distancia recorrida. Sin embargo, los taxistas de Nueva York cobran distintas cantidades por otros factores, como llevar pasajeros adicionales o pagar con tarjeta de crédito en lugar de efectivo. Quiere predecir el valor de precio, que es un valor real, en función de los demás factores del conjunto de datos. Para ello, se elige una tarea de aprendizaje automático de regresión.

Anexe la tarea de aprendizaje automático FastTreeRegressionTrainer a las definiciones de transformación de datos al agregar esto como siguiente línea de código de Train():

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

Entrenar el modelo

Ajuste el modelo a la dataview de entrenamiento y devuelva el modelo entrenado agregando la siguiente línea de código en el método Train():

var model = pipeline.Fit(dataView);

El método Fit() entrena el modelo al transformar el conjunto de datos y aplicar el aprendizaje.

Devuelva el modelo entrenado con la siguiente línea de código en el método Train():

return model;

Evaluar el modelo

Luego evalúe el rendimiento del modelo con los datos de prueba de control de calidad y validación. Cree el método Evaluate(), justo después de Train(), con el código siguiente:

void Evaluate(MLContext mlContext, ITransformer model)
{

}

El método Evaluate ejecuta las tareas siguientes:

  • Carga el conjunto de datos de prueba.
  • Crea el evaluador de regresión.
  • Evalúa el modelo y crea las métricas.
  • Muestra las métricas.

Agregue una llamada al nuevo método justo debajo de la llamada al método Train mediante el código siguiente:

Evaluate(mlContext, model);

Cargue el conjunto de datos de prueba con el método LoadFromTextFile(). Evalúe el modelo con este conjunto de datos como control de calidad al agregar el código siguiente en el método Evaluate:

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

Luego transforme los datos de Test al agregar el código siguiente a Evaluate():

var predictions = model.Transform(dataView);

El método Transform() realiza predicciones para las filas de entrada del conjunto de datos de prueba.

El método RegressionContext.Evaluate calcula las métricas de calidad para PredictionModel mediante el conjunto de datos especificado. Devuelve un objeto RegressionMetrics que contiene las métricas totales calculadas por evaluadores de regresión.

Para mostrar estos elementos a fin de determinar la calidad del modelo, debe obtener primero las métricas. Agregue el siguiente código como la siguiente línea en el método Evaluate:

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

Una vez que se ha establecido la predicción, el método Evaluate() valora el modelo, que compara los valores predichos con las Labels reales del conjunto de datos de prueba y devuelve métricas sobre el rendimiento del modelo.

Agregue el código siguiente para evaluar el modelo y generar las métricas de evaluación:

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

RSquared es otra métrica de evaluación de modelos de regresión. RSquared muestra valores comprendidos entre 0 y 1. Cuanto más se acerque el valor a 1, mejor será el modelo. Agregue el código siguiente al método Evaluate para mostrar el valor de RSquared:

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

RMS es una de las métricas de evaluación del modelo de regresión. Cuanto menor sea su valor, mejor será el modelo. Agregue el código siguiente al método Evaluate para mostrar el valor de RMS:

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

Usar el modelo para las predicciones

Cree el método TestSinglePrediction, justo después del método Evaluate, mediante el código siguiente:

void TestSinglePrediction(MLContext mlContext, ITransformer model)
{

}

El método TestSinglePrediction ejecuta las tareas siguientes:

  • Crea un único comentario de datos de prueba.
  • Predice la tarifa según los datos de prueba.
  • Combina datos de prueba y predicciones para la generación de informes.
  • Muestra los resultados de la predicción.

Agregue una llamada al nuevo método justo debajo de la llamada al método Evaluate mediante el código siguiente:

TestSinglePrediction(mlContext, model);

Use PredictionEngine para predecir la tarifa al agregar el código siguiente a TestSinglePrediction():

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

PredictionEngine es una API de conveniencia, que le permite realizar una predicción en una única instancia de datos. PredictionEngine no es seguro para subprocesos. Es aceptable usarlo en entornos de un solo subproceso o prototipo. Para mejorar el rendimiento y la seguridad para subprocesos en entornos de producción, use el servicio PredictionEnginePool, que crea un ObjectPool de objetos de PredictionEngine para su uso en toda la aplicación. Consulte esta guía sobre cómo usar PredictionEnginePool en una API web de ASP.NET Core.

Nota

La extensión del servicio PredictionEnginePool está actualmente en versión preliminar.

En este tutorial se utiliza un viaje de prueba en esta clase. Más adelante, puede agregar otros escenarios para experimentar con el modelo. Agregue un viaje para probar la predicción de costo del modelo entrenado en el método TestSinglePrediction() mediante la creación de una instancia 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
};

Luego, prediga el importe del servicio según una instancia única de los datos de carreras de taxi y páselo a la clase PredictionEngine agregando lo siguiente como próximas líneas de código en el método TestSinglePrediction():

var prediction = predictionFunction.Predict(taxiTripSample);

La función Predict() realiza una predicción sobre una única instancia de datos.

Para mostrar la tarifa prevista del viaje especificado, agregue el código siguiente al método TestSinglePrediction:

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

Ejecute el programa para ver la tarifa de taxi predicha para su caso de prueba.

¡Enhorabuena! Ya ha creado correctamente un modelo de aprendizaje automático para predecir tarifas de viajes en taxi, ha evaluado su precisión y lo ha usado para hacer predicciones. Puede encontrar el código fuente de este tutorial en el repositorio dotnet/samples de GitHub.

Pasos siguientes

En este tutorial ha aprendido a:

  • Preparar y entender los datos
  • Crear una canalización de aprendizaje
  • Cargar y transformar los datos
  • Elegir un algoritmo de aprendizaje
  • Entrenar el modelo
  • Evaluar el modelo
  • Usar el modelo para las predicciones

Siga con el siguiente tutorial para obtener más información.