编辑
目录
假期和特殊事件建模(Modeling Holidays and Special Events)
内置国家假日(Built-in Country Holidays)
季节性的傅里叶级数(Fourier Order for Seasonalities)
指定自定义季节(Specifying Custom Seasonalities)
取决于其他因素的季节性(Seasonalities that depend on other factors)
假日和季节性的先验尺度(Prior scale for holidays and seasonality)
额外的解释变量dditional regressors)
如果您有节假日或其他需要建模的重复事件,则必须为它们创建一个数据框架。它有两列(holiday和ds)和一行,分别表示假日的每一次出现。它必须包括节日发生的所有事件,包括过去的(追溯到历史数据)和未来的(直到做出预测)。如果它们在未来不会重复,先知将对它们进行建模,然后不将它们包括在预测中。
您还可以包含列lower_window和upper_window,它们将假日扩展到日期前后的[lower_window, upper_window]天。例如,如果你想在圣诞节之外还包括平安夜,你应该包括lower_window=-1,upper_window=0。如果你想在感恩节之外使用黑色星期五,你应该包括lower_window=0,upper_window=1。您还可以包含一个列prior_scale来为每个假日分别设置优先比例,如下所述。
在这里,我们创建了一个数据框架,其中包括佩顿·曼宁所有季后赛出场的日期:
# 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))
上面我们包括了超级碗的日子,包括季后赛和超级碗比赛。这意味着超级碗效应将成为季后赛效应之上的额外附加奖金。
一旦创建了表格,假日影响就会通过假日参数传入预测中。下面我们用《快速入门》Quick Start | Prophet中的佩顿·曼宁数据来做:
# Python
m = Prophet(holidays=holidays)
forecast = m.fit(df).predict(future)
假期的影响可以在预测数据框架中看到:
# Python
forecast[(forecast['playoff'] + forecast['superbowl']).abs() > 0][
['ds', 'playoff', 'superbowl']][-10:]
节日的影响也会在成分图中体现出来,我们可以看到季后赛出现的日子有一个峰值,超级碗出现的峰值尤其大:
# Python
fig = m.plot_components(forecast)
可以使用plot_forecast_component函数(从prophet导入)绘制单个假日。例如plot_forecast_component(m, forecast, 'superbowl')来绘制超级碗假日组件。
你可以使用add_country_holidays方法(Python)或函数(R)使用内置的特定于国家的假日集合。指定了国家的名称,然后该国家的主要假日将包括在通过上述假日参数指定的任何假日之外:
# Python
m = Prophet(holidays=holidays)
m.add_country_holidays(country_name='US')
m.fit(df)
你可以通过查看模型的train_holiday_names (Python)或train.holiday.names (R)属性来查看包含哪些假日:
# Python
m.train_holiday_names
0 playoff
1 superbowl
2 New Year's Day
3 Martin Luther King Jr. Day
4 Washington's Birthday
5 Memorial Day
6 Independence Day
7 Labor Day
8 Columbus Day
9 Veterans Day
10 Thanksgiving
11 Christmas Day
12 Christmas Day (Observed)
13 Veterans Day (Observed)
14 Independence Day (Observed)
15 New Year's Day (Observed)
dtype: object
每个国家的假日由Python中的假日包提供。可用的国家列表和要使用的国家名称可以在他们的页面上找到:https://github.com/dr-prodigy/python-holidays。除了这些国家,Prophet还包括巴西(BR)、印度尼西亚(ID)、印度(In)、马来西亚(MY)、越南(VN)、泰国(TH)、菲律宾(PH)、巴基斯坦(PK)、孟加拉国(BD)、埃及(EG)、中国(CN)以及俄罗斯(RU)、韩国(KR)、白俄罗斯(BY)和阿拉伯联合酋长国(AE)的假期。
在Python中,大多数假期都是确定性计算的,因此适用于任何日期范围;如果日期超出该国支持的范围,将发出警告。在R中,假日日期从1995年计算到2044年,并以data-raw/generated_holidays.csv的形式存储在包中。如果需要更大的日期范围,则可以使用此脚本将该文件替换为不同的日期范围:https://github.com/facebook/prophet/blob/main/python/scripts/generate_holidays_file.py。
如上所述,国家一级的假期将显示在组件图中:
# Python
forecast = m.predict(future)
fig = m.plot_components(forecast)
季节性是用部分傅里叶和估计的。详细信息请参阅论文,维基百科上的这张图说明了傅里叶部分和如何近似任意周期信号。部分和中的项数(顺序)是一个参数,它决定了季节性变化的快慢。为了说明这一点,请考虑《快速入门》中的Peyton Manning数据。年季节性的默认傅里叶顺序是10,这产生了这样的拟合:
# Python
from prophet.plot import plot_yearly
m = Prophet().fit(df)
a = plot_yearly(m)
默认值通常是合适的,但当季节性需要适应更高频率的变化时,可以增加默认值,而且通常不太平滑。在实例化模型时,可以为每个内置季节性指定傅里叶顺序,这里增加到20:
# Python
from prophet.plot import plot_yearly
m = Prophet(yearly_seasonality=20).fit(df)
a = plot_yearly(m)
增加傅里叶项的数量可以使季节性更适合变化更快的周期,但也可能导致过拟合:N个傅里叶项对应于用于建模周期的2N个变量
如果时间序列超过两个周期,Prophet将默认适合每周和每年的季节性。它还将适合每日时间序列的每日季节性。您可以使用add_seasonality方法(Python)或函数(R)添加其他季节性数据(每月、每季度、每小时)。
这个函数的输入是一个名称,以天为单位的季节周期,以及季节的傅里叶顺序。作为参考,默认情况下Prophet使用3的傅里叶顺序表示周季节性,10的傅里叶顺序表示年季节性。add_seasonality的一个可选输入是该季节成分的先验尺度——这将在下面讨论。
例如,这里我们拟合了《快速入门》中的Peyton Manning数据,但将周季节性替换为月季节性。每月季节性将出现在成分图中:
# Python
m = Prophet(weekly_seasonality=False)
m.add_seasonality(name='monthly', period=30.5, fourier_order=5)
forecast = m.fit(df).predict(future)
fig = m.plot_components(forecast)
在某些情况下,季节性可能取决于其他因素,例如夏季的每周季节性模式与一年中的其他时间不同,或者周末与工作日的每日季节性模式不同。这些类型的季节性可以用条件季节性来建模。
看看《快速入门》中的Peyton Manning的例子。默认的每周季节性假设每周季节性的模式在全年都是相同的,但我们预计每周季节性的模式在赛季(每个周日都有比赛)和淡季是不同的。我们可以使用条件季节性来构造单独的季节性季节性。
首先,我们在数据框架中添加一个布尔列,表示每个日期是在旺季还是淡季:
# Python
def is_nfl_season(ds):
date = pd.to_datetime(ds)
return (date.month > 8 or date.month < 2)
df['on_season'] = df['ds'].apply(is_nfl_season)
df['off_season'] = ~df['ds'].apply(is_nfl_season)
然后,我们禁用内置的每周季节性,并将其替换为两个每周季节性,并将这些列指定为条件。这意味着季节性将只应用于condition_name列为True的日期。我们还必须将该列添加到我们正在进行预测的未来数据框架中。
# Python
m = Prophet(weekly_seasonality=False)
m.add_seasonality(name='weekly_on_season', period=7, fourier_order=3, condition_name='on_season')
m.add_seasonality(name='weekly_off_season', period=7, fourier_order=3, condition_name='off_season')
future['on_season'] = future['ds'].apply(is_nfl_season)
future['off_season'] = ~future['ds'].apply(is_nfl_season)
forecast = m.fit(df).predict(future)
fig = m.plot_components(forecast)
这两个季节现在都显示在上面的成分图中。我们可以看到,在每个周日都有比赛的赛季期间,周日和周一的数据大幅增长,而在休赛期则完全没有。
如果您发现节假日过度拟合,您可以使用参数假日s_prior_scale调整它们的先验比例来平滑它们。默认情况下,这个参数是10,它提供了很少的正则化。降低这个参数会降低假日效应:
# 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:]
与以前相比,假日效应的程度有所降低,特别是对于超级碗来说,它的观测量最少。有一个参数seasonality_prior_scale,它类似地调整季节性模型拟合数据的程度。
通过在节假日数据框架中包含一个列prior_scale,可以为单个节假日单独设置优先比例。个体季节性的先验量表可以作为参数传递给add_seasonality。例如,仅每周季节性的先验尺度可以使用以下方法设置:
# Python
m = Prophet()
m.add_seasonality(
name='weekly', period=7, fourier_order=3, prior_scale=0.1)
可以使用add_regressor方法或函数向模型的线性部分添加额外的回归量。带有回归值的列需要同时出现在拟合和预测数据框架中。例如,我们可以在NFL赛季的周日添加一个额外的效果。在分量图中,这种效应将在“extra_regressors”图中显示:
# 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)
fig = m.plot_components(forecast)
NFL周日也可以使用上面描述的“假日”界面处理,通过创建过去和未来NFL周日的列表。add_regressor函数为定义额外的线性回归函数提供了更通用的接口,特别是不要求回归函数是二进制指示符。另一个时间序列可以用作回归函数,尽管它的未来值必须是已知的。
这本笔记本展示了一个在自行车使用预测中使用天气因素作为额外回归量的例子,并提供了一个很好的说明如何将其他时间序列作为额外回归量。
add_regressor函数有可选参数,用于指定优先比例(默认使用holiday优先比例)以及回归器是否标准化——请参阅Python中的docstring with help(Prophet.add_regressor)和r中的?add_regressor。注意,回归器必须在模型拟合之前添加。如果回归量在整个历史中是恒定的,先知也会提出一个错误,因为没有什么可以从它中拟合。
额外的回归量必须同时知道历史和未来的日期。因此,它必须要么是已知的未来值(例如nfl_sunday),要么是在其他地方单独预测的值。上面链接的笔记本中使用的天气回归器是一个额外回归器的很好的例子,它可以用于预测未来的值。也可以使用另一个时间序列作为回归量,该时间序列模型已经预测过,例如Prophet。例如,如果r(t)被包括为y(t)的回归量,则可以使用Prophet来预测r(t),然后在预测y(t)时,该预测可以作为未来的值插入。关于这种方法需要注意的是:除非r(t)比y(t)更容易预测,否则这种方法可能没有用处。这是因为r(t)的预测误差会导致y(t)的预测误差。这种方法很有用的一种情况是在分层时间序列中,其中有顶级预测,具有更高的信噪比,因此更容易预测。它的预测可以包含在每个较低级别系列的预测中。
额外的回归量被放入模型的线性分量中,因此底层模型是时间序列依赖于额外的回归量作为加性或乘性因子(关于乘性,请参阅下一节)。
附加回归系数(Coefficients of additional regressors)
要提取额外回归函数的beta系数,请使用效用函数regressor_coefficients (from prophet。实用程序在Python中导入regressor_coefficients, prophet::regressor_coefficients in R)在拟合的模型上。每个回归系数的估计beta系数大致表示回归值单位增加的预测值的增加(注意,返回的系数总是在原始数据的尺度上)。如果指定了mcmc_samples,还将返回每个系数的可信区间,这可以帮助确定每个回归量是否具有“统计显著性”。