[1]:
import logging
import warnings
import pandas as pd

# from prophet import Prophet
from neuralprophet import NeuralProphet, set_log_level

set_log_level("ERROR")
logging.getLogger("prophet").setLevel(logging.ERROR)
warnings.filterwarnings("ignore")

Migrating from Prophet to NeuralProphet#

Both the Prophet and the NeuralProphet model share the concept of decomposing a time series into it’s components which allows a human to inspect and interprete the individual components of the forecast. Since NeuralProphet adds new functionality, its interface may differ in part. We provide a guide on migrating a Prophet application to NeuralProphet. In the following we will provide code snippets for the most common functionalities when migrating from Prophet.

[2]:
df = pd.read_csv("https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv")

Trend#

In both frameworks, the trend can be configured during the init of the forecaster object. Pay attention to that the naming of the attributes might be slightly different between the two (eg. changepoint_range vs. changepoints_range)

# Prophet
p = Prophet(growth="linear", n_changepoints=10, changepoint_range=0.5)
p.fit(df)
[3]:
# NeuralProphet
np = NeuralProphet(growth="linear", n_changepoints=10, changepoints_range=0.5)
np.fit(df)
[3]:
MAE RMSE Loss RegLoss epoch
0 3.042294 3.721973 0.240254 0.0 0
1 2.858650 3.499020 0.215928 0.0 1
2 2.625173 3.210334 0.185687 0.0 2
3 2.314021 2.830819 0.147598 0.0 3
4 1.925760 2.352080 0.104436 0.0 4
... ... ... ... ... ...
137 0.349472 0.489684 0.004930 0.0 137
138 0.349406 0.491695 0.004922 0.0 138
139 0.349232 0.489923 0.004923 0.0 139
140 0.349017 0.491898 0.004918 0.0 140
141 0.348818 0.493281 0.004913 0.0 141

142 rows × 5 columns

Seasonality#

In both frameworks, custom seasonality can be added using the add_seasonality(...) function.

# Prophet
p = Prophet(weekly_seasonality=False)
p = p.add_seasonality(name="monthly", period=30.5, fourier_order=5)
p.fit(df)
[4]:
# NeuralProphet
np = NeuralProphet(weekly_seasonality=False)
np = np.add_seasonality(name="monthly", period=30.5, fourier_order=5)
np.fit(df)
[4]:
MAE RMSE Loss RegLoss epoch
0 6.970771 8.467905 0.840058 0.0 0
1 6.532929 7.965261 0.768197 0.0 1
2 5.960650 7.304036 0.674393 0.0 2
3 5.181200 6.403104 0.547921 0.0 3
4 4.161289 5.167398 0.386437 0.0 4
... ... ... ... ... ...
137 0.368285 0.516671 0.005415 0.0 137
138 0.368621 0.514440 0.005426 0.0 138
139 0.368627 0.515981 0.005387 0.0 139
140 0.368233 0.512572 0.005382 0.0 140
141 0.368327 0.514817 0.005379 0.0 141

142 rows × 5 columns

Country holidays#

The add_country_holidays(...) function works identical in both framework.

# Prophet
p = Prophet()
p = p.add_country_holidays(country_name="US")
p.fit(df)
[5]:
# NeuralProphet
np = NeuralProphet()
np = np.add_country_holidays(country_name="US")
np.fit(df)
[5]:
MAE RMSE Loss RegLoss epoch
0 6.797538 7.586237 0.799924 0.0 0
1 6.368385 7.140094 0.728214 0.0 1
2 5.797359 6.531570 0.634331 0.0 2
3 5.009449 5.698706 0.508090 0.0 3
4 3.973015 4.581055 0.350154 0.0 4
... ... ... ... ... ...
137 0.343491 0.474378 0.004594 0.0 137
138 0.342121 0.475136 0.004579 0.0 138
139 0.341720 0.476011 0.004581 0.0 139
140 0.341734 0.476153 0.004584 0.0 140
141 0.341740 0.476323 0.004578 0.0 141

142 rows × 5 columns

Future regressors#

[6]:
def nfl_sunday(ds):
    date = pd.to_datetime(ds)
    if date.weekday() == 6 and (date.month > 8 or date.month < 2):
        return 1
    else:
        return 0


