update docs

This commit is contained in:
Cuong Duong 2023-10-14 23:22:04 +11:00
parent 211d2ebd4d
commit 4c82cb0c87
33 changed files with 527 additions and 84 deletions

View file

@ -53,7 +53,7 @@ The json file will be portable across systems, and deserialization is backwards
For time series that exhibit strong seasonality patterns rather than trend changes, it may be useful to force the trend growth rate to be flat. This can be achieved simply by passing `growth=flat` when creating the model:
For time series that exhibit strong seasonality patterns rather than trend changes, or when we want to rely on the pattern of exogenous regressors (e.g. for causal inference with time series), it may be useful to force the trend growth rate to be flat. This can be achieved simply by passing `growth=flat` when creating the model:
```R
@ -110,7 +110,7 @@ def warm_start_params(m):
res[pname] = np.mean(m.params[pname], axis=0)
return res
df = pd.read_csv('https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv')
df = pd.read_csv('../examples/example_wp_log_peyton_manning.csv')
df1 = df.loc[df['ds'] < '2016-01-19', :] # All data except the last day
m1 = Prophet().fit(df1) # A model fit to all data except the last day
@ -133,8 +133,21 @@ There are few caveats that should be kept in mind when considering warm-starting
### External references
As we discuss in our [2023 blog post on the state of Prophet](https://medium.com/@cuongduong_35162/facebook-prophet-in-2023-and-beyond-c5086151c138), we have no plans to further develop the underlying Prophet model. If you're looking for state-of-the-art forecasting accuracy, we recommend the following libraries:
* [`statsforecast`](https://github.com/Nixtla/statsforecast), and other packages from the Nixtla group such as [`hierarchicalforecast`](https://github.com/Nixtla/hierarchicalforecast) and [`neuralforecast`](https://github.com/Nixtla/neuralforecast).
* [`NeuralProphet`](https://neuralprophet.com/), a Prophet-style model implemented in PyTorch, to be more adaptable and extensible.
These github repositories provide examples of building on top of Prophet in ways that may be of broad interest:
* [forecastr](https://github.com/garethcull/forecastr): A web app that provides a UI for Prophet.
* [NeuralProphet](https://github.com/ourownstory/neural_prophet): A Prophet-style model implemented in pytorch, to be more adaptable and extensible.

View file

@ -20,8 +20,8 @@ subsections:
Prophet includes functionality for time series cross validation to measure forecast error using historical data. This is done by selecting cutoff points in the history, and for each of them fitting the model using data only up to that cutoff point. We can then compare the forecasted values to the actual values. This figure illustrates a simulated historical forecast on the Peyton Manning dataset, where the model was fit to an initial history of 5 years, and a forecast was made on a one year horizon.
![png](/prophet/static/diagnostics_files/diagnostics_4_0.png)
![png](/prophet/static/diagnostics_files/diagnostics_4_0.png)
[The Prophet paper](https://peerj.com/preprints/3190.pdf) gives further description of simulated historical forecasts.
@ -270,8 +270,8 @@ plot_cross_validation_metric(df.cv, metric = 'mape')
from prophet.plot import plot_cross_validation_metric
fig = plot_cross_validation_metric(df_cv, metric='mape')
```
![png](/prophet/static/diagnostics_files/diagnostics_17_0.png)
![png](/prophet/static/diagnostics_files/diagnostics_17_0.png)
The size of the rolling window in the figure can be changed with the optional argument `rolling_window`, which specifies the proportion of forecasts to use in each rolling window. The default is 0.1, corresponding to 10% of rows from `df_cv` included in each window; increasing this will lead to a smoother average curve in the figure. The `initial` period should be long enough to capture all of the components of the model, in particular seasonalities and extra regressors: at least a year for yearly seasonality, at least a week for weekly seasonality, etc.
@ -455,7 +455,3 @@ The Prophet model has a number of input parameters that one might consider tunin
- `uncertainty_samples`: The uncertainty intervals are computed as quantiles from the posterior predictive interval, and the posterior predictive interval is estimated with Monte Carlo sampling. This parameter is the number of samples to use (defaults to 1000). The running time for predict will be linear in this number. Making it smaller will increase the variance (Monte Carlo error) of the uncertainty interval, and making it larger will reduce that variance. So, if the uncertainty estimates seem jagged this could be increased to further smooth them out, but it likely will not need to be changed. As with `interval_width`, this parameter only affects the uncertainty intervals and changing it will not affect in any way the forecast `yhat`; it does not need to be tuned.
- `stan_backend`: If both pystan and cmdstanpy backends set up, the backend can be specified. The predictions will be the same, this will not be tuned.

