Oktatóanyag: Kerékpárkölcsönzési szolgáltatási igények előrejelzése idősorozat-elemzéssel és ML.NET
Megtudhatja, hogyan jelezheti előre a kerékpárkölcsönző szolgáltatás iránti keresletet egyváltozós idősor-elemzéssel egy SQL Server adatbázisban tárolt adatokon ML.NET.
Eben az oktatóanyagban az alábbiakkal fog megismerkedni:
- A probléma ismertetése
- Adatok betöltése adatbázisból
- Előrejelzési modell létrehozása
- Előrejelzési modell kiértékelése
- Előrejelzési modell mentése
- Előrejelzési modell használata
Előfeltételek
- A Visual Studio 2022-ben telepítve van a ".NET Desktop-fejlesztés" számítási feladat.
Idősor-előrejelzési minta áttekintése
Ez a minta egy C# .NET Core-konzolalkalmazás , amely a Singular Spectrum Analysis nevű egyváltozós idősorozat-elemzési algoritmussal előrejelzi a kerékpárkölcsönzések iránti keresletet. A minta kódja a GitHub dotnet/machinelearning-samples adattárában található.
A probléma ismertetése
A hatékony művelet végrehajtása érdekében a készletkezelés kulcsfontosságú szerepet játszik. Ha túl sok termék van raktáron, az azt jelenti, hogy a polcokon ülő el nem adott termékek nem termelnek bevételt. Ha túl kevés termék van, akkor elvesznek az értékesítések, és az ügyfelek a versenytársaktól vásárolnak. Ezért az állandó kérdés az, hogy mi az optimális készletmennyiség, amelyet kézben kell tartani? Az idősorozat-elemzés segít választ adni ezekre a kérdésekre az előzményadatok megtekintésével, a minták azonosításával, valamint az adatok felhasználásával az értékek jövőbeli előrejelzésére.
Az oktatóanyagban használt adatok elemzésének technikája egyváltozós idősoros elemzés. Az egyváltozós idősoros elemzés egyetlen numerikus megfigyelést vizsgál egy adott időszak alatt, meghatározott időközönként, például havi értékesítések esetén.
Az oktatóanyagban használt algoritmus a Singular Spectrum Analysis (SSA). Az SSA úgy működik, hogy egy idősort fő összetevőkből álló készletbe bont. Ezek az összetevők a trendeknek, a zajnak, a szezonalitásnak és sok más tényezőnek megfelelő jel részeiként értelmezhetők. Ezután ezeket az összetevőket rekonstruáljuk, és az értékek előrejelzésére használjuk a jövőben.
Konzolalkalmazás létrehozása
Hozzon létre egy "BikeDemandForecasting" nevű C#- konzolalkalmazást . Kattintson a Tovább gombra.
Válassza a .NET 6-ot a használni kívánt keretrendszerként. Kattintson a Létrehozás gombra.
A NuGet-csomag Microsoft.ML verziójának telepítése
Megjegyzés
Ez a minta az említett NuGet-csomagok legújabb stabil verzióját használja, hacsak másként nem rendelkezik.
- A Megoldáskezelő kattintson a jobb gombbal a projektre, és válassza a Manage NuGet Packages (NuGet-csomagok kezelése) lehetőséget.
- Válassza a "nuget.org" lehetőséget a Csomag forrásaként, válassza a Tallózás lapot, és keresse meg a Microsoft.ML.
- Jelölje be az Előzetes verzió belefoglalása jelölőnégyzetet.
- Válassza a Telepítés gombot.
- Válassza az OK gombot a Módosítások előnézete párbeszédpanelen, majd válassza az Elfogadom gombot a Licenc elfogadása párbeszédpanelen, ha elfogadja a felsorolt csomagok licencfeltételét.
- Ismételje meg ezeket a lépéseket a System.Data.SqlClient és a Microsoft.ML.TimeSeries esetében.
Az adatok előkészítése és értelmezése
- Hozzon létre egy Data nevű könyvtárat.
- Töltse le a DailyDemand.mdf adatbázisfájlt , és mentse a Data könyvtárba.
Megjegyzés
Az oktatóanyagban használt adatok az UCI Bike Sharing Datasetből származnak. Fanaee-T, Hadi, and Gama, Joao, "Event labeling combining combining ensemble detectors and background knowledge", Progress in Artificial Intelligence (2013): pp. 1-15, Springer Berlin Heidelberg, Web Link.
Az eredeti adatkészlet több, szezonalitásnak és időjárásnak megfelelő oszlopot tartalmaz. A rövidség kedvéért, és mivel az ebben az oktatóanyagban használt algoritmus csak egyetlen numerikus oszlop értékeit igényli, az eredeti adatkészletet úgy tömörítettük, hogy csak a következő oszlopokat tartalmazza:
- dteday: A megfigyelés dátuma.
- year: A megfigyelés kódolt éve (0=2011, 1=2012).
- cnt: Az adott napra vonatkozó kerékpárkölcsönzések teljes száma.
Az eredeti adatkészlet egy adatbázistáblára van leképezve, amely az alábbi sémával rendelkezik egy SQL Server-adatbázisban.
CREATE TABLE [Rentals] (
[RentalDate] DATE NOT NULL,
[Year] INT NOT NULL,
[TotalRentals] INT NOT NULL
);
Az alábbiakban az adatok egy mintáját találja:
RentalDate | Year | TotalRentals |
---|---|---|
1/1/2011 | 0 | 985 |
1/2/2011 | 0 | 801 |
1/3/2011 | 0 | 1349 |
Bemeneti és kimeneti osztályok létrehozása
Nyissa meg a Program.cs fájlt, és cserélje le a meglévő
using
utasításokat a következőre:using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms.TimeSeries; using System.Data.SqlClient;
Hozza létre az
ModelInput
osztályt.Program
A osztály alatt adja hozzá a következő kódot.public class ModelInput { public DateTime RentalDate { get; set; } public float Year { get; set; } public float TotalRentals { get; set; } }
A
ModelInput
osztály a következő oszlopokat tartalmazza:- RentalDate: A megfigyelés dátuma.
- Év: A megfigyelés kódolt éve (0=2011, 1=2012).
- TotalRentals: Az adott napra vonatkozó kerékpárkölcsönzések teljes száma.
Hozzon létre
ModelOutput
osztályt az újonnan létrehozottModelInput
osztály alatt.public class ModelOutput { public float[] ForecastedRentals { get; set; } public float[] LowerBoundRentals { get; set; } public float[] UpperBoundRentals { get; set; } }
A
ModelOutput
osztály a következő oszlopokat tartalmazza:- ForecastedRentals: Az előrejelzett időszak előrejelzett értékei.
- LowerBoundRentals: Az előrejelzett időszak előrejelzett minimális értékei.
- UpperBoundRentals: Az előrejelzett időszak előrejelzett maximális értékei.
Elérési utak definiálása és változók inicializálása
A using utasítások alatt változókat definiálhat az adatok helyének, kapcsolati sztring és a betanított modell mentési helyének tárolásához.
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;";
Inicializálja a
mlContext
változót egy új példánnyalMLContext
a következő sor hozzáadásával az elérési utak definiálása után.MLContext mlContext = new MLContext();
Az
MLContext
osztály minden ML.NET művelet kiindulási pontja, és az mlContext inicializálása egy új ML.NET környezetet hoz létre, amely megosztható a modelllétrehozási munkafolyamat-objektumok között. Ez fogalmilag hasonló az Entity FrameworkhezDBContext
.
Az adatok betöltése
Hozza létre
DatabaseLoader
, amely betölti a típusúModelInput
rekordokat.DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();
Adja meg a lekérdezést, amely betölti az adatokat az adatbázisból.
string query = "SELECT RentalDate, CAST(Year as REAL) as Year, CAST(TotalRentals as REAL) as TotalRentals FROM Rentals";
ML.NET algoritmusok elvárják, hogy az adatok típusa
Single
. Ezért az adatbázisból érkező numerikus értékeket, amelyek nem típusúakReal
, egyetlen pontosságú lebegőpontos értéket kell konvertálni a típusraReal
.A
Year
ésTotalRental
az oszlop egész típusú az adatbázisban.CAST
A beépített függvénnyel mindkettő a következőre lesz öntöttveReal
: .Hozzon létre egy elemet
DatabaseSource
az adatbázishoz való csatlakozáshoz és a lekérdezés végrehajtásához.DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, connectionString, query);
Töltse be az adatokat egy
IDataView
fájlba.IDataView dataView = loader.Load(dbSource);
Az adathalmaz két évnyi adatot tartalmaz. A betanításhoz csak az első év adatait használja a rendszer, a második évet a tényleges értékek és a modell által előállított előrejelzés összehasonlítására. Szűrje az adatokat az
FilterRowsByColumn
átalakítással.IDataView firstYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", upperBound: 1); IDataView secondYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", lowerBound: 1);
Az első évben csak az 1-nél kisebb oszlop értékei
Year
lesznek kiválasztva aupperBound
paraméter 1 értékre állításával. Ezzel szemben a második évben az 1-nél nagyobb vagy azzal egyenlő értékeket a paraméter 1 értékre állításávallowerBound
választja ki.
Idősor-elemzési folyamat definiálása
Definiáljon egy folyamatot, amely a SsaForecastingEstimator használatával előrejelezi az idősoros adathalmaz értékeit.
var forecastingPipeline = mlContext.Forecasting.ForecastBySsa( outputColumnName: "ForecastedRentals", inputColumnName: "TotalRentals", windowSize: 7, seriesLength: 30, trainSize: 365, horizon: 7, confidenceLevel: 0.95f, confidenceLowerBoundColumn: "LowerBoundRentals", confidenceUpperBoundColumn: "UpperBoundRentals");
A
forecastingPipeline
az első évre 365 adatpontot vesz fel, és az idősor adathalmazát a paraméter általseriesLength
megadott 30 napos (havi) intervallumokra osztja. Ezek a minták hetente vagy 7 napos időszakon keresztül lesznek elemezve. A következő időszak(ok) előrejelzett értékének meghatározásakor a rendszer az előző hét nap értékeit használja az előrejelzéshez. A modell úgy van beállítva, hogy hét időszakot jelezzen előre a jövőbe ahorizon
paraméter által meghatározott módon. Mivel az előrejelzés tájékozott becslés, nem mindig 100%-os pontosságú. Ezért érdemes ismerni az értékek tartományát a legjobb és legrosszabb esetben a felső és az alsó határ által meghatározottak szerint. Ebben az esetben az alsó és felső határ megbízhatósági szintje 95%-ra van állítva. A megbízhatósági szint ennek megfelelően növelhető vagy csökkenthető. Minél nagyobb az érték, annál szélesebb a tartomány a felső és az alsó határ között a kívánt megbízhatósági szint eléréséhez.Fit
A metódus használatával betanítsa a modellt, és illesztse be az adatokat a korábban definiálthozforecastingPipeline
.SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData);
A modell értékelése
A modell teljesítményének kiértékelése a jövő évi adatok előrejelzésével és a tényleges értékekkel való összehasonlításával.
Hozzon létre egy nevű
Evaluate
új segédprogramot a Program.cs fájl alján.Evaluate(IDataView testData, ITransformer model, MLContext mlContext) { }
A metóduson
Evaluate
belül előrejelezheti a második év adatait a metódus és aTransform
betanított modell használatával.IDataView predictions = model.Transform(testData);
A metódussal lekérheti az adatok tényleges értékeit
CreateEnumerable
.IEnumerable<float> actual = mlContext.Data.CreateEnumerable<ModelInput>(testData, true) .Select(observed => observed.TotalRentals);
Az előrejelzési értékek lekérése a
CreateEnumerable
metódussal.IEnumerable<float> forecast = mlContext.Data.CreateEnumerable<ModelOutput>(predictions, true) .Select(prediction => prediction.ForecastedRentals[0]);
Számítsa ki a tényleges és az előrejelzési értékek közötti különbséget, amelyet gyakran hibaként neveznek.
var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);
A teljesítmény méréséhez számítsa ki az abszolút hiba középértékét és a gyökér középértékét négyzetes hibaértékekkel.
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
A teljesítmény kiértékeléséhez a rendszer a következő metrikákat használja:
- Átlagos abszolút hiba: Azt méri, hogy az előrejelzések mennyire közel állnak a tényleges értékhez. Ez az érték 0 és végtelen között van. Minél közelebb van a 0-hoz, annál jobb a modell minősége.
- Gyökér középérték négyzetes hiba: Összefoglalja a modell hibáját. Ez az érték 0 és végtelen között van. Minél közelebb van a 0-hoz, annál jobb a modell minősége.
Adja ki a metrikákat a konzolon.
Console.WriteLine("Evaluation Metrics"); Console.WriteLine("---------------------"); Console.WriteLine($"Mean Absolute Error: {MAE:F3}"); Console.WriteLine($"Root Mean Squared Error: {RMSE:F3}\n");
Hívja meg az
Evaluate
alábbi metódust a metódus meghívásáhozFit()
.Evaluate(secondYearData, forecaster, mlContext);
A modell mentése
Ha elégedett a modellel, mentse későbbi használatra más alkalmazásokban.
Evaluate()
A metódus alatt hozzon létre egyTimeSeriesPredictionEngine
.TimeSeriesPredictionEngine
egy egyszerű módszer, amely egyetlen előrejelzést készít.var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);
Mentse a modellt a korábban definiált
modelPath
változó által meghatározott nevűMLModel.zip
fájlba. A modell mentéséhez használja aCheckpoint
metódust.forecastEngine.CheckPoint(mlContext, modelPath);
A modell használata a kereslet előrejelzéséhez
Evaluate
A metódus alatt hozzon létre egy nevű új segédprogram-metódustForecast
.void Forecast(IDataView testData, int horizon, TimeSeriesPredictionEngine<ModelInput, ModelOutput> forecaster, MLContext mlContext) { }
A metóduson
Forecast
belül használja a metódust aPredict
következő hét nap bérleti díjainak előrejelzéséhez.ModelOutput forecast = forecaster.Predict();
A tényleges és előrejelzési értékek igazítása hét időszakra.
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"; });
Iterálja végig az előrejelzés kimenetét, és jelenítse meg azt a konzolon.
Console.WriteLine("Rental Forecast"); Console.WriteLine("---------------------"); foreach (var prediction in forecastOutput) { Console.WriteLine(prediction); }
Az alkalmazás futtatása
A metódus meghívása
Checkpoint()
alatt hívja meg a metódustForecast
.Forecast(secondYearData, 7, forecastEngine, mlContext);
Futtassa az alkalmazást. Az alábbihoz hasonló kimenetnek meg kell jelennie a konzolon. A rövidség kedvéért a kimenet kondenzálva lett.
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
A tényleges és az előrejelzett értékek vizsgálata a következő kapcsolatokat mutatja:
Bár az előrejelzett értékek nem a bérleti díjak pontos számát jelzik előre, szűkebb értéktartományt biztosítanak, amely lehetővé teszi egy művelet számára az erőforrások használatának optimalizálását.
Gratulálunk! Sikeresen létrehozott egy idősorozatos gépi tanulási modellt a kerékpárkölcsönzési igények előrejelzéséhez.
Az oktatóanyag forráskódját a dotnet/machinelearning-samples adattárban találja.
Következő lépések
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: