class: left, top, title-slide .title[ # Predictive Analytics Unit 13: Basic Forecasting ] .author[ ### Ken Arnold
Calvin University ] --- ## Main Takeaways - We can look for patterns in how things change over time. - Patterns may occur by chance, so we still need validation (but it's more tricky) - Good models show uncertainty about future too. --- ## Baseline Forecasting Methods - Mean - Drift - Naive ("random walk") - Trend --- ## Data: US retail employment ```r us_retail_employment <- us_employment %>% filter(year(Month) >= 1990, Title == "Retail Trade") %>% select(-Series_ID) autoplot(us_retail_employment, Employed) + labs(y = "Persons (thousands)", title = "Total employment in US retail") ``` <img src="slides13forecast1_files/figure-html/us-retail-timeplot-1.png" width="90%" style="display: block; margin: auto;" /> <!-- do decompositions? https://otexts.com/fpp3/components.html --> --- ## Mean Model: predict the mean of past data ```r fit_mean <- us_retail_employment %>% model( * MEAN(Employed), ) us_retail_employment %>% autoplot(Employed) + * autolayer(forecast(fit_mean, h = "2 years"), level = 80) ``` <img src="slides13forecast1_files/figure-html/mean-1.png" width="90%" style="display: block; margin: auto;" /> --- ## Naive Model: predict most recent observation ```r fit_naive <- us_retail_employment %>% model( * NAIVE(Employed) ) forecasts <- forecast(fit_naive, h = "2 years") us_retail_employment %>% autoplot(Employed) + autolayer(forecasts, level = 80) ``` <img src="slides13forecast1_files/figure-html/naive-1.png" width="90%" style="display: block; margin: auto;" /> --- ## Drift Model: predict last observation + a linear trend ```r fit_drift <- us_retail_employment %>% model( * drift = NAIVE(Employed ~ drift()), ) us_retail_employment %>% autoplot(Employed) + autolayer(forecast(fit_drift, h = "2 years"), level = 80) ``` <img src="slides13forecast1_files/figure-html/drift-1.png" width="90%" style="display: block; margin: auto;" /> --- ## Seasonal Naive: predict same as last year this time Optionally including drift too. ```r fit_seasonal <- us_retail_employment %>% model( * SNAIVE(Employed ~ lag("1 year") + drift()), ) us_retail_employment %>% autoplot(Employed) + autolayer(forecast(fit_seasonal, h = "2 years"), level = 80) ``` <img src="slides13forecast1_files/figure-html/snaive-1.png" width="90%" style="display: block; margin: auto;" /> --- ## Contrast this with a regression Suppose we're predicting for a date in March. - Seasonal Naive: use the most recent March value (last year?) - Linear Model with Seasonal features: use the value that best predicts *all* March values .pull-left[ ```r fit_tslm <- us_retail_employment %>% model( * snaive = SNAIVE(Employed ~ lag("1 year") + drift()), * tslm = TSLM(Employed ~ season("1 year") + trend()), ) ``` ] .pull-right[ ```r fit_tslm %>% forecast(h = "2 years") %>% autoplot( us_retail_employment %>% filter_index("2017 Jan" ~ .), # zoom in level = NULL) ``` <img src="slides13forecast1_files/figure-html/tslm-plot-1.png" width="90%" style="display: block; margin: auto;" /> ] --- ## Validation Train-test split: pick a *time* to be "present" ```r employment_train <- us_retail_employment %>% filter(Month < yearmonth("2018 Jan")) employment_test <- us_retail_employment %>% filter(Month >= yearmonth("2018 Jan")) c(nrow(employment_train), nrow(employment_test)) ``` ``` [1] 336 21 ``` --- ## Validation Fit on training data, evaluate on remaining data. ```r models <- employment_train %>% model( naive = NAIVE(Employed), seasonal = SNAIVE(Employed ~ lag("1 year")) ) forecasts <- models %>% forecast(employment_test) ``` .pull-left[ ```r forecasts %>% accuracy(employment_test) %>% select(.model, MAE, MAPE, RMSE) %>% knitr::kable() ``` |.model | MAE| MAPE| RMSE| |:--------|---------:|---------:|---------:| |naive | 537.97143| 3.4270696| 571.72667| |seasonal | 44.19524| 0.2814593| 56.07426| ] .pull-right[ ```r forecasts %>% autoplot(us_retail_employment, level = NULL) ``` <img src="slides13forecast1_files/figure-html/prediction-plot-1.png" width="90%" style="display: block; margin: auto;" /> ] --- ## Beyond this - Decompositions (e.g., "seasonally adjusted" values) - More complex temporal patterns (e.g., ARIMA) - Mixed / dynamic models: incorporate explanatory features - Better validation