Esercitazione: Stimare i prezzi usando la regressione con ML.NET
Questa esercitazione illustra come creare un modello di regressione usando ML.NET per stimare i prezzi, in particolare le tariffe dei taxi di New York.
In questa esercitazione verranno illustrate le procedure per:
- Preparare e identificare i dati
- Caricare e trasformare i dati
- Scegliere un algoritmo di apprendimento
- Eseguire il training del modello
- Valutare il modello
- Usare il modello per le stime
Prerequisiti
- Visual Studio 2022 con il carico di lavoro "NET Desktop Development" installato.
Creare un'applicazione console
Creare un'applicazione console C# denominata "TaxiFarePrediction".
Scegliere .NET 6 come framework da usare. Fare clic sul pulsante Crea.
Creare una directory Data nel progetto per archiviare il set di dati e i file di modello.
Installare il pacchetto NuGet di Microsoft.ML e Microsoft.ML.FastTree :
Nota
Questo esempio usa la versione stabile più recente dei pacchetti NuGet menzionati a meno che non sia specificato in altro modo.
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Gestisci pacchetti NuGet. Scegliere "nuget.org" come Origine del pacchetto, selezionare la scheda Sfoglia, trovare Microsoft.ML, selezionare il pacchetto nell'elenco e quindi selezionare il pulsante Installa. Selezionare il pulsante OK nella finestra di dialogo Anteprima modifiche e quindi selezionare il pulsante Accetto nella finestra di dialogo Accettazione della licenza se si accettano le condizioni di licenza per i pacchetti elencati. Eseguire la stessa operazione per il pacchetto NuGet Microsoft.ML.FastTree.
Preparare e identificare i dati
Scaricare i set di dati taxi-fare-train.csv e taxi-fare-test.csv e salvarli nella cartella Data creata nel passaggio precedente. Questi set di dati vengono usati per eseguire il training del modello di machine learning e quindi valutarne l'accuratezza. Questi set di dati sono originariamente ricavati dal set di dati NYC TLC Taxi Trip.
In Esplora soluzioni fare clic con il pulsante destro del mouse su ognuno dei file *.csv e selezionare Proprietà. In Avanzate modificare il valore di Copia in Directory di output in Copia se più recente.
Aprire il set di dati taxi-fare-train.csv e controllare le intestazioni di colonna nella prima riga. Esaminare ognuna delle colonne. Identificare i dati e decidere quali colonne sono funzionalità e qual è l'etichetta.
label
è la colonna sulla quale eseguire le stime. Gli elementi Features
identificati sono gli input assegnati al modello per la stima di Label
.
Il set di dati fornito contiene le colonne seguenti:
- vendor_id: l'ID della società di taxi è una funzionalità.
- rate_code: il tipo di tariffa del viaggio in taxi è una funzionalità.
- passenger_count: il numero di passeggeri è una funzionalità.
- trip_time_in_secs: il tempo impiegato per il viaggio. Si vuole stimare la tariffa del viaggio prima del termine. In quel momento, non sai quanto tempo avrebbe atteso il viaggio. Il tempo non è pertanto una funzionalità e si escluderà questa colonna dal modello.
- trip_distance: la distanza del viaggio è una funzionalità.
- payment_type: il metodo di pagamento (contanti o carta di credito) è una funzionalità.
- fare_amount: la tariffa totale per il viaggio in taxi è l'etichetta.
Creare classi di dati
Creare le classi per i dati di input e le stime:
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e quindi selezionare Aggiungi>Nuovo elemento.
Nella finestra di dialogo Aggiungi nuovo elemento selezionare Classe e impostare il campo Nome su TaxiTrip.cs. Selezionare quindi il pulsante Aggiungi.
Aggiungere le direttive
using
seguenti al nuovo file:using Microsoft.ML.Data;
Rimuovere la definizione di classe esistente e aggiungere il codice seguente, che contiene le due classi TaxiTrip
e TaxiTripFarePrediction
, al file 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
è la classe dei dati di input e contiene le definizioni per ognuna delle colonne del set di dati. Usare l'attributo LoadColumnAttribute per specificare gli indici delle colonne di origine nel set di dati.
La classe TaxiTripFarePrediction
rappresenta i risultati previsti. Ha un singolo campo float, FareAmount
, a cui è applicato un attributo Score
ColumnNameAttribute. Nel caso dell'attività di regressione, la colonna Score contiene valori di etichetta stimati.
Nota
Usare il tipo float
per rappresentare i valori a virgola mobile nelle classi di dati di input e di previsione.
Definire i percorsi dei dati e del modello
Aggiungere le istruzioni using
seguenti all'inizio del file Program.cs:
using Microsoft.ML;
using TaxiFarePrediction;
È necessario creare tre campi per i percorsi dei file con i set di dati e del file per il salvataggio del modello:
_trainDataPath
contiene il percorso del file con il set di dati usato per il training del modello._testDataPath
contiene il percorso del file con il set di dati usato per la valutazione del modello._modelPath
contiene il percorso del file in cui è archiviato il modello sottoposto a training.
Aggiungere il codice seguente sotto la sezione usings per specificare tali percorsi e per la _textLoader
variabile:
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");
Tutte le operazioni di ML.NET iniziano nella classe MLContext. L'inizializzazione di mlContext
crea un nuovo ambiente ML.NET che può essere condiviso tra gli oggetti del flusso di lavoro di creazione del modello. Dal punto di vista concettuale è simile a DBContext
in Entity Framework.
Inizializzare le variabili
Sostituire la riga con il codice seguente per dichiarare e inizializzare la Console.WriteLine("Hello World!")
mlContext
variabile:
MLContext mlContext = new MLContext(seed: 0);
Aggiungere quanto segue come riga di codice successiva per chiamare il Train
metodo:
var model = Train(mlContext, _trainDataPath);
Il metodo Train()
esegue le attività seguenti:
- Carica i dati.
- Estrae e trasforma i dati.
- Esegue il training del modello.
- Restituisce il modello.
Il metodo Train
esegue il training del modello. Creare il metodo appena seguente usando il codice seguente:
ITransformer Train(MLContext mlContext, string dataPath)
{
}
Caricare e trasformare i dati
ML.NET usa l'interfaccia IDataView come modo flessibile ed efficiente per descrivere i dati numerici o tabulari. IDataView
può caricare file testo o in tempo reale (ad esempio, file di database SQL o di log). Aggiungere il codice seguente come prima riga del metodo Train()
:
IDataView dataView = mlContext.Data.LoadFromTextFile<TaxiTrip>(dataPath, hasHeader: true, separatorChar: ',');
Come si vuole stimare la tariffa di viaggio del taxi, la FareAmount
colonna è quella Label
che si stima (l'output del modello). Usare la CopyColumnsEstimator
classe di trasformazione per copiare FareAmount
e aggiungere il codice seguente:
var pipeline = mlContext.Transforms.CopyColumns(outputColumnName: "Label", inputColumnName:"FareAmount")
L'algoritmo che esegue il training del modello richiede funzionalità numeriche, quindi è necessario trasformare i valori di dati categorici (, e ) in numeri (VendorId
VendorIdEncoded
, RateCode
RateCodeEncoded
e PaymentType
PaymentTypeEncoded
). Per fare ciò usare la classe di trasformazione OneHotEncodingTransformer, che assegna valori chiave numerica diversi ai differenti valori in ognuna delle colonne e quindi aggiungere il codice seguente:
.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"))
L'ultimo passaggio della preparazione dei dati combina tutte le colonne di funzionalità nella colonna Features usando la classe di trasformazione mlContext.Transforms.Concatenate
. Per impostazione predefinita, un algoritmo di apprendimento elabora solo le funzionalità della colonna Features. Aggiungere il codice seguente:
.Append(mlContext.Transforms.Concatenate("Features", "VendorIdEncoded", "RateCodeEncoded", "PassengerCount", "TripDistance", "PaymentTypeEncoded"))
Scegliere un algoritmo di apprendimento
Questo problema riguarda la stima del costo di una corsa in taxi nella città di New York. A prima vista, potrebbe sembrare dipendere semplicemente dalla distanza percorsa. Tuttavia, le società di taxi di New York applicano un addebito per quantità variabili di altri fattori, come i passeggeri aggiuntivi o il pagamento tramite carta di credito anziché in contanti. Si vuole stimare il valore del prezzo, ovvero un valore reale, in base ad altri fattori nel set di dati. Per fare ciò, scegliere un'attività di apprendimento automatico di tipo regressione.
Aggiungere l'attività di apprendimento automatico FastTreeRegressionTrainer alle definizioni di trasformazione dei dati aggiungendo il codice seguente come riga successiva in Train()
:
.Append(mlContext.Regression.Trainers.FastTree());
Eseguire il training del modello
Adattare il modello all'elemento di training dataview
e restituire il modello sottoposto a training aggiungendo la seguente riga di codice al metodo Train()
:
var model = pipeline.Fit(dataView);
Il metodo Fit() esegue il training del modello trasformando il set di dati e applicando il training.
Restituire il modello di cui è stato eseguito il training con la riga di codice seguente nel metodo Train()
:
return model;
Valutare il modello
In seguito valutare le prestazioni del modello con i dati di test, per la convalida e il controllo di qualità. Creare il metodo Evaluate()
subito dopo Train()
con il codice seguente:
void Evaluate(MLContext mlContext, ITransformer model)
{
}
Il metodo Evaluate
esegue le attività seguenti:
- Carica il set di dati di test.
- Crea l'analizzatore della regressione.
- Valuta il modello e crea le metriche.
- Visualizza le metriche.
Aggiungere una chiamata al nuovo metodo direttamente sotto la chiamata al Train
metodo usando il codice seguente:
Evaluate(mlContext, model);
Caricare il set di dati di test usando il metodo LoadFromTextFile(). Valutare il modello usando il set di dati come controllo di qualità tramite l'aggiunta del codice seguente nel metodo Evaluate
:
IDataView dataView = mlContext.Data.LoadFromTextFile<TaxiTrip>(_testDataPath, hasHeader: true, separatorChar: ',');
Quindi trasformare i dati Test
aggiungendo il codice seguente a Evaluate()
:
var predictions = model.Transform(dataView);
Il metodo Transform() esegue stime per le righe di input della serie di dati di test.
Il metodo RegressionContext.Evaluate
calcola le metriche di qualità per l'istanza di PredictionModel
usando il set di dati specificato. Restituisce un oggetto RegressionMetrics che contiene le metriche complessive calcolate dagli analizzatori della regressione.
Per visualizzare tali elementi per determinare la qualità del modello, è prima necessario ottenere le metriche. Aggiungere il codice seguente al metodo Evaluate
come riga successiva:
var metrics = mlContext.Regression.Evaluate(predictions, "Label", "Score");
Dopo aver impostato la previsione, il metodo Evaluate() valuta il modello confrontando i valori stimati con gli oggetti Labels
effettivi presenti nel set di dati di test e restituisce le metriche relative alle prestazioni del modello.
Aggiungere il codice seguente per valutare il modello e produrre le metriche di valutazione:
Console.WriteLine();
Console.WriteLine($"*************************************************");
Console.WriteLine($"* Model quality metrics evaluation ");
Console.WriteLine($"*------------------------------------------------");
RSquared è un'altra metrica di valutazione dei modelli di regressione. Accetta valori compresi tra 0 e 1. I valori più vicini a 1 producono modelli migliori. Aggiungere il codice seguente nel metodo Evaluate
per visualizzare il valore di RSquared:
Console.WriteLine($"* RSquared Score: {metrics.RSquared:0.##}");
RMS è una delle metriche di valutazione del modello di regressione. Più basso è il valore, migliore è il modello. Aggiungere il codice seguente nel metodo Evaluate
per visualizzare il valore di RMS:
Console.WriteLine($"* Root Mean Squared Error: {metrics.RootMeanSquaredError:#.##}");
Usare il modello per le stime
Creare il metodo TestSinglePrediction
subito dopo il metodo Evaluate
, usando il codice seguente:
void TestSinglePrediction(MLContext mlContext, ITransformer model)
{
}
Il metodo TestSinglePrediction
esegue le attività seguenti:
- Crea un singolo commento di dati di test.
- Esegue la stima dell'importo della tariffa in base ai dati di test.
- Combina i dati di test e le stime per i report.
- Visualizza i risultati stimati.
Aggiungere una chiamata al nuovo metodo direttamente sotto la chiamata al Evaluate
metodo usando il codice seguente:
TestSinglePrediction(mlContext, model);
Usare PredictionEngine
per stimare l'importo della tariffa aggiungendo il codice seguente a TestSinglePrediction()
:
var predictionFunction = mlContext.Model.CreatePredictionEngine<TaxiTrip, TaxiTripFarePrediction>(model);
PredictionEngine è un'API utile che consente di eseguire una stima su una singola istanza di dati. PredictionEngine
non è thread-safe. È accettabile usare in ambienti a thread singolo o prototipo. Per migliorare le prestazioni e la thread safety negli ambienti di produzione, usare il PredictionEnginePool
servizio , che crea un ObjectPool
oggetto di PredictionEngine
oggetti da usare in tutta l'applicazione. Vedere questa guida su come usare PredictionEnginePool
in un'API Web di ASP.NET Core.
Nota
L'estensione del servizio PredictionEnginePool
è attualmente in anteprima.
In questa esercitazione viene usato un solo viaggio di test all'interno di questa classe. Successivamente, è possibile aggiungere altri scenari da sperimentare con il modello. Aggiungere una corsa per testare la stima dei costi del modello sottoposto a training nel metodo TestSinglePrediction()
creando un'istanza di 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
};
Successivamente eseguire la stima della tariffa in base a una singola istanza dei dati relativi al viaggio in taxi e passarla a PredictionEngine
aggiungendo il codice seguente come righe successive di codice nel metodo TestSinglePrediction()
:
var prediction = predictionFunction.Predict(taxiTripSample);
La funzione Predict() esegue una stima su una singola istanza di dati.
Per visualizzare la tariffa stimata della corsa specificata, aggiungere il codice seguente nel metodo TestSinglePrediction
:
Console.WriteLine($"**********************************************************************");
Console.WriteLine($"Predicted fare: {prediction.FareAmount:0.####}, actual fare: 15.5");
Console.WriteLine($"**********************************************************************");
Eseguire il programma per visualizzare la tariffa del taxi stimata per il test case.
Congratulazioni! È stato creato un modello di machine learning per la stima delle tariffe delle corse in taxi e ne è stata valutata l'accuratezza, quindi il modello è stato usato per produrre stime. È possibile trovare il codice sorgente per questa esercitazione nel repository GitHub dotnet/samples.
Passaggi successivi
In questa esercitazione sono state illustrate le procedure per:
- Preparare e identificare i dati
- Creare una pipeline di apprendimento
- Caricare e trasformare i dati
- Scegliere un algoritmo di apprendimento
- Eseguire il training del modello
- Valutare il modello
- Usare il modello per le stime
Passare all'esercitazione successiva per altre informazioni.