Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
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 jednowariowej analizy szeregów czasowych na danych przechowywanych w bazie danych SQL Server z ML.NET.
Ten samouczek zawiera informacje na temat wykonywania następujących czynności:
- 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 z zainstalowanym obciążeniem ".NET Desktop Development".
Omówienie przykładu prognozowania szeregów czasowych
Ten przykład jest aplikacją konsolową platformy .NET Core w języku C# , która prognozuje zapotrzebowanie na wynajem rowerów przy użyciu jednowariowego 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 można było uruchomić wydajną operację, zarządzanie zapasami odgrywa kluczową rolę. Posiadanie zbyt dużej ilości produktu w magazynie oznacza, że produkty niesprzedazone 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, aby utrzymać się pod ręką? Analiza szeregów czasowych pomaga zapewnić odpowiedź na te pytania, przeglądają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 polega na niezmiennej analizie szeregów czasowych. Pojedyncza analiza szeregów czasowych analizuje pojedynczą obserwację liczbową w danym okresie w określonych odstępach czasu, takich jak miesięczna sprzedaż.
Algorytm używany w tym samouczku to Pojedyncza analiza spektrum (SSA). 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 odpowiadającego 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 Dalej.
Wybierz platformę .NET 6 jako platformę do użycia. Kliknij przycisk Utwórz.
Instalowanie pakietu NuGet w wersji Microsoft.ML
Uwaga
W tym przykładzie użyto najnowszej stabilnej wersji pakietów NuGet wymienionych, chyba że określono inaczej.
- W Eksplorator 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 Dołącz 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 wymienionych pakietów.
- 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
Dane używane w tym samouczku pochodzą z zestawu danych UCI Bike Sharing. Fanaee-T, Hadi i Gama, Joao, "Etykietowanie zdarzeń łączących detektory zespołu i wiedzę w tle", Progress in Artificial Intelligence (2013): pp. 1-15, Springer Berlin Berlin, Web Link.
Oryginalny zestaw danych zawiera kilka kolumn odpowiadających sezonowości i pogodzie. W przypadku zwięzłości i ponieważ algorytm używany w tym samouczku wymaga tylko wartości z jednej kolumny liczbowej, oryginalny zestaw danych został skrócony 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 dla tego dnia.
Oryginalny zestaw danych jest mapowany na tabelę bazy danych z następującym schematem w bazie danych SQL Server.
CREATE TABLE [Rentals] (
[RentalDate] DATE NOT NULL,
[Year] INT NOT NULL,
[TotalRentals] INT NOT NULL
);
Poniżej przedstawiono przykład danych:
| Wypożyczenie | Year (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
usinginstrukcje następującymi instrukcjami:using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms.TimeSeries; using System.Data.SqlClient;Utwórz klasę
ModelInput.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: Całkowita 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
Poniżej instrukcji using zdefiniuj 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
mlContextzmienną przy użyciu 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, że ł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, należy przekonwertować wartość zmiennoprzecinkową o pojedynczej precyzji naRealwartość .Kolumny
YeariTotalRentalsą zarówno typami całkowitymi w bazie danych. Za pomocą 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 elementu
IDataView.IDataView dataView = loader.Load(dbSource);Zestaw danych zawiera dwa lata wartości danych. 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
Yearkolumnie mniejszej niż 1, ustawiającupperBoundparametr na 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, który używa klasy 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");Obiekt
forecastingPipelineprzyjmuje 365 punktów danych dla pierwszego roku i próbki lub dzieli zestaw danych szeregów czasowych na 30-dniowe (miesięczne) interwały określone przezseriesLengthparametr . Każda z tych próbek jest analizowana przez cotygodniowe lub 7-dniowe okno. 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. W związku z tym dobrze jest znać zakres wartości w najlepszych i najgorszych scenariuszach, zgodnie z definicją w granicach górnych i dolnych. W tym przypadku poziom ufności dla dolnych i górnych granic wynosi 95%. Poziom ufności można odpowiednio zwiększyć lub zmniejszyć. Im wyższa wartość, tym szerszy zakres znajduje się między górną i dolną granicą w celu osiągnięcia żądanego poziomu 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 z przyszłego 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 obliczanie wartości Błędu bezwzględnego średniej i średniej kwadratu głównego.
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 przez następne siedem dni.ModelOutput forecast = forecaster.Predict();Wyrównuj wartości rzeczywiste i prognozowane 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.
Console.WriteLine("Rental Forecast"); Console.WriteLine("---------------------"); foreach (var prediction in forecastOutput) { Console.WriteLine(prediction); }
Uruchamianie aplikacji
Poniżej wywołania
Checkpoint()metody wywołaj metodęForecast.Forecast(secondYearData, 7, forecastEngine, mlContext);Uruchom aplikację. Dane wyjściowe podobne do poniższych powinny pojawić się w konsoli programu . 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ą operację optymalizacji wykorzystania zasobów.
Gratulacje! Udało Ci się utworzyć model uczenia maszynowego szeregów czasowych w celu prognozowania zapotrzebowania na wypożyczanie rowerów.
Kod źródłowy tego samouczka można znaleźć w repozytorium dotnet/machinelearning-samples .