library(foresightr)
y <- AirPassengersEvery model is a specification: a small list that says what to fit.
It can be printed, saved, renamed and combined; it is estimated only by
fit_model(), forecast_model() or inside a
backtest().
model_log(model_airline())
#> <foresight model> log_arima_011_011
#> ARIMA(0,1,1)(0,1,1) by exact maximum likelihood, on the log scaleYardsticks
model_naive(), model_drift(),
model_mean() and model_seasonal_naive() are
what any other model must beat. The seasonal naive forecast with
growth = TRUE repeats last year scaled by the growth of the
last twelve months, a strong benchmark for revenue.
forecast_model(model_seasonal_naive(growth = TRUE), y, 6)
#> Jan Feb Mar Apr May Jun
#> 1961 463.5677 434.6642 465.7911 512.4813 524.7097 594.7451Theta and Holt-Winters
model_theta() is the method that won the M3 competition,
equivalent to simple exponential smoothing with drift, on the seasonally
adjusted series. model_holt_winters() smooths level, trend
and a multiplicative seasonal pattern.
fit_model(model_holt_winters(), y)$params
#> alpha beta gamma phi sse_relative
#> 0.3000000 0.0200000 0.8000000 1.0000000 0.2195894Exponential smoothing
model_ets() fits one member of the family by its code
(error, trend, season); model_auto_ets() chooses by AICc
among those that suit the series.
fit <- fit_model(model_auto_ets(), y)
fit$details$code
#> [1] "MAM"
fit$details[c("alpha", "beta", "gamma")]
#> $alpha
#> [1] 0.7409353
#>
#> $beta
#> [1] 1e-04
#>
#> $gamma
#> [1] 1e-04ARIMA
model_arima() is estimated by exact maximum likelihood.
model_auto_arima() chooses the differences by tests and the
orders by a stepwise search.
Prophet-style trend
model_prophet() fits a trend that may bend at many
places, shrinking the bends that do not matter to exactly zero, plus
Fourier seasonality:
fit <- fit_model(model_prophet(), log(y))
fit$details$changepoints
#> [1] 10 15 19 28 37 51 60 65 88 101 115Events and lasting steps are covered in
vignette("regressors").
TBATS
model_tbats() handles several seasonal periods,
including periods that are not whole numbers (52.18 weeks in a year),
with trigonometric terms. Whatever is not fixed is chosen by AIC, which
takes seconds.
fit <- fit_model(model_tbats(), y)
fit$details[c("harmonics", "lambda", "trend", "arma")]
#> $harmonics
#> [1] 5
#>
#> $lambda
#> [1] 2.306312e-05
#>
#> $trend
#> [1] TRUE
#>
#> $arma
#> [1] 0 0Intermittent demand
For series where most periods have no demand, the forecast is a rate: Croston’s method and its SBA and TSB variants.
demand <- c(0, 0, 3, 0, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 2, 0, 0, 0)
forecast_model(model_croston("sba"), demand, 3)
#> [1] 0.8762393 0.8762393 0.8762393Combining models
Any model can run on the log or Box-Cox scale, and on the seasonally adjusted series:
model_name(model_log(model_decomposed(model_auto_ets())))
#> [1] "log_stl_auto_ets"
forecast_model(model_box_cox(model_theta(), "guerrero"), y, 3)
#> Jan Feb Mar
#> 1961 446.6416 437.0833 521.2054An ensemble learns its weights from its members’ errors on the end of
the series; with "stacked" weights, members that add
nothing get exactly zero.
fit <- fit_model(model_ensemble(candidates_default(), weighting = "stacked"), y)
round(fit$params[fit$params > 0], 3)
#> weight_naive weight_seasonal_naive
#> 0.010 0.059
#> weight_seasonal_naive_growth weight_holt_winters
#> 0.046 0.503
#> weight_log_linear
#> 0.382The ready sets
vapply(candidates_default(), model_name, "")
#> [1] "naive" "drift" "seasonal_naive"
#> [4] "seasonal_naive_growth" "theta" "holt_winters"
#> [7] "log_linear" "arima_011_011" "log_arima_011_011"
#> [10] "prophet" "log_prophet"
length(candidates_thorough())
#> [1] 18candidates_thorough() adds the automatic choices and two
ensembles, and takes seconds rather than milliseconds in a backtest.