教學課程:使用回歸與 ML.NET 預測價格
本教學課程會示範如何使用 ML.NET 建置迴歸模型,特別針對紐約市的計程車費用預測價格。
在本教學課程中,您會了解如何:
- 準備並了解資料
- 載入並轉換資料
- 選擇學習演算法
- 將模型定型
- 評估模型
- 使用模型來進行預測
必要條件
- 已安裝 「.NET Desktop Development」 工作負載的Visual Studio 2022。
建立主控台應用程式
建立名為 「TaxiFarePrediction」 的 C# 主控台應用程式 。
選擇 .NET 6 作為要使用的架構。 按一下 [ 建立 ] 按鈕。
在您專案中建立名為 Data 的目錄以用來儲存資料集和模型檔案。
安裝 Microsoft.ML 和 Microsoft.ML.FastTree NuGet 套件:
注意
除非另有說明,否則此樣本會使用所提及 NuGet 封裝的最新穩定版本。
在[方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [管理 NuGet 套件]。 選擇 "nuget.org" 作為 [套件來源]、選取 [瀏覽] 索引標籤、搜尋 Microsoft.ML、從清單中選取該套件,然後選取 [安裝] 按鈕。 在 [預覽變更] 對話方塊上,選取 [確定] 按鈕,然後在 [授權接受] 對話方塊上,如果您同意所列套件的授權條款,請選取 [我接受]。 針對 Microsoft.ML.FastTree NuGet 套件執行相同的動作。
準備並了解資料
下載 taxi-fare-train.csv 和 taxi-fare-test.csv 資料集,並將它們儲存至您在上一個步驟所建立的 Data 資料夾。 我們可以使用這些資料集將機器學習模型定型,然後評估模型的準確程度。 這些資料集原先來自 NYC TLC Taxi Trip 資料集。
在方案總管中,以滑鼠右鍵按一下每個 *.csv檔案,然後選取 [屬性]。 在 [進階] 底下,將 [複製到輸出目錄] 的值變更為 [有更新時才複製]。
開啟 taxi-fare-train.csv 資料集,然後查看第一個資料列中的資料行標頭。 請查看每個資料行。 了解資料,並決定哪些資料行是 features,以及哪一個資料行是 label。
label
是您希望進行預測的資料行。 識別的 Features
是您提供模型來預測 Label
的輸入。
提供的資料集包含下列資料行:
- vendor_id:計程車廠商的識別碼是一項特徵。
- rate_code:計程車行程的費率類型是一項特徵。
- passenger_count:行程的乘客數目是一項特徵。
- trip_time_in_secs:行程所花費的時間長度。 您想要在行程結束之前預測行程的車資。 此時,您不知道車程需要多少時間。 因此,行程時間不是一項特徵,您將從模型中排除這個資料行。
- trip_distance:行程的距離是一項特徵。
- payment_type:付款方式 (現金或信用卡) 是一項特徵。
- fare_amount:計程車車資總計是標籤。
建立資料類別
為輸入資料和預測建立類別:
在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增]>[新項目]。
在 [ 新增專案 ] 對話方塊中,選取 [ 類別 ],然後將 [名稱] 欄位變更為 TaxiTrip.cs。 接著,選取 [新增] 按鈕。
將下列的
using
指示詞加入新檔案:using Microsoft.ML.Data;
移除現有的類別定義,然後將下列程式碼 (具有 TaxiTrip
和 TaxiTripFarePrediction
這兩個類別) 新增至 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
是輸入資料類別,並含有每個資料集資料行的定義。 使用 LoadColumnAttribute 屬性來指定資料集中來源資料行的索引。
TaxiTripFarePrediction
類別代表預測的結果。 包含一個套用 Score
ColumnNameAttribute 屬性的單一浮點數欄位 FareAmount
。 如果是回歸工作, [分數 ] 資料行會包含預測的標籤值。
注意
使用 float
型別表示輸入和預測資料類別中的浮點值。
定義資料和模型路徑
在 Program.cs 檔案頂端新增下列額外的 using
陳述式:
using Microsoft.ML;
using TaxiFarePrediction;
您必須建立三個欄位,保存含有資料集的檔案與用來儲存模型之檔案的檔案路徑:
_trainDataPath
會針對具有用來定型模型之資料集的檔案,包含檔案的路徑。_testDataPath
會針對具有用來評估模型之資料集的檔案,包含檔案的路徑。_modelPath
會針對儲存定型模型的檔案,包含檔案的路徑。
在 usings 區段正下方新增下列程式碼,以指定這些路徑和 _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");
所有 ML.NET 作業都是從 MLContext 類別開始。 將 mlContext
初始化會建立新的 ML.NET 環境,可在模型建立工作流程物件間共用。 就概念而言,類似於 Entity Framework 中的 DBContext
。
將變數初始化
將 Console.WriteLine("Hello World!")
行替換成下列程式碼,宣告並初始化 mlContext
變數:
MLContext mlContext = new MLContext(seed: 0);
將下列程式碼新增為下一行程式碼,以呼叫 Train
方法:
var model = Train(mlContext, _trainDataPath);
Train()
方法會執行下列工作:
- 載入資料。
- 擷取並轉換資料。
- 將模型定型。
- 傳回模型。
Train
方法會將模型定型。 使用下列程式碼在下方建立該方法:
ITransformer Train(MLContext mlContext, string dataPath)
{
}
載入並轉換資料
ML.NET 使用 IDataView 介面 作為有彈性且有效率的方式來描述數值或文字表格式資料。 IDataView
可載入文字檔案或即時進行 (例如 SQL 資料庫或記錄檔)。 將下列程式碼新增為 Train()
方法的第一行:
IDataView dataView = mlContext.Data.LoadFromTextFile<TaxiTrip>(dataPath, hasHeader: true, separatorChar: ',');
當您想要預測出租車車程車資時,資料 FareAmount
行是 Label
您將預測 (模型輸出) 。 CopyColumnsEstimator
使用轉換類別來複製 FareAmount
,並新增下列程式碼:
var pipeline = mlContext.Transforms.CopyColumns(outputColumnName: "Label", inputColumnName:"FareAmount")
定型模型的演算法需要 數值 特徵,因此您必須將類別資料 (VendorId
、 RateCode
和 PaymentType
) 值轉換成數位 (VendorIdEncoded
、 RateCodeEncoded
和 PaymentTypeEncoded
) 。 若要進行該操作,請使用 OneHotEncodingTransformer 轉換類別,這會將不同數值索引鍵值指派給每個資料行中的不同值,並新增下列程式碼:
.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"))
資料準備工作的最後一個步驟是使用 mlContext.Transforms.Concatenate
轉換類別,將所有特徵資料行合併為 Features 資料行。 根據預設,學習演算法只會處理來自 Features 資料行的特徵。 新增下列程式碼:
.Append(mlContext.Transforms.Concatenate("Features", "VendorIdEncoded", "RateCodeEncoded", "PassengerCount", "TripDistance", "PaymentTypeEncoded"))
選擇學習演算法
此問題是關於預測紐約市的計程車車資。 乍看之下,這可能看似單純取決於行程遠近。 不過,紐約計程車廠商會針對其他因素 (例如額外的乘客,或使用信用卡而非現金付費) 收取不同的金額。 您希望根據資料集當中的其他因素來預測價格值,這是一個實際值。 為了執行該操作,您選擇迴歸機器學習服務工作。
請將下列內容新增為 Train()
中的下一行程式碼,來將 FastTreeRegressionTrainer 機器學習服務工作新增到資料轉換定義:
.Append(mlContext.Regression.Trainers.FastTree());
將模型定型
在 Train()
方法中新增下列程式碼,調整模型使其符合定型的 dataview
,並傳回已定型的模型:
var model = pipeline.Fit(dataView);
Fit() 方法透過轉換資料集和套用定型來定型模型。
使用 Train()
方法中的下列程式碼行,傳回定型的模型:
return model;
評估模型
接下來,使用測試資料評估您的模型效能,以進行品質保證和驗證。 在 Train()
之後,使用下列程式碼建立 Evaluate()
方法:
void Evaluate(MLContext mlContext, ITransformer model)
{
}
Evaluate
方法會執行下列工作:
- 載入測試資料集。
- 建立迴歸評估工具。
- 評估模型並建立計量。
- 顯示計量。
使用下列程式碼,在方法呼叫下 Train
,將呼叫新增至新方法:
Evaluate(mlContext, model);
使用 LoadFromTextFile() 方法載入測試資料集。 透過在 Evaluate
方法中新增下列程式碼,使用此資料集作為品質檢查來評估模型:
IDataView dataView = mlContext.Data.LoadFromTextFile<TaxiTrip>(_testDataPath, hasHeader: true, separatorChar: ',');
接下來,透過將下列程式碼新增到 Evaluate()
來轉換 Test
資料:
var predictions = model.Transform(dataView);
Transform() 方法會針對測試資料集輸入資料列進行預測。
RegressionContext.Evaluate
方法會使用指定的資料集來計算 PredictionModel
的品質計量。 它傳回的 RegressionMetrics 物件包含迴歸評估工具所計算的整體計量。
若要顯示這些計量以判斷模型的品質,您必須先取得計量。 將下列程式碼加入為 Evaluate
方法中的下一行:
var metrics = mlContext.Regression.Evaluate(predictions, "Label", "Score");
在您設定好預測後,Evaluate() 方法會評估模型,將預測值與測試資料集中的實際 Labels
進行比較,並傳回模型的執行情況。
新增下列程式碼來評估模型並產生評估計量:
Console.WriteLine();
Console.WriteLine($"*************************************************");
Console.WriteLine($"* Model quality metrics evaluation ");
Console.WriteLine($"*------------------------------------------------");
RSquared 是迴歸模型的另一個評估計量。 RSquared 接受介於 0 和 1 之間的值。 其值越接近 1,模型就越好。 將下列程式碼新增至 Evaluate
方法,以顯示 RSquared 值:
Console.WriteLine($"* RSquared Score: {metrics.RSquared:0.##}");
RMS 是迴歸模型的評估計量之一。 此計量值越低,模型就越好。 將下列程式碼新增至 Evaluate
方法,以顯示 RMS 值:
Console.WriteLine($"* Root Mean Squared Error: {metrics.RootMeanSquaredError:#.##}");
使用模型來進行預測
請使用下列程式碼,在緊接著 Evaluate
方法之後,建立 TestSinglePrediction
方法:
void TestSinglePrediction(MLContext mlContext, ITransformer model)
{
}
TestSinglePrediction
方法會執行下列工作:
- 建立單一評論的測試資料。
- 根據測試資料預測費用金額。
- 合併測試資料和預測來進行報告。
- 顯示預測的結果。
使用下列程式碼,在方法呼叫下 Evaluate
,將呼叫新增至新方法:
TestSinglePrediction(mlContext, model);
將下列程式碼新增到 TestSinglePrediction()
來使用 PredictionEngine
預測車資:
var predictionFunction = mlContext.Model.CreatePredictionEngine<TaxiTrip, TaxiTripFarePrediction>(model);
PredictionEngine 是一種便利的 API,可讓您在單一資料執行個體上接著執行預測。 PredictionEngine
不是安全執行緒。 可接受在單一執行緒或原型環境中使用。 為了提升效能和執行緒安全性,請使用 PredictionEnginePool
服務,以建立 PredictionEngine
物件的 ObjectPool
供整個應用程式使用。 請參閱本指南,以瞭解如何在ASP.NET Core Web API 中使用 PredictionEnginePool
。
注意
PredictionEnginePool
服務延伸模組目前處於預覽狀態。
本教學課程會使用此類別內的一個測試行程。 您可以稍後新增其他案例來對此方法進行實驗。 透過建立 TaxiTrip
的執行個體,在 TestSinglePrediction()
方法中新增車程,以測試定型模型的費用預測:
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
};
接下來,根據計程車車程資料的單一執行個體預測車資,然後透過將下列內容作為 TestSinglePrediction()
方法的下一行程式碼,來將它傳遞至 PredictionEngine
:
var prediction = predictionFunction.Predict(taxiTripSample);
Predict() 函式會在資料的單一執行個體上進行預測。
若要顯示指定之車程的預測費用,請將下列程式碼加入到 TestSinglePrediction
方法:
Console.WriteLine($"**********************************************************************");
Console.WriteLine($"Predicted fare: {prediction.FareAmount:0.####}, actual fare: 15.5");
Console.WriteLine($"**********************************************************************");
執行程式以查看您測試案例的預測計程車車資。
恭喜! 您現在已成功建置可預測計程車車資的機器學習模型、評估了它的準確率,並且也使用它進行了預測。 您可以在 dotnet/samples GitHub 存放庫中找到本教學課程的原始程式碼。
後續步驟
在本教學課程中,您已了解如何:
- 準備並了解資料
- 建立學習管線
- 載入並轉換資料
- 選擇學習演算法
- 將模型定型
- 評估模型
- 使用模型來進行預測
前進到下一個教學課程來深入了解。