Benchmarking

You can easily compare predictive performance of multiple algorithms such as Silverkite and Prophet using the BenchmarkForecastConfig class. In this tutorial we describe the step-by-step process of defining, running and monitoring a benchmark. We also demonstrate how to use the class functions to compute and plot errors for multiple models.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 from dataclasses import replace

 import plotly
 import plotly.graph_objects as go

 from greykite.common.evaluation import EvaluationMetricEnum
 from greykite.framework.benchmark.benchmark_class import BenchmarkForecastConfig
 from greykite.framework.benchmark.data_loader_ts import DataLoaderTS
 from greykite.framework.templates.autogen.forecast_config import ComputationParam
 from greykite.framework.templates.autogen.forecast_config import EvaluationMetricParam
 from greykite.framework.templates.autogen.forecast_config import EvaluationPeriodParam
 from greykite.framework.templates.autogen.forecast_config import MetadataParam
 from greykite.framework.templates.autogen.forecast_config import ForecastConfig
 from greykite.framework.templates.autogen.forecast_config import ModelComponentsParam
 from greykite.framework.templates.model_templates import ModelTemplateEnum
 from greykite.sklearn.cross_validation import RollingTimeSeriesSplit

Load the data

First load your dataset into a pandas dataframe. We will use the peyton-manning dataset as a running example.

35
36
37
38
 # Loads dataset into UnivariateTimeSeries
 dl = DataLoaderTS()
 ts = dl.load_peyton_manning_ts()
 df = ts.df  # cleaned pandas.DataFrame

Define the Configs

We specify the models we want to benchmark via the configs parameter. In this example we will benchmark 1 Prophet and 2 different Silverkite models. We first define the common components of the models such as MetadataParam and EvaluationMetricParam, and then update the configuration to specify individual models.

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 ## Define common components  of the configs
 # Specifies dataset information
 metadata = MetadataParam(
     time_col="ts",   # name of the time column
     value_col="y",   # name of the value column
     freq="D"         # "H" for hourly, "D" for daily, "W" for weekly, etc.
 )

 # Defines number of periods to forecast into the future
 forecast_horizon = 7

 # Specifies intended coverage of the prediction interval
 coverage = 0.95

 # Defines the metrics to evaluate the forecasts
 # We use Mean Absolute Percent Error (MAPE) in this tutorial
 evaluation_metric = EvaluationMetricParam(
     cv_selection_metric=EvaluationMetricEnum.MeanAbsolutePercentError.name,
     cv_report_metrics=None
 )

 # Defines the cross-validation config within pipeline
 evaluation_period = EvaluationPeriodParam(
     cv_max_splits=1,  # Benchmarking n_splits is defined in tscv, here we don't need split to choose parameter sets
     periods_between_train_test=0,
 )

 # Defines parameters related to grid-search computation
 computation = ComputationParam(
     hyperparameter_budget=None,
     n_jobs=-1,  # to debug, change to 1 for more informative error messages
     verbose=3)

 # Defines common components across all the configs
 # ``model_template`` and ``model_components_param`` changes between configs
 common_config = ForecastConfig(
     metadata_param=metadata,
     forecast_horizon=forecast_horizon,
     coverage=coverage,
     evaluation_metric_param=evaluation_metric,
     evaluation_period_param=evaluation_period,
     computation_param=computation,
 )

Now we update common_config to specify the individual models.

 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 # Defines ``Prophet`` model template with custom seasonality
 model_components = ModelComponentsParam(
     seasonality={
             "seasonality_mode": ["additive"],
             "yearly_seasonality": ["auto"],
             "weekly_seasonality": [True],
         },
         growth={
             "growth_term": ["linear"]
         }
 )
 param_update = dict(
     model_template=ModelTemplateEnum.PROPHET.name,
     model_components_param=model_components
 )
 Prophet = replace(common_config, **param_update)

 # Defines ``Silverkite`` model template with automatic autoregression
 # and changepoint detection
 model_components = ModelComponentsParam(
     changepoints={
         "changepoints_dict": {
             "method": "auto",
         }
     },
     autoregression={
         "autoreg_dict": "auto"
     }
 )
 param_update = dict(
     model_template=ModelTemplateEnum.SILVERKITE.name,
     model_components_param=model_components
 )
 Silverkite_1 = replace(common_config, **param_update)

 # Defines ``Silverkite`` model template via string encoding
 param_update = dict(
     model_template="DAILY_SEAS_NMQM_GR_LINEAR_CP_NM_HOL_SP2_FEASET_AUTO_ALGO_RIDGE_AR_AUTO_DSI_AUTO_WSI_AUTO",
     model_components_param=None
 )
 Silverkite_2 = replace(common_config, **param_update)

 # Define the list of configs to benchmark
 # The dictionary keys will be used to store the benchmark results
 configs = {
     "Prophet": Prophet,
     "SK_1": Silverkite_1,
     "SK_2": Silverkite_2,
 }

Define the Cross-Validation (CV)

In time-series forecasting we use a Rolling Window CV. You can easily define it by using RollingTimeSeriesSplit class. The CV parameters depend on the data frequency, forecast horizon as well as the speed of the models. See Benchmarking documentation for guidance on how to choose CV parameters for your use case.

157
158
159
160
161
162
163
164
165
166
167
168
169
170
 # Define the benchmark folds
 # CV parameters are changed for illustration purpose
 tscv = RollingTimeSeriesSplit(
     forecast_horizon=forecast_horizon,
     min_train_periods=2 * 365,
     expanding_window=True,
     use_most_recent_splits=True,
     periods_between_splits=5,
     periods_between_train_test=0,
     max_splits=4)  # reduced to 4 from 16 for faster runtime

 # Print the train, test split for benchmark folds
 for split_num, (train, test) in enumerate(tscv.split(X=df)):
     print(split_num, train, test)

Out:

0 [   0    1    2 ... 2939 2940 2941] [2942 2943 2944 2945 2946 2947 2948]
1 [   0    1    2 ... 2944 2945 2946] [2947 2948 2949 2950 2951 2952 2953]
2 [   0    1    2 ... 2949 2950 2951] [2952 2953 2954 2955 2956 2957 2958]
3 [   0    1    2 ... 2954 2955 2956] [2957 2958 2959 2960 2961 2962 2963]

Run the Benchmark

To start the benchmarking procedure execute its run method.

If you get an error message at this point, then there is a compatibility issue between your benchmark inputs. Check Debugging the Benchmark section for instructions on how to derive valid inputs.

180
181
 bm = BenchmarkForecastConfig(df=df, configs=configs, tscv=tscv)
 bm.run()

Out:

  0%|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | 0/3 [00:00<?, ?it/s]
Benchmarking 'Prophet' :   0%|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | 0/3 [00:00<?, ?it/s]

  0%|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | 0/4 [00:00<?, ?it/s]

Split '0' :   0%|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | 0/4 [00:00<?, ?it/s]Fitting 1 folds for each of 1 candidates, totalling 1 fits
INFO:prophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.


