library(fpp3)
library(tidyverse)
#import data
pigs_vic <- aus_livestock %>%
filter(State == "Victoria", Animal == "Pigs")
#a.
fit <- pigs_vic %>%
model(ETS(Count ~ error("A") + trend("N") + season("N")))
fc <- fit %>%
forecast(h = 4)
fc
## # A fable: 4 x 6 [1M]
## # Key: Animal, State, .model [1]
## Animal State .model Month
## <fct> <fct> <chr> <mth>
## 1 Pigs Victoria "ETS(Count ~ error(\"A\") + trend(\"N\") + season(\"… 2019 Jan
## 2 Pigs Victoria "ETS(Count ~ error(\"A\") + trend(\"N\") + season(\"… 2019 Feb
## 3 Pigs Victoria "ETS(Count ~ error(\"A\") + trend(\"N\") + season(\"… 2019 Mar
## 4 Pigs Victoria "ETS(Count ~ error(\"A\") + trend(\"N\") + season(\"… 2019 Apr
## # ℹ 2 more variables: Count <dist>, .mean <dbl>
#b.
resid_sd <- fit %>%
augment() %>%
summarise(s = sd(.resid, na.rm = TRUE)) %>%
pull(s)
first_fc <- fc %>%
as_tibble() %>%
slice(1) %>%
pull(.mean)
s <- fit %>%
glance() %>%
pull(sigma2) %>%
sqrt()
s
## [1] 9353.115
# my 95% interval
manual_interval <- tibble(
lower_95 = first_fc - 1.96 * s,
upper_95 = first_fc + 1.96 * s
)
manual_interval
## # A tibble: 1 × 2
## lower_95 upper_95
## <dbl> <dbl>
## 1 76854. 113519.
# R 95% interval
r_interval <- fc %>%
hilo(level = 95)
r_interval
## # A tsibble: 4 x 7 [1M]
## # Key: Animal, State, .model [1]
## Animal State .model Month
## <fct> <fct> <chr> <mth>
## 1 Pigs Victoria "ETS(Count ~ error(\"A\") + trend(\"N\") + season(\"… 2019 Jan
## 2 Pigs Victoria "ETS(Count ~ error(\"A\") + trend(\"N\") + season(\"… 2019 Feb
## 3 Pigs Victoria "ETS(Count ~ error(\"A\") + trend(\"N\") + season(\"… 2019 Mar
## 4 Pigs Victoria "ETS(Count ~ error(\"A\") + trend(\"N\") + season(\"… 2019 Apr
## # ℹ 3 more variables: Count <dist>, .mean <dbl>, `95%` <hilo>
# I choose Australia
country_data <- global_economy %>%
filter(Country == "Australia")
#a.
country_data %>%
autoplot(Exports) +
labs(
title = "Annual Exports for Australia",
y = "Exports",
x = "Year"
)
#b. fit ETS and forcast
fit_ann <- country_data %>%
model(
ANN = ETS(Exports ~ error("A") + trend("N") + season("N"))
)
report(fit_ann)
## Series: Exports
## Model: ETS(A,N,N)
## Smoothing parameters:
## alpha = 0.5659948
##
## Initial states:
## l[0]
## 12.98943
##
## sigma^2: 1.3621
##
## AIC AICc BIC
## 257.3943 257.8387 263.5756
fc_ann <- fit_ann %>%
forecast(h = 10)
fc_ann %>%
autoplot(country_data) +
labs(
title = "ETS(A,N,N) Forecasts for Australia Exports",
y = "Exports",
x = "Year"
)
#c. RMSE
acc_ann <- fit_ann %>%
accuracy()
acc_ann
## # A tibble: 1 × 11
## Country .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <fct> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Australia ANN Training 0.232 1.15 0.914 1.09 5.41 0.928 0.928 0.0125
rmse_ann <- acc_ann %>%
pull(RMSE)
rmse_ann
## [1] 1.146794
#d. fit ETS and compare
fit_aan <- country_data %>%
model(
AAN = ETS(Exports ~ error("A") + trend("A") + season("N"))
)
report(fit_aan)
## Series: Exports
## Model: ETS(A,A,N)
## Smoothing parameters:
## alpha = 0.4407571
## beta = 1e-04
##
## Initial states:
## l[0] b[0]
## 12.74993 0.1371607
##
## sigma^2: 1.3395
##
## AIC AICc BIC
## 258.3124 259.4662 268.6146
fc_aan <- fit_aan %>%
forecast(h = 10)
fc_aan %>%
autoplot(country_data) +
labs(
title = "ETS(A,A,N) Forecasts for Australia Exports",
y = "Exports",
x = "Year"
)
acc_aan <- fit_aan %>%
accuracy()
acc_aan
## # A tibble: 1 × 11
## Country .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <fct> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Australia AAN Training -7.46e-7 1.12 0.893 -0.387 5.39 0.907 0.904 0.109
rmse_aan <- acc_aan %>%
pull(RMSE)
rmse_aan
## [1] 1.116727
#put training accuracy side by side
bind_rows(acc_ann, acc_aan)
## # A tibble: 2 × 11
## Country .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <fct> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Australia ANN Training 2.32e-1 1.15 0.914 1.09 5.41 0.928 0.928 0.0125
## 2 Australia AAN Training -7.46e-7 1.12 0.893 -0.387 5.39 0.907 0.904 0.109
#e compare forecast
bind_rows(
fc_ann %>% mutate(Model = "ETS(A,N,N)"),
fc_aan %>% mutate(Model = "ETS(A,A,N)")
) %>%
autoplot(country_data, level = NULL) +
labs(
title = "Comparison of Forecasts",
y = "Exports",
x = "Year"
)
#f.Manual 95% prediction
first_ann <- fc_ann %>%
as_tibble() %>%
slice(1) %>%
transmute(
Model = "ETS(A,N,N)",
Forecast = .mean,
Lower_95_manual = .mean - 1.96 * rmse_ann,
Upper_95_manual = .mean + 1.96 * rmse_ann
)
first_aan <- fc_aan %>%
as_tibble() %>%
slice(1) %>%
transmute(
Model = "ETS(A,A,N)",
Forecast = .mean,
Lower_95_manual = .mean - 1.96 * rmse_aan,
Upper_95_manual = .mean + 1.96 * rmse_aan
)
manual_intervals <- bind_rows(first_ann, first_aan)
manual_intervals
## # A tibble: 2 × 4
## Model Forecast Lower_95_manual Upper_95_manual
## <chr> <dbl> <dbl> <dbl>
## 1 ETS(A,N,N) 20.6 18.4 22.9
## 2 ETS(A,A,N) 20.8 18.6 23.0
#R produced 95% interval
r_intervals_ann <- fc_ann %>%
hilo(level = 95) %>%
as_tibble() %>%
slice(1) %>%
mutate(Model = "ETS(A,N,N)")
r_intervals_aan <- fc_aan %>%
hilo(level = 95) %>%
as_tibble() %>%
slice(1) %>%
mutate(Model = "ETS(A,A,N)")
bind_rows(r_intervals_ann, r_intervals_aan)
## # A tibble: 2 × 7
## Country .model Year
## <fct> <chr> <dbl>
## 1 Australia ANN 2018
## 2 Australia AAN 2018
## # ℹ 4 more variables: Exports <dist>, .mean <dbl>, `95%` <hilo>, Model <chr>
# China GDP
china_gdp <- global_economy %>%
filter(Country == "China")
lambda_bc <- china_gdp %>%
features(GDP, guerrero) %>%
pull(lambda_guerrero)
lambda_bc
## [1] -0.03446284
fit_default <- china_gdp %>%
model(Default = ETS(GDP))
fit_damped <- china_gdp %>%
model(Damped = ETS(GDP ~ trend("Ad")))
china_gdp_bc <- china_gdp %>%
mutate(GDP_bc = box_cox(GDP, lambda_bc))
fit_boxcox <- china_gdp_bc %>%
model(BoxCox = ETS(GDP_bc))
fit_boxcox_damped <- china_gdp_bc %>%
model(BoxCox_Damped = ETS(GDP_bc ~ trend("Ad")))
# forecast
fc_default <- fit_default %>% forecast(h = 30)
fc_damped <- fit_damped %>% forecast(h = 30)
fc_boxcox <- fit_boxcox %>% forecast(h = 30)
fc_boxcox_damped <- fit_boxcox_damped %>% forecast(h = 30)
# plot and compare
autoplot(china_gdp, GDP) +
autolayer(fc_default, GDP, series = "Default", level = NULL) +
autolayer(fc_damped, GDP, series = "Damped", level = NULL) +
autolayer(fc_boxcox, GDP_bc, series = "BoxCox", level = NULL) +
autolayer(fc_boxcox_damped, GDP_bc, series = "BoxCox + Damped", level = NULL) +
labs(
title = "China GDP Forecasts with Different ETS Options",
y = "GDP",
x = "Year"
)
## 8.7
gas <- aus_production %>% select(Quarter, Gas)
# ETS model
fit1 <- gas %>% model(ETS(Gas))
fc1 <- fit1 %>% forecast(h = 32)
# Damped trend model
fit2 <- gas %>% model(ETS(Gas ~ trend("Ad")))
fc2 <- fit2 %>% forecast(h = 32)
# Plot forecasts
autoplot(gas, Gas) +
autolayer(fc1, series = "ETS") +
autolayer(fc2, series = "Damped ETS")
Multiplicative seasonality is needed because the seasonal
fluctuations increase as the level of gas production
increases.
Damped trend usually produces more realistic long-term forecasts
set.seed(12345678)
myseries <- aus_retail |>
filter(`Series ID` == sample(aus_retail$`Series ID`,1))
#a
autoplot(myseries, Turnover)
#b
fit_hw <- myseries |>
model(HW = ETS(Turnover ~ error("M") + trend("A") + season("M")))
fit_hw_damped <- myseries |>
model(HW_damped = ETS(Turnover ~ error("M") + trend("Ad") + season("M")))
#c
accuracy(fit_hw)
## # A tibble: 1 × 12
## State Industry .model .type ME RMSE MAE MPE MAPE MASE RMSSE
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Northern T… Clothin… HW Trai… -0.0128 0.613 0.450 -0.469 5.15 0.513 0.529
## # ℹ 1 more variable: ACF1 <dbl>
accuracy(fit_hw_damped)
## # A tibble: 1 × 12
## State Industry .model .type ME RMSE MAE MPE MAPE MASE RMSSE
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Northern T… Clothin… HW_da… Trai… 0.0398 0.616 0.444 -0.0723 5.06 0.507 0.531
## # ℹ 1 more variable: ACF1 <dbl>
#d
fit_hw |> gg_tsresiduals()
# train/test
train <- myseries |> filter(year(Month) < 2011)
test <- myseries |> filter(year(Month) >= 2011)
lambda_bc <- train |>
features(Turnover, guerrero) |>
pull(lambda_guerrero)
train_bc <- train |>
mutate(Turnover_bc = box_cox(Turnover, lambda_bc))
test_bc <- test |>
mutate(Turnover_bc = box_cox(Turnover, lambda_bc))
fit_hw <- train |>
model(HW = ETS(Turnover ~ error("M") + trend("A") + season("M")))
fit_stl <- train_bc |>
model(
STL_ETS = decomposition_model(
STL(Turnover_bc),
ETS(season_adjust)
)
)
fc_hw <- fit_hw |> forecast(new_data = test)
fc_stl <- fit_stl |> forecast(new_data = test_bc)
bind_rows(
accuracy(fc_hw, test),
accuracy(fc_stl, test_bc)
) |>
select(.model, RMSE)
## # A tibble: 2 × 2
## .model RMSE
## <chr> <dbl>
## 1 HW 1.78
## 2 STL_ETS 0.405
The STL + Box-Cox + ETS model performs much better because its RMSE is substantially lower. This means its forecasts are closer to the actual values on the test data.