View file

@ -4,14 +4,32 @@ docid: "handling_shocks"
title: "Handling Shocks"
permalink: /docs/handling_shocks.html
subsections:
- title: Case Study - Pedestrian Activity
id: case-study---pedestrian-activity
- title: Default model without any adjustments
id: default-model-without-any-adjustments
- title: Treating COVID-19 lockdowns as a one-off holidays
id: treating-covid-19-lockdowns-as-a-one-off-holidays
- title: Sense checking the trend
id: sense-checking-the-trend
- title: Changes in seasonality between pre- and post-COVID
id: changes-in-seasonality-between-pre--and-post-covid
- title: Further reading
id: further-reading
---
```python
# Python
%matplotlib inline
from prophet import Prophet
import pandas as pd
from matplotlib import pyplot as plt
import logging
logging.getLogger('prophet').setLevel(logging.ERROR)
import warnings
warnings.filterwarnings("ignore")
plt.rcParams['figure.figsize'] = 9, 6
```
As a result of the lockdowns caused by the COVID-19 pandemic, many time series experienced "shocks" during 2020, e.g. spikes in media consumption (Netflix, YouTube), e-commerce transactions (Amazon, eBay), whilst attendance to in-person events declined dramatically.
@ -39,7 +57,7 @@ In this page we'll explore some strategies for capturing these effects using Pro
For this case study we'll use [Pedestrian Sensor data from the City of Melbourne](https://data.melbourne.vic.gov.au/Transport/Pedestrian-Counting-System-Monthly-counts-per-hour/b2ak-trbp). This data measures foot traffic from sensors in various places in the central business district, and we've chosen one sensor (`Sensor_ID = 4`) and aggregated the values to a daily grain.
For this case study we'll use [Pedestrian Sensor data from the City of Melbourne](https://data.melbourne.vic.gov.au/Transport/Pedestrian-Counting-System-Monthly-counts-per-hour/b2ak-trbp). This data measures foot traffic from sensors in various places in the central business district, and we've chosen one sensor (`Sensor_ID = 4`) and aggregated the values to a daily grain.
@ -87,6 +105,9 @@ m = m.fit(df)
future = m.make_future_dataframe(periods=366)
forecast = m.predict(future)
```
02:53:41 - cmdstanpy - INFO - Chain [1] start processing
02:53:41 - cmdstanpy - INFO - Chain [1] done processing
```python
# Python
@ -106,7 +127,7 @@ m.plot_components(forecast);
![png](/prophet/static/handling_shocks_files/handling_shocks_9_0.png)
The model seems to fit reasonably to past data, but notice how we're capturing the dips, and the spikes after the dips, as a part of the trend component.
The model seems to fit reasonably to past data, but notice how we're capturing the dips, and the spikes after the dips, as a part of the trend component.
@ -218,6 +239,9 @@ m2 = m2.fit(df)
future2 = m2.make_future_dataframe(periods=366)
forecast2 = m2.predict(future2)
```
02:53:44 - cmdstanpy - INFO - Chain [1] start processing
02:53:45 - cmdstanpy - INFO - Chain [1] done processing
```python
# Python
@ -276,7 +300,7 @@ a = add_changepoints_to_plot(fig.gca(), m2, forecast2)
![png](/prophet/static/handling_shocks_files/handling_shocks_18_0.png)
The detected changepoints look reasonable, and the future trend tracks the latest upwards trend in activity, but not to the extent of late 2020. This seems suitable for a best guess of future activity.
The detected changepoints look reasonable, and the future trend tracks the latest upwards trend in activity, but not to the extent of late 2020. This seems suitable for a best guess of future activity.
@ -287,7 +311,7 @@ We can see what the forecast would look like if we wanted to emphasize COVID pat
# Python
m3_changepoints = (
# 10 potential changepoints in 2.5 years
pd.date_range('2017-06-02', '2020-01-01', periods=10).date.tolist() +
pd.date_range('2017-06-02', '2020-01-01', periods=10).date.tolist() +
# 15 potential changepoints in 1 year 2 months
pd.date_range('2020-02-01', '2021-04-01', periods=15).date.tolist()
)
@ -299,6 +323,9 @@ m3 = Prophet(holidays=lockdowns, changepoints=m3_changepoints, changepoint_prior
m3 = m3.fit(df)
forecast3 = m3.predict(future2)
```
02:53:49 - cmdstanpy - INFO - Chain [1] start processing
02:53:52 - cmdstanpy - INFO - Chain [1] done processing
```python
# Python
@ -365,6 +392,9 @@ m4.add_seasonality(
# Python
m4 = m4.fit(df2)
```
02:53:55 - cmdstanpy - INFO - Chain [1] start processing
02:53:56 - cmdstanpy - INFO - Chain [1] done processing
We also need to create the `pre_covid` and `post_covid` flags in the future dataframe. This is so that Prophet can apply the correct weekly seasonality parameters to each future date.
@ -417,3 +447,9 @@ A lot of the content in this page was inspired by this [GitHub discussion](https
Overall though it's difficult to be confident in our forecasts in these environments when rules are constantly changing and outbreaks occur randomly. In this scenario it's more important to constantly re-train / re-evaluate our models and clearly communicate the increased uncertainty in forecasts.
```python
# Python
```

View file

@ -68,7 +68,7 @@ fig = m.plot_components(forecast)
![png](/prophet/static/multiplicative_seasonality_files/multiplicative_seasonality_10_0.png)
With `seasonality_mode='multiplicative'`, holiday effects will also be modeled as multiplicative. Any added seasonalities or extra regressors will by default use whatever `seasonality_mode` is set to, but can be overridden by specifying `mode='additive'` or `mode='multiplicative'` as an argument when adding the seasonality or regressor.
With `seasonality_mode='multiplicative'`, holiday effects will also be modeled as multiplicative. Any added seasonalities or extra regressors will by default use whatever `seasonality_mode` is set to, but can be overriden by specifying `mode='additive'` or `mode='multiplicative'` as an argument when adding the seasonality or regressor.
@ -88,3 +88,4 @@ m.add_seasonality('quarterly', period=91.25, fourier_order=8, mode='additive')
m.add_regressor('regressor', mode='additive')
```
Additive and multiplicative extra regressors will show up in separate panels on the components plot. Note, however, that it is pretty unlikely to have a mix of additive and multiplicative seasonalities, so this will generally only be used if there is a reason to expect that to be the case.

View file

@ -95,7 +95,7 @@ The forecast seems quite poor, with much larger fluctuations in the future than
```R
# R
future2 <- future %>%
future2 <- future %>%
filter(as.numeric(format(ds, "%H")) < 6)
fcst <- predict(m, future2)
plot(m, fcst)
@ -200,3 +200,4 @@ In monthly data, yearly seasonality can also be modeled with binary extra regres
Holiday effects are applied to the particular date on which the holiday was specified. With data that has been aggregated to weekly or monthly frequency, holidays that don't fall on the particular date used in the data will be ignored: for example, a Monday holiday in a weekly time series where each data point is on a Sunday. To include holiday effects in the model, the holiday will need to be moved to the date in the history dataframe for which the effect is desired. Note that with weekly or monthly aggregated data, many holiday effects will be well-captured by the yearly seasonality, so added holidays may only be necessary for holidays that occur in different weeks throughout the time series.

View file

@ -99,3 +99,4 @@ fig = m.plot(m.predict(future))
```
![png](/prophet/static/outliers_files/outliers_13_0.png)

File diff suppressed because one or more lines are too long

View file

@ -24,11 +24,11 @@ Prophet allows you to make forecasts using a [logistic growth](https://en.wikipe
```R
# R
df <- read.csv('https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_R.csv')
df <- read.csv('https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv')
```
```python
# Python
df = pd.read_csv('https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_R.csv')
df = pd.read_csv('https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv')
```
We must specify the carrying capacity in a column `cap`. Here we will assume a particular value, but this would usually be set using data or expertise about the market size.
@ -119,3 +119,4 @@ fig = m.plot(fcst)
To use a logistic growth trend with a saturating minimum, a maximum capacity must also be specified.

View file

@ -8,6 +8,8 @@ subsections:
id: modeling-holidays-and-special-events
- title: Built-in Country Holidays
id: built-in-country-holidays
- title: Holidays for subdivisions (Python)
id: holidays-for-subdivisions-(python)
- title: Fourier Order for Seasonalities
id: fourier-order-for-seasonalities
- title: Specifying Custom Seasonalities
@ -99,8 +101,8 @@ The holiday effect can be seen in the `forecast` dataframe:
```R
# R
forecast %>%
select(ds, playoff, superbowl) %>%
forecast %>%
select(ds, playoff, superbowl) %>%
filter(abs(playoff + superbowl) > 0) %>%
tail(10)
```
@ -248,14 +250,14 @@ You can see which holidays were included by looking at the `train_holiday_names`
# R
m$train.holiday.names
```
[1] "playoff" "superbowl"
[3] "New Year's Day" "Martin Luther King Jr. Day"
[5] "Washington's Birthday" "Memorial Day"
[7] "Independence Day" "Labor Day"
[9] "Columbus Day" "Veterans Day"
[11] "Veterans Day (Observed)" "Thanksgiving"
[1] "playoff" "superbowl"
[3] "New Year's Day" "Martin Luther King Jr. Day"
[5] "Washington's Birthday" "Memorial Day"
[7] "Independence Day" "Labor Day"
[9] "Columbus Day" "Veterans Day"
[11] "Veterans Day (Observed)" "Thanksgiving"
[13] "Christmas Day" "Independence Day (Observed)"
[15] "Christmas Day (Observed)" "New Year's Day (Observed)"
[15] "Christmas Day (Observed)" "New Year's Day (Observed)"
```python
@ -285,7 +287,7 @@ m.train_holiday_names
The holidays for each country are provided by the `holidays` package in Python. A list of available countries, and the country name to use, is available on their page: https://github.com/dr-prodigy/python-holidays. In addition to those countries, Prophet includes holidays for these countries: Brazil (BR), Indonesia (ID), India (IN), Malaysia (MY), Vietnam (VN), Thailand (TH), Philippines (PH), Pakistan (PK), Bangladesh (BD), Egypt (EG), China (CN), and Russian (RU), Korea (KR), Belarus (BY), and United Arab Emirates (AE).
The holidays for each country are provided by the `holidays` package in Python. A list of available countries, and the country name to use, is available on their page: https://github.com/vacanza/python-holidays/.
@ -310,6 +312,112 @@ fig = m.plot_components(forecast)
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_24_0.png)
<a id="holidays-for-subdivisions-(python)"> </a>
#### Holidays for subdivisions (Python)
We can use the utility function `make_holidays_df` to easily create custom holidays DataFrames, e.g. for certain states, using data from the [holidays](https://pypi.org/project/holidays/) package. This can be passed directly to the `Prophet()` constructor.
```python
# Python
from prophet.make_holidays import make_holidays_df
nsw_holidays = make_holidays_df(
year_list=[2019 + i for i in range(10)], country='AU', province='NSW'
)
nsw_holidays.head(n=10)
```
<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>ds</th>
<th>holiday</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>2019-01-26</td>
<td>Australia Day</td>
</tr>
<tr>
<th>1</th>
<td>2019-01-28</td>
<td>Australia Day (Observed)</td>
</tr>
<tr>
<th>2</th>
<td>2019-04-25</td>
<td>Anzac Day</td>
</tr>
<tr>
<th>3</th>
<td>2019-12-25</td>
<td>Christmas Day</td>
</tr>
<tr>
<th>4</th>
<td>2019-12-26</td>
<td>Boxing Day</td>
</tr>
<tr>
<th>5</th>
<td>2019-04-20</td>
<td>Easter Saturday</td>
</tr>
<tr>
<th>6</th>
<td>2019-04-21</td>
<td>Easter Sunday</td>
</tr>
<tr>
<th>7</th>
<td>2019-10-07</td>
<td>Labour Day</td>
</tr>
<tr>
<th>8</th>
<td>2019-06-10</td>
<td>Queen's Birthday</td>
</tr>
<tr>
<th>9</th>
<td>2019-08-05</td>
<td>Bank Holiday</td>
</tr>
</tbody>
</table>
</div>
```python
# Python
from prophet import Prophet
m_nsw = Prophet(holidays=nsw_holidays)
```
<a id="fourier-order-for-seasonalities"> </a>
### Fourier Order for Seasonalities
@ -331,7 +439,7 @@ m = Prophet().fit(df)
a = plot_yearly(m)
```
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_27_0.png)
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_30_0.png)
The default values are often appropriate, but they can be increased when the seasonality needs to fit higher-frequency changes, and generally be less smooth. The Fourier order can be specified for each built-in seasonality when instantiating the model, here it is increased to 20:
@ -349,7 +457,7 @@ m = Prophet(yearly_seasonality=20).fit(df)
a = plot_yearly(m)
```
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_30_0.png)
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_33_0.png)
Increasing the number of Fourier terms allows the seasonality to fit faster changing cycles, but can also lead to overfitting: N Fourier terms corresponds to 2N variables used for modeling the cycle
@ -389,7 +497,7 @@ forecast = m.fit(df).predict(future)
fig = m.plot_components(forecast)
```
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_33_0.png)
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_36_0.png)
<a id="seasonalities-that-depend-on-other-factors"> </a>
@ -453,7 +561,7 @@ forecast = m.fit(df).predict(future)
fig = m.plot_components(forecast)
```
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_39_0.png)
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_42_0.png)
Both of the seasonalities now show up in the components plots above. We can see that during the on-season when games are played every Sunday, there are large increases on Sunday and Monday that are completely absent during the off-season.
@ -470,8 +578,8 @@ If you find that the holidays are overfitting, you can adjust their prior scale
# R
m <- prophet(df, holidays = holidays, holidays.prior.scale = 0.05)
forecast <- predict(m, future)
forecast %>%
select(ds, playoff, superbowl) %>%
forecast %>%
select(ds, playoff, superbowl) %>%
filter(abs(playoff + superbowl) > 0) %>%
tail(10)
```
@ -641,7 +749,7 @@ forecast = m.predict(future)
fig = m.plot_components(forecast)
```
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_49_0.png)
![png](/prophet/static/seasonality,_holiday_effects,_and_regressors_files/seasonality,_holiday_effects,_and_regressors_52_0.png)
NFL Sundays could also have been handled using the "holidays" interface described above, by creating a list of past and future NFL Sundays. The `add_regressor` function provides a more general interface for defining extra linear regressors, and in particular does not require that the regressor be a binary indicator. Another time series could be used as a regressor, although its future values would have to be known.
@ -656,7 +764,11 @@ The `add_regressor` function has optional arguments for specifying the prior sca
The extra regressor must be known for both the history and for future dates. It thus must either be something that has known future values (such as `nfl_sunday`), or something that has separately been forecasted elsewhere. The weather regressors used in the notebook linked above is a good example of an extra regressor that has forecasts that can be used for future values. One can also use as a regressor another time series that has been forecasted with a time series model, such as Prophet. For instance, if `r(t)` is included as a regressor for `y(t)`, Prophet can be used to forecast `r(t)` and then that forecast can be plugged in as the future values when forecasting `y(t)`. A note of caution around this approach: This will probably not be useful unless `r(t)` is somehow easier to forecast then `y(t)`. This is because error in the forecast of `r(t)` will produce error in the forecast of `y(t)`. One setting where this can be useful is in hierarchical time series, where there is top-level forecast that has higher signal-to-noise and is thus easier to forecast. Its forecast can be included in the forecast for each lower-level series.
The extra regressor must be known for both the history and for future dates. It thus must either be something that has known future values (such as `nfl_sunday`), or something that has separately been forecasted elsewhere. The weather regressors used in the notebook linked above is a good example of an extra regressor that has forecasts that can be used for future values.
One can also use as a regressor another time series that has been forecasted with a time series model, such as Prophet. For instance, if `r(t)` is included as a regressor for `y(t)`, Prophet can be used to forecast `r(t)` and then that forecast can be plugged in as the future values when forecasting `y(t)`. A note of caution around this approach: This will probably not be useful unless `r(t)` is somehow easier to forecast than `y(t)`. This is because error in the forecast of `r(t)` will produce error in the forecast of `y(t)`. One setting where this can be useful is in hierarchical time series, where there is top-level forecast that has higher signal-to-noise and is thus easier to forecast. Its forecast can be included in the forecast for each lower-level series.
@ -670,4 +782,5 @@ Extra regressors are put in the linear component of the model, so the underlying
To extract the beta coefficients of the extra regressors, use the utility function `regressor_coefficients` (`from prophet.utilities import regressor_coefficients` in Python, `prophet::regressor_coefficients` in R) on the fitted model. The estimated beta coefficient for each regressor roughly represents the increase in prediction value for a unit increase in the regressor value (note that the coefficients returned are always on the scale of the original data). If `mcmc_samples` is specified, a credible interval for each coefficient is also returned, which can help identify whether each regressor is "statistically significant".
To extract the beta coefficients of the extra regressors, use the utility function `regressor_coefficients` (`from prophet.utilities import regressor_coefficients` in Python, `prophet::regressor_coefficients` in R) on the fitted model. The estimated beta coefficient for each regressor roughly represents the increase in prediction value for a unit increase in the regressor value (note that the coefficients returned are always on the scale of the original data). If `mcmc_samples` is specified, a credible interval for each coefficient is also returned, which can help identify whether the regressor is meaningful to the model (a credible interval that includes the 0 value suggests the regressor is not meaningful).