Split '0' :  25%|############################################################################################################################################################################################2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 1/4 [00:42<02:08, 42.68s/it]

Split '1' :  25%|############################################################################################################################################################################################2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 1/4 [00:42<02:08, 42.68s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits
INFO:prophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.


Split '1' :  50%|########################################################################################################################################################################################################################################################################################################################################################################################5                                                                                                                                                                                                                                                                                                                                                                                        | 2/4 [01:22<01:23, 41.92s/it]

Split '2' :  50%|########################################################################################################################################################################################################################################################################################################################################################################################5                                                                                                                                                                                                                                                                                                                                                                                        | 2/4 [01:22<01:23, 41.92s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits
INFO:prophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.


Split '2' :  75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7                                                                                                                                                                                            | 3/4 [02:01<00:40, 40.97s/it]

Split '3' :  75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7                                                                                                                                                                                            | 3/4 [02:01<00:40, 40.97s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits
INFO:prophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.


Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [02:40<00:00, 40.43s/it]
Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [02:40<00:00, 40.19s/it]

Benchmarking 'Prophet' :  33%|######################################################################################################################################################################################################################################################3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | 1/3 [02:40<05:21, 160.74s/it]
Benchmarking 'SK_1' :  33%|#######################################################################################################################################################################################################################################################3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | 1/3 [02:40<05:21, 160.74s/it]

  0%|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | 0/4 [00:00<?, ?it/s]

Split '0' :   0%|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | 0/4 [00:00<?, ?it/s]Fitting 1 folds for each of 1 candidates, totalling 1 fits


Split '0' :  25%|############################################################################################################################################################################################2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 1/4 [00:18<00:56, 18.69s/it]

Split '1' :  25%|############################################################################################################################################################################################2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 1/4 [00:18<00:56, 18.69s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits


Split '1' :  50%|########################################################################################################################################################################################################################################################################################################################################################################################5                                                                                                                                                                                                                                                                                                                                                                                        | 2/4 [00:38<00:37, 18.93s/it]

Split '2' :  50%|########################################################################################################################################################################################################################################################################################################################################################################################5                                                                                                                                                                                                                                                                                                                                                                                        | 2/4 [00:38<00:37, 18.93s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits


Split '2' :  75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7                                                                                                                                                                                            | 3/4 [00:59<00:19, 19.55s/it]

Split '3' :  75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7                                                                                                                                                                                            | 3/4 [00:59<00:19, 19.55s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits


Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [01:24<00:00, 21.19s/it]
Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [01:24<00:00, 21.05s/it]

Benchmarking 'SK_1' :  67%|##############################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################6                                                                                                                                                                                                                                                       | 2/3 [04:04<02:17, 137.77s/it]
Benchmarking 'SK_2' :  67%|##############################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################6                                                                                                                                                                                                                                                       | 2/3 [04:04<02:17, 137.77s/it]

  0%|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | 0/4 [00:00<?, ?it/s]

Split '0' :   0%|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | 0/4 [00:00<?, ?it/s]Fitting 1 folds for each of 1 candidates, totalling 1 fits


Split '0' :  25%|############################################################################################################################################################################################2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 1/4 [00:21<01:03, 21.26s/it]

Split '1' :  25%|############################################################################################################################################################################################2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 1/4 [00:21<01:03, 21.26s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits


Split '1' :  50%|########################################################################################################################################################################################################################################################################################################################################################################################5                                                                                                                                                                                                                                                                                                                                                                                        | 2/4 [00:38<00:39, 20.00s/it]

Split '2' :  50%|########################################################################################################################################################################################################################################################################################################################################################################################5                                                                                                                                                                                                                                                                                                                                                                                        | 2/4 [00:38<00:39, 20.00s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits


Split '2' :  75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7                                                                                                                                                                                            | 3/4 [00:54<00:18, 18.99s/it]

Split '3' :  75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7                                                                                                                                                                                            | 3/4 [00:54<00:18, 18.99s/it]Fitting 1 folds for each of 1 candidates, totalling 1 fits


Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [01:08<00:00, 17.47s/it]
Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [01:08<00:00, 17.22s/it]

Benchmarking 'SK_2' : 100%|######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 3/3 [05:13<00:00, 117.10s/it]
Benchmarking 'SK_2' : 100%|######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 3/3 [05:13<00:00, 104.60s/it]

Monitor the Benchmark

During benchmarking a couple of color coded progress bars are displayed to inform the user of the advancement of the entire process. The first bar displays config level information, while the second bar displays split level information for the current config. See example in Benchmarking documentation.

On the left side of the progress bar, it shows which config/ split is currently being benchmarked and progress within that level as a percentage.

On the right side, the user can see how many configs/ splits have been benchmarked and how many are remaining. Additionally, this bar also displays elapsed time and remaining runtime for the corresponding level.

Benchmark Output

The output of a successful benchmark procedure is stored as a nested dictionary under the class attribute result. For details on the structure of this tree check Benchmarking documentation.

You can extract any specific information by navigating this tree. For example, you can check the summary and component plot of any config.

208
209
210
 # Check summary of SK_1 model on first fold
 model = bm.result["SK_2"]["rolling_evaluation"]["split_0"]["pipeline_result"].model
 model[-1].summary(max_colwidth=30)

Out:

================================ Model Summary =================================

Number of observations: 2942,   Number of features: 264
Method: Ridge regression
Number of nonzero features: 264
Regularization parameter: 3.29

Residuals:
         Min           1Q       Median           3Q          Max
       -2.26       -0.244     -0.05336       0.1658        3.222

                      Pred_col   Estimate Std. Err Pr(>)_boot sig. code                   95%CI
                     Intercept      6.121   0.1308     <2e-16       ***          (5.869, 6.371)
       events_Chinese New Year    0.03987   0.1844      0.834                 (-0.3125, 0.3882)
     events_Chinese New Year-1    -0.1146   0.1632      0.478                 (-0.4437, 0.1787)
     events_Chinese New Year-2     0.0957   0.1522      0.534                 (-0.2068, 0.3911)
     events_Chinese New Year+1    0.06812   0.1738      0.726                 (-0.2396, 0.4373)
     events_Chinese New Year+2     0.1147   0.1294      0.370                 (-0.1303, 0.3747)
          events_Christmas Day    -0.3475   0.1328      0.008        **      (-0.6145, -0.1146)
        events_Christmas Day-1    -0.1645   0.1378      0.204                (-0.4552, 0.06942)
        events_Christmas Day-2   -0.02654   0.1858      0.882                   (-0.4464, 0.26)
        events_Christmas Day+1    -0.2217   0.1301      0.084         .     (-0.4903, 0.006795)
        events_Christmas Day+2     0.1649  0.09989      0.092         .       (-0.0292, 0.3482)
 events_Easter...hern Ireland]    -0.1764  0.08424      0.034         *     (-0.3299, 0.006296)
 events_Easter...rn Ireland]-1    -0.1165  0.04871      0.018         *     (-0.1956, -0.01594)
 events_Easter...rn Ireland]-2   -0.07303  0.04154      0.078         .      (-0.158, 0.001253)
 events_Easter...rn Ireland]+1    -0.1049  0.05908      0.078         .     (-0.2255, 0.008691)
 events_Easter...rn Ireland]+2   -0.03001  0.04667      0.526                (-0.1219, 0.05607)
            events_Good Friday    -0.1721  0.05663      0.004        **     (-0.2722, -0.05113)
          events_Good Friday-1    -0.1372  0.05508      0.010         *     (-0.2445, -0.02352)
          events_Good Friday-2   -0.07536   0.0581      0.202                (-0.1863, 0.04267)
          events_Good Friday+1   -0.07303  0.04154      0.078         .      (-0.158, 0.001253)
          events_Good Friday+2    -0.1165  0.04871      0.018         *     (-0.1956, -0.01594)
       events_Independence Day   0.003024  0.05647      0.940                 (-0.1113, 0.1152)
     events_Independence Day-1   -0.02279  0.05547      0.666                (-0.1296, 0.08394)
     events_Independence Day-2   -0.04216  0.04385      0.346                (-0.1231, 0.04568)
     events_Independence Day+1   -0.06213  0.05343      0.236                 (-0.1592, 0.0355)
     events_Independence Day+2   -0.06166  0.05979      0.314                 (-0.168, 0.04784)
              events_Labor Day    -0.2306  0.08359      0.006        **     (-0.3846, -0.06306)
            events_Labor Day-1   -0.09868  0.07435      0.170                (-0.2414, 0.05636)
            events_Labor Day-2   -0.03386  0.06457      0.612                (-0.1488, 0.09914)
            events_Labor Day+1    -0.1594  0.06092      0.002        **     (-0.2626, -0.03995)
            events_Labor Day+2    -0.1815  0.05477     <2e-16       ***     (-0.2871, -0.07054)
           events_Memorial Day    -0.3316  0.05859     <2e-16       ***      (-0.4346, -0.1958)
         events_Memorial Day-1    -0.2073  0.06225     <2e-16       ***     (-0.3133, -0.07902)
         events_Memorial Day-2   -0.04301  0.07553      0.580                 (-0.1838, 0.1195)
         events_Memorial Day+1    -0.1084   0.0465      0.030         *    (-0.1916, -0.007244)
         events_Memorial Day+2    0.09382  0.06718      0.166                (-0.02517, 0.2251)
          events_New Years Day    0.01308  0.08883      0.904                  (-0.1759, 0.181)
        events_New Years Day-1     0.1007   0.1065      0.348                  (-0.114, 0.3028)
        events_New Years Day-2      0.218   0.1283      0.090         .      (-0.02571, 0.4768)
        events_New Years Day+1     0.2599   0.1115      0.018         *        (0.04788, 0.463)
        events_New Years Day+2     0.2414   0.1199      0.048         *      (-0.01308, 0.4614)
                  events_Other    0.01958   0.0327      0.546                (-0.0428, 0.08879)
                events_Other-1    0.01857  0.03091      0.560               (-0.04086, 0.08081)
                events_Other-2     0.0369  0.02991      0.238               (-0.02263, 0.09551)
                events_Other+1     0.0357  0.02975      0.226               (-0.02418, 0.09129)
                events_Other+2    0.01925   0.0289      0.514               (-0.03743, 0.07122)
           events_Thanksgiving    -0.2125  0.07321      0.002        **     (-0.3464, -0.07105)
         events_Thanksgiving-1    -0.3427  0.06202     <2e-16       ***       (-0.4426, -0.213)
         events_Thanksgiving-2    -0.2731  0.06256     <2e-16       ***      (-0.3841, -0.1449)
         events_Thanksgiving+1    -0.1429  0.08056      0.084         .      (-0.2899, 0.03023)
         events_Thanksgiving+2    -0.1906  0.06139      0.002        **     (-0.3136, -0.08111)
           events_Veterans Day   -0.03182  0.07754      0.654                 (-0.1807, 0.1196)
         events_Veterans Day-1   -0.06039  0.07229      0.428                  (-0.1835, 0.078)
         events_Veterans Day-2   -0.03399  0.08793      0.692                 (-0.2134, 0.1436)
         events_Veterans Day+1   -0.02362  0.07218      0.748                 (-0.1616, 0.1163)
         events_Veterans Day+2   -0.02298  0.06407      0.740                 (-0.1437, 0.1017)
                 str_dow_2-Tue    0.01161  0.01902      0.526               (-0.02697, 0.05122)
                 str_dow_3-Wed   -0.02085  0.01849      0.296               (-0.05691, 0.01418)
                 str_dow_4-Thu    -0.0306  0.01636      0.056         .  (-0.06281, -0.0003824)
                 str_dow_5-Fri   -0.03895  0.01736      0.032         *   (-0.07328, -0.006034)
                 str_dow_6-Sat     -0.109  0.01857     <2e-16       ***     (-0.1428, -0.07494)
                 str_dow_7-Sun    0.01306  0.02093      0.540               (-0.02611, 0.05831)
                           ct1   0.005576  0.08475      0.942                 (-0.1727, 0.1856)
                is_weekend:ct1    -0.0053  0.04748      0.922                 (-0.1003, 0.0841)
             str_dow_2-Tue:ct1     0.0146  0.04754      0.736                (-0.08367, 0.1021)
             str_dow_3-Wed:ct1   -0.01129  0.03614      0.756               (-0.07528, 0.06215)
             str_dow_4-Thu:ct1   -0.01104  0.03611      0.786               (-0.07261, 0.05655)
             str_dow_5-Fri:ct1    0.02998  0.03612      0.394                (-0.03674, 0.1048)
             str_dow_6-Sat:ct1    0.01225  0.03244      0.720               (-0.05578, 0.07043)
             str_dow_7-Sun:ct1   -0.01755   0.0491      0.732                 (-0.1208, 0.0706)
             cp0_2008_09_29_00     0.2106  0.03004     <2e-16       ***        (0.1524, 0.2731)
  is_weekend:cp0_2008_09_29_00    0.04802  0.01949      0.012         *     (0.008307, 0.08535)
 str_dow_2-Tue...2008_09_29_00    0.03298  0.02518      0.196               (-0.01487, 0.08302)
 str_dow_3-Wed...2008_09_29_00     0.0195  0.01848      0.298               (-0.01501, 0.05766)
 str_dow_4-Thu...2008_09_29_00    0.01775  0.01959      0.364               (-0.02013, 0.05791)
 str_dow_5-Fri...2008_09_29_00    0.04006  0.02117      0.060         .     (0.002355, 0.08473)
 str_dow_6-Sat...2008_09_29_00    0.02821   0.0186      0.128              (-0.004345, 0.06347)
 str_dow_7-Sun...2008_09_29_00    0.01983  0.02331      0.392               (-0.02996, 0.06191)
             cp1_2008_11_03_00     0.2332  0.02986     <2e-16       ***        (0.1783, 0.2962)
  is_weekend:cp1_2008_11_03_00    0.05349  0.01898      0.002        **      (0.01479, 0.09188)
 str_dow_2-Tue...2008_11_03_00    0.03588  0.02363      0.120               (-0.01185, 0.08303)
 str_dow_3-Wed...2008_11_03_00    0.02475   0.0174      0.156              (-0.008893, 0.06075)
 str_dow_4-Thu...2008_11_03_00    0.02351  0.01798      0.192               (-0.01068, 0.06049)
 str_dow_5-Fri...2008_11_03_00    0.04026  0.02028      0.046         *      (0.001017, 0.0798)
 str_dow_6-Sat...2008_11_03_00    0.03246  0.01735      0.056         .     (0.002444, 0.06851)
 str_dow_7-Sun...2008_11_03_00    0.02104  0.02241      0.354               (-0.02566, 0.05922)
             cp2_2008_12_15_00     0.2379  0.03297     <2e-16       ***        (0.1753, 0.2983)
  is_weekend:cp2_2008_12_15_00    0.05346  0.02179      0.014         *     (0.008505, 0.09601)
 str_dow_2-Tue...2008_12_15_00    0.03851  0.02228      0.098         .    (-0.005187, 0.08309)
 str_dow_3-Wed...2008_12_15_00    0.02435  0.01729      0.172              (-0.009442, 0.06073)
 str_dow_4-Thu...2008_12_15_00    0.02527  0.01719      0.138               (-0.00853, 0.05854)
 str_dow_5-Fri...2008_12_15_00    0.03448  0.02038      0.080         .    (-0.007206, 0.07034)
 str_dow_6-Sat...2008_12_15_00    0.03139  0.01755      0.068         .    (-0.0007694, 0.0678)
 str_dow_7-Sun...2008_12_15_00    0.02208  0.02354      0.354               (-0.02808, 0.06239)
             cp3_2009_01_12_00     0.2351  0.03627     <2e-16       ***        (0.1611, 0.3039)
  is_weekend:cp3_2009_01_12_00     0.0538  0.02446      0.026         *      (0.003711, 0.1002)
 str_dow_2-Tue...2009_01_12_00    0.03774  0.02218      0.092         .    (-0.007119, 0.08103)
 str_dow_3-Wed...2009_01_12_00    0.02263  0.01808      0.230              (-0.009728, 0.06055)
 str_dow_4-Thu...2009_01_12_00    0.02352  0.01749      0.184               (-0.01235, 0.05738)
 str_dow_5-Fri...2009_01_12_00    0.03076  0.02053      0.118               (-0.01236, 0.06933)
 str_dow_6-Sat...2009_01_12_00     0.0292  0.01861      0.114              (-0.004525, 0.06976)
 str_dow_7-Sun...2009_01_12_00    0.02461  0.02477      0.324                 (-0.03187, 0.066)
             cp4_2009_12_21_00    -0.1748  0.06432      0.010         *      (-0.3014, -0.0505)
  is_weekend:cp4_2009_12_21_00    -0.0623  0.04593      0.178                (-0.1477, 0.03633)
 str_dow_2-Tue...2009_12_21_00    -0.0522  0.04871      0.280                (-0.1444, 0.04903)
 str_dow_3-Wed...2009_12_21_00   -0.01079  0.03539      0.766                (-0.08197, 0.0541)
 str_dow_4-Thu...2009_12_21_00  -0.003596  0.03099      0.930               (-0.05586, 0.06692)
 str_dow_5-Fri...2009_12_21_00   -0.05109   0.0399      0.210                (-0.1342, 0.02574)
 str_dow_6-Sat...2009_12_21_00   -0.03801  0.03636      0.284                (-0.1109, 0.03471)
 str_dow_7-Sun...2009_12_21_00   -0.02431  0.04862      0.634                (-0.1129, 0.07034)
             cp5_2010_01_25_00    -0.1655  0.06952      0.028         *     (-0.3118, -0.02924)
  is_weekend:cp5_2010_01_25_00   -0.05751  0.05065      0.264                (-0.1507, 0.04434)
 str_dow_2-Tue...2010_01_25_00   -0.05325  0.05284      0.324                (-0.1537, 0.05824)
 str_dow_3-Wed...2010_01_25_00  -0.009916  0.03768      0.806               (-0.08841, 0.06197)
 str_dow_4-Thu...2010_01_25_00  -0.004032   0.0323      0.918               (-0.05859, 0.06857)
 str_dow_5-Fri...2010_01_25_00    -0.0539  0.04042      0.178                (-0.1343, 0.02469)
 str_dow_6-Sat...2010_01_25_00   -0.04035  0.03883      0.292                (-0.1209, 0.03564)
 str_dow_7-Sun...2010_01_25_00   -0.01718  0.05392      0.780                (-0.1228, 0.08942)
             cp6_2011_02_14_00     0.2479  0.08563     <2e-16       ***       (0.07717, 0.3993)
  is_weekend:cp6_2011_02_14_00    0.08769  0.05866      0.146                 (-0.01924, 0.196)
 str_dow_2-Tue...2011_02_14_00  -0.002812  0.05885      0.972                  (-0.1057, 0.105)
 str_dow_3-Wed...2011_02_14_00    0.04529  0.04753      0.370                (-0.04788, 0.1343)
 str_dow_4-Thu...2011_02_14_00    0.03514   0.0445      0.430                (-0.05313, 0.1239)
 str_dow_5-Fri...2011_02_14_00    0.01387  0.05536      0.816                 (-0.1041, 0.1162)
 str_dow_6-Sat...2011_02_14_00    0.02904  0.05066      0.570                 (-0.0768, 0.1243)
 str_dow_7-Sun...2011_02_14_00    0.05866  0.05573      0.296                (-0.04718, 0.1715)
             cp7_2012_02_27_00    -0.4777   0.0752     <2e-16       ***      (-0.6165, -0.3217)
  is_weekend:cp7_2012_02_27_00    -0.1036  0.05068      0.042         *    (-0.2051, -0.007028)
 str_dow_2-Tue...2012_02_27_00   -0.08741   0.0622      0.162                (-0.2028, 0.04099)
 str_dow_3-Wed...2012_02_27_00   -0.07809  0.06272      0.200                (-0.2097, 0.03976)
 str_dow_4-Thu...2012_02_27_00   -0.07505  0.05818      0.188                 (-0.197, 0.01622)
 str_dow_5-Fri...2012_02_27_00   -0.04907  0.05887      0.396                (-0.1608, 0.07046)
 str_dow_6-Sat...2012_02_27_00     -0.041  0.05018      0.418                 (-0.147, 0.04946)
 str_dow_7-Sun...2012_02_27_00   -0.06262  0.05508      0.268                 (-0.1633, 0.0457)
             cp8_2012_04_09_00    -0.4309  0.06645     <2e-16       ***      (-0.5421, -0.2945)
  is_weekend:cp8_2012_04_09_00    -0.1018  0.04692      0.028         *     (-0.191, -0.006727)
 str_dow_2-Tue...2012_04_09_00   -0.07685  0.06146      0.196                   (-0.2, 0.04112)
 str_dow_3-Wed...2012_04_09_00   -0.06452  0.05853      0.252                (-0.1858, 0.04967)
 str_dow_4-Thu...2012_04_09_00   -0.06475  0.05455      0.228                (-0.1783, 0.02238)
 str_dow_5-Fri...2012_04_09_00   -0.05388  0.05465      0.322                (-0.1561, 0.05266)
 str_dow_6-Sat...2012_04_09_00   -0.04202  0.04705      0.362                (-0.1433, 0.04837)
 str_dow_7-Sun...2012_04_09_00   -0.05983  0.05232      0.270                (-0.1624, 0.04524)
             cp9_2013_03_04_00     0.2744   0.0894      0.008        **        (0.07894, 0.421)
  is_weekend:cp9_2013_03_04_00   0.004669  0.06365      0.936                 (-0.1315, 0.1265)
 str_dow_2-Tue...2013_03_04_00    0.08076  0.06057      0.168                (-0.05543, 0.1905)
 str_dow_3-Wed...2013_03_04_00    0.07146  0.04074      0.076         .     (-0.003643, 0.1547)
 str_dow_4-Thu...2013_03_04_00    0.05999  0.04711      0.206                  (-0.03145, 0.15)
 str_dow_5-Fri...2013_03_04_00     0.0344  0.05268      0.504                 (-0.0654, 0.1377)
 str_dow_6-Sat...2013_03_04_00   0.009014  0.05064      0.848                (-0.09017, 0.1094)
 str_dow_7-Sun...2013_03_04_00  -0.004336  0.06377      0.960                 (-0.1368, 0.1086)
            cp10_2014_01_27_00    -0.2156   0.1003      0.036         *     (-0.4115, -0.00694)
 is_weekend:cp10_2014_01_27_00   -0.05926  0.07069      0.402                (-0.2037, 0.07971)
 str_dow_2-Tue...2014_01_27_00    0.04716   0.1142      0.690                 (-0.1812, 0.2712)
 str_dow_3-Wed...2014_01_27_00   -0.05215  0.06424      0.432                 (-0.1727, 0.0826)
 str_dow_4-Thu...2014_01_27_00   -0.03568  0.06769      0.602                 (-0.1673, 0.0949)
 str_dow_5-Fri...2014_01_27_00   -0.01206  0.07553      0.868                 (-0.1618, 0.1428)
 str_dow_6-Sat...2014_01_27_00   -0.05488  0.05657      0.328                (-0.1661, 0.05691)
 str_dow_7-Sun...2014_01_27_00   -0.00446  0.09091      0.968                 (-0.1801, 0.1533)
           ct1:sin1_tow_weekly  -0.007989  0.03406      0.834               (-0.07797, 0.05715)
           ct1:cos1_tow_weekly   -0.01605   0.0581      0.792                (-0.1287, 0.09516)
           ct1:sin2_tow_weekly    0.03773  0.03964      0.340                (-0.03916, 0.1217)
           ct1:cos2_tow_weekly  9.583e-05  0.05766      0.994                 (-0.1094, 0.1136)
 cp0_2008_09_2...n1_tow_weekly  -0.004049  0.01546      0.796                (-0.03375, 0.0282)
 cp0_2008_09_2...s1_tow_weekly    0.01201  0.02917      0.672               (-0.05038, 0.06993)
 cp0_2008_09_2...n2_tow_weekly    0.01747  0.01929      0.382               (-0.01781, 0.05387)
 cp0_2008_09_2...s2_tow_weekly    0.01781  0.02765      0.544               (-0.03174, 0.07227)
 cp1_2008_11_0...n1_tow_weekly  -0.001635  0.01453      0.932                (-0.0304, 0.02848)
 cp1_2008_11_0...s1_tow_weekly    0.01102  0.02684      0.660               (-0.04347, 0.06539)
 cp1_2008_11_0...n2_tow_weekly    0.01586  0.01802      0.388               (-0.01821, 0.05218)
 cp1_2008_11_0...s2_tow_weekly    0.01637  0.02455      0.550               (-0.02706, 0.06664)
 cp2_2008_12_1...n1_tow_weekly   0.001019    0.015      0.948               (-0.02832, 0.02999)
 cp2_2008_12_1...s1_tow_weekly    0.01772  0.02544      0.476               (-0.03162, 0.07143)
 cp2_2008_12_1...n2_tow_weekly    0.01349  0.01787      0.460                (-0.0187, 0.05158)
 cp2_2008_12_1...s2_tow_weekly    0.01873  0.02231      0.426               (-0.02239, 0.06238)
 cp3_2009_01_1...n1_tow_weekly   0.000366   0.0161      0.980               (-0.03049, 0.03119)
 cp3_2009_01_1...s1_tow_weekly    0.02388  0.02531      0.340               (-0.02265, 0.07708)
 cp3_2009_01_1...n2_tow_weekly    0.01095  0.01848      0.550               (-0.02172, 0.05107)
 cp3_2009_01_1...s2_tow_weekly    0.02112    0.022      0.384               (-0.01864, 0.06327)
 cp4_2009_12_2...n1_tow_weekly    0.01298   0.0364      0.706               (-0.05686, 0.08439)
 cp4_2009_12_2...s1_tow_weekly     0.0091  0.05284      0.896                (-0.09779, 0.1104)
 cp4_2009_12_2...n2_tow_weekly   -0.03903  0.04084      0.334                (-0.1208, 0.04009)
 cp4_2009_12_2...s2_tow_weekly    0.01676  0.04812      0.672                (-0.08828, 0.1025)
 cp5_2010_01_2...n1_tow_weekly    0.01183  0.03881      0.754               (-0.06203, 0.08931)
 cp5_2010_01_2...s1_tow_weekly      0.017  0.05621      0.770                 (-0.1034, 0.1213)
 cp5_2010_01_2...n2_tow_weekly   -0.04479  0.04453      0.314                (-0.1358, 0.04051)
 cp5_2010_01_2...s2_tow_weekly    0.01988  0.05156      0.658                (-0.08837, 0.1116)
 cp6_2011_02_1...n1_tow_weekly   -0.01186  0.04667      0.818                (-0.1013, 0.08092)
 cp6_2011_02_1...s1_tow_weekly    0.02282  0.06072      0.712                (-0.09485, 0.1407)
 cp6_2011_02_1...n2_tow_weekly   -0.04282  0.05034      0.388                (-0.1495, 0.05473)
 cp6_2011_02_1...s2_tow_weekly    0.01072  0.05671      0.868                (-0.09331, 0.1181)
 cp7_2012_02_2...n1_tow_weekly   -0.03426  0.04671      0.444                (-0.1256, 0.05757)
 cp7_2012_02_2...s1_tow_weekly    -0.0216  0.07247      0.776                 (-0.1664, 0.1179)
 cp7_2012_02_2...n2_tow_weekly   0.006135    0.054      0.902                (-0.09957, 0.1157)
 cp7_2012_02_2...s2_tow_weekly   -0.01171  0.06727      0.872                 (-0.1423, 0.1112)
 cp8_2012_04_0...n1_tow_weekly   -0.02049  0.04345      0.622                (-0.1018, 0.06555)
 cp8_2012_04_0...s1_tow_weekly   -0.01313  0.06951      0.880                  (-0.153, 0.1187)
 cp8_2012_04_0...n2_tow_weekly  0.0007326  0.05155      0.996                  (-0.104, 0.1105)
 cp8_2012_04_0...s2_tow_weekly  -0.009255  0.06332      0.876                  (-0.1369, 0.106)
 cp9_2013_03_0...n1_tow_weekly    0.07112  0.04393      0.106                (-0.01756, 0.1518)
 cp9_2013_03_0...s1_tow_weekly   -0.01629  0.06048      0.804                (-0.1427, 0.09955)
 cp9_2013_03_0...n2_tow_weekly    0.01856  0.05271      0.748                (-0.08961, 0.1218)
 cp9_2013_03_0...s2_tow_weekly   -0.00348  0.05773      0.960                 (-0.1113, 0.1067)
 cp10_2014_01_...n1_tow_weekly    0.01706  0.05605      0.780                (-0.08241, 0.1246)
 cp10_2014_01_...s1_tow_weekly  -0.006058   0.1201      0.974                 (-0.2325, 0.2317)
 cp10_2014_01_...n2_tow_weekly    0.03459  0.07346      0.644                 (-0.1203, 0.1619)
 cp10_2014_01_...s2_tow_weekly   -0.02519   0.1146      0.856                 (-0.2296, 0.1833)
               sin1_tow_weekly    0.04535  0.01934      0.018         *     (0.007471, 0.08489)
               cos1_tow_weekly     0.1482  0.03027     <2e-16       ***       (0.09042, 0.2089)
               sin2_tow_weekly   -0.02369  0.01903      0.210               (-0.06384, 0.01253)
               cos2_tow_weekly     0.1277  0.03117      0.002        **       (0.06679, 0.1892)
               sin3_tow_weekly   -0.03149  0.01646      0.054         .    (-0.06237, 0.001492)
               cos3_tow_weekly    0.04578  0.02747      0.094         .     (-0.01018, 0.09973)
              sin1_tom_monthly     0.1859  0.05875     <2e-16       ***       (0.06709, 0.2981)
              cos1_tom_monthly     0.3767  0.05665     <2e-16       ***        (0.2579, 0.4746)
              sin2_tom_monthly    0.05643  0.02437      0.020         *     (0.009282, 0.09914)
              cos2_tom_monthly   -0.07339  0.02494      0.004        **     (-0.1217, -0.02778)
              sin3_tom_monthly   -0.03187  0.02458      0.186               (-0.08035, 0.01574)
              cos3_tom_monthly   -0.01858  0.02372      0.428               (-0.06583, 0.02631)
              sin4_tom_monthly  -0.006362  0.02302      0.750               (-0.05514, 0.04018)
              cos4_tom_monthly   -0.02305  0.02409      0.354               (-0.07183, 0.02525)
            sin1_toq_quarterly    0.08598  0.02012     <2e-16       ***       (0.04452, 0.1246)
            cos1_toq_quarterly   -0.01023  0.02086      0.594               (-0.05165, 0.02999)
            sin2_toq_quarterly     0.1589  0.03778     <2e-16       ***       (0.08133, 0.2277)
            cos2_toq_quarterly    -0.1949  0.03343     <2e-16       ***      (-0.2492, -0.1188)
            sin3_toq_quarterly    0.04747  0.03828      0.234                (-0.02506, 0.1211)
            cos3_toq_quarterly   -0.06258  0.04182      0.136                (-0.1371, 0.02536)
            sin4_toq_quarterly   0.008761  0.02349      0.692               (-0.03544, 0.05565)
            cos4_toq_quarterly   -0.07979   0.0268      0.006        **     (-0.1272, -0.02602)
               sin1_ct1_yearly     -0.269  0.02615     <2e-16       ***      (-0.3213, -0.2185)
               cos1_ct1_yearly     0.6077  0.04753     <2e-16       ***        (0.5136, 0.7014)
               sin2_ct1_yearly    0.09748  0.02273     <2e-16       ***       (0.05403, 0.1381)
               cos2_ct1_yearly   -0.08239  0.02502     <2e-16       ***     (-0.1302, -0.03145)
               sin3_ct1_yearly     0.3049  0.03193     <2e-16       ***          (0.241, 0.369)
               cos3_ct1_yearly    0.09155  0.02525     <2e-16       ***       (0.03855, 0.1385)
               sin4_ct1_yearly    0.08301  0.02337     <2e-16       ***       (0.03685, 0.1251)
               cos4_ct1_yearly   -0.05274  0.01767     <2e-16       ***    (-0.08725, -0.01869)
               sin5_ct1_yearly    -0.1365   0.0269     <2e-16       ***     (-0.1887, -0.08733)
               cos5_ct1_yearly    -0.1073  0.02346     <2e-16       ***     (-0.1514, -0.05955)
               sin6_ct1_yearly    -0.1856  0.02433     <2e-16       ***      (-0.2303, -0.1337)
               cos6_ct1_yearly    -0.1549   0.0243     <2e-16       ***      (-0.2012, -0.1058)
               sin7_ct1_yearly    -0.1468  0.02436     <2e-16       ***     (-0.1925, -0.09707)
               cos7_ct1_yearly    0.03016  0.02389      0.220               (-0.01626, 0.07828)
               sin8_ct1_yearly     0.1714   0.0393     <2e-16       ***       (0.08597, 0.2398)
               cos8_ct1_yearly    0.09884  0.03189     <2e-16       ***       (0.04093, 0.1636)
               sin9_ct1_yearly    0.02567  0.02452      0.296               (-0.02198, 0.07334)
               cos9_ct1_yearly   -0.04162   0.0253      0.112              (-0.08752, 0.007619)
              sin10_ct1_yearly    -0.1246  0.02376     <2e-16       ***     (-0.1708, -0.07672)
              cos10_ct1_yearly    -0.1809  0.02611     <2e-16       ***      (-0.2329, -0.1278)
              sin11_ct1_yearly   -0.06943  0.02612      0.008        **     (-0.1156, -0.01552)
              cos11_ct1_yearly   -0.05633  0.02436      0.014         *    (-0.1032, -0.008811)
              sin12_ct1_yearly     0.3216  0.06579     <2e-16       ***        (0.1869, 0.4398)
              cos12_ct1_yearly   -0.06977  0.06146      0.258                (-0.1908, 0.05954)
              sin13_ct1_yearly    -0.0421  0.02544      0.110              (-0.09467, 0.004665)
              cos13_ct1_yearly     0.1119    0.025     <2e-16       ***       (0.06409, 0.1581)
              sin14_ct1_yearly    0.06953  0.02326      0.002        **       (0.02116, 0.1109)
              cos14_ct1_yearly   0.006995  0.02494      0.790               (-0.03874, 0.05754)
              sin15_ct1_yearly    0.06626  0.02481      0.006        **       (0.01499, 0.1154)
              cos15_ct1_yearly    -0.0559  0.02709      0.044         *     (-0.1071, 0.001567)
                        y_lag7     0.7975   0.1571     <2e-16       ***          (0.487, 1.124)
                        y_lag8     0.4715   0.1494     <2e-16       ***        (0.1867, 0.7742)
                        y_lag9    -0.0105   0.1275      0.926                 (-0.2681, 0.2607)
              y_avglag_7_14_21      1.504   0.1484     <2e-16       ***          (1.201, 1.794)
              y_avglag_7_to_13     0.4332   0.1397      0.002        **        (0.1516, 0.6995)
             y_avglag_14_to_20     0.1228  0.09928      0.224                 (-0.0673, 0.3188)
