Werken met een forecastobject

Forecasting-pijplijnen ontwerpen voor productie

Rami Krispin

Senior Manager, Data Science and Engineering

Werken met een forecastobject

  • Datavoorbereiding
  • Train en test meerdere voorspelmodellen
  • Evalueer de modelprestatie
  • Het statsforecast-pakket
    • mlforecast in de oefeningen
Forecasting-pijplijnen ontwerpen voor productie

Trainset

Tijdreeks

Testset

Testset

Forecasting-pijplijnen ontwerpen voor productie

Benodigde libraries

import pandas as pd 
import datetime 
Forecasting-pijplijnen ontwerpen voor productie

Benodigde libraries

from statsforecast import StatsForecast

from statsforecast.models import (
    DynamicOptimizedTheta,
    SeasonalNaive,
    AutoARIMA,
    HoltWinters,
    MSTL
)

from utilsforecast.plotting import plot_series
Forecasting-pijplijnen ontwerpen voor productie

Het statsforecast-dataformaat

Data-indeling:

  1. unique_id - het serie-ID
  2. ds - de seriestimestamp
  3. y - de seriewaarden
Forecasting-pijplijnen ontwerpen voor productie

Datavoorbereiding - data laden

ts = pd.read_csv("data/data.csv")
ts["ds"] = pd.to_datetime(ts["ds"])
ts = ts.sort_values("ds")
ts = ts[["unique_id", "ds", "y"]]

os.environ['NIXTLA_ID_AS_COL'] = '1'
 unique_id        ds             y
0    1    2022-11-11 23:00:00    456403
1    1    2022-11-12 00:00:00    458842
2    1    2022-11-12 01:00:00    455111
3    1    2022-11-12 02:00:00    448035
4    1    2022-11-12 03:00:00    438165
Forecasting-pijplijnen ontwerpen voor productie

Datavoorbereiding - train/test-split

  • Splits de tijdreeks in train- en testsets
    • met datetime.timedelta
    • laat de laatste 72 uur als testdata
test_length = 72

train_end = end  - datetime.timedelta(hours = test_length)

train = ts[ts["ds"] <= train_end]
test = ts[ts["ds"] > train_end]
Forecasting-pijplijnen ontwerpen voor productie

Datavoorbereiding

plot_series(train, engine = "plotly")

Tijdreeks

plot_series(test, engine = "plotly")

Testset

Forecasting-pijplijnen ontwerpen voor productie

Forecasten met StatsModels

# Instantieer modellen met uurlijkse seizoenspatronen
auto_arima = AutoARIMA()
s_naive = SeasonalNaive(season_length=24)
theta =  DynamicOptimizedTheta(season_length=24)

# Instantieer modellen met uurlijkse en wekelijkse seizoenen mstl1 = MSTL(season_length=[24, 24 * 7], trend_forecaster=AutoARIMA(), alias="MSTL_ARIMA_trend") mstl2 = MSTL(season_length=[24, 24 * 7], trend_forecaster=HoltWinters(), alias="MSTL_Holt_trend")
Forecasting-pijplijnen ontwerpen voor productie

Forecasten met StatsModels

# Combineer modellen in een lijst
stats_models = [auto_arima, s_naive, theta, mstl1, mstl2]

# Instantieer het modelobject sf = StatsForecast( models=stats_models, freq="h", fallback_model = AutoARIMA(), n_jobs= -1)
Forecasting-pijplijnen ontwerpen voor productie

Forecasten met StatsModels

# Combineer modellen in een lijst
stats_models = [auto_arima, s_naive, theta, mstl1, mstl2]

# Instantieer het modelobject sf = StatsForecast( models=stats_models, freq="h", fallback_model = AutoARIMA(), n_jobs= -1)
# Maak de forecast forecast_stats = sf.forecast(df=train, h=72, level=[95])
Forecasting-pijplijnen ontwerpen voor productie

Forecasten met StatsModels

p = sf.plot(test, forecast_stats, engine = "plotly", level=[95])
p.update_layout(height=400)

Forecastgrafiek

Forecasting-pijplijnen ontwerpen voor productie

Modelevaluatie

def mape(y, yhat):
    mape = mean(abs(y - yhat)/ y) 
    return mape

def rmse(y, yhat):
    rmse = (mean((y - yhat) ** 2 )) ** 0.5
    return rmse

def coverage(y, lower, upper):
    coverage = sum((y <= upper) & (y >= lower)) / len(y)
    return coverage
Forecasting-pijplijnen ontwerpen voor productie

Modelevaluatie

fc = forecast_stats.merge(test, how="left", on="ds")
fc_performance = None

for i in [str(m) for m in stats_models]:
    m = mape(y = fc["y"], yhat = fc[i])
    r = rmse(y = fc["y"], yhat = fc[i])
    c = coverage(y = fc["y"], lower = fc[i + "-lo-95"], upper = fc[i + "-hi-95"])

perf = {"model": i, "mape": m, "rmse": r, "coverage": c} if fc_performance is None: fc_performance = pd.DataFrame([perf]) else: fc_performance = pd.concat([fc_performance, pd.DataFrame([perf])]) fc_performance.reset_index(drop=True, inplace=True)
Forecasting-pijplijnen ontwerpen voor productie

Modelevaluatie

print(fc_performance.sort_values("rmse"))
     model                    mape        rmse            coverage
1    SeasonalNaive            0.041340    22410.483959    1.000000
4    MSTL_Holt_trend          0.053939    30201.299395    0.513889
3    MSTL_ARIMA_trend         0.053771    30428.240235    0.666667
2    DynamicOptimizedTheta    0.090566    45189.869437    0.916667
0    AutoARIMA                0.149790    70483.617198    1.000000
Forecasting-pijplijnen ontwerpen voor productie

Modelevaluatie

print(fc_performance.sort_values("rmse"))
     model                    mape        rmse            coverage
1    SeasonalNaive            0.041340    22410.483959    1.000000
4    MSTL_Holt_trend          0.053939    30201.299395    0.513889
3    MSTL_ARIMA_trend         0.053771    30428.240235    0.666667
2    DynamicOptimizedTheta    0.090566    45189.869437    0.916667
0    AutoARIMA                0.149790    70483.617198    1.000000

Kunnen we dit verbeteren?

  • Andere instellingen voor betere nauwkeurigheid
  • Experimenten helpen
Forecasting-pijplijnen ontwerpen voor productie

Laten we oefenen!

Forecasting-pijplijnen ontwerpen voor productie

Preparing Video For Download...