Sdílet prostřednictvím


Kurz: Prognóza poptávky po půjčování kol s využitím analýzy časových řad a ML.NET

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

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 Singulární analýza spektra (SSA).> SSA funguje tak, že rozloží časovou řadu do sady hlavních složek. Tyto komponenty lze interpretovat jako části signálu, které odpovídají trendům, šumu, sezónnosti a mnoha dalším faktorům. Tyto komponenty se pak rekonstruují a použijí se k předpovídání hodnot v budoucnu.

Vytvoření konzolové aplikace

  1. Vytvořte konzolovou aplikaci jazyka C# s názvem BikeDemandForecasting. Klikněte na tlačítko Next.

  2. Jako architekturu, která se má použít, zvolte .NET 8. Klikněte na tlačítko Vytvořit.

  3. 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.

    1. V Průzkumníku řešení klikněte pravým tlačítkem na projekt a vyberte Spravovat balíčky NuGet.
    2. Jako zdroj balíčku zvolte "nuget.org", vyberte kartu Procházet a vyhledejte Microsoft.ML.
    3. Zaškrtněte políčko Zahrnout předběžné verze .
    4. Vyberte tlačítko Instalovat.
    5. 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.
    6. Opakujte tyto kroky pro System.Data.SqlClient a Microsoft.ML.TimeSeries.

Příprava a pochopení dat

  1. Vytvořte adresář s názvem Data.
  2. 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

  1. Otevřete soubor Program.cs a nahraďte stávající using direktivy následujícími:

    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms.TimeSeries;
    using System.Data.SqlClient;
    
  2. Vytvořte ModelInput třídu. Program Pod 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 ModelInput obsahuje 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.
  3. Vytvořte ModelOutput třídu pod nově vytvořenou ModelInput třídou.

    public class ModelOutput
    {
        public float[] ForecastedRentals { get; set; }
    
        public float[] LowerBoundRentals { get; set; }
    
        public float[] UpperBoundRentals { get; set; }
    }
    

    Třída ModelOutput obsahuje 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

  1. using Pod 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;";
    
  2. Inicializace mlContext proměnné s novou instancí MLContext přidáním následujícího řádku po definování cest.

    MLContext mlContext = new MLContext();
    

    Třída MLContext je 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ě, jako DBContext v Entity Frameworku.

Načtení dat

  1. Vytvořit, který načte DatabaseLoader záznamy typu ModelInput.

    DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();
    
  2. 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 typu Real, musí být převedeny na hodnotu s plovoucí desetinnou čárkou s jednoduchou přesností Real.

    Year Oba TotalRental sloupce jsou celočíselné typy v databázi. CAST Pomocí předdefinované funkce se přetypují na Real.

  3. Vytvořte připojení DatabaseSource k databázi a spusťte dotaz.

    DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance,
                                    connectionString,
                                    query);
    
  4. Načtěte data do objektu IDataView.

    IDataView dataView = loader.Load(dbSource);
    
  5. 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í FilterRowsByColumn transformace.

    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 Year sloupci menší než 1 nastavením parametru upperBound na hodnotu 1. Naopak pro druhý rok jsou hodnoty větší než nebo rovno 1 vybrány nastavením parametru lowerBound na hodnotu 1.

Definování kanálu analýzy časových řad

  1. 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 forecastingPipeline 365 datových bodů a vezme vzorky nebo rozdělí datovou sadu časových řad na 30denní (měsíční) intervaly dle určení parametru seriesLength. 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 parametrem horizon . 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.

  2. Použijte metodu Fit k trénování modelu a přizpůsobení dat dříve definovaným forecastingPipeline.

    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.

  1. Vytvořte novou metodu nástroje volanou Evaluate v dolní části souboru Program.cs .

    Evaluate(IDataView testData, ITransformer model, MLContext mlContext)
    {
    
    }
    
  2. Evaluate V metodě předpovídá data druhého roku pomocí Transform metody s natrénovaným modelem.

    IDataView predictions = model.Transform(testData);
    
  3. Pomocí metody získejte skutečné hodnoty z dat CreateEnumerable .

    IEnumerable<float> actual =
        mlContext.Data.CreateEnumerable<ModelInput>(testData, true)
            .Select(observed => observed.TotalRentals);
    
  4. Získejte hodnoty prognózy pomocí CreateEnumerable metody.

    IEnumerable<float> forecast =
        mlContext.Data.CreateEnumerable<ModelOutput>(predictions, true)
            .Select(prediction => prediction.ForecastedRentals[0]);
    
  5. 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);
    
  6. 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 Error
    

    K 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.
  7. 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");
    
  8. Volejte metodu Evaluate níže, která metodu Fit() 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.

  1. Pod metodou Evaluate() vytvořte .TimeSeriesPredictionEngine TimeSeriesPredictionEngine je metoda pro usnadnění provádění jednoduchých předpovědí.

    var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);
    
  2. Uložte model do souboru volaný MLModel.zip podle dříve definované modelPath proměnné. Checkpoint Pomocí metody uložte model.

    forecastEngine.CheckPoint(mlContext, modelPath);
    

Použití modelu k prognózování poptávky

  1. Pod metodou Evaluate vytvořte novou metodu nástroje s názvem Forecast.

    void Forecast(IDataView testData, int horizon, TimeSeriesPredictionEngine<ModelInput, ModelOutput> forecaster, MLContext mlContext)
    {
    
    }
    
  2. Forecast Uvnitř metody použijte metodu Predict k prognózování pronájmů za příštích 7 dnů.

    ModelOutput forecast = forecaster.Predict();
    
  3. 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";
            });
    
  4. 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

  1. Pod voláním Checkpoint() metody metodu volejte metodu Forecast .

    Forecast(secondYearData, 7, forecastEngine, mlContext);
    
  2. 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:

Porovnání skutečných vs. prognóz

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 .

Další kroky