Regenerate all documentation
|
|
@ -2,12 +2,13 @@
|
|||
items:
|
||||
- id: installation
|
||||
- id: quick_start
|
||||
- id: forecasting_growth
|
||||
- id: saturating_forecasts
|
||||
- id: trend_changepoints
|
||||
- id: seasonality_and_holiday_effects
|
||||
- id: uncertainty_intervals
|
||||
- id: outliers
|
||||
- id: non-daily_data
|
||||
- id: diagnostics
|
||||
- id: contributing
|
||||
|
||||
# n title:, 1 items: per title:, n id: per items:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ title: "How to Contribute"
|
|||
permalink: /docs/contributing.html
|
||||
---
|
||||
|
||||
Prophet has an non-fixed release cycle but we will be making bugfixes in response to user feedback and adding features. Its current state is Beta (v0.1), we expect no obvious bugs. Please let us know if you encounter a bug by [filing an issue](https://github.com/facebookincubator/prophet/issues).
|
||||
Prophet has an non-fixed release cycle but we will be making bugfixes in response to user feedback and adding features. Its current state is Beta (v0.2), we expect no obvious bugs. Please let us know if you encounter a bug by [filing an issue](https://github.com/facebookincubator/prophet/issues).
|
||||
|
||||
We appreciate all contributions. If you are planning to contribute back bug-fixes, please do so without any further discussion.
|
||||
|
||||
|
|
|
|||
96
docs/_docs/diagnostics.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
layout: docs
|
||||
docid: "diagnostics"
|
||||
title: "Diagnostics"
|
||||
permalink: /docs/diagnostics.html
|
||||
---
|
||||
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 a initial history of 5 years, and a forecast was made on a one year horizon.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
[The Prophet paper](https://peerj.com/preprints/3190.pdf) gives further description of simulated historical forecasts.
|
||||
|
||||
This cross validation procedure can be done automatically for a range of historical cutoffs using the `cross_validation` function. We specify the forecast horizon (`horizon`), and then optionally the size of the initial training period (`initial`) and the spacing between cutoff dates (`period`). By default, the initial training period is set to three times the horizon, and cutoffs are made every half a horizon.
|
||||
|
||||
The output of `cross_validation` is a dataframe with the true values `y` and the out-of-sample forecast values `yhat`, at each simulated forecast date and for each cutoff date. This dataframe can then be used to compute error measures of `yhat` vs. `y`.
|
||||
|
||||
```R
|
||||
# R
|
||||
df.cv <- cross_validation(m, horizon = 730, units = 'days')
|
||||
head(df.cv)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
from fbprophet.diagnostics import cross_validation
|
||||
df_cv = cross_validation(m, horizon = '730 days')
|
||||
df_cv.head()
|
||||
```
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<table border="1" class="dataframe">
|
||||
<thead>
|
||||
<tr style="text-align: right;">
|
||||
<th></th>
|
||||
<th>ds</th>
|
||||
<th>yhat</th>
|
||||
<th>yhat_lower</th>
|
||||
<th>yhat_upper</th>
|
||||
<th>y</th>
|
||||
<th>cutoff</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>0</th>
|
||||
<td>2014-01-21</td>
|
||||
<td>9.439510</td>
|
||||
<td>8.799215</td>
|
||||
<td>10.080240</td>
|
||||
<td>10.542574</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>1</th>
|
||||
<td>2014-01-22</td>
|
||||
<td>9.267086</td>
|
||||
<td>8.645900</td>
|
||||
<td>9.882225</td>
|
||||
<td>10.004283</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2</th>
|
||||
<td>2014-01-23</td>
|
||||
<td>9.263447</td>
|
||||
<td>8.628803</td>
|
||||
<td>9.852847</td>
|
||||
<td>9.732818</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3</th>
|
||||
<td>2014-01-24</td>
|
||||
<td>9.277452</td>
|
||||
<td>8.693226</td>
|
||||
<td>9.897891</td>
|
||||
<td>9.866460</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>4</th>
|
||||
<td>2014-01-25</td>
|
||||
<td>9.087565</td>
|
||||
<td>8.447306</td>
|
||||
<td>9.728898</td>
|
||||
<td>9.370927</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
@ -4,7 +4,47 @@ docid: "non-daily_data"
|
|||
title: "Non-Daily Data"
|
||||
permalink: /docs/non-daily_data.html
|
||||
---
|
||||
Prophet doesn't strictly require daily data, but you can get strange results if you ask for daily forecasts from non-daily data and fit seasonalities. Here we forecast US retail sales volume for the next 10 years:
|
||||
## Sub-daily data
|
||||
|
||||
Prophet can make forecasts for time series with sub-daily observations by passing in a dataframe with timestamps in the `ds` column. When sub-daily data are used, daily seasonality will automatically be fit. Here we fit Prophet to data with 5-minute resolution (daily temperatures at Yosemite):
|
||||
|
||||
```R
|
||||
# R
|
||||
df <- read.csv('../examples/example_yosemite_temps.csv')
|
||||
m <- prophet(df, changepoint.prior.scale=0.01)
|
||||
future <- make_future_dataframe(m, periods = 300, freq = 60 * 60)
|
||||
fcst <- predict(m, future)
|
||||
plot(m, fcst);
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
df = pd.read_csv('../examples/example_yosemite_temps.csv')
|
||||
m = Prophet(changepoint_prior_scale=0.01).fit(df)
|
||||
future = m.make_future_dataframe(periods=300, freq='H')
|
||||
fcst = m.predict(future)
|
||||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
The daily seasonality will show up in the components plot:
|
||||
|
||||
```R
|
||||
# R
|
||||
prophet_plot_components(m, fcst)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
m.plot_components(fcst);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
## Monthly data
|
||||
|
||||
You can use Prophet to fit monthly data. However, the underlying model is continuous-time, which means that you can get strange results if you fit the model to monthly data and then ask for daily forecasts. Here we forecast US retail sales volume for the next 10 years:
|
||||
|
||||
```R
|
||||
# R
|
||||
|
|
@ -23,14 +63,14 @@ fcst = m.predict(future)
|
|||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
The forecast here seems very noisy. What's happening is that this particular data set only provides monthly data. When we fit the yearly seasonality, it only has data for the first of each month and the seasonality components for the remaining days are unidentifiable and overfit. When you are fitting Prophet to monthly data, only make monthly forecasts, which can be done by passing the frequency into make_future_dataframe:
|
||||
|
||||
```R
|
||||
# R
|
||||
future <- make_future_dataframe(m, periods = 120, freq = 'm')
|
||||
future <- make_future_dataframe(m, periods = 120, freq = 'month')
|
||||
fcst <- predict(m, future)
|
||||
plot(m, fcst)
|
||||
```
|
||||
|
|
@ -41,5 +81,5 @@ fcst = m.predict(future)
|
|||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -147,37 +147,37 @@ forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
|
|||
<tr>
|
||||
<th>3265</th>
|
||||
<td>2017-01-15</td>
|
||||
<td>8.205065</td>
|
||||
<td>7.488507</td>
|
||||
<td>8.887731</td>
|
||||
<td>8.206753</td>
|
||||
<td>7.485107</td>
|
||||
<td>8.920149</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3266</th>
|
||||
<td>2017-01-16</td>
|
||||
<td>8.530088</td>
|
||||
<td>7.862778</td>
|
||||
<td>9.223688</td>
|
||||
<td>8.531766</td>
|
||||
<td>7.779331</td>
|
||||
<td>9.284859</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3267</th>
|
||||
<td>2017-01-17</td>
|
||||
<td>8.317468</td>
|
||||
<td>7.644606</td>
|
||||
<td>9.021893</td>
|
||||
<td>8.319156</td>
|
||||
<td>7.610545</td>
|
||||
<td>8.986889</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3268</th>
|
||||
<td>2017-01-18</td>
|
||||
<td>8.150081</td>
|
||||
<td>7.462394</td>
|
||||
<td>8.889095</td>
|
||||
<td>8.151772</td>
|
||||
<td>7.415802</td>
|
||||
<td>8.875191</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3269</th>
|
||||
<td>2017-01-19</td>
|
||||
<td>8.162015</td>
|
||||
<td>7.438503</td>
|
||||
<td>8.877361</td>
|
||||
<td>8.163690</td>
|
||||
<td>7.427153</td>
|
||||
<td>8.884826</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -205,6 +205,8 @@ m.plot_components(forecast);
|
|||

|
||||
|
||||
|
||||
More details about the options available for each method are available in the docstrings, for example, via `help(Prophet)` or `help(Prophet.fit)`.
|
||||
|
||||
## R API
|
||||
|
||||
In R, we use the normal model fitting API. We provide a `prophet` function that performs fitting and returns a model object. You can then call `predict` and `plot` on this model object.
|
||||
|
|
@ -254,12 +256,12 @@ tail(forecast[c('ds', 'yhat', 'yhat_lower', 'yhat_upper')])
|
|||
```
|
||||
|
||||
ds yhat yhat_lower yhat_upper
|
||||
3265 2017-01-14 7.832396 7.140713 8.533132
|
||||
3266 2017-01-15 8.214232 7.460897 8.918678
|
||||
3267 2017-01-16 8.539239 7.788240 9.262142
|
||||
3268 2017-01-17 8.326654 7.615613 9.003147
|
||||
3269 2017-01-18 8.159337 7.382162 8.889958
|
||||
3270 2017-01-19 8.171276 7.354854 8.922918
|
||||
3265 2017-01-14 7.825609 7.183818 8.488012
|
||||
3266 2017-01-15 8.207400 7.478778 8.951113
|
||||
3267 2017-01-16 8.532394 7.826360 9.240482
|
||||
3268 2017-01-17 8.319785 7.596815 9.042505
|
||||
3269 2017-01-18 8.152424 7.440858 8.874581
|
||||
3270 2017-01-19 8.164327 7.419148 8.882906
|
||||
|
||||
|
||||
|
||||
|
|
@ -270,7 +272,7 @@ You can use the generic `plot` function to plot the forecast, by passing in the
|
|||
plot(m, forecast)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
You can use the `prophet_plot_components` function to see the forecast broken down into trend, weekly seasonality, and yearly seasonality.
|
||||
|
|
@ -280,5 +282,7 @@ You can use the `prophet_plot_components` function to see the forecast broken do
|
|||
prophet_plot_components(m, forecast)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
More details about the options available for each method are available in the docstrings, for example, via `?prophet` or `?fit.prophet`. This documentation is also available in the [reference manual](https://cran.r-project.org/web/packages/prophet/prophet.pdf) on CRAN.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
---
|
||||
layout: docs
|
||||
docid: "forecasting_growth"
|
||||
title: "Forecasting Growth"
|
||||
permalink: /docs/forecasting_growth.html
|
||||
docid: "saturating_forecasts"
|
||||
title: "Saturating Forecasts"
|
||||
permalink: /docs/saturating_forecasts.html
|
||||
---
|
||||
### Forecasting Growth
|
||||
|
||||
By default, Prophet uses a linear model for its forecast. When forecasting growth, there is usually some maximum achievable point: total market size, total population size, etc. This is called the carrying capacity, and the forecast should saturate at this point.
|
||||
|
||||
Prophet allows you to make forecasts using a [logistic growth](https://en.wikipedia.org/wiki/Logistic_function) trend model, with a specified carrying capacity. We illustrate this with the log number of page visits to the [R (programming language)](https://en.wikipedia.org/wiki/R_%28programming_language%29) page on Wikipedia:
|
||||
|
|
@ -44,13 +46,6 @@ m <- prophet(df, growth = 'logistic')
|
|||
```
|
||||
We make a dataframe for future predictions as before, except we must also specify the capacity in the future. Here we keep capacity constant at the same value as in the history, and forecast 3 years into the future:
|
||||
|
||||
```python
|
||||
# Python
|
||||
future = m.make_future_dataframe(periods=1826)
|
||||
future['cap'] = 8.5
|
||||
fcst = m.predict(future)
|
||||
m.plot(fcst);
|
||||
```
|
||||
```R
|
||||
# R
|
||||
future <- make_future_dataframe(m, periods = 1826)
|
||||
|
|
@ -58,6 +53,44 @@ future$cap <- 8.5
|
|||
fcst <- predict(m, future)
|
||||
plot(m, fcst);
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
future = m.make_future_dataframe(periods=1826)
|
||||
future['cap'] = 8.5
|
||||
fcst = m.predict(future)
|
||||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### Saturating Minimum
|
||||
|
||||
The logistic growth model can also handle a saturating minimum, which is specified with a column `floor` in the same way as the `cap` column specifies the maximum:
|
||||
|
||||
```R
|
||||
# R
|
||||
df$y <- 10 - df$y
|
||||
df$cap <- 6
|
||||
df$floor <- 1.5
|
||||
future$cap <- 6
|
||||
future$floor <- 1.5
|
||||
m <- prophet(df, growth = 'logistic')
|
||||
fcst <- predict(m, future)
|
||||
plot(m, fcst)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
df['y'] = 10 - df['y']
|
||||
df['cap'] = 6
|
||||
df['floor'] = 1.5
|
||||
future['cap'] = 6
|
||||
future['floor'] = 1.5
|
||||
m = Prophet(growth='logistic')
|
||||
m.fit(df)
|
||||
fcst = m.predict(future)
|
||||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||
|
||||
367
docs/_docs/seasonality_and_holiday_effects.md
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
---
|
||||
layout: docs
|
||||
docid: "seasonality_and_holiday_effects"
|
||||
title: "Seasonality And Holiday Effects"
|
||||
permalink: /docs/seasonality_and_holiday_effects.html
|
||||
---
|
||||
### Specifying Seasonalities
|
||||
|
||||
Prophet will by default fit weekly and yearly seasonalities, if the time series is more than two cycles long. It will also fit daily seasonality for a sub-daily time series. You can add other seasonalities (monthly, quarterly, hourly) using the `add_seasonality` method (Python) or function (R).
|
||||
|
||||
The inputs to this function are a name, the period of the seasonality in days, and the number of Fourier terms for the seasonality. 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. For reference, by default Prophet uses 3 terms for weekly seasonality and 10 for yearly seasonality. An optional input to `add_seasonality` is the prior scale for that seasonal component - this is discussed below.
|
||||
|
||||
As an example, here we fit the Peyton Manning data from the Quickstart, but replace the weekly seasonality with monthly seasonality. The monthly seasonality then will appear in the components plot:
|
||||
|
||||
```R
|
||||
# R
|
||||
m <- prophet(weekly.seasonality=FALSE)
|
||||
m <- add_seasonality(m, name='monthly', period=30.5, fourier.order=5)
|
||||
m <- fit.prophet(m, df)
|
||||
forecast <- predict(m, future)
|
||||
prophet_plot_components(m, forecast)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
m = Prophet(weekly_seasonality=False)
|
||||
m.add_seasonality(name='monthly', period=30.5, fourier_order=5)
|
||||
forecast = m.fit(df).predict(future)
|
||||
m.plot_components(forecast);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
### Modeling Holidays and Special Events
|
||||
If you have holidays or other recurring events that you'd like to model, you must create a dataframe for them. It has two columns (`holiday` and `ds`) and a row for each occurrence of the holiday. It must include all occurrences of the holiday, both in the past (back as far as the historical data go) and in the future (out as far as the forecast is being made). If they won't repeat in the future, Prophet will model them and then not include them in the forecast.
|
||||
|
||||
You can also include columns `lower_window` and `upper_window` which extend the holiday out to `[lower_window, upper_window]` days around the date. For instance, if you wanted to included Christmas Eve in addition to Christmas you'd include `lower_window=-1,upper_window=0`. If you wanted to use Black Friday in addition to Thanksgiving, you'd include `lower_window=0,upper_window=1`. You can also include a column `prior_scale` to set the prior scale separately for each holiday, as described below.
|
||||
|
||||
Here we create a dataframe that includes the dates of all of Peyton Manning's playoff appearances:
|
||||
|
||||
```python
|
||||
# Python
|
||||
playoffs = pd.DataFrame({
|
||||
'holiday': 'playoff',
|
||||
'ds': pd.to_datetime(['2008-01-13', '2009-01-03', '2010-01-16',
|
||||
'2010-01-24', '2010-02-07', '2011-01-08',
|
||||
'2013-01-12', '2014-01-12', '2014-01-19',
|
||||
'2014-02-02', '2015-01-11', '2016-01-17',
|
||||
'2016-01-24', '2016-02-07']),
|
||||
'lower_window': 0,
|
||||
'upper_window': 1,
|
||||
})
|
||||
superbowls = pd.DataFrame({
|
||||
'holiday': 'superbowl',
|
||||
'ds': pd.to_datetime(['2010-02-07', '2014-02-02', '2016-02-07']),
|
||||
'lower_window': 0,
|
||||
'upper_window': 1,
|
||||
})
|
||||
holidays = pd.concat((playoffs, superbowls))
|
||||
```
|
||||
```R
|
||||
# R
|
||||
library(dplyr)
|
||||
playoffs <- data_frame(
|
||||
holiday = 'playoff',
|
||||
ds = as.Date(c('2008-01-13', '2009-01-03', '2010-01-16',
|
||||
'2010-01-24', '2010-02-07', '2011-01-08',
|
||||
'2013-01-12', '2014-01-12', '2014-01-19',
|
||||
'2014-02-02', '2015-01-11', '2016-01-17',
|
||||
'2016-01-24', '2016-02-07')),
|
||||
lower_window = 0,
|
||||
upper_window = 1
|
||||
)
|
||||
superbowls <- data_frame(
|
||||
holiday = 'superbowl',
|
||||
ds = as.Date(c('2010-02-07', '2014-02-02', '2016-02-07')),
|
||||
lower_window = 0,
|
||||
upper_window = 1
|
||||
)
|
||||
holidays <- bind_rows(playoffs, superbowls)
|
||||
```
|
||||
Above we have include the superbowl days as both playoff games and superbowl games. This means that the superbowl effect will be an additional additive bonus on top of the playoff effect.
|
||||
|
||||
Once the table is created, holiday effects are included in the forecast by passing them in with the `holidays` argument. Here we do it with the Peyton Manning data from the Quickstart:
|
||||
|
||||
```python
|
||||
# Python
|
||||
m = Prophet(holidays=holidays)
|
||||
forecast = m.fit(df).predict(future)
|
||||
```
|
||||
```R
|
||||
# R
|
||||
m <- prophet(df, holidays = holidays)
|
||||
forecast <- predict(m, future)
|
||||
```
|
||||
The holiday effect can be seen in the `forecast` dataframe:
|
||||
|
||||
```R
|
||||
# R
|
||||
forecast %>%
|
||||
select(ds, playoff, superbowl) %>%
|
||||
filter(abs(playoff + superbowl) > 0) %>%
|
||||
tail(10)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
forecast[(forecast['playoff'] + forecast['superbowl']).abs() > 0][
|
||||
['ds', 'playoff', 'superbowl']][-10:]
|
||||
```
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<table border="1" class="dataframe">
|
||||
<thead>
|
||||
<tr style="text-align: right;">
|
||||
<th></th>
|
||||
<th>ds</th>
|
||||
<th>playoff</th>
|
||||
<th>superbowl</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>2190</th>
|
||||
<td>2014-02-02</td>
|
||||
<td>1.226679</td>
|
||||
<td>1.192500</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2191</th>
|
||||
<td>2014-02-03</td>
|
||||
<td>1.911294</td>
|
||||
<td>1.373781</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2532</th>
|
||||
<td>2015-01-11</td>
|
||||
<td>1.226679</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2533</th>
|
||||
<td>2015-01-12</td>
|
||||
<td>1.911294</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2901</th>
|
||||
<td>2016-01-17</td>
|
||||
<td>1.226679</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2902</th>
|
||||
<td>2016-01-18</td>
|
||||
<td>1.911294</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2908</th>
|
||||
<td>2016-01-24</td>
|
||||
<td>1.226679</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2909</th>
|
||||
<td>2016-01-25</td>
|
||||
<td>1.911294</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2922</th>
|
||||
<td>2016-02-07</td>
|
||||
<td>1.226679</td>
|
||||
<td>1.192500</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2923</th>
|
||||
<td>2016-02-08</td>
|
||||
<td>1.911294</td>
|
||||
<td>1.373781</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
The holiday effects will also show up in the components plot, where we see that there is a spike on the days around playoff appearances, with an especially large spike for the superbowl:
|
||||
|
||||
```python
|
||||
# Python
|
||||
m.plot_components(forecast);
|
||||
```
|
||||
```R
|
||||
# R
|
||||
prophet_plot_components(m, forecast);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
Individual holidays can be plotted using the `plot_forecast_component` method (Python) or function (R). For example, `m.plot_forecast_component(forecast, 'superbowl')` in Python and `plot_forecast_component(forecast, 'superbowl')` in R to plot just the superbowl holiday component.
|
||||
|
||||
### Prior scale for holidays and seasonality
|
||||
If you find that the holidays are overfitting, you can adjust their prior scale to smooth them using the parameter `holidays_prior_scale`. By default this parameter is 10, which provides very little regularization. Reducing this parameter dampens holiday effects:
|
||||
|
||||
```R
|
||||
# R
|
||||
m <- prophet(df, holidays = holidays, holidays.prior.scale = 0.05)
|
||||
forecast <- predict(m, future)
|
||||
forecast %>%
|
||||
select(ds, playoff, superbowl) %>%
|
||||
filter(abs(playoff + superbowl) > 0) %>%
|
||||
tail(10)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
m = Prophet(holidays=holidays, holidays_prior_scale=0.05).fit(df)
|
||||
forecast = m.predict(future)
|
||||
forecast[(forecast['playoff'] + forecast['superbowl']).abs() > 0][
|
||||
['ds', 'playoff', 'superbowl']][-10:]
|
||||
```
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<table border="1" class="dataframe">
|
||||
<thead>
|
||||
<tr style="text-align: right;">
|
||||
<th></th>
|
||||
<th>ds</th>
|
||||
<th>playoff</th>
|
||||
<th>superbowl</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>2190</th>
|
||||
<td>2014-02-02</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.957093</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2191</th>
|
||||
<td>2014-02-03</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.979777</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2532</th>
|
||||
<td>2015-01-11</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2533</th>
|
||||
<td>2015-01-12</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2901</th>
|
||||
<td>2016-01-17</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2902</th>
|
||||
<td>2016-01-18</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2908</th>
|
||||
<td>2016-01-24</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2909</th>
|
||||
<td>2016-01-25</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2922</th>
|
||||
<td>2016-02-07</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.957093</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2923</th>
|
||||
<td>2016-02-08</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.979777</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
The magnitude of the holiday effect has been reduced compared to before, especially for superbowls, which had the fewest observations. There is a parameter `seasonality_prior_scale` which similarly adjusts the extent to which the seasonality model will fit the data.
|
||||
|
||||
Prior scales can be set separately for individual holidays by including a column `prior_scale` in the holidays dataframe. Prior scales for individual seasonalities can be passed as an argument to `add_seasonality`. For instance, the prior scale for just weekly seasonality can be set using:
|
||||
|
||||
```python
|
||||
# Python
|
||||
m = Prophet()
|
||||
m.add_seasonality(
|
||||
name='weekly', period=7, fourier_order=3, prior_scale=0.1);
|
||||
```
|
||||
```R
|
||||
# R
|
||||
m <- prophet()
|
||||
m <- add_seasonality(
|
||||
m, name='weekly', period=7, fourier.order=3, prior.scale=0.1)
|
||||
```
|
||||
### Additional regressors
|
||||
Additional regressors can be added to the linear part of the model using the `add_regressor` method or function. A column with the regressor value will need to be present in both the fitting and prediction dataframes. For example, we can add an additional effect on Sundays during the NFL season. On the components plot, this effect will show up in the 'extra_regressors' plot:
|
||||
|
||||
```R
|
||||
# R
|
||||
nfl_sunday <- function(ds) {
|
||||
dates <- as.Date(ds)
|
||||
month <- as.numeric(format(dates, '%m'))
|
||||
as.numeric((weekdays(dates) == "Sunday") & (month > 8 | month < 2))
|
||||
}
|
||||
df$nfl_sunday <- nfl_sunday(df$ds)
|
||||
|
||||
m <- prophet()
|
||||
m <- add_regressor(m, 'nfl_sunday')
|
||||
m <- fit.prophet(m, df)
|
||||
|
||||
future$nfl_sunday <- nfl_sunday(future$ds)
|
||||
|
||||
forecast <- predict(m, future)
|
||||
prophet_plot_components(m, forecast)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
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_sunday'] = df['ds'].apply(nfl_sunday)
|
||||
|
||||
m = Prophet()
|
||||
m.add_regressor('nfl_sunday')
|
||||
m.fit(df)
|
||||
|
||||
future['nfl_sunday'] = future['ds'].apply(nfl_sunday)
|
||||
|
||||
forecast = m.predict(future)
|
||||
m.plot_components(forecast);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
|
@ -64,7 +64,7 @@ If you wish, rather than using automatic changepoint detection you can manually
|
|||
|
||||
```R
|
||||
# R
|
||||
m <- prophet(df, changepoints = c(as.Date('2014-01-01')))
|
||||
m <- prophet(df, changepoints = c('2014-01-01'))
|
||||
forecast <- predict(m, future)
|
||||
plot(m, forecast);
|
||||
```
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ By default Prophet will only return uncertainty in the trend and observation noi
|
|||
|
||||
```python
|
||||
# Python
|
||||
m = Prophet(mcmc_samples=500)
|
||||
m = Prophet(mcmc_samples=300)
|
||||
forecast = m.fit(df).predict(future)
|
||||
```
|
||||
```R
|
||||
# R
|
||||
m <- prophet(df, mcmc.samples = 500)
|
||||
m <- prophet(df, mcmc.samples = 300)
|
||||
forecast <- predict(m, future)
|
||||
```
|
||||
This replaces the typical MAP estimation with MCMC sampling, and takes much longer - think 10 minutes instead of 10 seconds. If you do full sampling, then you will see the uncertainty in seasonal components when you plot them:
|
||||
|
|
@ -53,4 +53,6 @@ prophet_plot_components(m, 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)`.
|
||||
|
||||
There are upstream issues in PyStan for Windows which make MCMC sampling extremely slow. The best choice for MCMC sampling in Windows is to use R, or Python in a Linux VM.
|
||||
|
|
|
|||
BIN
docs/static/diagnostics_files/diagnostics_3_0.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 52 KiB |
BIN
docs/static/non-daily_data_files/non-daily_data_10_0.png
vendored
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
docs/static/non-daily_data_files/non-daily_data_12_0.png
vendored
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
docs/static/non-daily_data_files/non-daily_data_13_0.png
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 48 KiB |
BIN
docs/static/non-daily_data_files/non-daily_data_9_1.png
vendored
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/static/outliers_files/outliers_10_0.png
vendored
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
BIN
docs/static/outliers_files/outliers_12_1.png
vendored
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
BIN
docs/static/outliers_files/outliers_13_0.png
vendored
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 70 KiB |
BIN
docs/static/outliers_files/outliers_3_1.png
vendored
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
BIN
docs/static/outliers_files/outliers_4_0.png
vendored
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 38 KiB |
BIN
docs/static/outliers_files/outliers_6_1.png
vendored
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
BIN
docs/static/outliers_files/outliers_7_0.png
vendored
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 73 KiB |
BIN
docs/static/outliers_files/outliers_9_1.png
vendored
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
BIN
docs/static/quick_start_files/quick_start_12_0.png
vendored
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 101 KiB |
BIN
docs/static/quick_start_files/quick_start_14_0.png
vendored
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
BIN
docs/static/quick_start_files/quick_start_26_0.png
vendored
|
Before Width: | Height: | Size: 86 KiB |
BIN
docs/static/quick_start_files/quick_start_27_0.png
vendored
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docs/static/quick_start_files/quick_start_28_0.png
vendored
|
Before Width: | Height: | Size: 42 KiB |
BIN
docs/static/quick_start_files/quick_start_29_0.png
vendored
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
docs/static/saturating_forecasts_files/saturating_forecasts_12_1.png
vendored
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
docs/static/saturating_forecasts_files/saturating_forecasts_13_0.png
vendored
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
docs/static/saturating_forecasts_files/saturating_forecasts_15_1.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
docs/static/saturating_forecasts_files/saturating_forecasts_16_0.png
vendored
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_15_0.png
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_16_0.png
vendored
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_25_1.png
vendored
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_26_0.png
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_3_1.png
vendored
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_4_0.png
vendored
Normal file
|
After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 72 KiB |
|
|
@ -63,7 +63,9 @@
|
|||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"input_hidden": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
|
|
@ -109,7 +111,7 @@
|
|||
"source": [
|
||||
"[The Prophet paper](https://peerj.com/preprints/3190.pdf) gives further description of simulated historical forecasts.\n",
|
||||
"\n",
|
||||
"This cross validation procedure can done automatically for a range of historical cutoffs using the `cross_validation` function. We specify the forecast horizon (`horizon`), and then optionally the size of the initial training period (`initial`) and the spacing between cutoff dates (`period`). By default, the initial training period is set to three times the horizon, and cutoffs are made every half a horizon.\n",
|
||||
"This cross validation procedure can be done automatically for a range of historical cutoffs using the `cross_validation` function. We specify the forecast horizon (`horizon`), and then optionally the size of the initial training period (`initial`) and the spacing between cutoff dates (`period`). By default, the initial training period is set to three times the horizon, and cutoffs are made every half a horizon.\n",
|
||||
"\n",
|
||||
"The output of `cross_validation` is a dataframe with the true values `y` and the out-of-sample forecast values `yhat`, at each simulated forecast date and for each cutoff date. This dataframe can then be used to compute error measures of `yhat` vs. `y`."
|
||||
]
|
||||
|
|
@ -117,7 +119,9 @@
|
|||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"output_hidden": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
"collapsed": false,
|
||||
"output_hidden": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -118,7 +119,8 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
"collapsed": false,
|
||||
"output_hidden": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
|
|||