Signif. Code: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Multiple R-squared: 0.7276,   Adjusted R-squared: 0.717
F-statistic: 66.694 on 110 and 2830 DF,   p-value: 1.110e-16
Model AIC: 18935.0,   model BIC: 19600.0

WARNING: the condition number is large, 2.56e+04. This might indicate that there are strong multicollinearity or other numerical problems.
WARNING: the F-ratio and its p-value on regularized methods might be misleading, they are provided only for reference purposes.
214
215
216
217
 # Check component plot of SK_2 on second fold
 model = bm.result["SK_2"]["rolling_evaluation"]["split_1"]["pipeline_result"].model
 fig = model[-1].plot_components()
 plotly.io.show(fig)

Compare forecasts

To obtain forecasts run the extract_forecasts method. You only need to run this once.

225
 bm.extract_forecasts()

This method does two things.

  • For every config, it gathers forecast results across rolling windows and stores it as a dataframe in rolling_forecast_df under the config key. This helps in comparing forecasts and prediction accuracy across splits for the config.

234
235
236
 # Forecast across rolling windows for SK_1
 forecast_sk_1 = bm.result["SK_1"]["rolling_forecast_df"]
 forecast_sk_1.head()
train_end_date forecast_step split_num ts actual forecast forecast_lower forecast_upper
0 2015-12-29 1 0 2015-12-30 8.391403 8.080527 7.364640 8.796415
1 2015-12-29 2 0 2015-12-31 8.004700 7.950023 7.260555 8.639492
2 2015-12-29 3 0 2016-01-01 7.589336 7.863855 7.046872 8.680838
3 2015-12-29 4 0 2016-01-02 7.825245 7.666822 6.934248 8.399396
4 2015-12-29 5 0 2016-01-03 8.249314 8.570062 7.637093 9.503032


  • Concatenates rolling_forecast_df for all the configs and stores it as a dataframe in the class attribute forecasts. This helps in comparing forecasts and prediction accuracies across configs.

