Design

Overview

Add simple bayesian structure time series model into pick best forecast component.

Detailed behavior

The mathematical models behind the approach are:

  • Observation Equation

\[Time Series = Trend + Seasonality + Regression + Noise\] \[Y_t = U_t + S_t + \beta^T X_t+ \epsilon_t\]

  • State/Transition/Process Equation

\[U_t=U_{t-1}+\delta_{t-1}+\omega_t\] \[\delta_t=\delta_{t-1}+v_t\] \[S_t=\sum_{s=1}^{s-1} S_{t-s}+\gamma_t\] Where \(\epsilon_t\), \(\omega_t\), \(v_t\) and \(\gamma_t\) are independent components of Gaussian random noise. \(U_t\) is the current level of the trend, the current slop of the trend is \(\delta_t\). The seasonal component \(S_t\) can be thought of as a set of \(s\) of seasons. \(X_t\) is the external regressors and \(\beta^T\) is the regression coefficients.

If the univariate time series data set is used for forecasting, the Bayesian structural model can be simplified as follow, since the series doesn’t have any regressors.

  • Observation Equation

\[Time Series = Trend + Seasonality + Noise\] \[Y_t = U_t + S_t + \epsilon_t\]

  • State/Transition/Process Equation

\[U_t=U_{t-1}+\delta_{t-1}+\omega_t\] \[\delta_t=\delta_{t-1}+v_t\] \[S_t=\sum_{s=1}^{s-1} S_{t-s}+\gamma_t\]

Considerations

  • The methodology in the prototype is simple Bayesian time series model for the univariate time series forecasting.
    • The pros of the prototyped model is that Bayesian time series models are more transparent than ARIMA model. They also facilitate better handling of uncertainty, a key feature when planning for the future. Bayesian time series model fits perfectly with sequential learning and decision making and it directly leads to exact small sample results.
    • The cons of the prototyped model is that the partial seasonality will be threw into noise/error term. The accurary of the forecasting results might be slighly worse than ARIMA model for some cases.
  • What are not in the prototype ?
    • The model with regressor (i.e. external variable) is not considered.
    • The input data is partial year data is not considered.
    • Since there is no project using Bayesian time series model at RA, the model is not covered in any Atlas Toolkit so far.

Function Overview

Function

rabsts(data, season.num, season.dur, pred.horizon)

Input

  •       data - Input data.
  •       season.num - The number of season to be modeled. 
          i.e., for a time series with quarterly seasonality, season.num=4.
  •       season.dur - The number of time periods in each season. 
          i.e., when season.num=4, 
          if it is monthly data, then season.dur=3;                
          if it is weekly data, then season.dur=13.
  •       pred.horizon - The number of periods you wish to predict. 
    Note: seasonal component (season.num and season.dur) can be determined by external analysis.

Output

A data frame containing the following as columns:

  •       result$mean - The posterior mean of the prediction; 
  •       result$median - The posterior median of the prediction.

Required R Package

  •       bsts

Prototype Code in R

Function Definition

## BEGIN: function ##
rabsts <- function(data, season.num, season.dur, pred.horizon) {
  ##get trend or/and seasonal state
  if(season.num==0){
    ss <- bsts::AddLocalLinearTrend(list(), data)}
  else{
    ss <- bsts::AddLocalLinearTrend(list(), data)
    ss <- bsts::AddSeasonal(ss, data, nseasons = season.num, season.duration = season.dur)}
  
  ##build Bayesial model
  bsts.model <- bsts::bsts(data, state.specification = ss, niter = 666, ping=0, seed=1000)
  
  ##predict
  result<-bsts::predict.bsts(bsts.model, horizon = pred.horizon, burn = SuggestBurn(0.1, bsts.model), quantiles = c(.025, .975))
  pred<-data.frame(result$mean,result$median)
  return(pred)
}
## END: function ##

Example of calling the function with sample data

First, we need to load the required R packages.

suppressMessages(library(bsts))

Now, we need some input data. The unit test data sets for rapbf package is hired for the prototype. It looks like:

Segment the data by seriesId:

#Input data
dat <- subset(inputData, seriesId=="1")
dat <- droplevels(dat)
#Holdout data
holdout.dat<-subset(holdoutData, seriesId=="1")
holdout.dat <- droplevels(holdout.dat)

