Tutorial: Memperkirakan permintaan layanan penyewaan sepeda dengan analisis rangkaian waktu dan ML.NET
Pelajari cara memperkirakan permintaan untuk layanan penyewaan sepeda menggunakan analisis rangkaian waktu univariat pada data yang disimpan dalam database SQL Server dengan ML.NET.
Dalam tutorial ini, Anda akan mempelajari cara:
- Memahami masalahnya
- Memuat data dari database
- Membuat model prakiraan
- Mengevaluasi model prakiraan
- Menyimpan model prakiraan
- Menggunakan model prakiraan
Prasyarat
- Visual Studio 2022 dengan beban kerja ".NET Desktop Development" terinstal.
Gambaran umum sampel prakiraan rangkaian waktu
Sampel ini adalah aplikasi konsol C# .NET Core yang memperkirakan permintaan penyewaan sepeda menggunakan algoritma analisis rangkaian waktu univariat yang dikenal sebagai Analisis Spektrum Tunggal. Kode untuk sampel ini dapat ditemukan di repositori dotnet/machinelearning-samples di GitHub.
Memahami masalahnya
Untuk menjalankan operasi yang efisien, manajemen inventaris memainkan peran kunci. Memiliki terlalu banyak produk dalam stok berarti produk yang tidak terjual duduk di rak tidak menghasilkan pendapatan apa pun. Memiliki terlalu sedikit produk menyebabkan kehilangan penjualan dan pelanggan yang membeli dari pesaing. Oleh karena itu, pertanyaan konstan adalah, berapa jumlah inventori optimal yang harus ditangani? Analisis rangkaian waktu membantu memberikan jawaban atas pertanyaan-pertanyaan ini dengan melihat data historis, mengidentifikasi pola, dan menggunakan informasi ini untuk memperkirakan nilai beberapa waktu di masa mendatang.
Teknik untuk menganalisis data yang digunakan dalam tutorial ini adalah analisis rangkaian waktu univariat. Analisis rangkaian waktu Univariat melihat satu pengamatan numerik selama periode waktu tertentu pada interval tertentu seperti penjualan bulanan.
Algoritma yang digunakan dalam tutorial ini adalah Analisis Spektrum Tunggal (SSA). SSA bekerja dengan menguraikan rangkaian waktu menjadi satu set komponen utama. Komponen-komponen ini dapat ditafsirkan sebagai bagian dari sinyal yang sesuai dengan tren, kebisingan, musiman, dan banyak faktor lainnya. Kemudian, komponen-komponen ini direkonstruksi dan digunakan untuk memperkirakan nilai beberapa waktu di masa depan.
Membuat aplikasi konsol
Buat Aplikasi Konsol C# yang disebut "BikeDemandForecasting". Klik tombol Berikutnya.
Pilih .NET 6 sebagai kerangka kerja yang akan digunakan. Klik tombol Buat.
Menginstal paket NuGet versi Microsoft.ML
Catatan
Sampel ini menggunakan versi stabil terbaru dari paket NuGet yang disebutkan kecuali dinyatakan lain.
- Di Penjelajah Solusi, klik kanan proyek Anda dan pilih Kelola Paket NuGet.
- Pilih "nuget.org" sebagai Sumber paket, pilih tab Telusuri , cari Microsoft.ML.
- Centang kotak sertakan prarilis .
- Pilih tombol Instal.
- Pilih tombol OK pada dialog Pratinjau Perubahan lalu pilih tombol Saya Terima pada dialog Penerimaan Lisensi jika Anda setuju dengan ketentuan lisensi untuk paket yang tercantum.
- Ulangi langkah-langkah ini untuk System.Data.SqlClient dan Microsoft.ML.TimeSeries.
Menyiapkan dan memahami data
- Buat direktori yang disebut Data.
- Unduh file database DailyDemand.mdf dan simpan ke direktori Data.
Catatan
Data yang digunakan dalam tutorial ini berasal dari Himpunan Data Berbagi Sepeda UCI. Fanaee-T, Hadi, dan Gama, Joao, 'Pelabelan peristiwa menggabungkan detektor ansambel dan pengetahuan latar belakang', Kemajuan dalam Kecerdasan Buatan (2013): pp. 1-15, Springer Berlin Heidelberg, Web Link.
Himpunan data asli berisi beberapa kolom yang sesuai dengan musiman dan cuaca. Untuk kemudahan dan karena algoritma yang digunakan dalam tutorial ini hanya memerlukan nilai dari satu kolom numerik, himpunan data asli telah dikondensasikan untuk hanya menyertakan kolom berikut:
- dteday: Tanggal pengamatan.
- tahun: Tahun pengamatan yang dikodekan (0=2011, 1=2012).
- cnt: Jumlah total penyewaan sepeda untuk hari itu.
Himpunan data asli dipetakan ke tabel database dengan skema berikut dalam database SQL Server.
CREATE TABLE [Rentals] (
[RentalDate] DATE NOT NULL,
[Year] INT NOT NULL,
[TotalRentals] INT NOT NULL
);
Berikut ini adalah sampel data:
RentalDate | Tahun | TotalRentals |
---|---|---|
1/1/2011 | 0 | 985 |
1/2/2011 | 0 | 801 |
1/3/2011 | 0 | 1349 |
Membuat kelas input dan output
Buka file Program.cs dan ganti pernyataan yang ada
using
dengan yang berikut ini:using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms.TimeSeries; using System.Data.SqlClient;
Buat
ModelInput
kelas . Di bawahProgram
kelas , tambahkan kode berikut.public class ModelInput { public DateTime RentalDate { get; set; } public float Year { get; set; } public float TotalRentals { get; set; } }
Kelas
ModelInput
berisi kolom berikut:- RentalDate: Tanggal pengamatan.
- Tahun: Tahun pengamatan yang dikodekan (0=2011, 1=2012).
- TotalRentals: Jumlah total penyewaan sepeda untuk hari itu.
Buat
ModelOutput
kelas di bawah kelas yang baru dibuatModelInput
.public class ModelOutput { public float[] ForecastedRentals { get; set; } public float[] LowerBoundRentals { get; set; } public float[] UpperBoundRentals { get; set; } }
Kelas
ModelOutput
berisi kolom berikut:- ForecastedRentals: Nilai yang diprediksi untuk periode prakiraan.
- LowerBoundRentals: Nilai minimum yang diprediksi untuk periode yang diperkirakan.
- UpperBoundRentals: Nilai maksimum yang diprediksi untuk periode prakiraan.
Menentukan jalur dan menginisialisasi variabel
Di bawah pernyataan penggunaan menentukan variabel untuk menyimpan lokasi data, string koneksi, dan tempat menyimpan model terlatih Anda.
string rootDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../")); string dbFilePath = Path.Combine(rootDir, "Data", "DailyDemand.mdf"); string modelPath = Path.Combine(rootDir, "MLModel.zip"); var connectionString = $"Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename={dbFilePath};Integrated Security=True;Connect Timeout=30;";
Inisialisasi
mlContext
variabel dengan instansMLContext
baru dengan menambahkan baris berikut setelah menentukan jalur.MLContext mlContext = new MLContext();
Kelas
MLContext
adalah titik awal untuk semua operasi ML.NET, dan menginisialisasi mlContext membuat lingkungan ML.NET baru yang dapat dibagikan di seluruh objek alur kerja pembuatan model. Ini mirip, secara konseptual, keDBContext
dalam Kerangka Kerja Entitas.
Muat data
Buat
DatabaseLoader
yang memuat rekaman jenisModelInput
.DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();
Tentukan kueri untuk memuat data dari database.
string query = "SELECT RentalDate, CAST(Year as REAL) as Year, CAST(TotalRentals as REAL) as TotalRentals FROM Rentals";
algoritma ML.NET mengharapkan data berjenis
Single
. Oleh karena itu, nilai numerik yang berasal dari database yang bukan jenisReal
, nilai floating-point presisi tunggal, harus dikonversi keReal
.Kolom
Year
danTotalRental
keduanya adalah jenis bilangan bulat dalam database. Menggunakan fungsi bawaanCAST
, keduanya ditransmisikan keReal
.DatabaseSource
Buat untuk menyambungkan ke database dan menjalankan kueri.DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, connectionString, query);
Muat data ke dalam
IDataView
.IDataView dataView = loader.Load(dbSource);
Himpunan data berisi data senilai dua tahun. Hanya data dari tahun pertama yang digunakan untuk pelatihan, tahun kedua diadakan untuk membandingkan nilai aktual dengan perkiraan yang dihasilkan oleh model. Filter data menggunakan
FilterRowsByColumn
transformasi.IDataView firstYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", upperBound: 1); IDataView secondYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", lowerBound: 1);
Untuk tahun pertama, hanya nilai dalam
Year
kolom kurang dari 1 yang dipilih dengan mengatur parameter keupperBound
1. Sebaliknya, untuk tahun kedua, nilai yang lebih besar dari atau sama dengan 1 dipilih dengan mengatur parameter kelowerBound
1.
Menentukan alur analisis rangkaian waktu
Tentukan alur yang menggunakan SsaForecastingEstimator untuk memperkirakan nilai dalam himpunan data rangkaian waktu.
var forecastingPipeline = mlContext.Forecasting.ForecastBySsa( outputColumnName: "ForecastedRentals", inputColumnName: "TotalRentals", windowSize: 7, seriesLength: 30, trainSize: 365, horizon: 7, confidenceLevel: 0.95f, confidenceLowerBoundColumn: "LowerBoundRentals", confidenceUpperBoundColumn: "UpperBoundRentals");
forecastingPipeline
mengambil 365 poin data untuk tahun pertama dan sampel atau membagi himpunan data rangkaian waktu menjadi interval 30 hari (bulanan) seperti yang ditentukan olehseriesLength
parameter . Masing-masing sampel ini dianalisis melalui jendela mingguan atau 7 hari. Saat menentukan berapa nilai prakiraan untuk periode berikutnya, nilai dari tujuh hari sebelumnya digunakan untuk membuat prediksi. Model diatur ke perkiraan tujuh periode ke masa depan seperti yanghorizon
didefinisikan oleh parameter . Karena perkiraan adalah tebakan yang diinformasikan, itu tidak selalu 100% akurat. Oleh karena itu, ada baiknya untuk mengetahui rentang nilai dalam skenario terbaik dan terburuk seperti yang didefinisikan oleh batas atas dan bawah. Dalam hal ini, tingkat keyakinan untuk batas bawah dan atas diatur ke 95%. Tingkat keyakinan dapat ditingkatkan atau dikurangi sesuai. Semakin tinggi nilainya, semakin luas rentangnya antara batas atas dan bawah untuk mencapai tingkat keyakinan yang diinginkan.Fit
Gunakan metode untuk melatih model dan menyesuaikan data dengan yang ditentukanforecastingPipeline
sebelumnya.SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData);
Mengevaluasi model
Evaluasi seberapa baik performa model dengan memperkirakan data tahun depan dan membandingkannya dengan nilai aktual.
Buat metode utilitas baru yang disebut
Evaluate
di bagian bawah file Program.cs .Evaluate(IDataView testData, ITransformer model, MLContext mlContext) { }
Evaluate
Di dalam metode , perkirakan data tahun kedua dengan menggunakanTransform
metode dengan model terlatih.IDataView predictions = model.Transform(testData);
Dapatkan nilai aktual dari data dengan menggunakan
CreateEnumerable
metode .IEnumerable<float> actual = mlContext.Data.CreateEnumerable<ModelInput>(testData, true) .Select(observed => observed.TotalRentals);
Dapatkan nilai prakiraan dengan menggunakan
CreateEnumerable
metode .IEnumerable<float> forecast = mlContext.Data.CreateEnumerable<ModelOutput>(predictions, true) .Select(prediction => prediction.ForecastedRentals[0]);
Hitung perbedaan antara nilai aktual dan prakiraan, yang biasa disebut sebagai kesalahan.
var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);
Mengukur performa dengan menghitung nilai Kesalahan Absolut Rata-Rata dan Kesalahan Kuadrat Rata-Rata Akar.
var MAE = metrics.Average(error => Math.Abs(error)); // Mean Absolute Error var RMSE = Math.Sqrt(metrics.Average(error => Math.Pow(error, 2))); // Root Mean Squared Error
Untuk mengevaluasi performa, metrik berikut digunakan:
- Kesalahan Absolut Rata-rata: Mengukur seberapa dekat prediksi dengan nilai aktual. Nilai ini berkisar antara 0 dan tak terbatas. Semakin dekat ke 0, semakin baik kualitas model.
- Kesalahan Kuadrat Rata-Rata Akar: Meringkas kesalahan dalam model. Nilai ini berkisar antara 0 dan tak terbatas. Semakin dekat ke 0, semakin baik kualitas model.
Keluarkan metrik ke konsol.
Console.WriteLine("Evaluation Metrics"); Console.WriteLine("---------------------"); Console.WriteLine($"Mean Absolute Error: {MAE:F3}"); Console.WriteLine($"Root Mean Squared Error: {RMSE:F3}\n");
Panggil metode di
Evaluate
bawah ini yang memanggilFit()
metode .Evaluate(secondYearData, forecaster, mlContext);
Menyimpan model
Jika Anda puas dengan model Anda, simpan untuk digunakan nanti di aplikasi lain.
Evaluate()
Di bawah metode membuatTimeSeriesPredictionEngine
.TimeSeriesPredictionEngine
adalah metode kenyamanan untuk membuat prediksi tunggal.var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);
Simpan model ke file yang disebut
MLModel.zip
sebagaimana ditentukan oleh variabel yang ditentukanmodelPath
sebelumnya.Checkpoint
Gunakan metode untuk menyimpan model.forecastEngine.CheckPoint(mlContext, modelPath);
Menggunakan model untuk memperkirakan permintaan
Evaluate
Di bawah metode , buat metode utilitas baru yang disebutForecast
.void Forecast(IDataView testData, int horizon, TimeSeriesPredictionEngine<ModelInput, ModelOutput> forecaster, MLContext mlContext) { }
Forecast
Di dalam metode , gunakanPredict
metode untuk memperkirakan penyewaan selama tujuh hari ke depan.ModelOutput forecast = forecaster.Predict();
Sejajarkan nilai aktual dan prakiraan selama tujuh periode.
IEnumerable<string> forecastOutput = mlContext.Data.CreateEnumerable<ModelInput>(testData, reuseRowObject: false) .Take(horizon) .Select((ModelInput rental, int index) => { string rentalDate = rental.RentalDate.ToShortDateString(); float actualRentals = rental.TotalRentals; float lowerEstimate = Math.Max(0, forecast.LowerBoundRentals[index]); float estimate = forecast.ForecastedRentals[index]; float upperEstimate = forecast.UpperBoundRentals[index]; return $"Date: {rentalDate}\n" + $"Actual Rentals: {actualRentals}\n" + $"Lower Estimate: {lowerEstimate}\n" + $"Forecast: {estimate}\n" + $"Upper Estimate: {upperEstimate}\n"; });
Iterasi melalui output prakiraan dan tampilkan di konsol.
Console.WriteLine("Rental Forecast"); Console.WriteLine("---------------------"); foreach (var prediction in forecastOutput) { Console.WriteLine(prediction); }
Menjalankan aplikasi
Di bawah ini memanggil
Checkpoint()
metode memanggilForecast
metode .Forecast(secondYearData, 7, forecastEngine, mlContext);
Jalankan aplikasi. Output yang mirip dengan yang di bawah ini akan muncul di konsol. Untuk keringkasan, output telah dikondensasi.
Evaluation Metrics --------------------- Mean Absolute Error: 726.416 Root Mean Squared Error: 987.658 Rental Forecast --------------------- Date: 1/1/2012 Actual Rentals: 2294 Lower Estimate: 1197.842 Forecast: 2334.443 Upper Estimate: 3471.044 Date: 1/2/2012 Actual Rentals: 1951 Lower Estimate: 1148.412 Forecast: 2360.861 Upper Estimate: 3573.309
Inspeksi nilai aktual dan prakiraan menunjukkan hubungan berikut:
Meskipun nilai yang diperkirakan tidak memprediksi jumlah sewa yang tepat, nilai tersebut memberikan rentang nilai yang lebih sempit yang memungkinkan operasi untuk mengoptimalkan penggunaan sumber daya mereka.
Selamat! Anda sekarang telah berhasil membangun model pembelajaran mesin rangkaian waktu untuk memperkirakan permintaan penyewaan sepeda.
Anda dapat menemukan kode sumber untuk tutorial ini di repositori dotnet/machinelearning-samples .