242
243
 # Forecasts across configs
 bm.forecasts.head()
train_end_date forecast_step split_num ts actual Prophet_forecast Prophet_forecast_lower Prophet_forecast_upper SK_1_forecast SK_1_forecast_lower SK_1_forecast_upper SK_2_forecast SK_2_forecast_lower SK_2_forecast_upper
0 2015-12-29 1 0 2015-12-30 8.391403 7.996546 7.110420 8.852439 8.080527 7.364640 8.796415 8.120876 7.415824 8.825928
1 2015-12-29 2 0 2015-12-31 8.004700 8.048773 7.067294 8.912848 7.950023 7.260555 8.639492 7.982857 7.296030 8.669684
2 2015-12-29 3 0 2016-01-01 7.589336 7.789153 6.889167 8.714828 7.863855 7.046872 8.680838 7.829421 7.021262 8.637579
3 2015-12-29 4 0 2016-01-02 7.825245 7.941097 7.087499 8.816744 7.666822 6.934248 8.399396 7.720617 6.990749 8.450485
4 2015-12-29 5 0 2016-01-03 8.249314 8.438396 7.590532 9.328039 8.570062 7.637093 9.503032 8.481487 7.555359 9.407616


For any config you can plot forecasts across splits. This allows you to quickly check if there is any particular time window where the test performance drops. The forecasts for adjacent folds will overlap if the time windows of the corresponding folds overlap.

