Share via


教學課程:使用回歸與 ML.NET 預測價格

本教學課程會示範如何使用 ML.NET 建置迴歸模型,特別針對紐約市的計程車費用預測價格。

在本教學課程中,您會了解如何:

  • 準備並了解資料
  • 載入並轉換資料
  • 選擇學習演算法
  • 將模型定型
  • 評估模型
  • 使用模型來進行預測

必要條件

建立主控台應用程式

  1. 建立名為 「TaxiFarePrediction」 的 C# 主控台應用程式

  2. 選擇 .NET 6 作為要使用的架構。 按一下 [ 建立 ] 按鈕。

  3. 在您專案中建立名為 Data 的目錄以用來儲存資料集和模型檔案。

  4. 安裝 Microsoft.MLMicrosoft.ML.FastTree NuGet 套件:

    注意

    除非另有說明,否則此樣本會使用所提及 NuGet 封裝的最新穩定版本。

    [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [管理 NuGet 套件]。 選擇 "nuget.org" 作為 [套件來源]、選取 [瀏覽] 索引標籤、搜尋 Microsoft.ML、從清單中選取該套件,然後選取 [安裝] 按鈕。 在 [預覽變更] 對話方塊上,選取 [確定] 按鈕,然後在 [授權接受] 對話方塊上,如果您同意所列套件的授權條款,請選取 [我接受]。 針對 Microsoft.ML.FastTree NuGet 套件執行相同的動作。

準備並了解資料

  1. 下載 taxi-fare-train.csvtaxi-fare-test.csv 資料集,並將它們儲存至您在上一個步驟所建立的 Data 資料夾。 我們可以使用這些資料集將機器學習模型定型,然後評估模型的準確程度。 這些資料集原先來自 NYC TLC Taxi Trip 資料集

  2. 方案總管中,以滑鼠右鍵按一下每個 *.csv檔案,然後選取 [屬性]。 在 [進階] 底下,將 [複製到輸出目錄] 的值變更為 [有更新時才複製]。

  3. 開啟 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:計程車車資總計是標籤。

建立資料類別

為輸入資料和預測建立類別:

  1. 在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增]>[新項目]

  2. 在 [ 新增專案 ] 對話方塊中,選取 [ 類別 ],然後將 [名稱] 欄位變更為 TaxiTrip.cs。 接著,選取 [新增] 按鈕。

  3. 將下列的 using 指示詞加入新檔案:

    using Microsoft.ML.Data;
    

移除現有的類別定義,然後將下列程式碼 (具有 TaxiTripTaxiTripFarePrediction 這兩個類別) 新增至 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 類別代表預測的結果。 包含一個套用 ScoreColumnNameAttribute 屬性的單一浮點數欄位 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")

定型模型的演算法需要 數值 特徵,因此您必須將類別資料 (VendorIdRateCodePaymentType) 值轉換成數位 (VendorIdEncodedRateCodeEncodedPaymentTypeEncoded) 。 若要進行該操作,請使用 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 存放庫中找到本教學課程的原始程式碼。

後續步驟

在本教學課程中,您已了解如何:

  • 準備並了解資料
  • 建立學習管線
  • 載入並轉換資料
  • 選擇學習演算法
  • 將模型定型
  • 評估模型
  • 使用模型來進行預測

前進到下一個教學課程來深入了解。