Advanced Prophet Usage

You can scan through fbprophet docs and find many options how to tweak your model. Some of that functionality is moved to initialization stage to be compatible with Sklearn API. We will showcase the parts that were moved to initialization, but you can also look for other model parameters that could help fine-tuning your model

[1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn')
plt.rcParams['figure.figsize'] = [12, 6]
[2]:
from hcrystalball.utils import generate_tsdata
X, y = generate_tsdata(n_dates=365*2)
[3]:
from hcrystalball.wrappers import ProphetWrapper
[4]:
ProphetWrapper?

Advanced Holidays

For holidays, we are able to define instead of single boolean attribute distribution around given day. We define lower_window, upper_window and prior_scales

[5]:
extra_holidays = {
    'Christmas Day':{'lower_window': -2, 'upper_window':2, 'prior_scale': 20},
#     'Good Friday':{'lower_window': -1, 'upper_window':1, 'prior_scale': 30}
}

Unusual Seasonalities

[6]:
extra_seasonalities = [
    {
        'name':'bi-weekly',
        'period': 14.,
        'fourier_order': 5,
        'prior_scale': 10.0,
        'mode': None
    },
    {
        'name':'bi-yearly',
        'period': 365*2.,
        'fourier_order': 5,
        'prior_scale': 5.0,
        'mode': None
    },
]

Exogenous Variables

[7]:
from sklearn.pipeline import Pipeline
from hcrystalball.feature_extraction import HolidayTransformer
[8]:
extra_regressors = ['trend_line']
X['trend_line'] = np.arange(len(X))
[9]:
prophet = ProphetWrapper(
    name='prophet',
)
prophet_extra = ProphetWrapper(
    extra_holidays=extra_holidays,
    extra_seasonalities=extra_seasonalities,
    extra_regressors=extra_regressors,
    name='prophet_extra',
)
[10]:
pipeline = Pipeline([
    ('holidays_de', HolidayTransformer(country_code = 'DE')),
    ('model', prophet)
])
pipeline_extra = Pipeline([
    ('holidays_de', HolidayTransformer(country_code = 'DE')),
    ('model', prophet_extra)
])
[11]:
prds = (pipeline.fit(X[:-10], y[:-10])
         .predict(X[-10:])
         .merge(y, left_index=True, right_index=True, how='outer')
         .tail(50))

prds.plot(title=f"MAE:{(prds['target']-prds['prophet']).abs().mean()}");
[11]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fcf5038b250>
../../../_images/examples_tutorial_wrappers_06_advanced_prophet_14_1.png
[12]:
prds_extra = (pipeline_extra.fit(X[:-10], y[:-10])
         .predict(X[-10:])
         .merge(y, left_index=True, right_index=True, how='outer')
         .tail(50))

prds_extra.plot(title=f"MAE:{(prds_extra['target']-prds_extra['prophet_extra']).abs().mean()}");
[12]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fcf4fdfcc50>
../../../_images/examples_tutorial_wrappers_06_advanced_prophet_15_1.png

Compared to non-tweaked model, we are able to better catch the series dynamics, but don’t win against roughly average predictions

[13]:
prds = (ProphetWrapper().fit(X[:-10], y[:-10])
                 .predict(X[-10:])
                 .merge(y, left_index=True, right_index=True, how='outer')
                 .tail(50)
)
prds.plot(title=f"MAE:{(prds['target']-prds['prophet']).abs().mean()}");
[13]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fcf4fed5150>
../../../_images/examples_tutorial_wrappers_06_advanced_prophet_17_1.png

Full Prophet Output

If you need, you can also pass full_prophet_output and get rich predict output

[14]:
(ProphetWrapper(full_prophet_output=True, conf_int=True)
     .fit(X[:-10], y[:-10])
     .predict(X[-10:])
)
[14]:
trend prophet_lower prophet_upper trend_lower trend_upper additive_terms additive_terms_lower additive_terms_upper weekly weekly_lower weekly_upper multiplicative_terms multiplicative_terms_lower multiplicative_terms_upper prophet
2018-12-22 6.164104 0.726242 11.297600 6.164104 6.164104 -0.013085 -0.013085 -0.013085 -0.013085 -0.013085 -0.013085 0.0 0.0 0.0 6.151019
2018-12-23 6.161729 0.892203 11.258480 6.161729 6.161729 -0.062742 -0.062742 -0.062742 -0.062742 -0.062742 -0.062742 0.0 0.0 0.0 6.098986
2018-12-24 6.159353 0.472390 11.274639 6.159353 6.159353 -0.014312 -0.014312 -0.014312 -0.014312 -0.014312 -0.014312 0.0 0.0 0.0 6.145041
2018-12-25 6.156978 0.605549 11.505890 6.156978 6.156978 0.022565 0.022565 0.022565 0.022565 0.022565 0.022565 0.0 0.0 0.0 6.179542
2018-12-26 6.154602 1.021553 11.742629 6.154602 6.154602 -0.028985 -0.028985 -0.028985 -0.028985 -0.028985 -0.028985 0.0 0.0 0.0 6.125617
2018-12-27 6.152227 1.165918 11.176845 6.152227 6.152227 0.066324 0.066324 0.066324 0.066324 0.066324 0.066324 0.0 0.0 0.0 6.218551
2018-12-28 6.149851 1.194814 11.091220 6.149851 6.149851 0.030236 0.030236 0.030236 0.030236 0.030236 0.030236 0.0 0.0 0.0 6.180088
2018-12-29 6.147476 0.558225 11.549557 6.147445 6.147496 -0.013085 -0.013085 -0.013085 -0.013085 -0.013085 -0.013085 0.0 0.0 0.0 6.134391
2018-12-30 6.145101 0.895119 11.502808 6.145044 6.145148 -0.062742 -0.062742 -0.062742 -0.062742 -0.062742 -0.062742 0.0 0.0 0.0 6.082358
2018-12-31 6.142725 0.910574 11.264777 6.142622 6.142822 -0.014312 -0.014312 -0.014312 -0.014312 -0.014312 -0.014312 0.0 0.0 0.0 6.128413