250
251
 fig = bm.plot_forecasts_by_config(config_name="SK_1")
 plotly.io.show(fig)

The importance of this function becomes more significant when assessing a models performance over a longer period e.g. a year or multiple years. You can quickly catch if models test performance drops during weekends, specific months or holiday seasons.

You can also compare forecasts from multiple configs by forecast_step which is defined as any number between 1 and forecast_horizon. This is useful in forecasts with longer forecast horizons to check if the forecast volatility changes over time.

262
263
 fig = bm.plot_forecasts_by_step(forecast_step=3)
 plotly.io.show(fig)

Compare Errors

You can compare the predictive performance of your models via multiple evaluation metrics. In this example we will use MAPE and RMSE, but you can use any metric from EvaluationMetricEnum.

271
272
273
274
 metric_dict = {
     "MAPE": EvaluationMetricEnum.MeanAbsolutePercentError,
     "RMSE": EvaluationMetricEnum.RootMeanSquaredError
 }

Non Grouping Errors

To compare evaluation metrics without any grouping use get_evaluation_metrics. The output shows metric values by config and split. We can group by config_name to get metric values aggregated across all folds.

283
284
285
286
287
 # Compute evaluation metrics
 evaluation_metrics_df = bm.get_evaluation_metrics(metric_dict=metric_dict)
 # Aggregate by model across splits
 error_df = evaluation_metrics_df.drop(columns=["split_num"]).groupby("config_name").mean()
 error_df
