Multiple Time Series Forecast & Demand Pattern Classification using R — Part 2 | by Gouthaman Tharmathasan | Towards Data Science

Ensemble, ARIMA, ETS, Dynamic Harmonic Regression, Time Series Linear Regression, STL Decomposition ETS, Holt’s Linear, Holt’s Linear Damp, Simple Exponential Smoothing, Drift, Seasonal NAIVE, NAIVE, CROSTON, SBA
This is a continuation of my previous blog. In the previous blog, we looked at how we perform basic data preprocessing & how to classify time series using the function idclass. This series will have the following 5 parts:
Part 1: Data Cleaning & Demand categorization.
Part 2: Fit statistical Time Series models (ARIMA, ETS, CROSTON etc.) using fpp3 (tidy forecasting) R Package.
Part 3: Time Series Feature Engineering using timetk R Package.
Part 4: Fit Machine Learning models (XGBoost, Random Forest, etc.) & Hyperparameter tuning using modeltime & tidymodels R packages.
Part 5: Fit Deeplearning models (NBeats & DeepAR) & Hyperparameter tuning using modeltime, modeltime.gluonts R packages.
In this blog, I will explain how to fit the classical time series models (ARIMA, ETS, Decomposition Model etc.) on a group time-series data (3,548 groups) and select suitable time series model for each group.
Let’s get started!
The above diagram shows the workflow carried out to fit classic statistical models. In this workflow, the first stage (Read Data, Data Preparation & Demand Categorization) was explained in my previous blog. Here we will focus on fitting statistical models & calculating Root Mean Squared Logarithmic Error (RMSLE) accuracy measure to select suitable models.
Let’s import libraries.
pacman::p_load(tidyverse, magrittr) # data wrangling packagespacman::p_load(lubridate, tsintermittent, fpp3, modeltime, timetk, modeltime.gluonts, tidymodels, modeltime.ensemble, modeltime.resample) # time series model packagespacman::p_load(foreach, future) # parallel functionspacman::p_load(viridis, plotly) # visualizations packagestheme_set(hrbrthemes::theme_ipsum()) # set default themes
We have already identified a demand type for each meal/centre group. Now we will filter only smooth & erratic demand types meal/centre groups time series data.
smooth_tbl <- master_data_tbl %>%  filter(demand_cate %in% c("Smooth", "Erratic"))
Now filtered data is split into train & test (last 10 weeks) data for each meal/centre combo.
train_tbl <- smooth_tbl %>%  filter_index(. ~ "2018-07-23")test_tbl <- smooth_tbl %>%  filter_index("2018-07-30" ~ .)
Note: Here our data frame is a tsibble object, which is a special type of data frame which works with time-series data. We have already specified “center & meal IDs” as key variables in tsibble “master_data_tbl”. So our tidyverse functions will apply to all the meal/center groups. For example, when we apply the function “filter_index” this will filter by date for all the groups.
Next, we are going to fit the following 11-time series models for each meal/centre group i.e. fit a total of 34,265 models.
How are there 34,265 models?
There are 1,839 smooth & 1,276 erratic types meal/centre groups, which makes a total of 3,115 different groups. We will fit 11 different models for each group, making a total of 3,115 * 11 = 34,265.
Naive: The Naive model sets all future values the same as the last observation value.
Seasonal Naive: The seasonal naive model is used for seasonal data. In this situation, each future value is equal to the last value of the same season.
Drift: The drift model is a variation of Naive model, allowing forecast to increase or decrease over time.
Simple Exponential Smooth: The simple exponential smooth model is used when a clear trend or seasonal pattern cannot be identified.
Holt’s Linear: The Holt’s Linear model is an extended version of SES allowing to forecast with the trend.
Damped Holt’s Linear: The Damped Additive Trend model is an extended version of Holt’s Linear, allowing the trend to change over time with a damped parameter phi.
Forecasting with Decomposition: The decomposition model is used to decompose the time series using the Seasonal and Trend decomposition using Loess (STL) method. ETS method can then be used to forecast the seasonally adjusted data, after which the seasonal component can be added to the forecast data.
ARIMA: The ARIMA models explain the autocorrelations in the data. Here we are going to fit an automatic ARIMA model which automatically selects the ARMA orders using min AICC.
Dynamic Harmonic Regression: The Dynamic Harmonic Regression model allows the inclusion of other data, such as base price, checkout price, email promotion & homepage featured.
Time Series Regression: The time series regression model is used to forecast the dependent variable Y assuming that it has a linear relationship with other independent variables X. i.e. in this situation, an assumption is made when forecasting that the number of orders and checkout price, base price, emailer for promotion & homepage featured have a linear relationship.
Ensemble: The ensemble model simply uses several different models at the same time and calculates an average value of the resulting forecasts. For example, here, ARIMA, SES & Decomposition models are used together to calculate the average forecast value.
Now, we will fit the above 11 models in R using the R package fpp3 . Here we have log-transformed the number of orders to impose a positive constraint. You can see in R code we have added one as an offset; this is to overcome log(0) infinity issue.
This will take longer to run since it is fitting 34k models.
fpp3_model_table <- train_tbl %>%  model(    ## Model 1: Naive ----    naive_mod = NAIVE(log(num_orders + 1)),    ## Model 2: Snaive ----    snaive_mod = SNAIVE(log(num_orders + 1)),    ## Model 3: Drift ----    drift_mod = RW(log(num_orders + 1) ~ drift()),    ## Model 4: SES ----    ses_mod = ETS(log(num_orders + 1) ~ error("A") + trend("N") + season("N"), opt_crit = "mse"),    ## Model 5: Holt's Linear ----    hl_mod = ETS(log(num_orders + 1) ~ error("A") + trend("A") + season("N"), opt_crit = "mse"),    ## Model 6: Damped Holt's Linear ----    hldamp_mod = ETS(log(num_orders + 1) ~ error("A") + trend("Ad") + season("N"), opt_crit = "mse"),    ## Model 7: STL decomposition with ETS ----    stl_ets_mod = decomposition_model(STL(log(num_orders + 1)), ETS(season_adjust ~ season("N"))),    ## Model 8: ARIMA ----    arima_mod = ARIMA(log(num_orders + 1)),    ## Model 9: Dynamic harmonic regression ----    dhr_mod = ARIMA(log(num_orders + 1) ~ PDQ(0,0,0) + fourier(K=6) + checkout_price + emailer_for_promotion),    ## Model 10: TSLM ----    tslm_mod = TSLM(log(num_orders + 1) ~ checkout_price + base_price + emailer_for_promotion)) %>%  ## Model 11: Ensemble Model ----  mutate(ensemble_sm_mod = combination_ensemble(arima_mod, ses_mod, stl_ets_mod))
In this step, we will filter the intermittent & lumpy meal/centre groups time series data.
inter_tbl <- master_data_tbl %>%  filter(demand_cate %in% c("Intermittent", "Lumpy"))
Now the filtered data is split into train & test (last 10 weeks) data for each meal/centre group.
train_tbl <- inter_tbl %>%  filter_index(. ~ "2018 W30")test_tbl <- inter_tbl %>%  filter_index("2018 W31" ~ .)
Next, we will fit the following 5-time series models for each meal/centre group i.e. fit a total of 1,960 models.
How are there 1,960 models?
There are 273 Intermittent & 119 lumpy types meal/centre groups, which makes a total of 392 different groups. We are going to fit 5 different models for each group, making a total of 392* 5= 1,960.
Simple Exponential Smooth: Refer to the above explanation.
ARIMA: Refer to the above explanation.
CROSTON: The Croston model is the most suitable method for slow-moving products (intermittent).
SBA: The SBA model is another variant / improved version of Croston method.
Ensemble: Here, CROSTON, SBA, ARIMA & SES models are used together to calculate the average forecast value.
Now, we will fit the above 5 models in R using the R package fpp3 .
fpp3_model_table <- train_tbl %>%  model(    ## Model 1: Croston ----    crost_mod = CROSTON(log(num_orders + 1)),    ## Model 2: SBA ----    sba_mod = CROSTON(log(num_orders + 1), type = "sba"),    ## Model 3: SES ----    ses_mod = ETS(log(num_orders + 1) ~ error("A") + trend("N") + season("N"), opt_crit = "mse"),    ## Model 4: ARIMA ----    arima_mod = ARIMA(log(num_orders + 1))) %>%  ## Model 5: Ensemble ----  mutate(ensemble_inter_mod = combination_ensemble(crost_mod, sba_mod, ses_mod, arima_mod))
We have now 36,225 (i.e. 34,265 + 1,960) fitted models. Next, we need to find out which model is suitable for each meal/centre group. In order to do this, we have to forecast each model on the Test period and calculate their accuracy measure.
Now we will forecast on the Test period.
forecast_tbl <- fpp3_model_table %>%    forecast(test_tbl, times = 0) %>%    as_tibble() %>%    select(week_date, meal_id, center_id, .model, fc_qty = .mean)
In this stage, we will calculate the accuracy of each model in order to select a suitable model for each meal/centre group. The accuracy measure used here was the Root Mean Squared Logarithmic Error (RMSLE). I chose RMSLE simply because it was the measure used for this competition to evaluate. However, I personally prefer RMSSE as this was used in the M5 forecasting competition.
RMSLE can be calculated in R by using the functionrmsle in the R package Metrics.
forecast_tbl <- master_data_tbl %>%  as_tibble() %>% # change tsibble -> tibble  select(week_date, center_id, meal_id, num_orders) %>%  right_join(forecast_tbl, by = c("week_date", "meal_id", "center_id")) %>% # join forecast values  mutate(fc_qty = ifelse(fc_qty < 0, 0, fc_qty)) # change negative & NA ordersaccuracy_tbl <- forecast_tbl %>%  group_by(center_id, meal_id, .model) %>%  summarise(accuracy_rmsle = Metrics::rmsle(num_orders, fc_qty)) # calculate RMSLE
In this stage, we are going to select a suitable model for each meal/centre group based on minimum RMSLE.
suitable_model_tbl <- accuracy_tbl %>%  ungroup() %>%  group_by(meal_id, center_id) %>%  filter(accuracy_rmsle == min(accuracy_rmsle)) %>%  slice(n = 1)
Now we have a list of models which are suitable for each meal/centre group.
For example, the table below shows us that for Centre 110 & Meal 2104, the most suitable model is Seasonal Naive (snaive_mod ), whereas, the most suitable model for Centre 67 & Meal 1885 is Holt’s Linear model (hl_mod). These corresponding models can be used for each group in the future to forecast the number of orders.
The above plot shows an overview of the accuracy of our suitable models. It shows that high accuracy (i.e. less than 1 RMSLE) was achieved for a majority of meal/centre groups. However, there were a few meal/centre groups which revealed low accuracy; for these low accuracy groups, other advanced time-series/machine learning models could be fitted to increase the forecast accuracy. Furthermore, the majority of groups with low accuracy were Lumpy/Intermittent which meant that for these type of groups, rather than fitting advance models, the focus should be on safety stock calculations.
The above plot shows the number of meal/centre groups against the suitable models, chosen by minimum RMSLE. It shows that ARIMA, Dynamic Harmonic Regression & Time-Series Regression models are the most fitted models for meal/centre groups.
So, now we know how to fit classical time series models for a group of time-series data. However, this has some disadvantage in practical/business world. What are those disadvantages?
Time: It takes a very long time to train when the number of groups increases. For example, in our case, we need to train nearly 35k models in order to find 3.5k suitable models.Reproducibility: Once you find a suitable model for a group we assume that the same model will also be used for the future. In practice, this is not the case, since the most suitable model can change when new transactions are added.No Scalability: There is no one global model. i.e. we have had to fit different models for each group.
Time: It takes a very long time to train when the number of groups increases. For example, in our case, we need to train nearly 35k models in order to find 3.5k suitable models.
Reproducibility: Once you find a suitable model for a group we assume that the same model will also be used for the future. In practice, this is not the case, since the most suitable model can change when new transactions are added.
No Scalability: There is no one global model. i.e. we have had to fit different models for each group.
What can we do to overcome these issues?
The answer to these issues is Machine Learning & Deep Learning models.
In my next blog, I will explain how we can fit Machine Learning & Deep Learning models and do feature engineering. This machine learning model also increases our accuracy significantly.
Hyndman, R.J., & Athanasopoulos, G. (2021) Forecasting: principles and practice, 3rd edition, OTexts: Melbourne, Australia. OTexts.com/fpp3. Accessed on [Accessed 08 February 2021].
Kourentzes, N., 2014. Intermittent Demand Forecasting Package For R — Nikolaos Kourentzes. Kourentzes.com. Available at: <https://kourentzes.com/forecasting/2014/06/23/intermittent-demand-forecasting-package-for-r/> [Accessed 22 January 2021].