View file

@ -21,15 +21,15 @@ You may have noticed in the earlier examples in this documentation that real tim
Prophet detects changepoints by first specifying a large number of *potential changepoints* at which the rate is allowed to change. It then puts a sparse prior on the magnitudes of the rate changes (equivalent to L1 regularization) - this essentially means that Prophet has a large number of *possible* places where the rate can change, but will use as few of them as possible. Consider the Peyton Manning forecast from the Quickstart. By default, Prophet specifies 25 potential changepoints which are uniformly placed in the first 80% of the time series. The vertical lines in this figure indicate where the potential changepoints were placed:
![png](/prophet/static/trend_changepoints_files/trend_changepoints_4_0.png)
![png](/prophet/static/trend_changepoints_files/trend_changepoints_4_0.png)
Even though we have a lot of places where the rate can possibly change, because of the sparse prior, most of these changepoints go unused. We can see this by plotting the magnitude of the rate change at each changepoint:
![png](/prophet/static/trend_changepoints_files/trend_changepoints_6_0.png)
![png](/prophet/static/trend_changepoints_files/trend_changepoints_6_0.png)
The number of potential changepoints can be set using the argument `n_changepoints`, but this is better tuned by adjusting the regularization. The locations of the signification changepoints can be visualized with:
@ -45,8 +45,8 @@ from prophet.plot import add_changepoints_to_plot
fig = m.plot(forecast)
a = add_changepoints_to_plot(fig.gca(), m, forecast)
```
![png](/prophet/static/trend_changepoints_files/trend_changepoints_9_0.png)
![png](/prophet/static/trend_changepoints_files/trend_changepoints_9_0.png)
By default changepoints are only inferred for the first 80% of the time series in order to have plenty of runway for projecting the trend forward and to avoid overfitting fluctuations at the end of the time series. This default works in many situations but not all, and can be changed using the `changepoint_range` argument. For example, `m = Prophet(changepoint_range=0.9)` in Python or `m <- prophet(changepoint.range = 0.9)` in R will place potential changepoints in the first 90% of the time series.
@ -71,8 +71,8 @@ m = Prophet(changepoint_prior_scale=0.5)
forecast = m.fit(df).predict(future)
fig = m.plot(forecast)
```
![png](/prophet/static/trend_changepoints_files/trend_changepoints_13_0.png)
![png](/prophet/static/trend_changepoints_files/trend_changepoints_13_0.png)
Decreasing it will make the trend *less* flexible:
@ -90,8 +90,8 @@ m = Prophet(changepoint_prior_scale=0.001)
forecast = m.fit(df).predict(future)
fig = m.plot(forecast)
```
![png](/prophet/static/trend_changepoints_files/trend_changepoints_16_0.png)
![png](/prophet/static/trend_changepoints_files/trend_changepoints_16_0.png)
When visualizing the forecast, this parameter can be adjusted as needed if the trend seems to be over- or under-fit. In the fully-automated setting, see the documentation on cross validation for recommendations on how this parameter can be tuned.
@ -117,6 +117,6 @@ m = Prophet(changepoints=['2014-01-01'])
forecast = m.fit(df).predict(future)
fig = m.plot(forecast)
```
![png](/prophet/static/trend_changepoints_files/trend_changepoints_21_0.png)
![png](/prophet/static/trend_changepoints_files/trend_changepoints_21_0.png)