train_MAPE test_MAPE train_RMSE test_RMSE
config_name
Prophet 3.751365 5.044681 0.451389 0.555563
SK_1 3.578317 4.567182 0.444619 0.440185
SK_2 3.559232 4.343178 0.441155 0.427722


291
292
293
 # Visualize
 fig = bm.plot_evaluation_metrics(metric_dict)
 plotly.io.show(fig)

Train MAPE is high because some values in training dataset are close to 0.

You can also compare the predictive accuracy across splits for any model from configs. This allows you to check if the model performance varies significantly across time periods.

301
302
303
304
305
 # Compute evaluation metrics for a single config
 evaluation_metrics_df = bm.get_evaluation_metrics(metric_dict=metric_dict, config_names=["SK_1"])
 # Aggregate by split number
 error_df = evaluation_metrics_df.groupby("split_num").mean()
 error_df.head()
train_MAPE test_MAPE train_RMSE test_RMSE
split_num
0 3.579395 2.980640 0.444575 0.270657
1 3.558770 2.076316 0.442725 0.212919
2 3.588188 6.263718 0.445499 0.556518
3 3.586916 6.948054 0.445678 0.720647


309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
 # Visualize
 title = "Average evaluation metric across rolling windows"
 data = []
 # Each row (index) is a config. Adds each row to the bar plot.
 for index in error_df.index:
     data.append(
         go.Bar(
             name=index,
             x=error_df.columns,
             y=error_df.loc[index].values
         )
     )
 layout = go.Layout(
     xaxis=dict(title=None),
     yaxis=dict(title="Metric Value"),
     title=title,
     title_x=0.5,
     showlegend=True,
     barmode="group",
 )
 fig = go.Figure(data=data, layout=layout)
 plotly.io.show(fig)

