’
fit <- aus_livestock %>%
filter(State == "Victoria") %>%
filter(Animal == "Pigs") %>%
model(ETS(Count ~ error("A") + trend("N") + season("N")))
report(fit)
## 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
fc <- fit %>%
forecast(h = 5)
fc %>%
autoplot(aus_livestock)
Alpha = 0.3221247 and the initial L0 is 100646.6
resid <- augment(fit) %>% select(.resid)
s <- sd(resid$.resid, na.rm = TRUE)
yhat <- fc$.mean[1]
manual_lower <- yhat - 1.96 * s
manual_upper <- yhat + 1.96 * s
fc_intervals <- fc %>%
hilo(level = 95) %>%
mutate(
r_lower = `95%`$lower,
r_upper = `95%`$upper
)
comparison <- fc_intervals %>%
slice(1) %>%
select(.mean, r_lower, r_upper) %>%
mutate(
manual_lower = manual_lower,
manual_upper = manual_upper
) %>%
select(.mean, manual_lower, manual_upper, r_lower, r_upper)
comparison
## # A tsibble: 1 x 6 [1M]
## .mean manual_lower manual_upper r_lower r_upper Month
## <dbl> <dbl> <dbl> <dbl> <dbl> <mth>
## 1 95187. 76871. 113502. 76855. 113518. 2019 Jan
The confidence interval ranges are almost identical, with the R estimated range being slightly wider at both ends
global_economy %>%
filter(Country == "India") %>%
autoplot(Exports)
The exports for India show a generally upward trend starting at 5
percent at the beginning of 1960s with a small dip during the 1980s
followed by exponential growth all the way up to 25 percent in the 2010s
followed by a sharp fall rise and another fall
india_exports <- global_economy %>%
filter(Country == "India") %>%
select(Year, Exports)
fit <- india_exports %>%
model(ETS(Exports ~ error("A") + trend("N") + season("N")))
fc <- fit %>%
forecast(h = 5)
fc %>%
autoplot(india_exports)
accuracy(fit)
## # A tibble: 1 × 10
## .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 "ETS(Exports ~ error(… Trai… 0.251 1.19 0.798 2.05 7.25 0.983 0.991 -0.0331
fit_trend <- india_exports %>%
model(ETS(Exports ~ error("A") + trend("A") + season("N")))
accuracy(fit_trend)
## # A tibble: 1 × 10
## .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 "ETS(Exports ~ erro… Trai… -0.0501 1.18 0.736 0.239 6.98 0.906 0.978 -0.0294
The RMSE is lower for the model with the trend component. Simple Exponential smoothing is more stable for short-term forecasting more centered around around the recent level. While ETS(A,A,N) adds one parameter for the trend and results in a lower RMSE and therefore a better fit, and is better suited fro a longer term forecast especially when we can see a clear trend in the data .
fc_trend <- fit_trend %>%
forecast(h = 5)
fc_trend %>%
autoplot(india_exports)
Here the trend related smoothing equation helps the model actually understand the recently decreasing characteristics of the exports and bring that into the forecasting, while the simple exponential smoothing models forecasts followed a more stable line across the next 5 years forecasts.
yhat_simple<- fc$.mean[1]
yhat_trend <- fc_trend$.mean[1]
rmse_simple <- accuracy(fit) %>% pull(RMSE)
rmse_trend <- accuracy(fit_trend) %>% pull(RMSE)
manual_simple <- c(
lower = yhat_simple - 1.96 * rmse_simple,
upper = yhat_simple + 1.96 * rmse_simple
)
manual_trend <- c(
lower = yhat_trend - 1.96 * rmse_trend,
upper = yhat_trend + 1.96 * rmse_trend
)
r_simple <- fc %>%
slice(1) %>%
hilo(level = 95) %>%
mutate(
r_lower = `95%`$lower,
r_upper = `95%`$upper
)
r_trend <- fc_trend %>%
slice(1) %>%
hilo(level = 95) %>%
mutate(
r_lower = `95%`$lower,
r_upper = `95%`$upper
)
tibble(
Model = c("ETS(A,N,N)", "ETS(A,A,N)"),
Forecast = c(yhat_simple, yhat_trend),
Manual_Lower = c(manual_simple["lower"], manual_trend["lower"]),
Manual_Upper = c(manual_simple["upper"], manual_trend["upper"]),
R_Lower = c(r_simple$r_lower, r_trend$r_lower),
R_Upper = c(r_simple$r_upper, r_trend$r_upper)
)
## # A tibble: 2 × 6
## Model Forecast Manual_Lower Manual_Upper R_Lower R_Upper
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 ETS(A,N,N) 19.0 16.7 21.4 16.7 21.4
## 2 ETS(A,A,N) 18.2 15.9 20.5 15.8 20.6
china_gdp <- global_economy %>%
filter(Country == "China") %>%
select(Year, GDP)
lambda <- china_gdp %>% features(GDP, features = guerrero) %>% pull(lambda_guerrero)
china_fit <- china_gdp %>%
model(
`ANN` = ETS(GDP ~ error("A") + trend("N") + season("N")),
`AAN ` = ETS(GDP ~ error("A") + trend("A") + season("N")),
`AMN ` = ETS(GDP ~ error("A") + trend("A") + season("N")),
`AAdN` = ETS(GDP ~ error("A") + trend("Ad") + season("N")),
`Box-Cox` = ETS(box_cox(GDP,lambda) ~ error("A") + trend("A") + season("N")),
`Damped Box-Cox` = ETS(box_cox(GDP,lambda) ~ error("A") + trend("Ad") + season("N"))
)
china_fc <- china_fit %>% forecast(h = 15)
china_fc %>%
autoplot(china_gdp, level = NULL)
accuracy(china_fit)
## # A tibble: 6 × 10
## .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 "ANN" Trai… 2.10e11 4.16e11 2.13e11 8.14 11.0 0.983 0.991 0.789
## 2 "AAN " Trai… 2.36e10 1.90e11 9.59e10 1.41 7.62 0.442 0.453 0.00905
## 3 "AMN " Trai… 2.36e10 1.90e11 9.59e10 1.41 7.62 0.442 0.453 0.00905
## 4 "AAdN" Trai… 2.95e10 1.90e11 9.49e10 1.62 7.62 0.438 0.454 -0.00187
## 5 "Box-Cox" Trai… -2.75e10 2.88e11 1.25e11 0.607 7.17 0.578 0.688 0.665
## 6 "Damped Box-C… Trai… 6.35e 9 1.96e11 1.02e11 1.77 7.26 0.472 0.468 0.135
We see that using holts method to incorporate trend based smoothing into the forecasting helps the model a lot more when compared to the simple exponential smoothing method of ANN, with AAN and AMN giving similar RMSE values. Damped versions AAdN provide a little more realistic version when it comes to producing better long term forecasts if the growth is expected to even out .
aus_production %>%
autoplot(Gas)
Here we see that clear seasonal fluctuations along with a clear trend
pattern that shows seasonal variations that increase over time. This
points towards the necessity of a multiplicative seasonality
pattern.
Gas_fit <- aus_production %>%
model(
`ETS(A,A,A)` = ETS(Gas ~ error("A") + trend("A") + season("A")), # additive trend & additive seasonality
`ETS(A,A,M)` = ETS(Gas ~ error("A") + trend("A") + season("M")), # additive trend & multiplicative seasonality
`Damped ETS(A,Ad,M)` = ETS(Gas ~ error("A") + trend("Ad") + season("M")) # additive damped trend & multiplicative seasonality
)
Gas_fc <- Gas_fit %>% forecast(h = "8 years")
Gas_fc %>%
autoplot(aus_production, level = NULL)
We see that the multiplicative forecast allows for increasing
fluctuations in seasonality within the predictions, while the additive
forecast retains the same variability. The damped forecasts look to be a
slightly better fit when considering long term forecasts as it reflects
how the trend gradually slows in different quarters and is not always at
a consistent rate of increase
set.seed(90483484)
myseries <- aus_retail %>%
filter(`Series ID` == sample(aus_retail$`Series ID`,1))
myseries %>%
autoplot(Turnover)
Similar to the previous example here the seasonal variance seems to
increase as the level of the series grows so we need to use
multiplicative seasonality that better scales with the level and is
better at capturing the seasonal peaks and lows that widen over
time.
fit_myseries <- myseries %>%
model(`HW_Multiplicative` = ETS(Turnover ~ error("M") + trend("A") + season("M")),
`HW_Damped_Multiplicative` = ETS(Turnover ~ error("M") + trend("Ad") + season("M")))
fit_myseries %>%
forecast(h=50) %>%
autoplot(myseries, level = NULL) +
facet_wrap(~ .model)
accuracy(fit_myseries)
## # A tibble: 2 × 12
## State Industry .model .type ME RMSE MAE MPE MAPE MASE RMSSE
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 South Austr… Superma… HW_Mu… Trai… 0.203 7.63 5.85 -0.0762 2.23 0.334 0.350
## 2 South Austr… Superma… HW_Da… Trai… 1.06 7.87 6.09 0.279 2.28 0.348 0.361
## # ℹ 1 more variable: ACF1 <dbl>
Here for one-step forecasts the Multiplicative model seems to have a lower RSME than the Damped multiplicative model showing us that damping maybe unnecessary. The damping reduces the trend and affects short term forecast accuracy
fit_myseries %>%
select(HW_Multiplicative) %>%
gg_tsresiduals()
Residuals seems almost normally distributed with not skewing and not
specific patterns. While they seem to oscillate around 0 there seems to
be a slightly higher variations in the earlier periods. The acf shows
peaks and bottoms random but crossing the significance intervals meaning
that the residuals are not fully uncorrelated and it doesn’t fully
satisfy the conditions for it being white noise
myseries_train <- myseries %>%
filter(year(Month) < 2011)
fit_myseries_train <- myseries_train %>%
model(`HW_Multiplicative` = ETS(Turnover ~ error("M") + trend("M") + season("M")),
`HW_Damped_Multiplicative` = ETS(Turnover ~ error("M") + trend("Md") + season("M")),
snaive = SNAIVE(Turnover))
fc_myseries_train <- fit_myseries_train %>%
forecast(new_data = anti_join(myseries, myseries_train))
fc_myseries_train %>% autoplot(myseries, level = NULL)
fc_myseries_train %>% accuracy(myseries) %>% select(.model, RMSE)
## # A tibble: 3 × 2
## .model RMSE
## <chr> <dbl>
## 1 HW_Damped_Multiplicative 109.
## 2 HW_Multiplicative 68.5
## 3 snaive 124.
The HW_Multiplicative method was able to beat the Snaive here.
lambda_retail <- myseries %>%
features(Turnover, features = guerrero) %>%
pull(lambda_guerrero)
stl_fit <- myseries %>%
model(STL(box_cox(Turnover, lambda_retail) ~ season(window = "periodic"), robust = TRUE))
Decomp <- components(stl_fit)
myseries_adj <- myseries %>%
mutate(Turnover_sa = Decomp$season_adjust)
fit <- myseries_train %>%
model(ETS(Turnover ~ error("M") + trend("A") + season("N")))
fc <- fit %>%
forecast(new_data = anti_join(myseries_adj, myseries_train))
accuracy_summary <- bind_rows(
fit %>%
accuracy() %>%
select(.model, .type, RMSE) %>%
mutate(Data = "Training"),
fc %>%
accuracy(myseries_adj) %>%
select(.model, .type, RMSE) %>%
mutate(Data = "Test")
)
accuracy_summary
## # A tibble: 2 × 4
## .model .type RMSE Data
## <chr> <chr> <dbl> <chr>
## 1 "ETS(Turnover ~ error(\"M\") + trend(\"A\") + season(\"N\")… Trai… 15.2 Trai…
## 2 "ETS(Turnover ~ error(\"M\") + trend(\"A\") + season(\"N\")… Test 31.9 Test