Facebook时序预测算法Prophet研究

简介

Prophet是Facebook开源的一个时序预测算法,不仅可以处理时间序列存在一些异常值的情况,也可以处理部分缺失值的情形,还能够几乎全自动地预测时间序列未来的走势。

从论文上的描述来看,这个 prophet 算法是基于时间序列分解和机器学习的拟合来做的,其中在拟合模型的时候使用了 pyStan 这个开源工具,因此能够在较快的时间内得到需要预测的结果。除此之外,为了方便统计学家,机器学习从业者等人群的使用,prophet 同时提供了 R 语言和 Python 语言的接口。从整体的介绍来看,如果是一般的商业分析或者数据分析的需求,都可以尝试使用这个开源算法来预测未来时间序列的走势。

参考文献:

  1. GitHub - facebook/prophet

  2. Prophet官网

  3. 论文 - Forecasting at scale

快速开始

Prophet提供了R语言与Python两种语言的接口库,本文聚焦于Python实现。

环境构建

1
python -m pip install prophet
  • From v0.6 onwards, Python 2 is no longer supported.
  • As of v1.0, the package name on PyPI is “prophet”; prior to v1.0 it was “fbprophet”.
  • As of v1.1, the minimum supported Python version is 3.7.

加载数据集

演示代码加载的是开源数据集,实际使用可替换为环境的数据集,数据集要求如下:

  • 数据集包含两列内容,分为ds列与y列。

  • ds列为时间序列的时间戳,需要pandas的日期格式。

  • y列为需要预测的值,需要为数值类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pandas as pd
from prophet import Prophet
from matplotlib import pyplot

# Load data
file_path='https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv'
df = pd.read_csv(file_path)

# Summarize shape
print(df.shape)

# Show first few rows
print(df.head())

# Plot the time series
df.plot()
pyplot.show()

运行输出如下:

  • 数据集的总览及前5列数据

Prophet-01

  • 数据集时序数据图表

Prophet-02

构建模型

通过实例化一个新的Prophet对象来拟合模型。预测过程的任何设置都会传递给构造函数。然后调用其fit方法并传入历史数据帧。安装应需要1-5秒。

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
from prophet import Prophet
from matplotlib import pyplot

# Load data
file_path='https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv'
df = pd.read_csv(file_path)

# Define the model
model = Prophet()

# Fit the model
model.fit(df)

运行输出如下:

  • 构建模型日志输出

Prophet-03

构建预测时间序列

然后对数据帧进行预测,数据帧中的ds列包含要进行预测的日期。您可以使用辅助方法Prophet.make_future_dataframe获得一个合适的数据帧,该数据帧可以扩展到未来指定的天数。默认情况下,它还将包括历史记录中的日期,因此我们也会看到模型是否合适。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pandas as pd
from prophet import Prophet
from matplotlib import pyplot

# Load data
file_path='https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv'
df = pd.read_csv(file_path)

# Define the model
model = Prophet()

# Fit the model
model.fit(df)

# Generate and construct future time series
future = model.make_future_dataframe(periods=365)
print(future.tail(20))

运行输出如下:

  • 预测时间序列输出

Prophet-04

生成预测数据

predict方法将在未来为每一行分配一个预测值,并将其命名为yhat。如果你输入历史日期,它将提供样本拟合。这里的预测对象是一个新的数据框架,其中包括一个带有预测的列yhat,以及用于组件和不确定性区间的列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
from prophet import Prophet
from matplotlib import pyplot

# Load data
file_path='https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv'
df = pd.read_csv(file_path)

# Define the model
model = Prophet()

# Fit the model
model.fit(df)

# Generate and construct future time series
future = model.make_future_dataframe(periods=365)

# Generate predictive data
forecast = model.predict(future)
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(20))

运行输出如下:

  • 预测数据。yhat列表示时间序列的预测值,yhat_lower列表示预测值的下界,yhat_upper列表示预测值的上界。

