یک برنامه نویس که هرآنچه را که یاد میگیرد در دفترچه یادداشت ویرگولیش یادداشت میکرد(!) حتی یک خط ! تا درصورت نیاز به آن رجوع کند...
پیشبینی قیمت ها با استفاده از Regression در ml.net (قسمت 4)
در این آموزش ما میخواهیم یک مدل رگرسیون regression model برای پیشبینی قیمت های کرایه تاکسی های شهر نیویورک استفاده کنیم !
1- ابتدا یک پروژه با نام TaxiFarePrediction از نوع .NET Core Console Application ایجاد کنید .
2- سپس یک پوشه با نام Data برای ذخیره data set (مجموعه داده) ها ایجاد کنید
3- بعد این پکیج های Microsoft.ML و Microsoft.ML.FastTree را نصب کنید.
آماده سازی و درک داده ها
1- فایل های taxi-fare-train.csv و taxi-fare-test.csv دانلود کرده و درون این پوشه قرار دهید سپس ازطریق پنجره Properties مقدار Copy to Output Directory را به Copy if newer تغییر دهید.
2- دیتاست taxi-fare-train.csv بازکنید و نگاهی به header های ستون ها بیندازید، خواهید فهمید که کدام ستون ها باید features باشند و کدام یک lable .
برچسب/lable ستونی است که میخواهیم پیشبینی اش کنیم. features ورودی های مدل برای پیشبینی کردن lable هستند.
دیتاست فراهم شده شامل ستون های زیر هست:
- آی دی فروشنده vendor_id : آی دی فروشنده تاکسی یک feature است.
- کد نرخ rate_code : نوع نرخ سفر تاکسی یک feature است.
- تعداد مسافر passenger_count : تعداد مسافر در سفر یک feature است.
- زمان سفر trip_time_in_secs : مدت زمانی که سفر به طول انجامید. میخواهید کرایه تاکسی را قبل از به اتمام رسیدن سفر پیشبینی کنید. در این لحظه نمیدانید سفر چقدر طول میکشد.بنابراین ، زمان سفر یک feature نیست و شما این ستون را از مدل خارج می کنید.
- مسافت سفر trip_distance : مسافت سفر یک feature است.
- نوع پرداخت payment_type : روش پرداخت (نقدی یا پرداخت آنلاین) یک feature است.
- مقدار کرایه fare_amount : کل کرایه تاکسی پرداختی یک label است
ساخت کلاس های داده
ساخت کلاس ها برای داده های ورودی پیشیبینی:
1- یک کلاس جدید با نام TaxiTrip.cs ایجاد کنید
2- فضای نام زیر را به آن اضافه کنید:
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 نتایج پیش بینی شده را نشان می دهد.یک فیلد float با نام FareAmount دارد که صفت Score از طریق ColumnNameAttribute گرفته است.در صورت کار رگرسیون، ستون Score شامل مقادیر lable پیش بینی شده است.
توجه: از نوع float برای نشان دادن مقادیر نقطه شناور(floating-point) در کلاسهای داده ورودی و پیش بینی استفاده کنید.
تعریف داده و مسیر مدل
ابتدا using های زیر را به فایل Program.cs اضافه کنید
using System;
using System.IO;
using Microsoft.ML;
همچنین ما نیاز به تعریف 3 فیلد برای نگهداری مسیر فایل های با data set ها و فایل برای ذخیره مدل داریم
- فیلد اول _trainDataPath : شامل مسیر فایل مجموعه داده های مورد استفاده برای آموزش مدل
- فیلد دوم _testDataPath : شامل مسیر فایل مجموعه داده های مورد استفاده برای ارزیابی مدل
- فیلد سوم _modelPath : شامل مسیر فایلی است که مدل آموزش دیده در آن ذخیره شده است.
کدهای زیر را بالای متد Main برای مشخص کردن مسیر ها و برای متغییر _textLoader بنویسید:
static readonly string _trainDataPath = Path.Combine(Environment.CurrentDirectory, "Data", "taxi-fare-train.csv");
static readonly string _testDataPath = Path.Combine(Environment.CurrentDirectory, "Data", "taxi-fare-test.csv");
static readonly string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "Model.zip");
تمام عملیات ML.NET در کلاس MLContext شروع می شود. با شروع mlContext یک محیط ML.NET جدید ایجاد می شود که می تواند در میان اشیاء گردش کار ایجاد مدل به اشتراک گذاشته شود. از نظر مفهومی مشابه DBContext در Entity Framework است.
مقداردهی اولیه متغییرها در متد Main
بجای خط Console.WriteLine("Hello World!") یک متغییر mlContext تعیرف و مقداردهی اولیه کنید:
MLContext mlContext = new MLContext(seed: 0);
و در خط بعدی متد Train صدا بزنید (بعدا می سازیمش)
var model = Train(mlContext, _trainDataPath);
متد Train وظایف زیر را انجام میدهد:
- لود کردن داده ها/بارگذاری داده ها
- استخراج و تبدیل کردن داده ها
- آموزش مدل
- برگرداندن مدل
متد Train مدل را آموزش میدهد. در زیر متد Main کد زیر را بنویسید:
public static ITransformer Train(MLContext mlContext, string dataPath)
{
}
بارگذاری و تبدیل دادها
(خوشتبختانه) ML.NET از کلاس IDataView به عنوان روشی انعطاف پذیر و کارآمد برای توصیف داده های جداول عددی یا متنی استفاده می کند.IDataView می تواند فایلهای متنی یا در زمان واقعی (مثلاً پایگاه داده SQL یا فایل های log) را بارگیری کند. در خط اول متد Train() کد زیر را بنویسید:
IDataView dataView = mlContext.Data.LoadFromTextFile<TaxiTrip>(dataPath, hasHeader: true, separatorChar: ',');
همانطور که می خواهید کرایه سفر تاکسی را پیش بینی کنید ، ستون FareAmount لیبل است که شما پیش بینی می کنید (خروجی مدل) از کلاس transformation CopyColumnsEstimator برای کپی کردن FareAmount استفاده کنید و کد زیر را اضافه کنید:
var pipeline = mlContext.Transforms.CopyColumns(outputColumnName: "Label", inputColumnName:"FareAmount")
الگوریتمی که مدل را آموزش می دهد نیاز به featureهای عددی(numeric features) دارد ، بنابراین شما باید مقادیر داده های دسته بندی شده (VendorId ، RateCode و PaymentType) را به اعداد (VendorIdEncoded ، RateCodeEncoded و PaymentTypeEncoded) تبدیل کنید.برای انجام این کار ، از کلاس transformation 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"))
آخرین مرحله در تهیه داده ، تمام ستون های feature را با استفاده از کلاس transformation mlContext.Transforms.Concatenate در یک ستون Features ترکیب می کند.به طور پیش فرض ، یک الگوریتم یادگیری فقط ویژگی های ستون Features را پردازش می کند.کد زیر را اضافه کنید:
.Append(mlContext.Transforms.Concatenate("Features", "VendorIdEncoded", "RateCodeEncoded", "PassengerCount", "TripTime", "TripDistance", "PaymentTypeEncoded"))
انتخاب الگوریتم یادگیری
این مشکل در مورد پیش بینی کرایه سفر تاکسی در شهر نیویورک است.در نگاه اول ممکن است به سادگی ،به مسافت طی شده بستگی داشته باشد.با این حال ، فروشندگان تاکسی در نیویورک مبلغ متفاوتی را برای فاکتورهای دیگر مانند مسافر اضافی یا پرداخت با کارت اعتباری به جای وجه نقد می پردازند. شما می خواهید براساس سایر عوامل موجود در مجموعه داده ، مقدار قیمت را که یک مقدار واقعی است پیش بینی کنید.برای انجام این کار ، شما یک وظیفه یادگیری ماشین رگرسیون/regression را انتخاب می کنید.
وظیفه یادگیری ماشین FastTreeRegressionTrainer را با اضافه کردن موارد زیر به عنوان خط بعدی کد در Train() به تعاریف تبدیل داده اضافه کنید:
.Append(mlContext.Regression.Trainers.FastTree());
آمئزش مدل
فیت Fit کردن مدل برای آموزش dataView و برگرداندن مدل آموزش دیده شده با اضافه کردن خط زیر به متد Train():
var model = pipeline.Fit(dataView);
متد Fit() با تبدیل دیتاست و اعمال آموزش ، مدل شما را آموزش می دهد.
مدل آموزش داده شده را با کد زیر در متد Train() برگردانید.
return model;
ارزیابی مدل
در مرحله بعدی ، عملکرد مدل خود را با داده های تستی خود برای اطمینان از کیفیت و اعتبار سنجی ارزیابی کنید. بعداز متد Train() متد Evalute() بنویسید:
private static void Evaluate(MLContext mlContext, ITransformer model)
{
}
متد Evaluate وظایف زیر را برعهده دارد
- بارگذاری/لودکردن داده های تستی
- ایجاد ارزیاب رگرسیون
- ارزیابی مدل و ایجاد معیارها
- نمایش معیارها
متد Evaluate بعد از متد Train در متد Main به صورت زیر صدا بزنید
Evaluate(mlContext, model);
مجموعه داده های تستی را با استفاده از متد LoadFromTextFile() لود کنید.با اضافه کردن کد زیر در متد Evaluate ، کیفیت مدل را با استفاده از این مجموعه داده ارزیابی کنید:
IDataView dataView = mlContext.Data.LoadFromTextFile<TaxiTrip>(_testDataPath, hasHeader: true, separatorChar: ',');
بعد ، داده های Test را با اضافه کردن کد زیر به EvaluateModel() تبدیل کنید:
var predictions = model.Transform(dataView);
متد Transform() برای ردیفهای ورودی مجموعه داده تستی پیش بینی می کند.
متد RegressionContext.Evaluate معیارهای کیفیت را برای PredictionModel با استفاده از مجموعه داده های مشخص شده محاسبه می کند که یک شی RegressionMetrics را برمیگرداند که شامل معیارهای کلی محاسبه شده توسط ارزیابان رگرسیون است.
برای نمایش اینها برای تعیین کیفیت مدل ، ابتدا باید معیارها را بدست آورید.کد زیر را به عنوان خط بعدی در متد Evaluate اضافه کنید:
var metrics = mlContext.Regression.Evaluate(predictions, "Label", "Score");
پس از تنظیم پیش بینی ، متد Evaluate() مدل را ارزیابی می کند ، که مقادیر پیش بینی شده را با Labelهای واقعی در مجموعه داده های تستی مقایسه می کند و معیارهای مربوط به نحوه عملکرد مدل را برمی گرداند.
برای ارزیابی مدل و تولید معیارهای ارزیابی ، کد زیر را اضافه کنید:
Console.WriteLine();
Console.WriteLine($"*************************************************");
Console.WriteLine($"* Model quality metrics evaluation ");
Console.WriteLine($"*------------------------------------------------");
یکی از معیارهای ارزیابی مدلهای رگرسیون RSquared است.RSquared مقادیر بین 0 و 1 را می گیرد. هرچه مقدار آن به 1 نزدیک تر باشد ، مدل بهتر می شود.برای نمایش مقدار RSquared ، کد زیر را به متد Evaluate اضافه کنید:
Console.WriteLine($"* RSquared Score: {metrics.RSquared:0.##}");
یکی دیگر از معیارهای ارزیابی مدل رگرسیون RMS است.هرچه پایین تر باشد ، مدل بهتر است.برای نمایش مقدار RMS ، کد زیر را به متد Evaluate اضافه کنید:
Console.WriteLine($"* Root Mean Squared Error: {metrics.RootMeanSquaredError:#.##}");
استفاده از مدل برای پیشبینی ها
بعد از متد Evaluate ، متد TestSinglePrediction بنویسید:
private static void TestSinglePrediction(MLContext mlContext, ITransformer model)
{
}
متد TestSinglePrediction وظایف زیر را برعهده دارد:
- ایجاد یک TaxiTrip
- پیشبینی کرایه را بر اساس داده تستی
- ترکیب داده تستی و پیشبینی برای ایجاد گزارش
- نمایش نتایج پیشبینی شده
کد زیر را در آخرین خط متد Main اضافه کنید:
TestSinglePrediction(mlContext, model);
با اضافه کردن کد زیر به TestSinglePrediction() از PredictionEngine برای پیش بینی کرایه استفاده کنید:
var predictionFunction = mlContext.Model.CreatePredictionEngine<TaxiTrip, TaxiTripFarePrediction>(model);
کلاس PredictionEngine یک API راحتی است که به شما امکان می دهد نمونه ای از داده را منتقل کنید و سپس یک پیش بینی در مورد آن انجام دهید.
در این آموزش از یک سفر تستی در این کلاس استفاده می شود. بعدا می توانید سناریوهای دیگری را برای آزمایش با مدل اضافه کنید. سفارشی را برای تست پیش بینی مدل آموزش دیده از هزینه در متد TestSinglePrediction() با ایجاد نمونه ای از 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
};
در مرحله بعد ،کرایه را بر اساس یک نمونه از داده taxi trip پیش بینی کرده و با اضافه کردن موارد زیر به عنوان خط های بعدی کد در متد TestSinglePrediction() ، آنرا به PredictionEngine منتقل کنید:
var prediction = predictionFunction.Predict(taxiTripSample);
تابع Predict() پیش بینی را در یک نمونه(single/تکی) از داده انجام می دهد.
برای نمایش کرایه پیش بینی شده از سفر مشخص شده ، کد زیر را به متد TestSinglePrediction اضافه کنید:
Console.WriteLine($"**********************************************************************");
Console.WriteLine($"Predicted fare: {prediction.FareAmount:0.####}, actual fare: 15.5");
Console.WriteLine($"**********************************************************************");
برنامه را اجرا کنید تا کرایه تاکسی پیش بینی شده برای تست مورد نظر خود را ببینید.
تبریک می گویم! اکنون یک مدل یادگیری ماشین با موفقیت برای پیش بینی کرایه سفر تاکسی ساخته اید ، صحت آن را ارزیابی کرده و از آن برای پیش بینی استفاده کرده اید. شما می توانید منبع این آموزش را در dotnet/samples مخزن GitHub پیدا کنید.
مطلبی دیگر از این انتشارات
مفاهیم بنیادی کوواریانس و همبستگی در یادگیری ماشین
مطلبی دیگر از این انتشارات
معرفی کپسول نت (قسمت دوم)
مطلبی دیگر از این انتشارات
پیاده سازی اولین شبکه عصبی برای طبقه بندی تصاویر (قسمت دوم)