Tutoriel : Prédire des prix en utilisant la régression avec ML.NET

Ce tutoriel montre comment créer un modèle de régression avec ML.NET pour prédire des prix, plus précisément, des courses de taxi à New York.

Dans ce tutoriel, vous allez apprendre à :

  • Préparer et comprendre les données
  • Charger et transformer les données
  • Choisir un algorithme d’apprentissage
  • Effectuer l’apprentissage du modèle
  • Évaluer le modèle
  • Utiliser le modèle pour les prévisions

Prérequis

  • Visual Studio 2022 avec la charge de travail « Développement .NET Desktop » installée.

Création d’une application console

  1. Créez une application console C# appelée « TaxiFarePrediction ».

  2. Choisissez .NET 6 comme framework à utiliser. Cliquez sur le bouton Créer.

  3. Créez un répertoire nommé Data (Données) dans votre projet pour y stocker les fichiers du jeu de données et du modèle.

  4. Installez les packages NuGet Microsoft.ML et Microsoft.ML.FastTree :

    Notes

    Cet exemple utilise la dernière version stable des packages NuGet mentionnés, sauf indication contraire.

    Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Gérer les packages NuGet. Choisissez « nuget.org » comme source du package, sélectionnez l’onglet Parcourir, recherchez Microsoft.ML, sélectionnez le package dans la liste, puis sélectionnez le bouton Installer. Cliquez sur le bouton OK dans la boîte de dialogue Aperçu des modifications, puis sur le bouton J’accepte dans la boîte de dialogue Acceptation de la licence si vous acceptez les termes du contrat de licence pour les packages répertoriés. Faites de même pour le package NuGet Microsoft.ML.FastTree.

Préparer et comprendre les données

  1. Téléchargez les jeux de données taxi-fare-train.csv et taxi-fare-test.csv, puis enregistrez-les dans le dossier Données créé à l’étape précédente. Nous utilisons ces jeux de données pour le modèle Machine Learning et pour évaluer la précision du modèle. Ces jeux de données proviennent du jeu de données NYC TLC Taxi Trip.

  2. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur chacun des fichiers .csv, puis sélectionnez Propriétés. Sous Avancé, définissez la valeur Copier dans le répertoire de sortie sur Copier si plus récent.

  3. Ouvrez le jeu de données taxi-fare-train.csv et examinez les en-têtes de colonne dans la première ligne. Examinons chacune des colonnes. Analysez les données et identifiez les colonnes qui sont des fonctionnalités et celle qui est l’étiquette.

label est la colonne à prédire. Les valeurs Features identifiées sont les entrées que vous fournissez au modèle pour prédire l’étiquette (Label).

Le jeu de données fourni contient les colonnes suivantes :

  • vendor_id : l’ID du taxi est une fonctionnalité.
  • rate_code : le type de tarif de la course de taxi est une fonctionnalité.
  • passenger_count : le nombre de passagers embarqués est une fonctionnalité.
  • trip_time_in_secs : durée totale de la course. Vous voulez prédire le prix de la course avant de l’effectuer. À ce stade, vous ne connaissez pas la durée de la course. Par conséquent, la durée de la course n’est pas une fonctionnalité et vous devez exclure cette colonne du modèle.
  • trip_distance : la distance de la course est une fonctionnalité.
  • payment_type : le mode de paiement (espèces ou carte de crédit) est une fonctionnalité.
  • fare_amount : le prix total payé pour la course est l’étiquette.

Créer des classes de données

Créez des classes pour les données d’entrée et les prédictions :

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter>Nouvel élément.

  2. Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Classe, puis remplacez la valeur du champ Nom par TaxiTrip.cs. Ensuite, sélectionnez le bouton Ajouter.

  3. Ajoutez les directives using suivantes au nouveau fichier :

    using Microsoft.ML.Data;
    

Supprimez la définition de classe existante et ajoutez le code suivant, qui contient deux classes, TaxiTrip et TaxiTripFarePrediction, au fichier 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 est la classe des données d’entrée et a des définitions pour chacune des colonnes du jeu de données. Utilisez l’attribut LoadColumnAttribute pour spécifier les index des colonnes sources dans le jeu de données.

La classe TaxiTripFarePrediction représente les résultats prédits. Elle comporte un seul champ float, FareAmount, avec un attribut ScoreColumnNameAttribute appliqué. Dans le cas de la tâche de régression, la colonne Score contient les valeurs d’étiquette prédites.

Notes

Utilisez le type float pour représenter les valeurs à virgule flottante dans les classes de données d’entrée et de prédiction.

Définir des chemins de données et de modèle

Ajoutez les instructions using supplémentaires suivantes en haut du fichier Program.cs :