Prophet-05

图形化显示

可以通过调用Prophet.plot方法并传入预测数据帧来绘制预测。如果想看到预测组件,可以使用Prophet.plot_components方法。默认情况下,您将看到时间序列的趋势、年度季节性和每周季节性。如果你把假期包括在内,你也会在这里看到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import pandas as pd
from prophet import Prophet
from matplotlib import pyplot

# Load data
file_path='https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv'
df = pd.read_csv(file_path)

# Define the model
model = Prophet()

# Fit the model
model.fit(df)

# Generate and construct future time series
future = model.make_future_dataframe(periods=365)

# Generate predictive data
forecast = model.predict(future)

# Draw predictions
model.plot(forecast)
pyplot.show()

# Draw predictions for each component
model.plot_components(forecast)
pyplot.show()

运行输出如下:

  • 预测数据绘制图。黑色表示原始的时间序列离散点,深蓝色的线表示使用时间序列来拟合所得到的取值,而浅蓝色的线表示时间序列的一个置信区间,也就是所谓的合理的上界和下界。

Prophet-06

  • 各组件预测数据绘制图,分别为趋势图、周度季节性、月度季节性。

Prophet-07

算法实现

Prophet使用一个可分解的时间序列模型(Harvey & Peters1990),有三个主要模型组件:趋势、季节性和假日。核心算法如下:

$$
y(t) = g(t) + s(t) + h(t) + ε_{t}
$$

模型主体由三部分组成:

  • growth:增长趋势

  • seasonality:季节趋势

  • holidays:节假日对预测值的影响

算法内各模型含义:

  • $g(t)$ 表示趋势项,表示时间序列在非周期上面的变化趋势。

  • $s(t)$ 表示周期项(或称为季节项),一般来说是以周或者年为单位,表示周期内的波动情况。

  • $h(t)$ 表示节假日项,表示在当天是否存在节假日。

  • $ε_{t}$ 表示剩余项(或称为误差项),表示模型未预测到的波动,服从高斯分布。

算法优劣势

优势:不需要特征工程即可得到趋势、季节因素和节假日因素,轻量,效率高。

劣势:缺乏影响因子的自定义能力,只能做基础数据的预测,对复杂商业场景如产品销量预测,无法利用产品信息、销售地域、促销等因子进行精准预测。

算法参数

Prophet V1.1.6版本源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Prophet V1.1.6
class Prophet(object):
...
def __init__(
self,
growth='linear',
changepoints=None,
n_changepoints=25,
changepoint_range=0.8,
yearly_seasonality='auto',
weekly_seasonality='auto',
daily_seasonality='auto',
holidays=None,
seasonality_mode='additive',
seasonality_prior_scale=10.0,
holidays_prior_scale=10.0,
changepoint_prior_scale=0.05,
mcmc_samples=0,
interval_width=0.80,
uncertainty_samples=1000,
stan_backend=None,
scaling: str = 'absmax',
holidays_mode=None,
):
...

在 Prophet 中,用户一般可以设置以下四种参数:

  1. Capacity:在增量函数是逻辑回归函数的时候,需要设置的容量值。

  2. Change Points:可以通过 n_changepointschangepoint_range 来进行等距的变点设置,也可以通过人工设置的方式来指定时间序列的变点。

  3. 季节性和节假日:可以根据实际的业务需求来指定相应的节假日。

  4. 光滑参数:

    • changepoint_prior_scale 可以用来控制趋势的灵活度。

    • seasonality_prior_scale 用来控制季节项的灵活度。

    • holidays prior scale 用来控制节假日的灵活度。

如果不想设置的话,使用 Prophet 默认的参数即可。

参考文献

  1. GitHub - facebook/prophet: Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth.

  2. 官网

  3. 论文 - Forecasting at scale

  4. 官方文档:Quick Start

  5. Facebook 时间序列预测算法 Prophet 的研究

  6. 手把手教你用Python的Prophet库进行时间序列预测