Grouping Errors

To compare evaluation metrics with grouping use get_grouping_evaluation_metrics. This allows you to group the error values by time features such as day of week, month etc.

338
339
340
341
342
343
344
345
 # Compute grouped evaluation metrics
 grouped_evaluation_df = bm.get_grouping_evaluation_metrics(
     metric_dict=metric_dict,
     which="test",
     groupby_time_feature="str_dow")
 # Aggregate by split number
 error_df = grouped_evaluation_df.groupby(["str_dow", "config_name"]).mean()
 error_df
split_num test MAPE test RMSE
str_dow config_name
1-Mon Prophet 1.5 10.860639 1.023216
SK_1 1.5 7.085543 0.674806
SK_2 1.5 7.455146 0.709448
2-Tue Prophet 1.5 8.355137 0.719243
SK_1 1.5 5.846745 0.497415
SK_2 1.5 5.672472 0.482423
3-Wed Prophet 1.5 5.367433 0.454766
SK_1 1.5 4.660303 0.393819
SK_2 1.5 4.447991 0.375831
4-Thu Prophet 1.5 2.800949 0.225455
SK_1 1.5 3.407122 0.273651
SK_2 1.5 2.983100 0.240295
5-Fri Prophet 1.5 3.410852 0.271291
SK_1 1.5 3.946984 0.312966
SK_2 1.5 3.111686 0.246473
6-Sat Prophet 1.5 2.249235 0.175364
SK_1 1.5 2.325308 0.181463
SK_2 1.5 2.004758 0.156340
7-Sun Prophet 1.5 2.268522 0.195552
SK_1 1.5 4.698268 0.410511
SK_2 1.5 4.727095 0.414697