df_nfl = df.copy()
df_nfl["nfl_sunday"] = df_nfl["ds"].apply(nfl_sunday)
# Prophet
p = Prophet()
p = p.add_regressor("nfl_sunday")
p.fit(df_nfl)
future_p = p.make_future_dataframe(periods=30)
future_p["nfl_sunday"] = future_p["ds"].apply(nfl_sunday)
_ = p.predict(future_p)
[7]:
# NeuralProphet
np = NeuralProphet()
future_np = np.make_future_dataframe(df_nfl, periods=30)
np = np.add_future_regressor("nfl_sunday")
np.fit(df_nfl)
future_np["nfl_sunday"] = future_np["ds"].apply(nfl_sunday)
_ = np.predict(future_np)

Holidays & Events#

What is referred to as “holidays” in Prophet is named “events” more generically in NeuralProphet. In Prophet, holidays are passed during the init of the Prophet forecaster. In NeuralProphet, they are added using the add_events(...) function.

# Prophet
superbowl_p = pd.DataFrame(
    {
        "holiday": "superbowl",
        "ds": pd.to_datetime(["2010-02-07", "2014-02-02", "2016-02-07"]),
        "lower_window": 0,
        "upper_window": 1,
    }
)

p = Prophet(holidays=superbowl_p)
p = p.fit(df)
future_p = p.make_future_dataframe(periods=30)
forecast_p = p.predict(future_p)
[8]:
# NeuralProphet
superbowl_np = pd.DataFrame(
    {
        "event": "superbowl",
        "ds": pd.to_datetime(["2010-02-07", "2014-02-02", "2016-02-07"]),
    }
)

np = NeuralProphet()
np = np.add_events("superbowl", lower_window=0, upper_window=1)
history_df = np.create_df_with_events(df, superbowl_np)
_ = np.fit(history_df)
future_np = np.make_future_dataframe(history_df, events_df=superbowl_np, periods=30)
forecast_np = np.predict(future_np)

Regularization#

In Prophet, the argument prior_scale can be used to configure regularization. In NeuralProphet, regularization is controlled via the reg argument. prior_scale and reg have an inverse relationship and therefore cannot directly be translated.

# Prophet
from prophet import Prophet

p = Prophet(seasonality_prior_scale=0.5)
[9]:
# NeuralProphet
from neuralprophet import NeuralProphet

np = NeuralProphet(seasonality_reg=0.1)

Uncertainty#

In Prophet, all forecasts are configured to use uncertainty intervals automatically. In NeuralProphet, the uncertaintly intervals need to be configured by the user. TorchProphet uses the default uncertainty intervals as defined in Prophet to mirror the behviour.

However, the uncertainty interval calculation differs between Prophet and NeuralProphet. Since Prophet uses a MAP estimate for uncertainty by default Thread, NeuralProphet relies on quantile regression. Thus, the values are not directly comparable.

# Prophet
p = Prophet(interval_width=0.80)
[10]:
# NeuralProphet
np = NeuralProphet(quantiles=[0.90, 0.10])

Unsupported features in TorchProphet#

  • Saturating forecasts Saturating forecasts limit the predicted value to a certain limit called capacity. In Prophet, this is archieved by passing the growth='logistic' argument during initialization and providing a capacity limit. This functionality is currently not supported by NeuralProphet.

  • Conditional seasonality Conditional seasonality allows to model certain events as seasonal effects (eg. whether it’s currently NFL season). This can be archieved in Prophet by passing the argument condition_name to add_seasonality(...). This feature is currently also not supported in NeuralProphet.

Additional features of TorchProphet#

  • Autoregression TorchProphet allows to model autoregression of arbitrary lag lengths by building on a Neural Network implementation of the autoregression algorithm (called AR-Net). More information can be found here Autoregression.

  • Lagged regressors TorchProphet does not only support “future” regressors like in Prophet, but also lagged regressors that are simultaneous to the time series to predict. More information can be found here Lagged covariates.

  • Global model TorchProphet supports hierachical forecasts by training a global model on many simultaneous time series that is used to improve the performance of predicting an individual time series. More infos can be found here Global Model.

  • Neural Network architecture TorchProphet models the forecast components using a Neural Network. By default, the network has no hidden layers. However, for more complex time series, the depth of the network can be increased to learn more complex relations.

  • PyTorch TorchProphet is build on Pytorch (soon PyTorch Lightning) and thus provides interfaces for developers to extend the vanilla model for specific use cases.

  • Flexible multiplicativity Multiplicativity of future regressors and seasonality can be set separately.