using Microsoft.ML;
using TaxiFarePrediction;

Il faut créer trois champs qui contiendront les chemins des fichiers comportant des jeux de données et le fichier permettant d’enregistrer le modèle :

  • _trainDataPath contient le chemin du fichier avec le jeu de données utilisé pour l’apprentissage du modèle.
  • _testDataPath contient le chemin du fichier avec le jeu de données utilisé pour l’évaluation du modèle.
  • _modelPath contient le chemin du fichier où le modèle formé est stocké.

Ajoutez le code suivant juste en dessous de la section usings pour spécifier ces chemins et pour 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");

Toutes les opérations de ML.NET commencent dans la classe MLContext. L’initialisation de mlContext crée un environnement ML.NET qui peut être partagé par les objets du workflow de création de modèle. Sur le plan conceptuel, elle est similaire à DBContext dans Entity Framework.

Initialiser les variables

Remplacez la ligne Console.WriteLine("Hello World!") par le code suivant pour déclarer et initialiser la variable mlContext :

MLContext mlContext = new MLContext(seed: 0);

Ajoutez ceci à la ligne suivante pour appeler la méthode Train :

var model = Train(mlContext, _trainDataPath);

La méthode Train() exécute les tâches suivantes :

  • Charge les données.
  • Extrait et transforme les données.
  • Effectue l’apprentissage du modèle.
  • Retourne le modèle.

La méthode Train effectue l’apprentissage du modèle. Créez cette méthode juste en dessous en utilisant le code suivant :

ITransformer Train(MLContext mlContext, string dataPath)
{

}

Charger et transformer les données

ML.NET utilise l’interface IDataView comme un moyen flexible et efficace de décrire des données tabulaires numériques ou texte. IDataView peut charger des fichiers texte ou en temps réel (par exemple, une base de données SQL ou des fichiers journaux). Ajoutez le code suivant comme première ligne de la méthode Train() :

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

Comme vous voulez prédire le prix de la course de taxi, la colonne FareAmount est la Label que vous allez prédire (la sortie du modèle). Utilisez la classe de transformation CopyColumnsEstimator pour copier FareAmount et ajoutez le code suivant :

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

L’algorithme qui effectue l’apprentissage du modèle exige des fonctionnalités numériques. Il faut donc transformer les données catégoriques (VendorId, RateCode et PaymentType) en nombres (VendorIdEncoded, RateCodeEncoded et PaymentTypeEncoded). Pour cela, utilisez la classe de transformation OneHotEncodingTransformer, qui assigne différentes valeurs de clé numérique aux différentes valeurs de chaque colonne, puis ajoutez le code suivant :

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

La dernière étape de préparation des données regroupe toutes les colonnes de fonctionnalités dans la colonne Fonctionnalités à l’aide de la classe de transformation mlContext.Transforms.Concatenate. Par défaut, un algorithme d’apprentissage traite uniquement les caractéristiques issues de la colonne Features. Ajoutez le code suivant :

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

Choisir un algorithme d’apprentissage

Ce problème consiste à prédire le prix d’une course de taxi à New York. À première vue, ce prix semble dépendre simplement de la distance parcourue. Mais les chauffeurs de taxi à New York appliquent différents tarifs selon des facteurs comme le nombre de passagers supplémentaires ou le paiement par carte de crédit plutôt que par espèces. Vous souhaitez prédire le prix, qui est une valeur réelle, en fonction des autres facteurs du jeu de données. Pour ce faire, choisissez une tâche de machine learning par régression.

Ajoutez la tâche de machine learning FastTreeRegressionTrainer aux définitions de transformation des données en ajoutant la ligne de code suivante dans Train() :

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

Entraîner le modèle

Ajustez le modèle aux données d’entraînement dataview et retournez le modèle entraîné en ajoutant la ligne de code suivante à la méthode Train() :

var model = pipeline.Fit(dataView);

La méthode Fit() entraîne votre modèle en transformant le jeu de données et en appliquant l’entraînement.

Retournez le modèle entraîné avec la ligne suivante de code dans la méthode Train() :

return model;

Évaluer le modèle

Ensuite, évaluez les performances de votre modèle avec vos données de test à des fins d’assurance qualité et de validation. Créez la méthode Evaluate() juste après Train(), en utilisant le code suivant :

void Evaluate(MLContext mlContext, ITransformer model)
{

}

La méthode Evaluate exécute les tâches suivantes :

  • Charge le jeu de données de test.
  • Crée l’évaluateur de régression.
  • Évalue le modèle et crée des métriques.
  • Affiche les métriques.