View file

@ -78,3 +78,4 @@ fig = m.plot_components(forecast)
You can access the raw posterior predictive samples in Python using the method `m.predictive_samples(future)`, or in R using the function `predictive_samples(m, future)`.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -146,7 +146,7 @@
"source": [
"### Flat trend and custom trends\n",
"\n",
"For time series that exhibit strong seasonality patterns rather than trend changes, it may be useful to force the trend growth rate to be flat. This can be achieved simply by passing `growth=flat` when creating the model:"
"For time series that exhibit strong seasonality patterns rather than trend changes, or when we want to rely on the pattern of exogenous regressors (e.g. for causal inference with time series), it may be useful to force the trend growth rate to be flat. This can be achieved simply by passing `growth=flat` when creating the model:"
]
},
{
@ -267,16 +267,22 @@
"metadata": {},
"source": [
"### External references\n",
"\n",
"As we discuss in our [2023 blog post on the state of Prophet](https://medium.com/@cuongduong_35162/facebook-prophet-in-2023-and-beyond-c5086151c138), we have no plans to further develop the underlying Prophet model. If you're looking for state-of-the-art forecasting accuracy, we recommend the following libraries:\n",
"\n",
"* [`statsforecast`](https://github.com/Nixtla/statsforecast), and other packages from the Nixtla group such as [`hierarchicalforecast`](https://github.com/Nixtla/hierarchicalforecast) and [`neuralforecast`](https://github.com/Nixtla/neuralforecast).\n",
"* [`NeuralProphet`](https://neuralprophet.com/), a Prophet-style model implemented in PyTorch, to be more adaptable and extensible.\n",
"\n",
"These github repositories provide examples of building on top of Prophet in ways that may be of broad interest:\n",
"* [forecastr](https://github.com/garethcull/forecastr): A web app that provides a UI for Prophet.\n",
"* [NeuralProphet](https://github.com/ourownstory/neural_prophet): A Prophet-style model implemented in pytorch, to be more adaptable and extensible."
"\n",
"* [forecastr](https://github.com/garethcull/forecastr): A web app that provides a UI for Prophet."
]
}
],
"metadata": {
"celltoolbar": "Edit Metadata",
"kernelspec": {
"display_name": "Python 3",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@ -290,7 +296,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10 (default, Mar 25 2022, 22:18:25) \n[Clang 12.0.5 (clang-1205.0.22.11)]"
"version": "3.9.17"
},
"vscode": {
"interpreter": {

View file

@ -771,7 +771,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
"version": "3.9.17"
}
},
"nbformat": 4,

View file

@ -292,7 +292,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
"version": "3.9.17"
}
},
"nbformat": 4,

