Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Naučte se předpovídat poptávku po službě půjčování kol pomocí analýzy jednovariátových časových řad na datech uložených v databázi SQL Serveru s ML.NET.
V tomto návodu se naučíte, jak:
- Pochopení problému
- Načtení dat z databáze
- Vytvoření modelu prognózování
- Vyhodnocení modelu prognózování
- Uložení modelu prognózování
- Použití modelu prognózování
Požadavky
- Visual Studio 2022 nebo novější s nainstalovanou úlohou vývoj aplikací pro .NET Desktop
Přehled ukázky prognózování časových řad
Tato ukázka je konzolová aplikace jazyka C# , která předpovídá poptávku po půjčování kol pomocí jednovariátového analytického algoritmu časové řady označovaného jako Jednorozměrná analýza spektra. Kód pro tuto ukázku najdete v úložišti dotnet/machinelearning-samples na GitHubu.
Pochopení problému
Aby bylo možné spustit efektivní operaci, hraje správa inventáře klíčovou roli. Příliš mnoho produktů na skladě znamená, že nevydělané produkty sedící na policách negenerují žádné výnosy. Příliš malý produkt vede ke ztrátě prodeje a zákazníků, kteří nakupují od konkurentů. Proto je konstantní otázkou, jaké je optimální množství zásob, které je třeba držet na ruce? Analýza časových řad pomáhá poskytnout odpověď na tyto otázky tím, že se podívá na historická data, identifikuje vzory a použije tyto informace k prognózování hodnot v určitou dobu v budoucnu.
Technika analýzy dat používaných v tomto kurzu je jednovariátní analýza časových řad. Jednovariátová analýza časových řad se dívá na jedno číselné pozorování v určitém časovém období v konkrétních intervalech, jako jsou měsíční prodeje.
Algoritmus použitý v tomto kurzu je
Vytvoření konzolové aplikace
Vytvořte konzolovou aplikaci jazyka C# s názvem BikeDemandForecasting. Klikněte na tlačítko Next.
Jako architekturu, která se má použít, zvolte .NET 8. Klikněte na tlačítko Vytvořit.
Instalace balíčku NuGet verze Microsoft.ML
Poznámka:
Tato ukázka používá nejnovější stabilní verzi uvedených balíčků NuGet, pokud není uvedeno jinak.
- V Průzkumníku řešení klikněte pravým tlačítkem na projekt a vyberte Spravovat balíčky NuGet.
- Jako zdroj balíčku zvolte "nuget.org", vyberte kartu Procházet a vyhledejte Microsoft.ML.
- Zaškrtněte políčko Zahrnout předběžné verze .
- Vyberte tlačítko Instalovat.
- V dialogovém okně Náhled změn vyberte tlačítko OK a pak v dialogovém okně Přijetí licence vyberte tlačítko Přijmout, pokud souhlasíte s licenčními podmínkami pro uvedené balíčky.
- Opakujte tyto kroky pro System.Data.SqlClient a Microsoft.ML.TimeSeries.
Příprava a pochopení dat
- Vytvořte adresář s názvem Data.
- Stáhněte soubor databáze DailyDemand.mdf a uložte ho do adresáře Data.
Poznámka:
Data použitá v tomto kurzu pocházejí z datové sady sdílení kol UCI. Hadi Fanaee-T a João Gama, 'Označování událostí kombinující soubor detektorů a pozadí znalostí', Progress in Artificial Intelligence (2013): str. 1-15, Springer Berlin Heidelberg, Web Link.
Původní datová sada obsahuje několik sloupců odpovídajících sezónnosti a počasí. Kvůli stručnosti a vzhledem k tomu, že algoritmus použitý v tomto kurzu vyžaduje pouze hodnoty z jednoho číselného sloupce, byla původní datová sada zhuštěna tak, aby obsahovala pouze následující sloupce:
- dteday: Datum pozorování.
- year: Kódovaný rok pozorování (0=2011, 1=2012).
- cnt: Celkový počet pronájmů kol pro tento den.
Původní datová sada se mapuje na tabulku databáze s následujícím schématem v databázi SQL Serveru.
CREATE TABLE [Rentals] (
[RentalDate] DATE NOT NULL,
[Year] INT NOT NULL,
[TotalRentals] INT NOT NULL
);
Následuje ukázka dat:
| RentalDate | Rok | TotalRentals |
|---|---|---|
| 1/1/2011 | 0 | 985 |
| 1/2/2011 | 0 | 801 |
| 1/3/2011 | 0 | 1349 |
Vytvoření vstupních a výstupních tříd
Otevřete soubor Program.cs a nahraďte stávající
usingdirektivy následujícími:using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms.TimeSeries; using System.Data.SqlClient;Vytvořte
ModelInputtřídu.ProgramPod třídu přidejte následující kód.public class ModelInput { public DateTime RentalDate { get; set; } public float Year { get; set; } public float TotalRentals { get; set; } }Třída
ModelInputobsahuje následující sloupce:- RentalDate: Datum pozorování.
- Rok: Kódovaný rok pozorování (0=2011, 1=2012).
- TotalRentals: Celkový počet půjčování kol za tento den.
Vytvořte
ModelOutputtřídu pod nově vytvořenouModelInputtřídou.public class ModelOutput { public float[] ForecastedRentals { get; set; } public float[] LowerBoundRentals { get; set; } public float[] UpperBoundRentals { get; set; } }Třída
ModelOutputobsahuje následující sloupce:- ForecastedRentals: Predikované hodnoty pro předpokládané období.
- LowerBoundRentals: Predikované minimální hodnoty pro předpokládané období.
- UpperBoundRentals: Predikované maximální hodnoty pro předpokládané období.
Definování cest a inicializace proměnných
usingPod direktivami se definují proměnné pro ukládání dat, připojovacího řetězce a umístění pro uložení natrénovaného modelu.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;";Inicializace
mlContextproměnné s novou instancíMLContextpřidáním následujícího řádku po definování cest.MLContext mlContext = new MLContext();Třída
MLContextje výchozím bodem pro všechny operace ML.NET a inicializace mlContext vytvoří nové ML.NET prostředí, které lze sdílet napříč objekty pracovního postupu vytváření modelu. Je to podobné, koncepčně, jakoDBContextv Entity Frameworku.
Načtení dat
Vytvořit, který načte
DatabaseLoaderzáznamy typuModelInput.DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();Definujte dotaz pro načtení dat z databáze.
string query = "SELECT RentalDate, CAST(Year as REAL) as Year, CAST(TotalRentals as REAL) as TotalRentals FROM Rentals";ML.NET algoritmy očekávají, že data budou typu
Single. Číselné hodnoty pocházející z databáze, které nejsou typuReal, musí být převedeny na hodnotu s plovoucí desetinnou čárkou s jednoduchou přesnostíReal.YearObaTotalRentalsloupce jsou celočíselné typy v databázi.CASTPomocí předdefinované funkce se přetypují naReal.Vytvořte připojení
DatabaseSourcek databázi a spusťte dotaz.DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, connectionString, query);Načtěte data do objektu
IDataView.IDataView dataView = loader.Load(dbSource);Datová sada obsahuje data za dva roky. K trénování se používají pouze data z prvního roku, druhý rok se uchovává k porovnání skutečných hodnot s prognózou vytvořenou modelem. Filtrujte data pomocí
FilterRowsByColumntransformace.IDataView firstYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", upperBound: 1); IDataView secondYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", lowerBound: 1);Pro první rok jsou vybrány pouze hodnoty ve
Yearsloupci menší než 1 nastavením parametruupperBoundna hodnotu 1. Naopak pro druhý rok jsou hodnoty větší než nebo rovno 1 vybrány nastavením parametrulowerBoundna hodnotu 1.
Definování kanálu analýzy časových řad
Definujte kanál, který používá SsaForecastingEstimator k prognózování hodnot v datové sadě časových řad.
var forecastingPipeline = mlContext.Forecasting.ForecastBySsa( outputColumnName: "ForecastedRentals", inputColumnName: "TotalRentals", windowSize: 7, seriesLength: 30, trainSize: 365, horizon: 7, confidenceLevel: 0.95f, confidenceLowerBoundColumn: "LowerBoundRentals", confidenceUpperBoundColumn: "UpperBoundRentals");Pro první rok bere
forecastingPipeline365 datových bodů a vezme vzorky nebo rozdělí datovou sadu časových řad na 30denní (měsíční) intervaly dle určení parametruseriesLength. Každý z těchto vzorků se analyzuje prostřednictvím týdenního nebo 7denního intervalu. Při určování toho, jaká je předpovídaná hodnota pro další období, se hodnoty z předchozích sedmi dnů použijí k předpovědím. Model je nastavený na prognózu sedmi období do budoucnosti, jak je definován parametremhorizon. Protože prognóza je informovaný odhad, není vždy 100% přesné. Proto je vhodné znát rozsah hodnot v nejlepších a nejhorších scénářích definovaných horními a dolními hranicemi. V tomto případě je úroveň spolehlivosti dolní a horní hranice nastavena na 95%. Úroveň spolehlivosti lze odpovídajícím způsobem zvýšit nebo snížit. Čím vyšší je hodnota, tím širší je rozsah mezi horní a dolní mezí, aby se dosáhlo požadované úrovně spolehlivosti.Použijte metodu
Fitk trénování modelu a přizpůsobení dat dříve definovanýmforecastingPipeline.SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData);
Vyhodnocení modelu
Vyhodnoťte, jak dobře model funguje, a to prognózou dat příštího roku a porovnáním se skutečnými hodnotami.
Vytvořte novou metodu nástroje volanou
Evaluatev dolní části souboru Program.cs .Evaluate(IDataView testData, ITransformer model, MLContext mlContext) { }EvaluateV metodě předpovídá data druhého roku pomocíTransformmetody s natrénovaným modelem.IDataView predictions = model.Transform(testData);Pomocí metody získejte skutečné hodnoty z dat
CreateEnumerable.IEnumerable<float> actual = mlContext.Data.CreateEnumerable<ModelInput>(testData, true) .Select(observed => observed.TotalRentals);Získejte hodnoty prognózy pomocí
CreateEnumerablemetody.IEnumerable<float> forecast = mlContext.Data.CreateEnumerable<ModelOutput>(predictions, true) .Select(prediction => prediction.ForecastedRentals[0]);Vypočítat rozdíl mezi skutečnými a prognózovými hodnotami, které se běžně označují jako chyba.
var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);Měření výkonu výpočtem střední absolutní chyby a odmocniny střední střední kvadratická chyba.
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 ErrorK vyhodnocení výkonu se používají následující metriky:
- Střední absolutní chyba: Měří, jak se predikce blíží skutečné hodnotě. Tato hodnota se pohybuje mezi 0 a nekonečnem. Čím blíž k 0, tím lépe kvalita modelu.
- Původní střední kvadratická chyba: Shrnuje chybu v modelu. Tato hodnota se pohybuje mezi 0 a nekonečnem. Čím blíž k 0, tím lépe kvalita modelu.
Vypíše metriky do konzoly.
Console.WriteLine("Evaluation Metrics"); Console.WriteLine("---------------------"); Console.WriteLine($"Mean Absolute Error: {MAE:F3}"); Console.WriteLine($"Root Mean Squared Error: {RMSE:F3}\n");Volejte metodu
Evaluateníže, která metoduFit()volá.Evaluate(secondYearData, forecaster, mlContext);
Uložení modelu
Pokud jste s modelem spokojení, uložte ho pro pozdější použití v jiných aplikacích.
Pod metodou
Evaluate()vytvořte .TimeSeriesPredictionEngineTimeSeriesPredictionEngineje metoda pro usnadnění provádění jednoduchých předpovědí.var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);Uložte model do souboru volaný
MLModel.zippodle dříve definovanémodelPathproměnné.CheckpointPomocí metody uložte model.forecastEngine.CheckPoint(mlContext, modelPath);
Použití modelu k prognózování poptávky
Pod metodou
Evaluatevytvořte novou metodu nástroje s názvemForecast.void Forecast(IDataView testData, int horizon, TimeSeriesPredictionEngine<ModelInput, ModelOutput> forecaster, MLContext mlContext) { }ForecastUvnitř metody použijte metoduPredictk prognózování pronájmů za příštích 7 dnů.ModelOutput forecast = forecaster.Predict();Zarovnejte skutečné hodnoty a hodnoty prognózy pro sedm období.
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"; });Iterujte výstupem prognózy a zobrazte ho v konzole.
Console.WriteLine("Rental Forecast"); Console.WriteLine("---------------------"); foreach (var prediction in forecastOutput) { Console.WriteLine(prediction); }
Spuštění aplikace
Pod voláním
Checkpoint()metody metodu volejte metoduForecast.Forecast(secondYearData, 7, forecastEngine, mlContext);Aplikaci spusťte. Výstup podobný následujícímu by se měl zobrazit v konzole. Pro stručnost byl výstup zhuštěný.
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
Kontrola skutečných a prognózovaných hodnot ukazuje následující relace:
Zatímco předpovídané hodnoty nepředikují přesný počet pronájmů, poskytují užší rozsah hodnot, který operaci umožňuje optimalizovat využití prostředků.
Gratulujeme! Nyní jste úspěšně vytvořili model strojového učení časových řad pro prognózu poptávky po půjčování kol.
Zdrojový kód pro tento kurz najdete v úložišti dotnet/machinelearning-samples .