Ajoutez un appel à la nouvelle méthode juste en dessous de l’appel de la méthode Train, en utilisant le code suivant :

Evaluate(mlContext, model);

Chargez le jeu de données de test à l’aide de la méthode LoadFromTextFile(). Évaluez le modèle avec ce jeu de données afin d’en contrôler la qualité, en ajoutant le code suivant à la méthode Evaluate :

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

Transformez ensuite les données Test en ajoutant le code suivant à Evaluate() :

var predictions = model.Transform(dataView);

La méthode Transform() établit des prédictions pour les lignes d’entrée du jeu de données de test.

La méthode RegressionContext.Evaluate calcule les métriques de qualité pour PredictionModel à l’aide du jeu de données spécifié. Elle retourne un objet RegressionMetrics qui contient les métriques globales calculées par les évaluateurs de régression.

Pour afficher ces informations afin d’évaluer la qualité du modèle, vous devez d’abord obtenir les métriques. Ajoutez le code suivant comme première ligne de la méthode Evaluate :

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

Une fois que vous avez le jeu de prédiction, la méthode Evaluate() évalue le modèle (elle compare les valeurs prédites aux Labels réelles dans le jeu de données de test et retourne des métriques relatives aux performances du modèle).

Ajoutez le code suivant pour évaluer le modèle et produire les métriques d’évaluation :

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

RSquared est une autre métrique d’évaluation des modèles de régression. RSquared prend des valeurs entre 0 et 1. Plus sa valeur est proche de 1, plus le modèle est bon. Ajoutez le code suivant dans la méthode Evaluate pour afficher la valeur RSquared :

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

RMS est une des métriques d’évaluation du modèle de régression. Plus sa valeur est faible, plus le modèle est bon. Ajoutez le code suivant dans la méthode Evaluate pour afficher la valeur RMS :

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

Utiliser le modèle pour les prévisions

Créez la méthode TestSinglePrediction juste après la méthode Evaluate, en utilisant le code suivant :

void TestSinglePrediction(MLContext mlContext, ITransformer model)
{

}

La méthode TestSinglePrediction exécute les tâches suivantes :

  • Crée un commentaire unique de données de test.
  • Prédit le prix de la course en fonction des données de test.
  • Combine les données de test et les prédictions pour générer des rapports.
  • Affiche les résultats prédits.

Ajoutez un appel à la nouvelle méthode juste en dessous de l’appel de la méthode Evaluate, en utilisant le code suivant :

TestSinglePrediction(mlContext, model);

Utilisez PredictionEngine pour prédire le prix de la course en ajoutant le code suivant à TestSinglePrediction() :

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

PredictionEngine est une API pratique qui vous permet d’effectuer une prédiction sur une seule instance de données. PredictionEngine n’est pas thread-safe. Il est acceptable de l’utiliser dans des environnements monothreads ou de prototype. Pour améliorer les performances et la sécurité des threads dans les environnements de production, utilisez le service PredictionEnginePool, qui crée un ObjectPool d’objets PredictionEngine à utiliser dans votre application. Consultez ce guide sur l’utilisation de PredictionEnginePool dans une API web ASP.NET Core.

Notes

L’extension de service PredictionEnginePool est disponible en préversion.

Ce tutoriel utilise une course test au sein de cette classe. Par la suite, vous pouvez ajouter d’autres scénarios à tester avec le modèle. Ajoutez une course pour tester la prédiction de coût du modèle formé dans la méthode TestSinglePrediction() en créant une instance 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
};

Ensuite, prédisez le prix basé sur une instance unique des données d’une course de taxi et passez le résultat à PredictionEngine en ajoutant les lignes de code suivantes à la méthode TestSinglePrediction() :

var prediction = predictionFunction.Predict(taxiTripSample);

La fonction Predict() établit une prédiction sur une instance unique de données.

Pour afficher le prix prédit de la course spécifiée, ajoutez le code suivant à la méthode TestSinglePrediction :

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

Exécutez le programme afin d’afficher le prix prédit de la course pour votre cas de test.

Félicitations ! Vous avez créé un modèle Machine Learning pour prédire le prix des courses de taxi, avez évalué sa précision et l’avez utilisé pour faire des prédictions. Vous trouverez le code source de ce tutoriel dans le dépôt GitHub dotnet/samples.

Étapes suivantes

Dans ce didacticiel, vous avez appris à :

  • Préparer et comprendre les données
  • Créer un pipeline d’apprentissage
  • Charger et transformer les données
  • Choisir un algorithme d’apprentissage
  • Effectuer l’apprentissage du modèle
  • Évaluer le modèle
  • Utiliser le modèle pour les prévisions

Passez au tutoriel suivant pour en savoir plus.