File diff suppressed because one or more lines are too long

View file

@ -541,7 +541,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The holidays for each country are provided by the `holidays` package in Python. A list of available countries, and the country name to use, is available on their page: https://github.com/dr-prodigy/python-holidays. In addition to those countries, Prophet includes holidays for these countries: Brazil (BR), Indonesia (ID), India (IN), Malaysia (MY), Vietnam (VN), Thailand (TH), Philippines (PH), Pakistan (PK), Bangladesh (BD), Egypt (EG), China (CN), and Russian (RU), Korea (KR), Belarus (BY), and United Arab Emirates (AE).\n",
"The holidays for each country are provided by the `holidays` package in Python. A list of available countries, and the country name to use, is available on their page: https://github.com/vacanza/python-holidays/.\n",
"\n",
"In Python, most holidays are computed deterministically and so are available for any date range; a warning will be raised if dates fall outside the range supported by that country. In R, holiday dates are computed for 1995 through 2044 and stored in the package as `data-raw/generated_holidays.csv`. If a wider date range is needed, this script can be used to replace that file with a different date range: https://github.com/facebook/prophet/blob/main/python/scripts/generate_holidays_file.py.\n",
"\n",
@ -590,6 +590,139 @@
"fig = m.plot_components(forecast)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Holidays for subdivisions (Python)\n",
"\n",
"We can use the utility function `make_holidays_df` to easily create custom holidays DataFrames, e.g. for certain states, using data from the [holidays](https://pypi.org/project/holidays/) package. This can be passed directly to the `Prophet()` constructor."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>ds</th>\n",
" <th>holiday</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2019-01-26</td>\n",
" <td>Australia Day</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2019-01-28</td>\n",
" <td>Australia Day (Observed)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2019-04-25</td>\n",
" <td>Anzac Day</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2019-12-25</td>\n",
" <td>Christmas Day</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2019-12-26</td>\n",
" <td>Boxing Day</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>2019-04-20</td>\n",
" <td>Easter Saturday</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>2019-04-21</td>\n",
" <td>Easter Sunday</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>2019-10-07</td>\n",
" <td>Labour Day</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>2019-06-10</td>\n",
" <td>Queen's Birthday</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>2019-08-05</td>\n",
" <td>Bank Holiday</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" ds holiday\n",
"0 2019-01-26 Australia Day\n",
"1 2019-01-28 Australia Day (Observed)\n",
"2 2019-04-25 Anzac Day\n",
"3 2019-12-25 Christmas Day\n",
"4 2019-12-26 Boxing Day\n",
"5 2019-04-20 Easter Saturday\n",
"6 2019-04-21 Easter Sunday\n",
"7 2019-10-07 Labour Day\n",
"8 2019-06-10 Queen's Birthday\n",
"9 2019-08-05 Bank Holiday"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from prophet.make_holidays import make_holidays_df\n",
"\n",
"nsw_holidays = make_holidays_df(\n",
" year_list=[2019 + i for i in range(10)], country='AU', province='NSW'\n",
")\n",
"nsw_holidays.head(n=10)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"from prophet import Prophet\n",
"\n",
"m_nsw = Prophet(holidays=nsw_holidays)"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -1211,13 +1344,15 @@
"\n",
"The `add_regressor` function has optional arguments for specifying the prior scale (holiday prior scale is used by default) and whether or not the regressor is standardized - see the docstring with `help(Prophet.add_regressor)` in Python and `?add_regressor` in R. Note that regressors must be added prior to model fitting. Prophet will also raise an error if the regressor is constant throughout the history, since there is nothing to fit from it.\n",
"\n",
"The extra regressor must be known for both the history and for future dates. It thus must either be something that has known future values (such as `nfl_sunday`), or something that has separately been forecasted elsewhere. The weather regressors used in the notebook linked above is a good example of an extra regressor that has forecasts that can be used for future values. One can also use as a regressor another time series that has been forecasted with a time series model, such as Prophet. For instance, if `r(t)` is included as a regressor for `y(t)`, Prophet can be used to forecast `r(t)` and then that forecast can be plugged in as the future values when forecasting `y(t)`. A note of caution around this approach: This will probably not be useful unless `r(t)` is somehow easier to forecast then `y(t)`. This is because error in the forecast of `r(t)` will produce error in the forecast of `y(t)`. One setting where this can be useful is in hierarchical time series, where there is top-level forecast that has higher signal-to-noise and is thus easier to forecast. Its forecast can be included in the forecast for each lower-level series.\n",
"The extra regressor must be known for both the history and for future dates. It thus must either be something that has known future values (such as `nfl_sunday`), or something that has separately been forecasted elsewhere. The weather regressors used in the notebook linked above is a good example of an extra regressor that has forecasts that can be used for future values. \n",
"\n",
"One can also use as a regressor another time series that has been forecasted with a time series model, such as Prophet. For instance, if `r(t)` is included as a regressor for `y(t)`, Prophet can be used to forecast `r(t)` and then that forecast can be plugged in as the future values when forecasting `y(t)`. A note of caution around this approach: This will probably not be useful unless `r(t)` is somehow easier to forecast than `y(t)`. This is because error in the forecast of `r(t)` will produce error in the forecast of `y(t)`. One setting where this can be useful is in hierarchical time series, where there is top-level forecast that has higher signal-to-noise and is thus easier to forecast. Its forecast can be included in the forecast for each lower-level series.\n",
"\n",
"Extra regressors are put in the linear component of the model, so the underlying model is that the time series depends on the extra regressor as either an additive or multiplicative factor (see the next section for multiplicativity).\n",
"\n",
"#### Coefficients of additional regressors\n",
"\n",
"To extract the beta coefficients of the extra regressors, use the utility function `regressor_coefficients` (`from prophet.utilities import regressor_coefficients` in Python, `prophet::regressor_coefficients` in R) on the fitted model. The estimated beta coefficient for each regressor roughly represents the increase in prediction value for a unit increase in the regressor value (note that the coefficients returned are always on the scale of the original data). If `mcmc_samples` is specified, a credible interval for each coefficient is also returned, which can help identify whether each regressor is \"statistically significant\"."
"To extract the beta coefficients of the extra regressors, use the utility function `regressor_coefficients` (`from prophet.utilities import regressor_coefficients` in Python, `prophet::regressor_coefficients` in R) on the fitted model. The estimated beta coefficient for each regressor roughly represents the increase in prediction value for a unit increase in the regressor value (note that the coefficients returned are always on the scale of the original data). If `mcmc_samples` is specified, a credible interval for each coefficient is also returned, which can help identify whether the regressor is meaningful to the model (a credible interval that includes the 0 value suggests the regressor is not meaningful)."
]
}
],
@ -1238,7 +1373,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
"version": "3.9.17"
}
},
"nbformat": 4,