Apply the Bayesial time series model for forecast:

  • Seasonal series:
x<-rabsts(dat$value,season.num=12,season.dur=1,pred.horizon=3) #assume that there are 12 seasons and each season is one month.
data.frame(x,holdout.dat$value)
  • Non-seasonal series:
y<-rabsts(dat$value,season.num=0,pred.horizon=3) #If no season, set season.num=0.
data.frame(y,holdout.dat$value)
LS0tDQp0aXRsZTogJ01BIENvbXBvbmVudDogQWRkIEJheWVzaWFuIFN0cnVjdHVyZSBUaW1lIFNlcmllcyBNb2RlbCBpbnRvIHJhcGJmJw0KYXV0aG9yOiAiSnVzdGluIEppIg0KZGF0ZTogIk1heSAxNSwgMjAxOCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KLS0tDQoNCiMgRGVzaWduDQoNCiMjIyBPdmVydmlldw0KQWRkIHNpbXBsZSBiYXllc2lhbiBzdHJ1Y3R1cmUgdGltZSBzZXJpZXMgbW9kZWwgaW50byBwaWNrIGJlc3QgZm9yZWNhc3QgY29tcG9uZW50Lg0KDQojIyMgRGV0YWlsZWQgYmVoYXZpb3INClRoZSBtYXRoZW1hdGljYWwgbW9kZWxzIGJlaGluZCB0aGUgYXBwcm9hY2ggYXJlOg0KDQoqIE9ic2VydmF0aW9uIEVxdWF0aW9uDQoNCiQkVGltZSBTZXJpZXMgPSBUcmVuZCArIFNlYXNvbmFsaXR5ICsgUmVncmVzc2lvbiArIE5vaXNlJCQNCiQkWV90ID0gVV90ICsgU190ICsgXGJldGFeVCBYX3QrIFxlcHNpbG9uX3QkJA0KDQoqIFN0YXRlL1RyYW5zaXRpb24vUHJvY2VzcyBFcXVhdGlvbg0KDQokJFVfdD1VX3t0LTF9K1xkZWx0YV97dC0xfStcb21lZ2FfdCQkDQokJFxkZWx0YV90PVxkZWx0YV97dC0xfSt2X3QkJA0KJCRTX3Q9XHN1bV97cz0xfV57cy0xfSBTX3t0LXN9K1xnYW1tYV90JCQNCldoZXJlICRcZXBzaWxvbl90JCwgJFxvbWVnYV90JCwgJHZfdCQgYW5kICRcZ2FtbWFfdCQgYXJlIGluZGVwZW5kZW50IGNvbXBvbmVudHMgb2YgR2F1c3NpYW4gcmFuZG9tIG5vaXNlLiAkVV90JCBpcyB0aGUgY3VycmVudCBsZXZlbCBvZiB0aGUgdHJlbmQsIHRoZSBjdXJyZW50IHNsb3Agb2YgdGhlIHRyZW5kIGlzICRcZGVsdGFfdCQuIFRoZSBzZWFzb25hbCBjb21wb25lbnQgJFNfdCQgY2FuIGJlIHRob3VnaHQgb2YgYXMgYSBzZXQgb2YgJHMkIG9mIHNlYXNvbnMuICRYX3QkIGlzIHRoZSBleHRlcm5hbCByZWdyZXNzb3JzIGFuZCAkXGJldGFeVCQgaXMgdGhlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLg0KDQpJZiB0aGUgdW5pdmFyaWF0ZSB0aW1lIHNlcmllcyBkYXRhIHNldCBpcyB1c2VkIGZvciBmb3JlY2FzdGluZywgdGhlIEJheWVzaWFuIHN0cnVjdHVyYWwgbW9kZWwgY2FuIGJlIHNpbXBsaWZpZWQgYXMgZm9sbG93LCBzaW5jZSB0aGUgc2VyaWVzIGRvZXNuJ3QgaGF2ZSBhbnkgcmVncmVzc29ycy4gDQoNCiogT2JzZXJ2YXRpb24gRXF1YXRpb24NCg0KJCRUaW1lIFNlcmllcyA9IFRyZW5kICsgU2Vhc29uYWxpdHkgKyBOb2lzZSQkDQokJFlfdCA9IFVfdCArIFNfdCArIFxlcHNpbG9uX3QkJA0KDQoqIFN0YXRlL1RyYW5zaXRpb24vUHJvY2VzcyBFcXVhdGlvbg0KDQokJFVfdD1VX3t0LTF9K1xkZWx0YV97dC0xfStcb21lZ2FfdCQkDQokJFxkZWx0YV90PVxkZWx0YV97dC0xfSt2X3QkJA0KJCRTX3Q9XHN1bV97cz0xfV57cy0xfSBTX3t0LXN9K1xnYW1tYV90JCQNCg0KIyMjIENvbnNpZGVyYXRpb25zDQoqIFRoZSBtZXRob2RvbG9neSBpbiB0aGUgcHJvdG90eXBlIGlzIHNpbXBsZSBCYXllc2lhbiB0aW1lIHNlcmllcyBtb2RlbCBmb3IgdGhlIHVuaXZhcmlhdGUgdGltZSBzZXJpZXMgZm9yZWNhc3RpbmcuIA0KICAgIC0gVGhlIHByb3Mgb2YgdGhlIHByb3RvdHlwZWQgbW9kZWwgaXMgdGhhdCBCYXllc2lhbiB0aW1lIHNlcmllcyBtb2RlbHMgYXJlIG1vcmUgdHJhbnNwYXJlbnQgdGhhbiBBUklNQSBtb2RlbC4gVGhleSBhbHNvIGZhY2lsaXRhdGUgYmV0dGVyIGhhbmRsaW5nIG9mIHVuY2VydGFpbnR5LCBhIGtleSBmZWF0dXJlIHdoZW4gcGxhbm5pbmcgZm9yIHRoZSBmdXR1cmUuIEJheWVzaWFuIHRpbWUgc2VyaWVzIG1vZGVsIGZpdHMgcGVyZmVjdGx5IHdpdGggc2VxdWVudGlhbCBsZWFybmluZyBhbmQgZGVjaXNpb24gbWFraW5nIGFuZCBpdCBkaXJlY3RseSBsZWFkcyB0byBleGFjdCBzbWFsbCBzYW1wbGUgcmVzdWx0cy4gDQogICAgLSBUaGUgY29ucyBvZiB0aGUgcHJvdG90eXBlZCBtb2RlbCBpcyB0aGF0IHRoZSBwYXJ0aWFsIHNlYXNvbmFsaXR5IHdpbGwgYmUgdGhyZXcgaW50byBub2lzZS9lcnJvciB0ZXJtLiBUaGUgYWNjdXJhcnkgb2YgdGhlIGZvcmVjYXN0aW5nIHJlc3VsdHMgbWlnaHQgYmUgc2xpZ2hseSB3b3JzZSB0aGFuIEFSSU1BIG1vZGVsIGZvciBzb21lIGNhc2VzLiAgDQoNCiogV2hhdCBhcmUgbm90IGluIHRoZSBwcm90b3R5cGUgPw0KICAgIC0gVGhlIG1vZGVsIHdpdGggcmVncmVzc29yIChpLmUuIGV4dGVybmFsIHZhcmlhYmxlKSBpcyBub3QgY29uc2lkZXJlZC4gDQogICAgLSBUaGUgaW5wdXQgZGF0YSBpcyBwYXJ0aWFsIHllYXIgZGF0YSBpcyBub3QgY29uc2lkZXJlZC4gDQogICAgLSBTaW5jZSB0aGVyZSBpcyBubyBwcm9qZWN0IHVzaW5nIEJheWVzaWFuIHRpbWUgc2VyaWVzIG1vZGVsIGF0IFJBLCB0aGUgbW9kZWwgaXMgbm90IGNvdmVyZWQgaW4gYW55IEF0bGFzIFRvb2xraXQgc28gZmFyLiANCg0KIyBGdW5jdGlvbiBPdmVydmlldw0KDQojIyMgRnVuY3Rpb24NCg0KYGBge3IgZXZhbD1GQUxTRX0NCnJhYnN0cyhkYXRhLCBzZWFzb24ubnVtLCBzZWFzb24uZHVyLCBwcmVkLmhvcml6b24pDQpgYGANCiMjIyBJbnB1dA0KKiAgICAgICAgICAgICBkYXRhIC0gSW5wdXQgZGF0YS4NCiogICAgICAgICAgICAgc2Vhc29uLm51bSAtIFRoZSBudW1iZXIgb2Ygc2Vhc29uIHRvIGJlIG1vZGVsZWQuIA0KICAgICAgICAgICAgICBpLmUuLCBmb3IgYSB0aW1lIHNlcmllcyB3aXRoIHF1YXJ0ZXJseSBzZWFzb25hbGl0eSwgc2Vhc29uLm51bT00Lg0KKiAgICAgICAgICAgICBzZWFzb24uZHVyIC0gVGhlIG51bWJlciBvZiB0aW1lIHBlcmlvZHMgaW4gZWFjaCBzZWFzb24uIA0KICAgICAgICAgICAgICBpLmUuLCB3aGVuIHNlYXNvbi5udW09NCwgDQogICAgICAgICAgICAgIGlmIGl0IGlzIG1vbnRobHkgZGF0YSwgdGhlbiBzZWFzb24uZHVyPTM7ICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICBpZiBpdCBpcyB3ZWVrbHkgZGF0YSwgdGhlbiBzZWFzb24uZHVyPTEzLg0KKiAgICAgICAgICAgICBwcmVkLmhvcml6b24gLSBUaGUgbnVtYmVyIG9mIHBlcmlvZHMgeW91IHdpc2ggdG8gcHJlZGljdC4gDQpOb3RlOiBzZWFzb25hbCBjb21wb25lbnQgKHNlYXNvbi5udW0gYW5kIHNlYXNvbi5kdXIpIGNhbiBiZSBkZXRlcm1pbmVkIGJ5IGV4dGVybmFsIGFuYWx5c2lzLg0KDQojIyMgT3V0cHV0DQoNCkEgZGF0YSBmcmFtZSBjb250YWluaW5nIHRoZSBmb2xsb3dpbmcgYXMgY29sdW1uczoNCg0KKiAgICAgICAgICAgICByZXN1bHQkbWVhbiAtIFRoZSBwb3N0ZXJpb3IgbWVhbiBvZiB0aGUgcHJlZGljdGlvbjsgDQoqICAgICAgICAgICAgIHJlc3VsdCRtZWRpYW4gLSBUaGUgcG9zdGVyaW9yIG1lZGlhbiBvZiB0aGUgcHJlZGljdGlvbi4NCg0KIyMjIFJlcXVpcmVkIFIgUGFja2FnZQ0KKiAgICAgICAgICAgICBic3RzDQoNCiMgUHJvdG90eXBlIENvZGUgaW4gUg0KDQojIyMgRnVuY3Rpb24gRGVmaW5pdGlvbg0KYGBge3J9DQojIyBCRUdJTjogZnVuY3Rpb24gIyMNCnJhYnN0cyA8LSBmdW5jdGlvbihkYXRhLCBzZWFzb24ubnVtLCBzZWFzb24uZHVyLCBwcmVkLmhvcml6b24pIHsNCiAgIyNnZXQgdHJlbmQgb3IvYW5kIHNlYXNvbmFsIHN0YXRlDQogIGlmKHNlYXNvbi5udW09PTApew0KICAgIHNzIDwtIGJzdHM6OkFkZExvY2FsTGluZWFyVHJlbmQobGlzdCgpLCBkYXRhKX0NCiAgZWxzZXsNCiAgICBzcyA8LSBic3RzOjpBZGRMb2NhbExpbmVhclRyZW5kKGxpc3QoKSwgZGF0YSkNCiAgICBzcyA8LSBic3RzOjpBZGRTZWFzb25hbChzcywgZGF0YSwgbnNlYXNvbnMgPSBzZWFzb24ubnVtLCBzZWFzb24uZHVyYXRpb24gPSBzZWFzb24uZHVyKX0NCiAgDQogICMjYnVpbGQgQmF5ZXNpYWwgbW9kZWwNCiAgYnN0cy5tb2RlbCA8LSBic3RzOjpic3RzKGRhdGEsIHN0YXRlLnNwZWNpZmljYXRpb24gPSBzcywgbml0ZXIgPSA2NjYsIHBpbmc9MCwgc2VlZD0xMDAwKQ0KICANCiAgIyNwcmVkaWN0DQogIHJlc3VsdDwtYnN0czo6cHJlZGljdC5ic3RzKGJzdHMubW9kZWwsIGhvcml6b24gPSBwcmVkLmhvcml6b24sIGJ1cm4gPSBTdWdnZXN0QnVybigwLjEsIGJzdHMubW9kZWwpLCBxdWFudGlsZXMgPSBjKC4wMjUsIC45NzUpKQ0KICBwcmVkPC1kYXRhLmZyYW1lKHJlc3VsdCRtZWFuLHJlc3VsdCRtZWRpYW4pDQogIHJldHVybihwcmVkKQ0KfQ0KIyMgRU5EOiBmdW5jdGlvbiAjIw0KYGBgDQoNCiMjIyBFeGFtcGxlIG9mIGNhbGxpbmcgdGhlIGZ1bmN0aW9uIHdpdGggc2FtcGxlIGRhdGENCg0KRmlyc3QsIHdlIG5lZWQgdG8gbG9hZCB0aGUgcmVxdWlyZWQgUiBwYWNrYWdlcy4NCmBgYHtyfQ0Kc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KGJzdHMpKQ0KYGBgDQoNCk5vdywgd2UgbmVlZCBzb21lIGlucHV0IGRhdGEuIFRoZSB1bml0IHRlc3QgZGF0YSBzZXRzIGZvciByYXBiZiBwYWNrYWdlIGlzIGhpcmVkIGZvciB0aGUgcHJvdG90eXBlLiBJdCBsb29rcyBsaWtlOg0KYGBge3IgZWNobz1GQUxTRX0NCiNzZXR3ZChjaG9vc2UuZGlyKCkpICN0aGlzIGlzIHVzZWQgdG8gc2V0IHRoZSB3b3JraW5nIGRpcmVjdG9yeQ0KaW5wdXREYXRhPC1yZWFkLmNzdigiaGlzdG9yaWNhbC5jc3YiKSAjIHNob3cgaW5wdXQgZGF0YQ0KaG9sZG91dERhdGE8LXJlYWQuY3N2KCJob2xkb3V0LmNzdiIpICMgc2hvdyBob2xkb3V0IGRhdGENCmBgYA0KDQpTZWdtZW50IHRoZSBkYXRhIGJ5IHNlcmllc0lkOg0KYGBge3J9DQojSW5wdXQgZGF0YQ0KZGF0IDwtIHN1YnNldChpbnB1dERhdGEsIHNlcmllc0lkPT0iMSIpDQpkYXQgPC0gZHJvcGxldmVscyhkYXQpDQojSG9sZG91dCBkYXRhDQpob2xkb3V0LmRhdDwtc3Vic2V0KGhvbGRvdXREYXRhLCBzZXJpZXNJZD09IjEiKQ0KaG9sZG91dC5kYXQgPC0gZHJvcGxldmVscyhob2xkb3V0LmRhdCkNCmBgYA0KDQpBcHBseSB0aGUgQmF5ZXNpYWwgdGltZSBzZXJpZXMgbW9kZWwgZm9yIGZvcmVjYXN0Og0KDQoqIFNlYXNvbmFsIHNlcmllczoNCmBgYHtyfQ0KeDwtcmFic3RzKGRhdCR2YWx1ZSxzZWFzb24ubnVtPTEyLHNlYXNvbi5kdXI9MSxwcmVkLmhvcml6b249MykgI2Fzc3VtZSB0aGF0IHRoZXJlIGFyZSAxMiBzZWFzb25zIGFuZCBlYWNoIHNlYXNvbiBpcyBvbmUgbW9udGguDQpkYXRhLmZyYW1lKHgsaG9sZG91dC5kYXQkdmFsdWUpDQpgYGANCiogTm9uLXNlYXNvbmFsIHNlcmllczoNCmBgYHtyfQ0KeTwtcmFic3RzKGRhdCR2YWx1ZSxzZWFzb24ubnVtPTAscHJlZC5ob3Jpem9uPTMpICNJZiBubyBzZWFzb24sIHNldCBzZWFzb24ubnVtPTAuDQpkYXRhLmZyYW1lKHksaG9sZG91dC5kYXQkdmFsdWUpDQpgYGANCg==