使用ML.NET预测纽约出租车费
有了上一篇《.NET Core玩轉(zhuǎn)機器學習》打基礎(chǔ),這一次我們以紐約出租車費的預測做為新的場景案例,來體驗一下回歸模型。
場景概述
我們的目標是預測紐約的出租車費,乍一看似乎僅僅取決于行程的距離和時長,然而紐約的出租車供應(yīng)商對其他因素,如額外的乘客數(shù)、信用卡而不是現(xiàn)金支付等,會綜合考慮而收取不同數(shù)額的費用。紐約市官方給出了一份樣本數(shù)據(jù)。
?
確定策略
為了能夠預測出租車費,我們選擇通過機器學習建立一個回歸模型。使用官方提供的真實數(shù)據(jù)進行擬合,在訓練模型的過程中確定真正能影響出租車費的決定性特征。在獲得模型后,對模型進行評估驗證,如果偏差在接受的范圍內(nèi),就以這個模型來對新的數(shù)據(jù)進行預測。
?
解決方案
創(chuàng)建項目
看過上一篇文章的讀者,就比較輕車熟路了,推薦使用Visual Studio 2017創(chuàng)建一個.NET Core的控制臺應(yīng)用程序項目,命名為TaxiFarePrediction。使用NuGet包管理工具添加對Microsoft.ML的引用。
準備數(shù)據(jù)集
下載訓練數(shù)據(jù)集taxi-fare-train.csv和驗證數(shù)據(jù)集taxi-fare-test.csv,數(shù)據(jù)集的內(nèi)容類似為:
vendor_id,rate_code,passenger_count,trip_time_in_secs,trip_distance,payment_type,fare_amount
VTS,1,1,1140,3.75,CRD,15.5
VTS,1,1,480,2.72,CRD,10.0
VTS,1,1,1680,7.8,CSH,26.5
VTS,1,1,600,4.73,CSH,14.5
VTS,1,1,600,2.18,CRD,9.5
...
對字段簡單說明一下:
字段名 含義 說明 vendor_id 供應(yīng)商編號 特征值 rate_code 比率碼 特征值 passenger_count 乘客人數(shù) 特征值 trip_time_in_secs 行程時長 特征值 trip_distance 行程距離 特征值 payment_type 支付類型 特征值 fare_amount 費用 目標值 在項目中添加一個Data目錄,將兩份數(shù)據(jù)集復制到該目錄下,對文件屬性設(shè)置“復制到輸出目錄”。
定義數(shù)據(jù)類型和路徑
首先聲明相關(guān)的包引用。
using System;
using Microsoft.ML.Models;
using Microsoft.ML.Runtime;
using Microsoft.ML.Runtime.Api;
using Microsoft.ML.Trainers;
using Microsoft.ML.Transforms;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML;
在Main函數(shù)的上方定義一些使用到的常量。
接下來定義一些使用到的數(shù)據(jù)類型,以及和數(shù)據(jù)集中每一行的位置對應(yīng)關(guān)系。
public class TaxiTrip
{
? ? [Column(ordinal: "0")]
? ? public string vendor_id;
? ? [Column(ordinal: "1")]
? ? public string rate_code;
? ? [Column(ordinal: "2")]
? ? public float passenger_count;
? ? [Column(ordinal: "3")]
? ? public float trip_time_in_secs;
? ? [Column(ordinal: "4")]
? ? public float trip_distance;
? ? [Column(ordinal: "5")]
? ? public string payment_type;
? ? [Column(ordinal: "6")]
? ? public float fare_amount;
}
public class TaxiTripFarePrediction
{
? ? [ColumnName("Score")]
? ? public float fare_amount;
}
static class TestTrips
{
? ? internal static readonly TaxiTrip Trip1 = new TaxiTrip
? ? {
? ? ? ? vendor_id = "VTS",
? ? ? ? rate_code = "1",
? ? ? ? passenger_count = 1,
? ? ? ? trip_distance = 10.33f,
? ? ? ? payment_type = "CSH",
? ? ? ? fare_amount = 0 // predict it. actual = 29.5
? ? };
}
創(chuàng)建處理過程
創(chuàng)建一個Train方法,定義對數(shù)據(jù)集的處理過程,隨后聲明一個模型接收訓練后的結(jié)果,在返回前把模型保存到指定的位置,以便以后直接取出來使用不需要再重新訓練。
public static async Task<PredictionModel<TaxiTrip, TaxiTripFarePrediction>> Train()
{
? ? var pipeline = new LearningPipeline();
? ? pipeline.Add(new TextLoader<TaxiTrip>(DataPath, useHeader: true, separator: ","));
? ? pipeline.Add(new ColumnCopier(("fare_amount", "Label")));
? ? pipeline.Add(new CategoricalOneHotVectorizer("vendor_id",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "rate_code",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "payment_type"));
? ? pipeline.Add(new ColumnConcatenator("Features",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "vendor_id",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "rate_code",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "passenger_count",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "trip_distance",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "payment_type"));
? ? pipeline.Add(new FastTreeRegressor());
? ? PredictionModel<TaxiTrip, TaxiTripFarePrediction> model = pipeline.Train<TaxiTrip, TaxiTripFarePrediction>();
? ? if (!Directory.Exists(ModelDirectory))
? ? {
? ? ? ? Directory.CreateDirectory(ModelDirectory);
? ? }
? ? await model.WriteAsync(ModelPath);
? ? return model;
}
評估驗證模型
創(chuàng)建一個Evaluate方法,對訓練后的模型進行驗證評估。
public static void Evaluate(PredictionModel<TaxiTrip, TaxiTripFarePrediction> model)
{
? ? var testData = new TextLoader<TaxiTrip>(TestDataPath, useHeader: true, separator: ",");
? ? var evaluator = new RegressionEvaluator();
? ? RegressionMetrics metrics = evaluator.Evaluate(model, testData);
? ? // Rms should be around 2.795276
? ? Console.WriteLine("Rms=" + metrics.Rms);
? ? Console.WriteLine("RSquared = " + metrics.RSquared);
}
預測新數(shù)據(jù)
定義一個被用于預測的新數(shù)據(jù),對于各個特征進行恰當?shù)刭x值。
static class TestTrips
{
? ? internal static readonly TaxiTrip Trip1 = new TaxiTrip
? ? {
? ? ? ? vendor_id = "VTS",
? ? ? ? rate_code = "1",
? ? ? ? passenger_count = 1,
? ? ? ? trip_distance = 10.33f,
? ? ? ? payment_type = "CSH",
? ? ? ? fare_amount = 0 // predict it. actual = 29.5
? ? };
}
預測的方法很簡單,prediction即預測的結(jié)果,從中打印出預測的費用和真實費用。
var prediction = model.Predict(TestTrips.Trip1);Console.WriteLine("Predicted fare: {0}, actual fare: 29.5", prediction.fare_amount);?
運行結(jié)果
到此我們完成了所有的步驟,關(guān)于這些代碼的詳細說明,可以參看《Tutorial: Use ML.NET to Predict New York Taxi Fares (Regression)》,只是要注意該文中的部分代碼有誤,由于使用到了C# 7.1的語法特性,本文的代碼是經(jīng)過了修正的。完整的代碼如下:
using System;
using Microsoft.ML.Models;
using Microsoft.ML.Runtime;
using Microsoft.ML.Runtime.Api;
using Microsoft.ML.Trainers;
using Microsoft.ML.Transforms;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML;
using System.Threading.Tasks;
using System.IO;
namespace TaxiFarePrediction
{
? ? class Program
? ? {
? ? ? ? const string DataPath = @".\Data\taxi-fare-test.csv";
? ? ? ? const string TestDataPath = @".\Data\taxi-fare-train.csv";
? ? ? ? const string ModelPath = @".\Models\Model.zip";
? ? ? ? const string ModelDirectory = @".\Models";
? ? ? ? public class TaxiTrip
? ? ? ? {
? ? ? ? ? ? [Column(ordinal: "0")]
? ? ? ? ? ? public string vendor_id;
? ? ? ? ? ? [Column(ordinal: "1")]
? ? ? ? ? ? public string rate_code;
? ? ? ? ? ? [Column(ordinal: "2")]
? ? ? ? ? ? public float passenger_count;
? ? ? ? ? ? [Column(ordinal: "3")]
? ? ? ? ? ? public float trip_time_in_secs;
? ? ? ? ? ? [Column(ordinal: "4")]
? ? ? ? ? ? public float trip_distance;
? ? ? ? ? ? [Column(ordinal: "5")]
? ? ? ? ? ? public string payment_type;
? ? ? ? ? ? [Column(ordinal: "6")]
? ? ? ? ? ? public float fare_amount;
? ? ? ? }
? ? ? ? public class TaxiTripFarePrediction
? ? ? ? {
? ? ? ? ? ? [ColumnName("Score")]
? ? ? ? ? ? public float fare_amount;
? ? ? ? }
? ? ? ? static class TestTrips
? ? ? ? {
? ? ? ? ? ? internal static readonly TaxiTrip Trip1 = new TaxiTrip
? ? ? ? ? ? {
? ? ? ? ? ? ? ? vendor_id = "VTS",
? ? ? ? ? ? ? ? rate_code = "1",
? ? ? ? ? ? ? ? passenger_count = 1,
? ? ? ? ? ? ? ? trip_distance = 10.33f,
? ? ? ? ? ? ? ? payment_type = "CSH",
? ? ? ? ? ? ? ? fare_amount = 0 // predict it. actual = 29.5
? ? ? ? ? ? };
? ? ? ? }
? ? ? ? public static async Task<PredictionModel<TaxiTrip, TaxiTripFarePrediction>> Train()
? ? ? ? {
? ? ? ? ? ? var pipeline = new LearningPipeline();
? ? ? ? ? ? pipeline.Add(new TextLoader<TaxiTrip>(DataPath, useHeader: true, separator: ","));
? ? ? ? ? ? pipeline.Add(new ColumnCopier(("fare_amount", "Label")));
? ? ? ? ? ? pipeline.Add(new CategoricalOneHotVectorizer("vendor_id",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "rate_code",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "payment_type"));
? ? ? ? ? ? pipeline.Add(new ColumnConcatenator("Features",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "vendor_id",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "rate_code",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "passenger_count",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "trip_distance",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "payment_type"));
? ? ? ? ? ? pipeline.Add(new FastTreeRegressor());
? ? ? ? ? ? PredictionModel<TaxiTrip, TaxiTripFarePrediction> model = pipeline.Train<TaxiTrip, TaxiTripFarePrediction>();
? ? ? ? ? ? if (!Directory.Exists(ModelDirectory))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Directory.CreateDirectory(ModelDirectory);
? ? ? ? ? ? }
? ? ? ? ? ? await model.WriteAsync(ModelPath);
? ? ? ? ? ? return model;
? ? ? ? }
? ? ? ? public static void Evaluate(PredictionModel<TaxiTrip, TaxiTripFarePrediction> model)
? ? ? ? {
? ? ? ? ? ? var testData = new TextLoader<TaxiTrip>(TestDataPath, useHeader: true, separator: ",");
? ? ? ? ? ? var evaluator = new RegressionEvaluator();
? ? ? ? ? ? RegressionMetrics metrics = evaluator.Evaluate(model, testData);
? ? ? ? ? ? // Rms should be around 2.795276
? ? ? ? ? ? Console.WriteLine("Rms=" + metrics.Rms);
? ? ? ? ? ? Console.WriteLine("RSquared = " + metrics.RSquared);
? ? ? ? }
? ? ? ? static async Task Main(string[] args)
? ? ? ? {
? ? ? ? ? ? PredictionModel<TaxiTrip, TaxiTripFarePrediction> model = await Train();
? ? ? ? ? ? Evaluate(model);
? ? ? ? ? ? var prediction = model.Predict(TestTrips.Trip1);
? ? ? ? ? ? Console.WriteLine("Predicted fare: {0}, actual fare: 29.5", prediction.fare_amount);
? ? ? ? }
? ? }
}
不知不覺我們的ML.NET之旅又向前進了一步,是不是對于使用.NET Core進行機器學習解決現(xiàn)實生活中的問題更有興趣了?請保持關(guān)注吧。
原文地址: http://www.cnblogs.com/BeanHsiang/p/9017618.html?
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的使用ML.NET预测纽约出租车费的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用ASP.NET Core 2.0 建立
- 下一篇: 使用ML.NET实现情感分析[新手篇]