Summary of Findings

Exercise Finding
8.1 Pigs alpha = 0.322, l[0] = 100,646.6. Manual and R 95% intervals are nearly identical.
8.5 Algeria ANN beats AAN on RMSE (5.87 vs 5.89) and AICc (447 vs 452). No trend needed.
8.6 China GDP Box-Cox/log trends explode; damped models give more plausible forecasts.
8.7 Gas Multiplicative seasonality; HWm preferred (AICc 1682 vs 1685).
8.8 Retail HWmd has best test RMSE (1.15) and beats SNAIVE (1.55); HWm does not (1.78).
8.9 STL + ETS RMSE 1.13, narrowly beats HWmd (1.15).

8.1 Victorian Pigs

pigs <- aus_livestock |> filter(Animal == "Pigs", State == "Victoria")
fit81 <- pigs |> model(ETS(Count ~ error("A") + trend("N") + season("N")))
report(fit81)
## Series: Count 
## Model: ETS(A,N,N) 
##   Smoothing parameters:
##     alpha = 0.3221247 
## 
##   Initial states:
##      l[0]
##  100646.6
## 
##   sigma^2:  87480760
## 
##      AIC     AICc      BIC 
## 13737.10 13737.14 13750.07
fc81 <- fit81 |> forecast(h = 4)
fc81 |> autoplot(pigs |> filter(year(Month) >= 2010))

s <- augment(fit81) |> pull(.resid) |> sd(na.rm = TRUE)
c(lower = fc81$.mean[1] - 1.96 * s, upper = fc81$.mean[1] + 1.96 * s)
##     lower     upper 
##  76871.01 113502.10
fc81 |> hilo(level = 95) |> slice(1) |> pull(`95%`)
## <hilo[1]>
## [1] [76854.79, 113518.3]95

Findings: alpha = 0.322 and l[0] = 100,646.6. The forecast is flat at the last smoothed level. My manual interval [76,871, 113,502] is very close to R’s [76,855, 113,518]. R’s is slightly wider because it uses the exact forecast variance.

8.5 Algeria Exports

alg <- global_economy |> filter(Country == "Algeria")
alg |> autoplot(Exports)

fit85 <- alg |> model(
  ANN = ETS(Exports ~ error("A") + trend("N") + season("N")),
  AAN = ETS(Exports ~ error("A") + trend("A") + season("N")))

fit85 |> forecast(h = 5) |> autoplot(alg, level = NULL)

accuracy(fit85) |> select(.model, RMSE)
glance(fit85) |> select(.model, AICc)
fc85 <- fit85 |> forecast(h = 1)
rmse85 <- accuracy(fit85)$RMSE
fc85 |> mutate(lo = .mean - 1.96 * rmse85, hi = .mean + 1.96 * rmse85) |>
  as_tibble() |> select(.model, .mean, lo, hi)
fc85 |> hilo(level = 95) |> as_tibble() |> select(.model, `95%`)

Findings: Exports have no seasonality and no persistent trend, just large fluctuations. ANN has the lower RMSE (5.87 vs 5.89) and lower AICc (447 vs 452), so it is the better model. Manual intervals (ANN [10.9, 33.9], AAN [10.4, 33.5]) are close to R’s (ANN [10.75, 34.14], AAN [10.02, 33.94]), with R’s slightly wider.

8.6 China GDP

chn <- global_economy |> filter(Country == "China")
lam6 <- chn |> features(GDP, guerrero) |> pull(lambda_guerrero)

fit86 <- chn |> model(
  AAN        = ETS(GDP ~ error("A") + trend("A") + season("N")),
  damped     = ETS(GDP ~ error("A") + trend("Ad") + season("N")),
  boxcox     = ETS(box_cox(GDP, lam6) ~ error("A") + trend("A") + season("N")),
  boxcox_d   = ETS(box_cox(GDP, lam6) ~ error("A") + trend("Ad") + season("N")),
  log_damped = ETS(log(GDP) ~ error("A") + trend("Ad") + season("N")))

fit86 |> forecast(h = 30) |> autoplot(chn, level = NULL)

Findings: AAN and damped give the lowest, roughly linear forecasts. Box-Cox and log curve upward because the transformation makes growth exponential-like in original units. The undamped Box-Cox model reaches about 1e15 by 2050, which is unrealistic. Damping tempers it, so damped models are more plausible over 30 years.

8.7 Australian Gas Production

fit87 <- aus_production |> model(
  HWm  = ETS(Gas ~ error("M") + trend("A")  + season("M")),
  HWmd = ETS(Gas ~ error("M") + trend("Ad") + season("M")))

fit87 |> forecast(h = "5 years") |>
  autoplot(aus_production |> filter(year(Quarter) > 1990), level = NULL)

accuracy(fit87)
glance(fit87)

Findings: Seasonal swings grow with the level, so multiplicative seasonality is needed. RMSE is almost identical (4.60 vs 4.59), but HWm has the lower AICc (1682 vs 1685). The trend is close to linear, so damping is not needed.

8.8 Retail Series

set.seed(12345678)
myseries <- aus_retail |>
  filter(`Series ID` == sample(aus_retail$`Series ID`, 1))
myseries |> autoplot(Turnover)

fit88 <- myseries |> model(
  HWm  = ETS(Turnover ~ error("M") + trend("A")  + season("M")),
  HWmd = ETS(Turnover ~ error("M") + trend("Ad") + season("M")))
accuracy(fit88) |> select(.model, RMSE)
fit88 |> select(HWm) |> gg_tsresiduals()

augment(fit88) |> features(.innov, ljung_box, lag = 24)
train <- myseries |> filter(year(Month) <= 2010)
test  <- anti_join(myseries, train, by = "Month")
fit88t <- train |> model(
  HWm    = ETS(Turnover ~ error("M") + trend("A")  + season("M")),
  HWmd   = ETS(Turnover ~ error("M") + trend("Ad") + season("M")),
  snaive = SNAIVE(Turnover))
fit88t |> forecast(new_data = test) |> accuracy(myseries) |> select(.model, RMSE)

Findings: Seasonal swings grow with the level, so seasonality is multiplicative. HWm has the slightly lower one-step RMSE (0.613 vs 0.616). Its Ljung-Box p-value is 0.0765 (above 0.05, borderline); HWmd’s is 0.472. On the test set HWmd is best (1.15), SNAIVE is 1.55, and HWm is worst (1.78). So HWmd beats the seasonal naive benchmark, but HWm does not.

8.9 STL + ETS on Box-Cox Data

lam9 <- myseries |> features(Turnover, guerrero) |> pull(lambda_guerrero)
fit89 <- train |> model(
  stl_ets = decomposition_model(
    STL(box_cox(Turnover, lam9) ~ season(window = "periodic"), robust = TRUE),
    ETS(season_adjust ~ error("A") + trend("Ad") + season("N"))))

fit89 |> forecast(new_data = test) |> accuracy(myseries) |> select(.model, RMSE)

Findings: STL + ETS has test RMSE 1.13, slightly lower than the best model from 8.8(e), HWmd at 1.15. STL + ETS wins, but only narrowly.