Facebook Prophet For Time Series Forecasting in Python | by Praneel Nihar | Towards Data Science

Prophet is an open source time series forecasting algorithm designed by Facebook for ease of use without any expert knowledge in statistics or time series forecasting. Prophet builds a model by finding a best smooth line which can be represented as a sum of the following components:
y(t) = g(t) + s(t) + h(t) + εt
Overall growth trend. g(t)
Yearly seasonality. s(t)
Weekly seasonality. s(t)
Holidays effects h(t)
In this blog post, we will see some of the useful functions present in the library fbprophet listed below with an example.
Prophet.fitProphet.predictProphet.plotProphet.plot_componentsProphet.add_seasonalityProphet.add_regressorsProphet.seasonalitiesProphet.predictive_samples
Prophet.fit
Prophet.predict
Prophet.plot
Prophet.plot_components
Prophet.add_seasonality
Prophet.add_regressors
Prophet.seasonalities
Prophet.predictive_samples
Let’s start by describing the sample data set that we will be using for our demonstration.
We will be using a synthetic daily time series data(shown below) with columns (date, target, regr1, regr2) for 180 days, where target is a value which we want to be predicted for each day and regr1, regr2 are external factor which effect the target value.
Let's see the data visually by plotting the target and regressor columns.
# Importing Librariesimport pandas as pd# loading the time series data into a dataframedf = pd.read_csv('ts_with_2regressors.csv')df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')# plotting the time series datadf.plot(x='date', y='target', figsize=(20, 5), title='Time series Data')
# plotting the regressorsax = df.plot(x='date', y='target', figsize=(20, 5), title='Regressors Effect')ticks, _ = plt.xticks()y_min = df.target.min()y_max = df.target.max()plt.vlines(x=list(df[df['regr1'] == 1]['date'].values), ymin=y_min, ymax=y_max, colors='purple', ls='--', lw=2, label='regr1')plt.vlines(x=list(df[df['regr2'] == 1]['date'].values), ymin=y_min, ymax=y_max, colors='green', ls=':', lw=2, label='regr2')plt.legend(bbox_to_anchor=(1.04, 0.5), loc="center left")plt.show()
We can see that the spikes in the time series data are due to the regressors (regr1, regr2). We will see how to capture and model these regressors in the coming sections.
As with every python library you can install fbprophet using pip. The major dependency that Prophet has is pystan.
# Install pystan with pip before using pip to install fbprophetpip install pystanpip install fbprophet
Let us now see how to use the above functions:
Prophet follows the sklearn model API. We create an instance of the Prophet class and then call its fit(Prophet.fit) and predict(Prophet.predict) methods.
The input to Prophet is always a data frame with two columns: ds and y. The ds (date stamp) column should be of a format expected by Pandas, ideally YYYY-MM-DD for a date or YYYY-MM-DD HH:MM:SS for a time stamp. The y column must be numeric, and represents the measurement we wish to forecast.
For demonstration we will use the target values for first 150 days as training data and predict target for all 180 days.
Note : For this step we will be considering only the date and target columns
# Creating train and predict dataframedf = df.rename(columns={'date':'ds', 'target':'y'})df_train = df[['ds', 'y']].iloc[:150]df_predict = df[['ds']]# Fitting a Prophet modelmodel = Prophet()model.fit(df_train)forecast = model.predict(df_predict)forecast.head()
# plotting the actual and forecast valuesax = (df.plot(x='ds',y='y',figsize=(20,5),title='Actual Vs Forecast'))forecast.plot(x='ds',y='yhat',figsize=(20,5),title='Actual vs Forecast', ax=ax)
From the above output we can see that prophet pretty much gave a good fit on the data, but still it is unable to capture the sudden jumps in the data. These jumps are basically caused by the external regressors which prophet is unable to detect by default. We will see how to model Prophet to capture these external factors in the coming sections.
We can plot the forecast and the components by calling the Prophet.plot & Prophet.plot_components method and passing in the forecast dataframe as shown below
The forecast plot is a single graph containing a scatter plot of historical data points indicated by black dots and the forecast/fitted curve indicated by a blue line. The graph also contains a light blue shaded region which corresponds to the uncertainty bands.
The components plot is a group of plots corresponding to various time series components(trend, seasoanilities) and external effects.
# Plotting the generated forecastfig1 = model.plot(forecast, uncertainty=True)
# Plotting the forecast components.fig2 = model.plot_components(forecast)
As mentioned in the starting Prophet estimates the trend and weekly_seasonality based on the training data.
Let us now understand the above 2 Plots:
X-axis represents the date values (ds ) for both history and future dates.
Y-axis represents the target values(y, yhat)for both history and future dates.
In the graph the black dotted points represent the historical training data points.
The blue line represents the forecasts generated for both history and future.
Along with there is light blue region which represents the uncertainty bands(We will see more about this in the coming sections.)
X-axis represents the date values (ds ) for both history and future dates.
Y-axis represents the prophet estimate for respective forecast compoent (trend, seasonality)
Graph1: trend value for all dates(history and future).
Graph2: weekly_seasonality a weekly profile for each day in a week based on the training data.
As we can see it is very easy to start and get a reasonable forecast model on your time series data using prophet.
In Prophet we can model custom seasonalities using the functions Prophet.add_seasonality.
By default Prophet automatically models a additive daily, weekly, yearly seasonalities based on available training data.
We can get the details of inferred seasonalities using the function Prophet.seasonalities
Let us now use the above method to model a monthly seasonality.
# Modelling a custom monthly seasonalitymodel2 = Prophet()model2.add_seasonality(name='custom_monthly', period=30.5, fourier_order=10)model2.fit(df_train)forecast2 = model2.predict(df_predict)print(model2.seasonalities)
fig1 = model2.plot(forecast2, uncertainty=True)
fig2 = model2.plot_components(forecast2, uncertainty=True)
From the above graph We can see that the Prophet has modeled a custom_monthly seasonality and the forecast is also a bit modified compared to the default forecast.
Till now the prophet model is not able to model some of points in the training data. We know that these values deviate from the regular value because of the external regressors (regr1, regr2).
let us now see how to capture these values and model them.
Similar to seasonalities prophet also has a way to capture/model external factors which have an effect on the target value using the function Prophet.add_regressors.
In the sample data we are using we have mentioned that there are two external regressors which are effecting the target value.
In order to model and predict the regressor effects, both the training and prediction dataframes should contain the regressor data.
Let us now see how to model these regressors using the above function.
Note : The regressor’s should be numeric values, you will have to perform one hot encoding if the regressor contains string data.
# adding regressor data in historical and future datesdf_train3 = (df[['ds', 'y', 'regr1', 'regr2']]             .iloc[:150]             .copy())df_predict3 = df[['ds', 'regr1', 'regr2']].copy()# modelling external regressors prior to model fittingmodel3 = Prophet()model3.add_regressor('regr1')model3.add_regressor('regr2')# fit and predcitmodel3.fit(df_train3)forecast3 = model3.predict(df_predict3)# Plot the forecastfig1 = model3.plot(forecast3, uncertainty=True)
# plot model componentsfig2 = model3.plot_components(forecast3, uncertainty=True)
From the above output we can observe that the model has pretty much captured the two external effects, from the ouptut graph we can that there is approx 5% and 20% lift on the target value w.r.t the regressors.
By default prophet generates 1000 posterior samples for each day inorder to estimating the upper and lower bound’s of the uncertainity bands. On a given day the mean of the posterior samples is almost equal to the forecast value yhat
Prophet has a way to access the posterior samples for a particular day both in history and future using the function Prophet.predictive_samples
We can modify the no of samples at the time of prophet instantiation using the parameter uncertainty_samples
let us now generate a data frame with posterior samples for 1 week in the prediction data frame.
# Select one week from prediction dfdf_1wk = df_predict3.iloc[:7]df_1wk
# fetching the posterior samples.samples = model3.predictive_samples(df_1wk)df_samples = pd.DataFrame(data=samples['yhat'], index=df_1wk['ds']).reset_index()df_samples
Let us now compute the mean of posterior samples for one day and compare it with that day’s forecast.
# Forecast forecast3[forecast3['ds'] == '2018-09-02'][['ds', 'yhat']]
# Mean of the posterior samples.df_samples[df_samples['ds'] == '2018-09-02'].set_index('ds').mean(axis=1)
We can see that the mean of the posterior samples is almost equal to the forecast value for a particular day.
This brings us to the end of our demonstration. Hope you find the post informative. You can find the data and Jupyter notebook used in the below repository:
github.com
Do try modelling your time series data using prophet and share your thoughts in the comments section.