Tune your first forecast model

This is a basic tutorial for creating and tuning a forecast model. It is intended to provide a basic sense of a forecast process without assuming background knowledge in forecasting.

You can use the PROPHET or SILVERKITE model. In this tutorial, we focus on SILVERKITE. However, the basic ideas of tuning are similar to both models. You may see detailed information about PROPHET at Prophet.

SILVERKITE decomposes time series into various components, and it creates time-based features, autoregressive features, together with user-provided features such as macro-economic features and their interactions, then performs a machine learning regression model to learn the relationship between the time series and these features. The forecast is based on the learned relationship and the future values of these features. Therefore, including the correct features is the key to success.

Common features include:

Datetime derivatives:

Including features derived from datetime such as day of year, hour of day, weekday, is_weekend and etc. These features are useful in capturing special patterns. For example, the patterns of weekdays and weekends are different for most business related time series, and this can be modeled with is_weekend.

Growth:

First defines the basic feature ct1 that counts how long has passed in terms of years (could be fraction) since the first day of training data. For example, if the training data starts with “2018-01-01”, then the date has ct1=0.0, and “2018-01-02” has ct1=1/365. “2019-01-01” has ct1=1.0. This ct1 can be as granular as needed. A separate growth function can be applied to ct1 to support different types of growth model. For example, ct2 is defined as the square of ct1 to model quadratic growth.

Trend:

Trend describes the average tendency of the time series. It is defined through the growth term with possible changepoints. At every changepoint, the growth rate could change (faster or slower). For example, if ct1 (linear growth) is used with changepoints, the trend is modeled as piece-wise linear.

Seasonality:

Seasonality describes the periodical pattern of the time series. It contains multiple levels including daily seasonality, weekly seasonality, monthly seasonality, quarterly seasonality and yearly seasonality. Seasonality are defined through Fourier series with different orders. The greater the order, the more detailed periodical pattern the model can learn. However, an order that is too large can lead to overfitting.

Events:

Events include holidays and other short-term occurrences that could temporarily affect the time series, such as Thanksgiving long weekend. Typically, events are regular and repeat at know times in the future. These features made of indicators that covers the event day and their neighbor days.

Autoregression:

Autoregressive features include the time series observations in the past and their aggregations. For example, the past day’s observation, the same weekday on the past week, or the average of the past 7 days, etc. can be used. Note that autoregression features are very useful in short term forecasts, however, this should be avoided in long term forecast. The reason is that long-term forecast focuses more on the correctness of trend, seasonality and events. The lags and autoregressive terms in a long-term forecast are calculated based on the forecasted values. The further we forecast into the future, the more forecasted values we need to create the autoregressive terms, making the forecast less stable.

Custom:

Extra features that are relevant to the time series such as macro-ecomonic features that are expected to affect the time series. Note that these features need to be manually provided for both the training and forecasting periods.

Interactions:

Any interaction between the features above.

Now let’s use an example to go through the full forecasting and tuning process. In this example, we’ll load a dataset representing log(daily page views) on the Wikipedia page for Peyton Manning. It contains values from 2007-12-10 to 2016-01-20. More dataset info here.

 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 import datetime

 import numpy as np
 import pandas as pd
 import plotly

 from greykite.algo.changepoint.adalasso.changepoint_detector import ChangepointDetector
 from greykite.algo.forecast.silverkite.constants.silverkite_holiday import SilverkiteHoliday
 from greykite.algo.forecast.silverkite.constants.silverkite_seasonality import SilverkiteSeasonalityEnum
 from greykite.algo.forecast.silverkite.forecast_simple_silverkite_helper import cols_interact
 from greykite.common import constants as cst
 from greykite.common.features.timeseries_features import build_time_features_df
 from greykite.common.features.timeseries_features import convert_date_to_continuous_time
 from greykite.framework.benchmark.data_loader_ts import DataLoaderTS
 from greykite.framework.templates.autogen.forecast_config import EvaluationPeriodParam
 from greykite.framework.templates.autogen.forecast_config import ForecastConfig
 from greykite.framework.templates.autogen.forecast_config import MetadataParam
 from greykite.framework.templates.autogen.forecast_config import ModelComponentsParam
 from greykite.framework.templates.forecaster import Forecaster
 from greykite.framework.templates.model_templates import ModelTemplateEnum
 from greykite.framework.utils.result_summary import summarize_grid_search_results


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

Exploratory data analysis (EDA)

After reading in a time series, we could first do some exploratory data analysis. The UnivariateTimeSeries class is used to store a timeseries and perform EDA.

122
123
124
 # describe
 print(ts.describe_time_col())
 print(ts.describe_value_col())

Out:

{'data_points': 2964, 'mean_increment_secs': 86400.0, 'min_timestamp': Timestamp('2007-12-10 00:00:00'), 'max_timestamp': Timestamp('2016-01-20 00:00:00')}
count    2905.000000
mean        8.138958
std         0.845957
min         5.262690
25%         7.514800
50%         7.997999
75%         8.580168
max        12.846747
Name: y, dtype: float64

The df has two columns, time column “ts” and value column “y”. The data is daily that ranges from 2007-12-10 to 2016-01-20. The data value ranges from 5.26 to 12.84

Let’s plot the original timeseries. (The interactive plot is generated by plotly: click to zoom!)

134
135
 fig = ts.plot()
 plotly.io.show(fig)

A few exploratory plots can be plotted to reveal the time series’s properties. The UnivariateTimeSeries class has a very powerful plotting tool plot_quantiles_and_overlays. A tutorial of using the function can be found at Seasonality.

Baseline model

A simple forecast can be created on the data set, see details in Simple Forecast. Note that if you do not provide any extra parameters, all model parameters are by default. The default parameters are chosen conservatively, so consider this a baseline model to assess forecast difficulty and make further improvements if necessary.

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
 # 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.
 )

 forecaster = Forecaster()
 result = forecaster.run_forecast_config(
     df=df,
     config=ForecastConfig(
         model_template=ModelTemplateEnum.SILVERKITE.name,
         forecast_horizon=365,  # forecasts 365 steps ahead
         coverage=0.95,  # 95% prediction intervals
         metadata_param=metadata
     )
 )

Out:

Fitting 3 folds for each of 1 candidates, totalling 3 fits

For a detailed documentation about the output from run_forecast_config, see Check Forecast Result. Here we could plot the forecast.

176
177
178
 forecast = result.forecast
 fig = forecast.plot()
 plotly.io.show(fig)