Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Megtudhatja, hogyan jelezheti előre a kerékpárkölcsönző szolgáltatás iránti keresletet az SQL Server-adatbázisban ML.NET tárolt adatok egyváltozós idősor-elemzésével.
Ebben az oktatóanyagban a következőket sajátíthatja el:
- 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 vagy újabb verziója telepítve van a .NET Desktop Development számítási feladattal.
Idősor-előrejelzési minta áttekintése
Ez a minta egy C#-konzolalkalmazás , amely a kerékpárkölcsönzések iránti keresletet egy nem változó idősorozat-elemzési algoritmus, az úgynevezett Singular Spectrum Analysis használatával jelzi előre. 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ásához a leltárkezelés kulcsfontosságú szerepet játszik. Ha túl sok termék van raktáron, az azt jelenti, hogy a polcokon ülő eladatlan termékek nem termelnek bevételt. Ha túl kevés termék van, akkor elvesznek az értékesítések és a versenytársaktól vásárolt ügyfelek. 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 és az adatok felhasználásával az értékek jövőbeli előrejelzéséhez.
Az ebben 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 vesz igénybe adott időközönként, például havi értékesítések során.
Az oktatóanyagban használt algoritmus a Singular Spectrum Analysis (SSA). Az SSA úgy működik, hogy egy idősort fő összetevők készletére 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 szolgálnak 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 8-at a használni kívánt keretrendszerként. Kattintson a Létrehozás gombra.
A Microsoft.ML verziójú NuGet-csomag 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őben kattintson a jobb gombbal a projektre, és válassza a 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, keresse meg Microsoft.ML.
- Jelölje be az Include prerelease (Előzetes befoglalás) jelölőnégyzetet.
- Válassza a Telepítés gombot.
- Kattintson az OK gombra a Változá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 az adatkönyvtárba .
Megjegyzés:
Az oktatóanyagban használt adatok az UCI Bike Sharing Datasetből származnak. Hadi Fanaee-T és João Gama, "Eseménycímkézés együttes detektorok és háttértudás kombinálásával", Progress in Artificial Intelligence (2013): pp. 1-15, Springer Berlin Heidelberg, Weblink.
Az eredeti adatkészlet több, a szezonalitásnak és az időjárásnak megfelelő oszlopot tartalmaz. A rövidség kedvéért, és mivel 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.
- év: 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ábbi adatok mintája:
| RentalDate | Év | 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 Program.cs fájlt, és cserélje le a meglévő
usingirányelveket a következőre:using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms.TimeSeries; using System.Data.SqlClient;Osztály létrehozása
ModelInput.ProgramAz 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; } }Az
ModelInputosztá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
ModelOutputosztályt az újonnan létrehozottModelInputosztály alatt.public class ModelOutput { public float[] ForecastedRentals { get; set; } public float[] LowerBoundRentals { get; set; } public float[] UpperBoundRentals { get; set; } }Az
ModelOutputosztá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
usingAz irányelvek alatt változókat határozunk meg az adatok helyének, a kapcsolati sztringnek é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
mlContextváltozót egy új példánnyalMLContextaz elérési utak meghatározása után a következő sor hozzáadásával.MLContext mlContext = new MLContext();Az
MLContextosztály az összes ML.NET művelet kiindulópontja, és az mlContext inicializálása ú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.
Töltse be az adatokat
Olyan rekordokat hoz létre
DatabaseLoader, amelyek betöltik a rekordokatModelInput.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 legyen
Single. Ezért az adatbázisból érkező numerikus értékeket, amelyek nemRealtípusúak, az egyszeres pontosságú lebegőpontos értékké kellReal-re konvertálni.YearAzTotalRentaloszlopok mind egész típusúak az adatbázisban.CASTA beépített függvény használatával mindkettőt a rendszer a következőreRealöntötte: .Hozzon létre egy kapcsolatot
DatabaseSourceaz adatbázissal, és hajtsa végre a lekérdezést.DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, connectionString, query);Töltse be az adatokat egy
IDataView.IDataView dataView = loader.Load(dbSource);Az adathalmaz két évnyi adatot tartalmaz. A betanításhoz csak az első év adatai használhatók, a második év pedig a tényleges értékek összehasonlítására szolgál a modell által előállított előrejelzéssel. 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
Yearlesznek kiválasztva aupperBoundparaméter 1 értékre állításával. Ezzel szemben a második évben az 1-nél nagyobb vagy azzal egyenlő értékeket választja ki alowerBoundparaméter 1 értékre állításával.
Idősor-elemzési folyamat definiálása
Definiáljon egy folyamatot, amely a SsaForecastingEstimatort használja az idősoros adathalmaz értékeinek előrejelzéséhez.
var forecastingPipeline = mlContext.Forecasting.ForecastBySsa( outputColumnName: "ForecastedRentals", inputColumnName: "TotalRentals", windowSize: 7, seriesLength: 30, trainSize: 365, horizon: 7, confidenceLevel: 0.95f, confidenceLowerBoundColumn: "LowerBoundRentals", confidenceUpperBoundColumn: "UpperBoundRentals");Az
forecastingPipelineelső évben 365 adatpontot vesz fel, és a paraméter által megadott 30 napos (havi) időközökre osztja az idősor adathalmazátseriesLength. Ezeket a mintákat hetente vagy 7 napos időszakon keresztül elemzik. 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 ahorizonparaméter által meghatározott módon. Mivel az előrejelzés megalapozott becslés, nem mindig 100% pontos. Ezért érdemes ismerni az értékek tartományát a felső és az alsó határ által meghatározott legjobb és legrosszabb forgatókönyvekben. Ebben az esetben az alsó és a felső határ megbízhatósági szintje 95%. A megbízhatósági szint ennek megfelelően növelhető vagy csökkenthető. Minél magasabb 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.Ezzel a
Fitmódszerrel betanítsa a modellt, és illeszkedjen az adatokhoz a korábban definiálthozforecastingPipeline.SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData);
A modell kiértékelése
Értékelje ki, hogy a modell milyen jól teljesít a jövő évi adatok előrejelzésével és a tényleges értékekkel való összehasonlításával.
Hozzon létre egy új segédprogrammetódust
Evaluatea Program.cs fájl alján.Evaluate(IDataView testData, ITransformer model, MLContext mlContext) { }A metóduson
Evaluatebelül a betanított modellel előre jelezheti a második év adatait.TransformIDataView predictions = model.Transform(testData);A metódus használatával 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
CreateEnumerablemódszerrel.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 általában hibaként nevezünk.
var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);A teljesítmény méréséhez számítsa ki az átlagos abszolút hibát és a gyökátlag négyzetes hibát.
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 ErrorA teljesítmény kiértékeléséhez a következő metrikákat használja a rendszer:
- Átlagos abszolút hiba: Azt méri, hogy az előrejelzések milyen közel állnak a tényleges értékhez. Ez az érték 0 és végtelen közötti. Minél közelebb van a 0-hoz, annál jobb a modell minősége.
- Négyzetes középérték hiba: A modell hibájának összegzése. Ez az érték 0 és végtelen közötti. 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
Evaluatealá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.TimeSeriesPredictionEngineegy egyszerű módszer az egyszeri előrejelzések készítésére.var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);Mentse a modellt a korábban definiált
MLModel.zipváltozó által megadott fájlbamodelPath. A metódus használatávalCheckpointmentse a modellt.forecastEngine.CheckPoint(mlContext, modelPath);
Igény előrejelzése a modell használatával
EvaluateA metódus alatt hozzon létre egy új, úgynevezett segédprogrammetódustForecast.void Forecast(IDataView testData, int horizon, TimeSeriesPredictionEngine<ModelInput, ModelOutput> forecaster, MLContext mlContext) { }A metóduson
Forecastbelül használja a módszert aPredictkövetkező hét napra vonatkozó bérleti díjak előrejelzésére.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 át az előrejelzés kimenetét, és jelenítse meg a konzolon.
Console.WriteLine("Rental Forecast"); Console.WriteLine("---------------------"); foreach (var prediction in forecastOutput) { Console.WriteLine(prediction); }
Az alkalmazás futtatása
Az alábbiakban a metódus meghívása
Checkpoint()hívja meg a metódustForecast.Forecast(secondYearData, 7, forecastEngine, mlContext);Indítsa el 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, hogy egy művelet optimalizálja az erőforrások használatát.
Gratulálok! 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.