Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dowiedz się, jak prognozować zapotrzebowanie na usługę wypożyczania rowerów przy użyciu niezmiennej analizy szeregów czasowych na danych przechowywanych w bazie danych programu SQL Server z ML.NET.
W tym poradniku nauczysz się, jak:
- Omówienie problemu
- Ładowanie danych z bazy danych
- Tworzenie modelu prognozowania
- Ocena modelu prognozowania
- Zapisywanie modelu prognozowania
- Korzystanie z modelu prognozowania
Wymagania wstępne
- Program Visual Studio 2022 lub nowszy z zainstalowanym pakietem roboczym programowanie aplikacji dla komputerów stacjonarnych .NET.
Omówienie przykładu prognozowania szeregów czasowych
Ten przykład jest aplikacją konsolową języka C# , która prognozuje zapotrzebowanie na wypożyczanie rowerów przy użyciu niezmiennego algorytmu analizy szeregów czasowych znanego jako Analiza pojedynczego spektrum. Kod dla tego przykładu można znaleźć w repozytorium dotnet/machinelearning-samples w witrynie GitHub.
Omówienie problemu
Aby uruchomić wydajną operację, zarządzanie zapasami odgrywa kluczową rolę. Posiadanie zbyt dużej ilości produktu w magazynie oznacza, że produkty niesprzedane siedzą na półkach, nie generując żadnych przychodów. Zbyt mało produktów prowadzi do utraty sprzedaży i klientów kupujących od konkurentów. W związku z tym stałe pytanie brzmi: jaka jest optymalna ilość zapasów do utrzymania na bieżąco? Analiza szeregów czasowych pomaga zapewnić odpowiedź na te pytania, analizując dane historyczne, identyfikując wzorce i używając tych informacji do prognozowania wartości w przyszłości.
Technika analizowania danych używanych w tym samouczku jest niezmienna analiza szeregów czasowych. Pojedyncza analiza szeregów czasowych analizuje pojedynczą obserwację liczbową w danym okresie w określonych interwałach, takich jak miesięczna sprzedaż.
Algorytm używany w tym samouczku to Analiza Pojedynczego Spektrum (SSA). Usługa SSA działa przez rozdzielenie szeregów czasowych na zestaw głównych składników. Te składniki można interpretować jako części sygnału, które odpowiadają trendom, szumowi, sezonowości i wielu innym czynnikom. Następnie te składniki są odtwarzane i używane do prognozowania wartości w przyszłości.
Tworzenie aplikacji konsolowej
Utwórz aplikację konsolową języka C# o nazwie "BikeDemandForecasting". Kliknij przycisk Next (Dalej).
Wybierz platformę .NET 8 jako platformę do użycia. Kliknij przycisk Utwórz.
Instalowanie pakietu NuGet w wersji Microsoft.ML
Uwaga / Notatka
W tym przykładzie użyto najnowszej stabilnej wersji pakietów NuGet wymienionych, chyba że określono inaczej.
- W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Zarządzaj pakietami NuGet.
- Wybierz pozycję "nuget.org" jako źródło pakietu, wybierz kartę Przeglądaj , wyszukaj Microsoft.ML.
- Zaznacz pole wyboru Uwzględnij wersję wstępną .
- Wybierz przycisk Zainstaluj.
- Wybierz przycisk OK w oknie dialogowym Podgląd zmian , a następnie wybierz przycisk Akceptuję w oknie dialogowym Akceptacja licencji, jeśli zgadzasz się z postanowieniami licencyjnymi dla pakietów wymienionych.
- Powtórz te kroki dla programów System.Data.SqlClient i Microsoft.ML.TimeSeries.
Przygotowywanie i zrozumienie danych
- Utwórz katalog o nazwie Dane.
- Pobierz plik bazy danych DailyDemand.mdf i zapisz go w katalogu Data.
Uwaga / Notatka
Dane używane w tym samouczku pochodzą z zbioru danych UCI Bike Sharing. Hadi Fanaee-T i João Gama, "Etykietowanie zdarzeń łączące detektory zbiorowe i wiedzę tła", Progress in Artificial Intelligence (2013): s. 1-15, Springer Berlin Heidelberg, Link internetowy.
Oryginalny zestaw danych zawiera kilka kolumn odpowiadających sezonowości i pogodzie. W przypadku zwięzłości i dlatego, że algorytm używany w tym samouczku wymaga tylko wartości z jednej kolumny liczbowej, oryginalny zestaw danych został skondensowany w celu uwzględnienia tylko następujących kolumn:
- dteday: data obserwacji.
- year: zakodowany rok obserwacji (0=2011, 1=2012).
- cnt: Całkowita liczba wypożyczeń rowerów w tym dniu.
Oryginalny zestaw danych jest mapowany na tabelę bazy danych z następującym schematem w bazie danych programu SQL Server.
CREATE TABLE [Rentals] (
[RentalDate] DATE NOT NULL,
[Year] INT NOT NULL,
[TotalRentals] INT NOT NULL
);
Poniżej przedstawiono przykładowe dane:
| DataWypożyczenia | Rok | TotalRentals |
|---|---|---|
| 1/1/2011 | 0 | 985 |
| 1/2/2011 | 0 | 801 |
| 1/3/2011 | 0 | 1349 |
Tworzenie klas wejściowych i wyjściowych
Otwórz plik Program.cs i zastąp istniejące
usingdyrektywy następującymi:using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms.TimeSeries; using System.Data.SqlClient;Utwórz
ModelInputklasę.ProgramPoniżej klasy dodaj następujący kod.public class ModelInput { public DateTime RentalDate { get; set; } public float Year { get; set; } public float TotalRentals { get; set; } }Klasa
ModelInputzawiera następujące kolumny:- RentalDate: data obserwacji.
- Rok: zakodowany rok obserwacji (0=2011, 1=2012).
- TotalRentals: łączna liczba wypożyczeń rowerów dla tego dnia.
Utwórz
ModelOutputklasę poniżej nowo utworzonejModelInputklasy.public class ModelOutput { public float[] ForecastedRentals { get; set; } public float[] LowerBoundRentals { get; set; } public float[] UpperBoundRentals { get; set; } }Klasa
ModelOutputzawiera następujące kolumny:- ForecastedRentals: przewidywane wartości dla prognozowanego okresu.
- LowerBoundRentals: przewidywane wartości minimalne dla prognozowanego okresu.
- UpperBoundRentals: przewidywane wartości maksymalne dla prognozowanego okresu.
Definiowanie ścieżek i inicjowanie zmiennych
usingPoniżej dyrektywy definiują zmienne do przechowywania lokalizacji danych, parametrów połączenia i miejsca zapisania wytrenowanego 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;";Zainicjuj zmienną
mlContextza pomocą nowego wystąpieniaMLContext, dodając następujący wiersz po zdefiniowaniu ścieżek.MLContext mlContext = new MLContext();Klasa
MLContextjest punktem wyjścia dla wszystkich operacji ML.NET, a inicjowanie metody mlContext tworzy nowe środowisko ML.NET, które może być współużytkowane przez obiekty przepływu pracy tworzenia modelu. Jest ona podobna, koncepcyjnie, doDBContextw programie Entity Framework.
Ładowanie danych
Utwórz
DatabaseLoader, który ładuje rekordy typuModelInput.DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();Zdefiniuj zapytanie, aby załadować dane z bazy danych.
string query = "SELECT RentalDate, CAST(Year as REAL) as Year, CAST(TotalRentals as REAL) as TotalRentals FROM Rentals";ML.NET algorytmy oczekują, że dane będą typu
Single. W związku z tym wartości liczbowe pochodzące z bazy danych, które nie są typuReal, czyli nie są wartością zmiennoprzecinkową o pojedynczej precyzji, muszą zostać przekonwertowane naReal.Kolumny
YeariTotalRentalsą typami liczb całkowitych w bazie danych. Przy użyciu wbudowanejCASTfunkcji są one rzutowane naReal.Utwórz element ,
DatabaseSourceaby nawiązać połączenie z bazą danych i wykonać zapytanie.DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, connectionString, query);Załaduj dane do obiektu
IDataView.IDataView dataView = loader.Load(dbSource);Zestaw danych zawiera dane z dwóch lat. Tylko dane z pierwszego roku są używane do trenowania, drugi rok jest przechowywany w celu porównania rzeczywistych wartości z prognozą wygenerowaną przez model. Przefiltruj
FilterRowsByColumndane przy użyciu przekształcenia.IDataView firstYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", upperBound: 1); IDataView secondYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", lowerBound: 1);W pierwszym roku wybierane są tylko wartości w kolumnie mniejszej
Yearniż 1 przez ustawienie parametruupperBoundna 1. Z drugiej strony dla drugiego roku wartości większe lub równe 1 są wybierane przez ustawienie parametrulowerBoundna 1.
Definiowanie potoku analizy szeregów czasowych
Zdefiniuj potok przetwarzania, który używa SsaForecastingEstimator do prognozowania wartości w zestawie danych szeregów czasowych.
var forecastingPipeline = mlContext.Forecasting.ForecastBySsa( outputColumnName: "ForecastedRentals", inputColumnName: "TotalRentals", windowSize: 7, seriesLength: 30, trainSize: 365, horizon: 7, confidenceLevel: 0.95f, confidenceLowerBoundColumn: "LowerBoundRentals", confidenceUpperBoundColumn: "UpperBoundRentals");forecastingPipelinepobiera 365 punktów danych dla pierwszego roku i dzieli lub próbuje zestaw danych szeregów czasowych na 30-dniowe (miesięczne) interwały, określone przez parametrseriesLength. Każda z tych próbek jest analizowana co tydzień lub przez 7 dni. Podczas określania, jaka jest prognozowana wartość dla następnych okresów, wartości z poprzednich siedmiu dni są używane do przewidywania. Model jest ustawiony na prognozowanie siedmiu okresów w przyszłości zgodnie z definicją parametruhorizon. Ponieważ prognoza jest świadomym zgadywaniem, nie zawsze jest to 100% dokładne. Dlatego dobrze jest znać zakres wartości w najlepszych i najgorszych scenariuszach zdefiniowanych przez górne i dolne granice. W tym przypadku poziom ufności dla dolnej i górnej granicy wynosi 95%. Poziom ufności można odpowiednio zwiększyć lub zmniejszyć. Im większa wartość, tym szerszy zakres znajduje się między górną i dolną granicą, aby osiągnąć żądany poziom ufności.FitUżyj metody , aby wytrenować model i dopasować dane do wcześniej zdefiniowanegoforecastingPipelineelementu .SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData);
Ocena modelu
Oceń, jak dobrze działa model, prognozując dane w przyszłym roku i porównując je z rzeczywistymi wartościami.
Utwórz nową metodę narzędzia o nazwie
Evaluatew dolnej części pliku Program.cs .Evaluate(IDataView testData, ITransformer model, MLContext mlContext) { }EvaluateWewnątrz metody prognozowanie danych z drugiego roku przy użyciuTransformmetody z wytrenowanym modelem.IDataView predictions = model.Transform(testData);Pobierz rzeczywiste wartości z danych przy użyciu
CreateEnumerablemetody .IEnumerable<float> actual = mlContext.Data.CreateEnumerable<ModelInput>(testData, true) .Select(observed => observed.TotalRentals);Pobierz wartości prognozy przy użyciu
CreateEnumerablemetody .IEnumerable<float> forecast = mlContext.Data.CreateEnumerable<ModelOutput>(predictions, true) .Select(prediction => prediction.ForecastedRentals[0]);Oblicz różnicę między wartościami rzeczywistymi i prognozami, często określanymi jako błąd.
var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);Mierzenie wydajności przez obliczenie wartości Błędu bezwzględnego średniej i średniej średniokwadratowej.
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 ErrorAby ocenić wydajność, używane są następujące metryki:
- Średni błąd bezwzględny: mierzy, jak bliskie są przewidywania rzeczywistej wartości. Ta wartość waha się od 0 do nieskończoności. Im bliżej 0, tym lepsza jakość modelu.
- Główny błąd średniokwadratowy: podsumowuje błąd w modelu. Ta wartość waha się od 0 do nieskończoności. Im bliżej 0, tym lepsza jakość modelu.
Wyprowadź metryki do konsoli.
Console.WriteLine("Evaluation Metrics"); Console.WriteLine("---------------------"); Console.WriteLine($"Mean Absolute Error: {MAE:F3}"); Console.WriteLine($"Root Mean Squared Error: {RMSE:F3}\n");Wywołaj metodę
Evaluateponiżej wywołującą metodęFit().Evaluate(secondYearData, forecaster, mlContext);
Zapisywanie modelu
Jeśli model jest zadowalający, zapisz go do późniejszego użycia w innych aplikacjach.
Evaluate()Poniżej metody utwórz elementTimeSeriesPredictionEngine.TimeSeriesPredictionEnginejest wygodną metodą tworzenia pojedynczych przewidywań.var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);Zapisz model w pliku o nazwie
MLModel.zipokreślonej przez wcześniej zdefiniowanąmodelPathzmienną.CheckpointUżyj metody , aby zapisać model.forecastEngine.CheckPoint(mlContext, modelPath);
Prognozowanie zapotrzebowania przy użyciu modelu
EvaluatePoniżej metody utwórz nową metodę narzędzia o nazwieForecast.void Forecast(IDataView testData, int horizon, TimeSeriesPredictionEngine<ModelInput, ModelOutput> forecaster, MLContext mlContext) { }ForecastWewnątrz metody użyjPredictmetody , aby prognozować wypożyczenie w ciągu najbliższych siedmiu dni.ModelOutput forecast = forecaster.Predict();Wyrównywanie rzeczywistych i prognozowanych wartości dla siedmiu okresów.
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"; });Iteruj dane wyjściowe prognozy i wyświetlaj je w konsoli programu .
Console.WriteLine("Rental Forecast"); Console.WriteLine("---------------------"); foreach (var prediction in forecastOutput) { Console.WriteLine(prediction); }
Uruchamianie aplikacji
Poniżej wywołaj metodę
Checkpoint()wywołaj metodęForecast.Forecast(secondYearData, 7, forecastEngine, mlContext);Uruchom aplikację. Dane wyjściowe podobne do poniższych powinny pojawić się na konsoli. W celu zwięzłości dane wyjściowe zostały skondensowane.
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
Inspekcja rzeczywistych i prognozowanych wartości pokazuje następujące relacje:
Chociaż prognozowane wartości nie przewidują dokładnej liczby wypożyczeń, zapewniają bardziej wąski zakres wartości, które umożliwiają operacjom optymalizowanie ich wykorzystania zasobów.
Gratulacje! Udało Ci się utworzyć model uczenia maszynowego szeregów czasowych w celu prognozowania zapotrzebowania na wynajem rowerów.
Kod źródłowy tego samouczka można znaleźć w repozytorium dotnet/machinelearning-samples .