349
350
351
352
353
354
 # Visualize
 fig = bm.plot_grouping_evaluation_metrics(
     metric_dict=metric_dict,
     which="test",
     groupby_time_feature="str_dow")
 plotly.io.show(fig)

As you can see all the models have higher MAPE and RMSE during weekends. That means adding is_weekend indicator to the models will help.

Compare runtimes

You can compare and visualize runtimes of the models using the following codes.

364
365
366
367
368
 # Compute runtimes
 runtime_df = bm.get_runtimes()
 # Aggregate across splits
 runtimes_df = runtime_df.drop(columns=["split_num"]).groupby("config_name").mean()
 runtimes_df
runtime_sec
config_name
Prophet 40.1825
SK_1 21.0435
SK_2 17.2160


372
373
374
 # Visualize
 fig = bm.plot_runtimes()
 plotly.io.show(fig)

You can see Silverkite models run almost 3 times faster compared to Prophet.

Debugging the Benchmark

When the run method is called, the input configs are first assessed of their suitability for a cohesive benchmarking procedure via the validate method. This is done prior to passing the configs to the forecasting pipeline to save wasted computing time for the user. Though not necessary, the user is encouraged to use validate for debugging.

The validate method runs a series of checks to ensure that

  • The configs are compatible among themselves. For example, it checks if all the configs have the same forecast horizon.

  • The configs are compatible with the CV schema. For example, forecast_horizon and periods_between_train_test parameters of configs are matched against that of the tscv.

Note that the validate method does not guarantee that the models will execute properly while in the pipeline. It is a good idea to do a test run on a smaller data and/ or smaller number of splits before running the full procedure.

In the event of a mismatch a ValueError is raised with informative error messages to help the user in debugging. Some examples are provided below.

Error due to incompatible model components in config

405
406
407
408
409
410
411
412
413
414
415
416
417
 # regressor_cols is not part of Prophet's model components
 model_components=ModelComponentsParam(
     regressors={
         "regressor_cols": ["regressor1", "regressor2", "regressor_categ"]
     }
 )
 invalid_prophet = replace(Prophet, model_components_param=model_components)
 invalid_configs = {"invalid_prophet": invalid_prophet}
 bm = BenchmarkForecastConfig(df=df, configs=invalid_configs, tscv=tscv)
 try:
     bm.validate()
 except ValueError as err:
     print(err)

Out:

Unexpected key(s) found: {'regressor_cols'}. The valid keys are: dict_keys(['add_regressor_dict'])

Error due to wrong template name

423
424
425
426
427
428
429
430
 # model template name is not part of TemplateEnum, thus invalid
 unknown_template = replace(Prophet, model_template="SOME_TEMPLATE")
 invalid_configs = {"unknown_template": unknown_template}
 bm = BenchmarkForecastConfig(df=df, configs=invalid_configs, tscv=tscv)
 try:
     bm.validate()
 except ValueError as err:
     print(err)

Out:

Model Template 'SOME_TEMPLATE' is not recognized! Must be one of: SILVERKITE, SILVERKITE_DAILY_1_CONFIG_1, SILVERKITE_DAILY_1_CONFIG_2, SILVERKITE_DAILY_1_CONFIG_3, SILVERKITE_DAILY_1, SILVERKITE_DAILY_90, SILVERKITE_WEEKLY, SILVERKITE_MONTHLY, SILVERKITE_HOURLY_1, SILVERKITE_HOURLY_24, SILVERKITE_HOURLY_168, SILVERKITE_HOURLY_336, SILVERKITE_EMPTY, SK, PROPHET, AUTO_ARIMA, SILVERKITE_TWO_STAGE, MULTISTAGE_EMPTY, AUTO, LAG_BASED, SILVERKITE_WOW or satisfy the `SimpleSilverkiteTemplate` rules.

Error due to different forecast horizons in configs

436
437
438
439
440
441
442
443
444
445
446
447
 # the configs are valid by themselves, however incompatible for
 # benchmarking as these have different forecast horizons
 Prophet_forecast_horizon_30 = replace(Prophet, forecast_horizon=30)
 invalid_configs = {
     "Prophet": Prophet,
     "Prophet_30": Prophet_forecast_horizon_30
 }
 bm = BenchmarkForecastConfig(df=df, configs=invalid_configs, tscv=tscv)
 try:
     bm.validate()
 except ValueError as err:
     print(err)

Out:

Prophet_30's 'forecast_horizon' (30) does not match that of 'tscv' (7).

Error due to different forecast horizons in config and tscv

453
454
455
456
457
458
459
 ## Error due to different forecast horizons in config and tscv
 tscv = RollingTimeSeriesSplit(forecast_horizon=15)
 bm = BenchmarkForecastConfig(df=df, configs=configs, tscv=tscv)
 try:
     bm.validate()
 except ValueError as err:
     print(err)

Out:

Prophet's 'forecast_horizon' (7) does not match that of 'tscv' (15).

Total running time of the script: ( 5 minutes 25.219 seconds)

Gallery generated by Sphinx-Gallery