Note
Click here to download the full example code
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 | from dataclasses import replace
import plotly
import plotly.graph_objs 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,
EvaluationMetricParam,
EvaluationPeriodParam,
MetadataParam, ForecastConfig,
ModelComponentsParam)
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.
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.
46 47 48 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 | ## 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.
93 94 95 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 | # 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="PROPHET",
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="SILVERKITE",
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.
154 155 156 157 158 159 160 161 162 163 164 165 166 167 | # 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 BM 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.
Out:
0%| | 0/3 [00:00<?, ?it/s]
Benchmarking 'Prophet' : 0%| | 0/3 [00:00<?, ?it/s]
0%| | 0/4 [00:00<?, ?it/s][A
Split '0' : 0%| | 0/4 [00:00<?, ?it/s][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '0' : 25%|############################################################################################################################################################################################ | 1/4 [01:55<05:47, 115.81s/it][A
Split '1' : 25%|############################################################################################################################################################################################ | 1/4 [01:55<05:47, 115.81s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '1' : 50%|######################################################################################################################################################################################################################################################################################################################################################################################## | 2/4 [04:26<04:12, 126.13s/it][A
Split '2' : 50%|######################################################################################################################################################################################################################################################################################################################################################################################## | 2/4 [04:26<04:12, 126.13s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '2' : 75%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################### | 3/4 [06:44<02:09, 129.71s/it][A
Split '3' : 75%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################### | 3/4 [06:44<02:09, 129.71s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '3' : 100%|################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [09:02<00:00, 132.35s/it][A
Split '3' : 100%|################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [09:02<00:00, 135.65s/it]
Benchmarking 'Prophet' : 33%|######################################################################################################################################################################################################################################################3 | 1/3 [09:02<18:05, 542.60s/it]
Benchmarking 'SK_1' : 33%|#######################################################################################################################################################################################################################################################3 | 1/3 [09:02<18:05, 542.60s/it]
0%| | 0/4 [00:00<?, ?it/s][A
Split '0' : 0%| | 0/4 [00:00<?, ?it/s][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '0' : 25%|############################################################################################################################################################################################2 | 1/4 [01:05<03:17, 65.74s/it][A
Split '1' : 25%|############################################################################################################################################################################################2 | 1/4 [01:05<03:17, 65.74s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '1' : 50%|########################################################################################################################################################################################################################################################################################################################################################################################5 | 2/4 [02:09<02:10, 65.24s/it][A
Split '2' : 50%|########################################################################################################################################################################################################################################################################################################################################################################################5 | 2/4 [02:09<02:10, 65.24s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '2' : 75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7 | 3/4 [03:11<01:04, 64.03s/it][A
Split '3' : 75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7 | 3/4 [03:11<01:04, 64.03s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [04:14<00:00, 63.82s/it][A
Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [04:14<00:00, 63.59s/it]
Benchmarking 'SK_1' : 67%|##############################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################6 | 2/3 [13:16<07:36, 456.13s/it]
Benchmarking 'SK_2' : 67%|##############################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################6 | 2/3 [13:16<07:36, 456.13s/it]
0%| | 0/4 [00:00<?, ?it/s][A
Split '0' : 0%| | 0/4 [00:00<?, ?it/s][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '0' : 25%|############################################################################################################################################################################################2 | 1/4 [00:55<02:47, 55.91s/it][A
Split '1' : 25%|############################################################################################################################################################################################2 | 1/4 [00:55<02:47, 55.91s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '1' : 50%|########################################################################################################################################################################################################################################################################################################################################################################################5 | 2/4 [01:54<01:53, 56.73s/it][A
Split '2' : 50%|########################################################################################################################################################################################################################################################################################################################################################################################5 | 2/4 [01:54<01:53, 56.73s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '2' : 75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7 | 3/4 [02:51<00:56, 56.68s/it][A
Split '3' : 75%|####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################7 | 3/4 [02:51<00:56, 56.68s/it][AFitting 1 folds for each of 1 candidates, totalling 1 fits
Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [03:46<00:00, 56.29s/it][A
Split '3' : 100%|#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 4/4 [03:46<00:00, 56.62s/it]
Benchmarking 'SK_2' : 100%|######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 3/3 [17:03<00:00, 387.24s/it]
Benchmarking 'SK_2' : 100%|######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################| 3/3 [17:03<00:00, 341.15s/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
.
205 206 207 |
Out:
================================ Model Summary =================================
Number of observations: 2942, Number of features: 264
Method: Ridge regression
Number of nonzero features: 264
Regularization parameter: 117.7
Residuals:
Min 1Q Median 3Q Max
-2.302 -0.247 -0.05622 0.1641 3.282
Pred_col Estimate Std. Err Pr(>)_boot sig. code 95%CI
Intercept 2.965 0.2146 <2e-16 *** (2.545, 3.325)
events_Chinese New Year 0.002148 0.01935 0.924 (-0.0356, 0.04148)
events_Chinese New Year-1 -0.0003129 0.01508 0.994 (-0.02966, 0.02855)
events_Chinese New Year-2 0.004799 0.01785 0.782 (-0.02738, 0.04052)
events_Chinese New Year+1 -0.007786 0.01708 0.634 (-0.03934, 0.02314)
events_Chinese New Year+2 0.01831 0.01984 0.360 (-0.01399, 0.06172)
events_Christmas Day -0.02864 0.01385 0.030 * (-0.05593, -0.005676)
events_Christmas Day-1 -0.009914 0.01161 0.372 (-0.03412, 0.01092)
events_Christmas Day-2 0.001638 0.01739 0.924 (-0.04038, 0.02898)
events_Christmas Day+1 -0.01828 0.0123 0.116 (-0.04586, 0.00232)
events_Christmas Day+2 0.01689 0.008987 0.054 . (0.0007832, 0.03557)
events_Easter...hern Ireland] -0.01211 0.007236 0.072 . (-0.02564, 0.001168)
events_Easter...rn Ireland]-1 -0.01403 0.007814 0.068 . (-0.0298, 7.455e-06)
events_Easter...rn Ireland]-2 -0.008355 0.005601 0.128 (-0.01916, 0.00152)
events_Easter...rn Ireland]+1 -0.007089 0.005003 0.134 (-0.0177, 0.003148)
events_Easter...rn Ireland]+2 -0.001197 0.003581 0.744 (-0.008669, 0.004887)
events_Good Friday -0.01387 0.00586 0.020 * (-0.02637, -0.003954)
events_Good Friday-1 -0.01211 0.005847 0.034 * (-0.02383, -0.001626)
events_Good Friday-2 -0.006028 0.005172 0.230 (-0.01705, 0.002368)
events_Good Friday+1 -0.008355 0.005601 0.128 (-0.01916, 0.00152)
events_Good Friday+2 -0.01403 0.007814 0.068 . (-0.0298, 7.455e-06)
events_Independence Day -0.0004059 0.006711 0.960 (-0.01341, 0.01157)
events_Independence Day-1 -0.003586 0.007002 0.610 (-0.01793, 0.009871)
events_Independence Day-2 -0.006493 0.005578 0.232 (-0.01733, 0.005663)
events_Independence Day+1 -0.009756 0.007056 0.164 (-0.02436, 0.003927)
events_Independence Day+2 -0.008646 0.007696 0.236 (-0.02265, 0.008173)
events_Labor Day -0.02678 0.01185 0.032 * (-0.05173, -0.005683)
events_Labor Day-1 -0.00912 0.01033 0.376 (-0.0275, 0.01019)
events_Labor Day-2 -0.0003302 0.008008 0.976 (-0.01579, 0.01546)
events_Labor Day+1 -0.01662 0.00796 0.036 * (-0.03177, 0.0003294)
events_Labor Day+2 -0.01963 0.007856 0.016 * (-0.03582, -0.004106)
events_Memorial Day -0.0257 0.008769 0.006 ** (-0.04371, -0.009865)
events_Memorial Day-1 -0.01463 0.006196 0.016 * (-0.0272, -0.003756)
events_Memorial Day-2 -0.001185 0.006291 0.860 (-0.01143, 0.01245)
events_Memorial Day+1 -0.006978 0.003855 0.064 . (-0.01502, 7.853e-05)
events_Memorial Day+2 0.009476 0.006523 0.138 (-0.002129, 0.02387)
events_New Years Day 0.0008261 0.007409 0.910 (-0.01354, 0.01419)
events_New Years Day-1 0.008853 0.008764 0.282 (-0.006885, 0.02613)
events_New Years Day-2 0.01817 0.0116 0.134 (-0.002898, 0.04142)
events_New Years Day+1 0.02199 0.01141 0.042 * (0.003301, 0.04657)
events_New Years Day+2 0.01874 0.01178 0.098 . (-0.002799, 0.04327)
events_Other 0.001592 0.02118 0.926 (-0.03814, 0.044)
events_Other-1 -0.00562 0.02102 0.772 (-0.04689, 0.03643)
events_Other-2 0.01376 0.02015 0.480 (-0.02411, 0.05337)
events_Other+1 0.02336 0.02 0.230 (-0.01767, 0.05932)
events_Other+2 0.01555 0.01814 0.398 (-0.01947, 0.05182)
events_Thanksgiving -0.01042 0.005737 0.056 . (-0.02334, 6.895e-05)
events_Thanksgiving-1 -0.02257 0.007241 0.002 ** (-0.03656, -0.008663)
events_Thanksgiving-2 -0.01715 0.006528 0.004 ** (-0.02972, -0.00496)
events_Thanksgiving+1 -0.004335 0.006127 0.488 (-0.0163, 0.00671)
events_Thanksgiving+2 -0.009613 0.004641 0.044 * (-0.01969, -0.001681)
events_Veterans Day -0.002063 0.00643 0.740 (-0.0132, 0.01085)
events_Veterans Day-1 -0.004134 0.005363 0.432 (-0.01459, 0.005312)
events_Veterans Day-2 -0.002291 0.006887 0.744 (-0.0152, 0.01189)
events_Veterans Day+1 -0.001116 0.005746 0.834 (-0.01234, 0.01091)
events_Veterans Day+2 -0.001456 0.005062 0.746 (-0.01166, 0.008859)
str_dow_2-Tue 0.003042 0.007193 0.664 (-0.009373, 0.01712)
str_dow_3-Wed -0.002967 0.005761 0.592 (-0.01493, 0.008705)
str_dow_4-Thu -0.005705 0.005448 0.288 (-0.0157, 0.004974)
str_dow_5-Fri -0.008719 0.00509 0.082 . (-0.01931, 0.000179)
str_dow_6-Sat -0.0261 0.005833 <2e-16 *** (-0.03684, -0.01496)
str_dow_7-Sun 0.008548 0.006406 0.176 (-0.004155, 0.02088)
ct1 0.0009674 0.01556 0.940 (-0.03066, 0.02832)
is_weekend:ct1 -0.007118 0.006727 0.292 (-0.02003, 0.006299)
str_dow_2-Tue:ct1 0.002968 0.007431 0.674 (-0.01103, 0.01694)
str_dow_3-Wed:ct1 -0.0005901 0.005543 0.920 (-0.01215, 0.009532)
str_dow_4-Thu:ct1 -0.00504 0.004834 0.312 (-0.0138, 0.00479)
str_dow_5-Fri:ct1 0.001917 0.005259 0.710 (-0.006832, 0.01327)
str_dow_6-Sat:ct1 -0.008615 0.005765 0.130 (-0.02022, 0.002987)
str_dow_7-Sun:ct1 0.001497 0.007249 0.830 (-0.01109, 0.01583)
cp0_2008_09_29_00 0.02922 0.004456 <2e-16 *** (0.02059, 0.03691)
is_weekend:cp0_2008_09_29_00 0.007848 0.002311 <2e-16 *** (0.003824, 0.01264)
str_dow_2-Tue...2008_09_29_00 0.003291 0.003209 0.316 (-0.002739, 0.009701)
str_dow_3-Wed...2008_09_29_00 0.004256 0.002247 0.058 . (-0.000304, 0.008407)
str_dow_4-Thu...2008_09_29_00 0.00267 0.002242 0.238 (-0.001623, 0.007243)
str_dow_5-Fri...2008_09_29_00 0.005361 0.002501 0.030 * (0.0005428, 0.01021)
str_dow_6-Sat...2008_09_29_00 0.00428 0.002634 0.104 (-0.001278, 0.009033)
str_dow_7-Sun...2008_09_29_00 0.003568 0.002926 0.226 (-0.001755, 0.00936)
cp1_2008_11_03_00 0.03152 0.004737 <2e-16 *** (0.0228, 0.04053)
is_weekend:cp1_2008_11_03_00 0.008616 0.002514 <2e-16 *** (0.004164, 0.01355)
str_dow_2-Tue...2008_11_03_00 0.003657 0.003087 0.248 (-0.002243, 0.009831)
str_dow_3-Wed...2008_11_03_00 0.00489 0.002214 0.020 * (0.0004298, 0.009113)
str_dow_4-Thu...2008_11_03_00 0.003777 0.002107 0.084 . (-0.0003134, 0.007828)
str_dow_5-Fri...2008_11_03_00 0.005404 0.002537 0.040 * (0.0004999, 0.01046)
str_dow_6-Sat...2008_11_03_00 0.00542 0.002588 0.028 * (8.521e-05, 0.01004)
str_dow_7-Sun...2008_11_03_00 0.003196 0.002921 0.304 (-0.001685, 0.009098)
cp2_2008_12_15_00 0.03103 0.005684 <2e-16 *** (0.0195, 0.04277)
is_weekend:cp2_2008_12_15_00 0.008592 0.003369 0.010 * (0.001916, 0.0152)
str_dow_2-Tue...2008_12_15_00 0.004015 0.003026 0.196 (-0.001702, 0.01003)
str_dow_3-Wed...2008_12_15_00 0.004366 0.002393 0.070 . (-0.0003183, 0.008972)
str_dow_4-Thu...2008_12_15_00 0.00419 0.002183 0.046 * (2.479e-05, 0.008457)
str_dow_5-Fri...2008_12_15_00 0.0045 0.00288 0.126 (-0.001128, 0.01021)
str_dow_6-Sat...2008_12_15_00 0.005632 0.002859 0.042 * (-0.0001776, 0.01076)
str_dow_7-Sun...2008_12_15_00 0.00296 0.003413 0.366 (-0.003385, 0.00981)
cp3_2009_01_12_00 0.03041 0.006358 <2e-16 *** (0.0174, 0.04297)
is_weekend:cp3_2009_01_12_00 0.008949 0.00396 0.026 * (0.001178, 0.01672)
str_dow_2-Tue...2009_01_12_00 0.003926 0.003205 0.220 (-0.002148, 0.01029)
str_dow_3-Wed...2009_01_12_00 0.003784 0.002599 0.164 (-0.001291, 0.008962)
str_dow_4-Thu...2009_01_12_00 0.003876 0.002356 0.096 . (-0.0006992, 0.008372)
str_dow_5-Fri...2009_01_12_00 0.004037 0.002993 0.168 (-0.001878, 0.01007)
str_dow_6-Sat...2009_01_12_00 0.005608 0.003119 0.072 . (-0.0006804, 0.01116)
str_dow_7-Sun...2009_01_12_00 0.003341 0.003841 0.370 (-0.003849, 0.01116)
cp4_2009_12_21_00 -0.03082 0.01087 0.010 * (-0.05171, -0.009794)
is_weekend:cp4_2009_12_21_00 -0.008329 0.006246 0.186 (-0.02081, 0.00408)
str_dow_2-Tue...2009_12_21_00 -0.007882 0.007274 0.274 (-0.02324, 0.006738)
str_dow_3-Wed...2009_12_21_00 -0.002528 0.004707 0.596 (-0.01075, 0.007469)
str_dow_4-Thu...2009_12_21_00 -0.0004468 0.004216 0.900 (-0.009454, 0.008539)
str_dow_5-Fri...2009_12_21_00 -0.006564 0.005557 0.236 (-0.0179, 0.003604)
str_dow_6-Sat...2009_12_21_00 -0.002288 0.005564 0.640 (-0.01305, 0.009377)
str_dow_7-Sun...2009_12_21_00 -0.006042 0.007721 0.428 (-0.02169, 0.008202)
cp5_2010_01_25_00 -0.02797 0.01164 0.024 * (-0.05229, -0.004409)
is_weekend:cp5_2010_01_25_00 -0.006982 0.006911 0.294 (-0.02157, 0.005805)
str_dow_2-Tue...2010_01_25_00 -0.007745 0.007792 0.308 (-0.02362, 0.007967)
str_dow_3-Wed...2010_01_25_00 -0.002453 0.004925 0.618 (-0.01084, 0.008115)
str_dow_4-Thu...2010_01_25_00 -0.0005292 0.004377 0.898 (-0.009801, 0.008546)
str_dow_5-Fri...2010_01_25_00 -0.006771 0.00554 0.212 (-0.01808, 0.003404)
str_dow_6-Sat...2010_01_25_00 -0.002401 0.005933 0.654 (-0.0133, 0.009878)
str_dow_7-Sun...2010_01_25_00 -0.004581 0.008432 0.616 (-0.02199, 0.01046)
cp6_2011_02_14_00 0.01602 0.01231 0.210 (-0.007926, 0.03829)
is_weekend:cp6_2011_02_14_00 0.008336 0.008472 0.320 (-0.009036, 0.02347)
str_dow_2-Tue...2011_02_14_00 -0.0006635 0.007799 0.924 (-0.01624, 0.01541)
str_dow_3-Wed...2011_02_14_00 0.003052 0.006272 0.648 (-0.009195, 0.01539)
str_dow_4-Thu...2011_02_14_00 0.002093 0.005781 0.742 (-0.008913, 0.01277)
str_dow_5-Fri...2011_02_14_00 0.0007987 0.007397 0.920 (-0.0144, 0.0135)
str_dow_6-Sat...2011_02_14_00 0.0037 0.007286 0.590 (-0.01096, 0.01726)
str_dow_7-Sun...2011_02_14_00 0.004635 0.008709 0.616 (-0.01209, 0.01988)
cp7_2012_02_27_00 -0.07575 0.01362 <2e-16 *** (-0.1034, -0.04888)
is_weekend:cp7_2012_02_27_00 -0.01921 0.006737 0.004 ** (-0.03128, -0.005497)
str_dow_2-Tue...2012_02_27_00 -0.01029 0.009019 0.264 (-0.02777, 0.007098)
str_dow_3-Wed...2012_02_27_00 -0.01247 0.008473 0.132 (-0.03037, 0.002102)
str_dow_4-Thu...2012_02_27_00 -0.0111 0.007484 0.118 (-0.02612, 0.002988)
str_dow_5-Fri...2012_02_27_00 -0.008443 0.00754 0.252 (-0.02178, 0.006009)
str_dow_6-Sat...2012_02_27_00 -0.009238 0.007131 0.204 (-0.02226, 0.005324)
str_dow_7-Sun...2012_02_27_00 -0.009974 0.00842 0.244 (-0.02603, 0.006197)
cp8_2012_04_09_00 -0.06728 0.01181 <2e-16 *** (-0.09017, -0.04434)
is_weekend:cp8_2012_04_09_00 -0.01848 0.00612 <2e-16 *** (-0.0294, -0.005122)
str_dow_2-Tue...2012_04_09_00 -0.008347 0.009049 0.368 (-0.02496, 0.009479)
str_dow_3-Wed...2012_04_09_00 -0.01062 0.007845 0.162 (-0.02667, 0.002899)
str_dow_4-Thu...2012_04_09_00 -0.009507 0.007079 0.174 (-0.02299, 0.003687)
str_dow_5-Fri...2012_04_09_00 -0.008424 0.006853 0.202 (-0.0216, 0.005182)
str_dow_6-Sat...2012_04_09_00 -0.009212 0.006754 0.172 (-0.02101, 0.004623)
str_dow_7-Sun...2012_04_09_00 -0.009268 0.008055 0.248 (-0.02436, 0.006525)
cp9_2013_03_04_00 0.002548 0.01267 0.806 (-0.02352, 0.02647)
is_weekend:cp9_2013_03_04_00 -0.007725 0.007656 0.312 (-0.02368, 0.007796)
str_dow_2-Tue...2013_03_04_00 0.008536 0.009363 0.354 (-0.009349, 0.02618)
str_dow_3-Wed...2013_03_04_00 0.001876 0.006594 0.754 (-0.01152, 0.01506)
str_dow_4-Thu...2013_03_04_00 0.001485 0.006206 0.800 (-0.01147, 0.01227)
str_dow_5-Fri...2013_03_04_00 0.0006274 0.006843 0.918 (-0.01208, 0.01409)
str_dow_6-Sat...2013_03_04_00 -0.004657 0.006851 0.528 (-0.01769, 0.007507)
str_dow_7-Sun...2013_03_04_00 -0.003068 0.009318 0.756 (-0.02325, 0.01371)
cp10_2014_01_27_00 -0.03711 0.02067 0.070 . (-0.07718, 0.003437)
is_weekend:cp10_2014_01_27_00 -0.01337 0.009989 0.192 (-0.0326, 0.00706)
str_dow_2-Tue...2014_01_27_00 0.003891 0.01325 0.782 (-0.02058, 0.03063)
str_dow_3-Wed...2014_01_27_00 -0.006759 0.008454 0.404 (-0.02386, 0.01007)
str_dow_4-Thu...2014_01_27_00 -0.005404 0.008104 0.514 (-0.02242, 0.01037)
str_dow_5-Fri...2014_01_27_00 -0.004542 0.008923 0.622 (-0.0214, 0.01278)
str_dow_6-Sat...2014_01_27_00 -0.009578 0.007971 0.240 (-0.02545, 0.005015)
str_dow_7-Sun...2014_01_27_00 -0.003789 0.01234 0.772 (-0.02807, 0.02115)
ct1:sin1_tow_weekly 0.005955 0.008689 0.520 (-0.01092, 0.02242)
ct1:cos1_tow_weekly 0.01648 0.01132 0.138 (-0.006328, 0.03811)
ct1:sin2_tow_weekly 0.003391 0.009525 0.744 (-0.01633, 0.02153)
ct1:cos2_tow_weekly 0.01418 0.01112 0.210 (-0.008981, 0.03286)
cp0_2008_09_2...n1_tow_weekly -0.001408 0.003273 0.662 (-0.008022, 0.004449)
cp0_2008_09_2...s1_tow_weekly 0.0009381 0.004232 0.842 (-0.007451, 0.008913)
cp0_2008_09_2...n2_tow_weekly 0.001845 0.003642 0.606 (-0.005356, 0.008831)
cp0_2008_09_2...s2_tow_weekly 0.001587 0.003902 0.682 (-0.006375, 0.008485)
cp1_2008_11_0...n1_tow_weekly -0.0008633 0.003403 0.810 (-0.00747, 0.005344)
cp1_2008_11_0...s1_tow_weekly -0.001117 0.004173 0.780 (-0.009166, 0.007148)
cp1_2008_11_0...n2_tow_weekly 0.001951 0.003779 0.574 (-0.006246, 0.009017)
cp1_2008_11_0...s2_tow_weekly 8.768e-05 0.004002 0.982 (-0.007737, 0.007573)
cp2_2008_12_1...n1_tow_weekly -0.0005445 0.004117 0.878 (-0.008426, 0.007792)
cp2_2008_12_1...s1_tow_weekly -0.00034 0.004695 0.942 (-0.009489, 0.009353)
cp2_2008_12_1...n2_tow_weekly 0.001821 0.004483 0.678 (-0.007229, 0.01031)
cp2_2008_12_1...s2_tow_weekly 0.0002237 0.004601 0.966 (-0.008219, 0.009245)
cp3_2009_01_1...n1_tow_weekly -0.00139 0.004741 0.762 (-0.01038, 0.008207)
cp3_2009_01_1...s1_tow_weekly 0.001146 0.005215 0.844 (-0.008965, 0.01215)
cp3_2009_01_1...n2_tow_weekly 0.001488 0.005097 0.756 (-0.008687, 0.01169)
cp3_2009_01_1...s2_tow_weekly 0.0006887 0.005093 0.890 (-0.008513, 0.01116)
cp4_2009_12_2...n1_tow_weekly 0.0009814 0.008167 0.910 (-0.01544, 0.01668)
cp4_2009_12_2...s1_tow_weekly -0.006367 0.01107 0.592 (-0.02757, 0.01452)
cp4_2009_12_2...n2_tow_weekly -0.006472 0.01017 0.514 (-0.02629, 0.01427)
cp4_2009_12_2...s2_tow_weekly -0.002008 0.01012 0.854 (-0.02063, 0.01789)
cp5_2010_01_2...n1_tow_weekly 0.0001843 0.008682 0.988 (-0.01647, 0.01831)
cp5_2010_01_2...s1_tow_weekly -0.003521 0.01158 0.734 (-0.02666, 0.01807)
cp5_2010_01_2...n2_tow_weekly -0.007942 0.01087 0.440 (-0.02865, 0.01557)
cp5_2010_01_2...s2_tow_weekly -0.0009288 0.01069 0.938 (-0.02111, 0.02035)
cp6_2011_02_1...n1_tow_weekly -0.004213 0.01098 0.678 (-0.02556, 0.01811)
cp6_2011_02_1...s1_tow_weekly 0.000776 0.0115 0.944 (-0.02145, 0.0231)
cp6_2011_02_1...n2_tow_weekly -0.005897 0.01162 0.600 (-0.0288, 0.01606)
cp6_2011_02_1...s2_tow_weekly -0.002756 0.01225 0.828 (-0.02542, 0.02025)
cp7_2012_02_2...n1_tow_weekly -0.004553 0.01071 0.662 (-0.02621, 0.01579)
cp7_2012_02_2...s1_tow_weekly -0.004436 0.0131 0.742 (-0.02997, 0.02129)
cp7_2012_02_2...n2_tow_weekly 0.003173 0.01124 0.772 (-0.01886, 0.02762)
cp7_2012_02_2...s2_tow_weekly -0.002348 0.01259 0.844 (-0.02698, 0.02236)
cp8_2012_04_0...n1_tow_weekly -0.001123 0.009783 0.894 (-0.02112, 0.01684)
cp8_2012_04_0...s1_tow_weekly -0.002317 0.01202 0.838 (-0.02545, 0.02266)
cp8_2012_04_0...n2_tow_weekly 0.002356 0.01015 0.822 (-0.01715, 0.0233)
cp8_2012_04_0...s2_tow_weekly -0.001294 0.01142 0.910 (-0.02429, 0.02076)
cp9_2013_03_0...n1_tow_weekly 0.01581 0.009492 0.090 . (-0.002842, 0.03379)
cp9_2013_03_0...s1_tow_weekly -0.0001271 0.01213 0.988 (-0.02361, 0.02478)
cp9_2013_03_0...n2_tow_weekly 0.007808 0.011 0.468 (-0.01347, 0.02998)
cp9_2013_03_0...s2_tow_weekly 0.0003552 0.01209 0.974 (-0.02084, 0.02529)
cp10_2014_01_...n1_tow_weekly 0.008378 0.01494 0.570 (-0.02069, 0.0376)
cp10_2014_01_...s1_tow_weekly 0.001725 0.0217 0.956 (-0.04159, 0.04517)
cp10_2014_01_...n2_tow_weekly 0.006939 0.01684 0.678 (-0.02915, 0.03634)
cp10_2014_01_...s2_tow_weekly -0.002438 0.02101 0.898 (-0.04341, 0.03631)
sin1_tow_weekly 0.01956 0.01279 0.132 (-0.004834, 0.0435)
cos1_tow_weekly 0.05859 0.01558 <2e-16 *** (0.0303, 0.0914)
sin2_tow_weekly -0.01776 0.01293 0.170 (-0.04278, 0.01027)
cos2_tow_weekly 0.04652 0.01557 0.008 ** (0.01639, 0.0768)
sin3_tow_weekly -0.01754 0.009763 0.062 . (-0.03664, 0.002085)
cos3_tow_weekly 0.006547 0.01426 0.674 (-0.01898, 0.03328)
sin1_tom_monthly 0.02233 0.005416 <2e-16 *** (0.01081, 0.03215)
cos1_tom_monthly 0.02842 0.005281 <2e-16 *** (0.01712, 0.03776)
sin2_tom_monthly 0.02867 0.01099 0.008 ** (0.006127, 0.04821)
cos2_tom_monthly -0.02478 0.01111 0.024 * (-0.04721, -0.00451)
sin3_tom_monthly -0.01921 0.01199 0.112 (-0.04193, 0.004727)
cos3_tom_monthly -0.003312 0.01094 0.772 (-0.02549, 0.01774)
sin4_tom_monthly -0.005385 0.01112 0.628 (-0.02664, 0.01633)
cos4_tom_monthly -0.0124 0.0112 0.288 (-0.03324, 0.009852)
sin1_toq_quarterly 0.03636 0.006721 <2e-16 *** (0.0242, 0.0495)
cos1_toq_quarterly 0.02053 0.005024 <2e-16 *** (0.01084, 0.03056)
sin2_toq_quarterly 0.003046 0.005687 0.606 (-0.008508, 0.01312)
cos2_toq_quarterly -0.06041 0.005912 <2e-16 *** (-0.07223, -0.04949)
sin3_toq_quarterly 0.01459 0.00479 0.004 ** (0.004617, 0.02455)
cos3_toq_quarterly 0.00309 0.004651 0.520 (-0.006203, 0.01255)
sin4_toq_quarterly 0.002259 0.01028 0.830 (-0.01854, 0.02303)
cos4_toq_quarterly -0.02962 0.01145 0.008 ** (-0.05136, -0.007799)
sin1_ct1_yearly -0.1227 0.01207 <2e-16 *** (-0.1456, -0.09552)
cos1_ct1_yearly 0.2492 0.01864 <2e-16 *** (0.2114, 0.2803)
sin2_ct1_yearly 0.0559 0.01146 <2e-16 *** (0.03258, 0.07864)
cos2_ct1_yearly -0.03518 0.01007 <2e-16 *** (-0.05542, -0.01618)
sin3_ct1_yearly 0.1348 0.01285 <2e-16 *** (0.1087, 0.1587)
cos3_ct1_yearly 0.04073 0.01069 <2e-16 *** (0.02094, 0.06258)
sin4_ct1_yearly 0.02773 0.005227 <2e-16 *** (0.01688, 0.03822)
cos4_ct1_yearly -0.03414 0.006627 <2e-16 *** (-0.04717, -0.02168)
sin5_ct1_yearly -0.05092 0.01167 <2e-16 *** (-0.07431, -0.02776)
cos5_ct1_yearly -0.05316 0.009833 <2e-16 *** (-0.07312, -0.03545)
sin6_ct1_yearly -0.07759 0.011 <2e-16 *** (-0.0999, -0.05628)
cos6_ct1_yearly -0.0769 0.01092 <2e-16 *** (-0.09715, -0.05366)
sin7_ct1_yearly -0.06547 0.01112 <2e-16 *** (-0.08643, -0.04322)
cos7_ct1_yearly 0.006718 0.01032 0.530 (-0.01234, 0.02609)
sin8_ct1_yearly 0.004615 0.006156 0.450 (-0.008523, 0.01652)
cos8_ct1_yearly 0.05866 0.006071 <2e-16 *** (0.04764, 0.07057)
sin9_ct1_yearly 0.01066 0.01153 0.376 (-0.01032, 0.03256)
cos9_ct1_yearly -0.01645 0.01193 0.166 (-0.03802, 0.007638)
sin10_ct1_yearly -0.05963 0.01073 <2e-16 *** (-0.08049, -0.03975)
cos10_ct1_yearly -0.08051 0.01185 <2e-16 *** (-0.1029, -0.05578)
sin11_ct1_yearly -0.03618 0.01157 0.004 ** (-0.05784, -0.01294)
cos11_ct1_yearly -0.01758 0.009939 0.070 . (-0.03535, 0.00238)
sin12_ct1_yearly 0.01414 0.005565 0.008 ** (0.002397, 0.02443)
cos12_ct1_yearly 0.01044 0.00588 0.084 . (-0.0003434, 0.02263)
sin13_ct1_yearly -0.02856 0.01113 0.010 * (-0.05241, -0.008149)
cos13_ct1_yearly 0.0608 0.01072 <2e-16 *** (0.04014, 0.08253)
sin14_ct1_yearly 0.02795 0.01079 0.016 * (0.009399, 0.0497)
cos14_ct1_yearly 0.01523 0.01129 0.188 (-0.006551, 0.03663)
sin15_ct1_yearly 0.03284 0.01099 0.002 ** (0.01068, 0.05478)
cos15_ct1_yearly -0.0228 0.01157 0.058 . (-0.04557, 0.001174)
y_lag7 0.144 0.02394 <2e-16 *** (0.09695, 0.188)
y_lag8 0.07066 0.02364 0.004 ** (0.02508, 0.1191)
y_lag9 0.001779 0.01866 0.912 (-0.03848, 0.03627)
y_avglag_7_14_21 0.2651 0.02725 <2e-16 *** (0.2095, 0.3163)
y_avglag_7_to_13 0.08815 0.02336 <2e-16 *** (0.0392, 0.1313)
y_avglag_14_to_20 0.04537 0.01895 0.022 * (0.01083, 0.08469)
Signif. Code: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Multiple R-squared: 0.7174, Adjusted R-squared: 0.7103
F-statistic: 97.082 on 71 and 2869 DF, p-value: 1.110e-16
Model AIC: 18966.0, model BIC: 19400.0
WARNING: the condition number is large, 1.23e+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.
211 212 213 214 |
Compare forecasts¶
To obtain forecasts run the extract_forecasts
method. You only need to run this once.
222 | bm.extract_forecasts()
|
This method does two things.
For every
config
, it gathers forecast results across rolling windows and stores it as a dataframe inrolling_forecast_df
under theconfig
key. This helps in comparing forecasts and prediction accuracy across splits for theconfig
.
231 232 233 | # 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 | 7.978806 | 7.267350 | 8.690262 |
1 | 2015-12-29 | 2 | 0 | 2015-12-31 | 8.004700 | 7.916108 | 7.241671 | 8.590545 |
2 | 2015-12-29 | 3 | 0 | 2016-01-01 | 7.589336 | 7.859820 | 7.042581 | 8.677060 |
3 | 2015-12-29 | 4 | 0 | 2016-01-02 | 7.825245 | 7.509112 | 6.771791 | 8.246432 |
4 | 2015-12-29 | 5 | 0 | 2016-01-03 | 8.249314 | 8.322843 | 7.358467 | 9.287219 |
Concatenates
rolling_forecast_df
for all theconfigs
and stores it as a dataframe in the class attributeforecasts
. This helps in comparing forecasts and prediction accuracies acrossconfigs
.
239 240 | # 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 | 8.019895 | 7.029674 | 8.958333 | 7.978806 | 7.267350 | 8.690262 | 7.957234 | 7.247341 | 8.667127 |
1 | 2015-12-29 | 2 | 0 | 2015-12-31 | 8.004700 | 8.039185 | 7.091612 | 8.979686 | 7.916108 | 7.241671 | 8.590545 | 7.899861 | 7.220490 | 8.579233 |
2 | 2015-12-29 | 3 | 0 | 2016-01-01 | 7.589336 | 8.070296 | 7.105856 | 9.027433 | 7.859820 | 7.042581 | 8.677060 | 7.834294 | 7.022134 | 8.646453 |
3 | 2015-12-29 | 4 | 0 | 2016-01-02 | 7.825245 | 7.856180 | 6.904412 | 8.832527 | 7.509112 | 6.771791 | 8.246432 | 7.521520 | 6.784284 | 8.258756 |
4 | 2015-12-29 | 5 | 0 | 2016-01-03 | 8.249314 | 8.243508 | 7.248844 | 9.280235 | 8.322843 | 7.358467 | 9.287219 | 8.346246 | 7.390849 | 9.301642 |
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.
247 248 | 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.
259 260 | 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
.
268 269 270 271 | 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.
280 281 282 283 284 | # 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 | 4.009155 | 4.064214 | 0.485801 | 0.427914 |
SK_1 | 3.603298 | 4.572780 | 0.450865 | 0.443342 |
SK_2 | 3.600322 | 4.496454 | 0.449541 | 0.442640 |
288 289 290 | # 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.
298 299 300 301 302 | # 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.611241 | 3.072742 | 0.451962 | 0.280462 |
1 | 3.599799 | 2.308179 | 0.450181 | 0.220802 |
2 | 3.601513 | 6.009099 | 0.450544 | 0.535961 |
3 | 3.600639 | 6.901099 | 0.450773 | 0.736143 |
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | # 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,
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.
334 335 336 337 338 339 340 341 | # 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 | 8.235986 | 0.793895 |
SK_1 | 1.5 | 7.271136 | 0.692728 | |
SK_2 | 1.5 | 7.069657 | 0.674420 | |
2-Tue | Prophet | 1.5 | 3.634147 | 0.311949 |
SK_1 | 1.5 | 5.880363 | 0.501733 | |
SK_2 | 1.5 | 6.069028 | 0.517991 | |
3-Wed | Prophet | 1.5 | 3.548818 | 0.299014 |
SK_1 | 1.5 | 5.148044 | 0.435114 | |
SK_2 | 1.5 | 5.119414 | 0.432500 | |
4-Thu | Prophet | 1.5 | 2.755924 | 0.221571 |
SK_1 | 1.5 | 3.357612 | 0.269911 | |
SK_2 | 1.5 | 3.166958 | 0.255332 | |
5-Fri | Prophet | 1.5 | 4.299685 | 0.338231 |
SK_1 | 1.5 | 3.493988 | 0.276743 | |
SK_2 | 1.5 | 2.825097 | 0.223435 | |
6-Sat | Prophet | 1.5 | 3.153319 | 0.245955 |
SK_1 | 1.5 | 2.717081 | 0.212107 | |
SK_2 | 1.5 | 2.751691 | 0.214711 | |
7-Sun | Prophet | 1.5 | 2.821620 | 0.251621 |
SK_1 | 1.5 | 4.141234 | 0.365619 | |
SK_2 | 1.5 | 4.473329 | 0.394380 |
345 346 347 348 349 350 | # 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.
360 361 362 363 364 | # 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 | 135.6450 |
SK_1 | 63.5855 |
SK_2 | 56.6165 |
368 369 370 | # 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 theconfigs
have the sameforecast horizon
.The
configs
are compatible with the CV schema. For example,forecast_horizon
andperiods_between_train_test
parameters ofconfigs
are matched against that of thetscv
.
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¶
401 402 403 404 405 406 407 408 409 410 411 412 413 | # 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¶
419 420 421 422 423 424 425 426 | # 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_90, SILVERKITE_WEEKLY, SILVERKITE_HOURLY_1, SILVERKITE_HOURLY_24, SILVERKITE_HOURLY_168, SILVERKITE_HOURLY_336, SILVERKITE_EMPTY, SK, PROPHET or satisfy the `SimpleSilverkiteTemplate` rules.
Error due to different forecast horizons in configs¶
432 433 434 435 436 437 438 439 440 441 442 443 | # 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¶
449 450 451 452 453 454 455 | ## 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: ( 17 minutes 22.053 seconds)