prophet中文翻译(五)季节性、节假日效应和回归变量

季节性、节假日效应和回归变量

节假日和特殊事件建模

如果您有节假日或其他周期性事件需要建模,您需要创建一个包含这些事件的数据框。该数据框包含两列(holiday和ds),每个事件的发生都有一行数据。数据框中需要包括所有事件的发生日期,既包括历史数据范围内的事件,也包括未来预测的时间范围内的事件。如果事件在未来不会重复发生,Prophet会对其进行建模,但不会包括在预测结果中。
(译者注:例如,假设您要建模每年的圣诞节。您的数据框将包含holiday列和ds列,其中holiday列中的值为"Christmas",ds列中的值为每年圣诞节的日期。数据框中将有过去和未来所有圣诞节的日期。Prophet会根据这些日期来建模圣诞节对时间序列的影响,并将其考虑在预测中。
通过提供节假日和周期性事件的数据框,Prophet可以更准确地捕捉到这些事件对时间序列的影响,从而提高预测的准确性。)

您还可以在数据框中包含lower_window和upper_window列,用于将节假日扩展到日期周围的[lower_window, upper_window]天范围内。例如,如果您想在圣诞节之前包括平安夜,您可以设置lower_window=-1,upper_window=0。如果您想在感恩节之外使用黑色星期五,您可以设置lower_window=0,upper_window=1。您还可以增加prior_scale列,以单独设置每个节假日的先验尺度,如下所述。

在这里,我们创建一个包含所有 Peyton Manning 季后赛出场日期的数据框:

# 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))

在上面的示例中,我们将超级碗(Super Bowl)的日期既包含在季后赛数据中,又作为独立的超级碗比赛数据。这意味着超级碗效应将作为附加的影响因子添加到季后赛效应之上。
这种方法可以适用于您希望将特殊事件作为额外效应考虑在内的情况。您可以根据需要在节假日数据框中添加其他相关事件,并为每个事件指定适当的时间窗口和优先刻度。这样,模型将能够捕捉到不同事件的影响,并对其进行合适的建模。

创建完数据表后,可以通过将节假日效应作为参数传递给holidays来将其包含在预测中。以下是使用Peyton Manning数据的示例: 数据:

# Python
m = Prophet(holidays=holidays)
forecast = m.fit(df).predict(future)

可以在forecast数据框中看到节假日效应:

# Python
forecast[(forecast['playoff'] + forecast['superbowl']).abs() > 0][
        ['ds', 'playoff', 'superbowl']][-10:]
ds playoff superbowl
2190 2014-02-02 1.223965 1.201517
2191 2014-02-03 1.901742 1.460471
2532 2015-01-11 1.223965 0.000000
2533 2015-01-12 1.901742 0.000000
2901 2016-01-17 1.223965 0.000000
2902 2016-01-18 1.901742 0.000000
2908 2016-01-24 1.223965 0.000000
2909 2016-01-25 1.901742 0.000000
2922 2016-02-07 1.223965 1.201517
2923 2016-02-08 1.901742 1.460471

节假日效应也可以在图中看出来,我们可以看到在季后赛出现的前后几天有一个峰值,而超级碗的峰值尤为显著:

# Python
fig = m.plot_components(forecast)

image

可以使用plot_forecast_component函数(从Python中导入的prophet.plot)绘制单个节假日效应,例如使用plot_forecast_component(m, forecast, 'superbowl')只绘制超级碗节假日效应。

内置的国家节假日

您可以使用add_country_holidays方法(Python)来使用内置的国家特定节假日。指定国家的名称,然后该国家的主要节假日将被包括在内,除此之外,还可以通过上述holidays参数指定其他节假日:

# Python
m = Prophet(holidays=holidays)
m.add_country_holidays(country_name='US')
m.fit(df)

您可以通过查看模型的train_holiday_names属性(Python)来查看包含的节假日:

# 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中的holidays包提供的。可以在其页面上找到可用国家的列表和要使用的国家名称:https://github.com/dr-prodigy/python-holidays 。 除了这些国家,Prophet还包括以下国家的节假日:巴西(BR)、印度尼西亚(ID)、印度(IN)、马来西亚(MY)、越南(VN)、泰国(TH)、菲律宾(PH)、巴基斯坦(PK)、孟加拉国(BD)、埃及(EG)、中国(CN)、俄罗斯(RU)、韩国(KR)、白俄罗斯(BY)和阿拉伯联合酋长国(AE)。

在Python中,大多数节假日是确定性计算的,因此可以适用于任何日期范围;如果日期超出了该国家支持的范围,将会发出警告。

与前面类似,国家级的节假日也会在图中显示其影响效果:

# Python
forecast = m.predict(future)
fig = m.plot_components(forecast)

image

季节性的傅里叶阶数

季节性使用部分傅里叶级数进行估计。完整的细节请参阅论文,并参考维基百科 上的图示,图中展示了部分傅里叶级数如何近似表示任意周期信号。部分和中的项数(阶数)是一个参数,决定了季节性的变化速度。为了说明这一点,以快速入门中的 Peyton Manning 数据为例,默认的年度季节性的傅里叶阶数为 10,产生了以下拟合结果:

# Python
from prophet.plot import plot_yearly
m = Prophet().fit(df)
a = plot_yearly(m)

image

默认值通常是合适的,但在需要适应更高频率变化和更不平滑的季节性时,可以增加傅里叶阶数。可以在实例化模型时为每个内置季节性指定傅里叶阶数,这里将其增加为 20:

# Python
from prophet.plot import plot_yearly
m = Prophet(yearly_seasonality=20).fit(df)
a = plot_yearly(m)

image

增加傅里叶项的数量可以使季节性适应更快速变化的周期,但也可能导致过拟合:N个傅里叶项对应于用于建模周期的2N个变量。

指定自定义季节性

Prophet默认会自动适应每周和每年的季节性,如果时间序列超过两个周期。对于每日时间序列,它还会适应每日季节性。您可以使用add_seasonality方法(Python)添加其他季节性(例如每月、每季、每小时)。

该函数的输入包括名称、季节性的周期(以天为单位)和季节性的傅里叶级数。默认情况下,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)

image

季节性依赖的其他因素

在某些情况下,季节性可能依赖于其他因素,比如夏季与其他季节不同的每周季节模式,或者周末与工作日不同的每日季节模式。可以使用条件季节性来建模这些类型的季节性。

在上述的 Peyton Manning 的例子中,Prophet 的默认每周季节性假设每周的季节性模式在整年都是相同的。但我们可以预期在赛季期(每个星期日都有比赛)和休赛期每周的季节性模式会有所不同。我们可以使用条件季节性来构建独立的赛季期和休赛期的每周季节性。
首先,我们在数据框中添加一个布尔列,用于指示每个日期是赛季期间还是休赛期间:

# 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的日期。我们还必须将该列添加到用于进行预测的future数据框中。

# 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)

image

在上面的组件图中,我们可以看到这两个季节性。在赛季期间,即每个星期日都有比赛的时候,我们可以看到在星期日和星期一有明显的增加,而在休赛期间则完全没有这种变化。这说明我们成功地使用条件性季节性来建模赛季期间和休赛期间的不同季节模式。

节假日和季节性的先验尺度

如果发现假期效应过度拟合,可以通过调整参数 holidays_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:]
ds playoff superbowl
2190 2014-02-02 1.206086 0.964914
2191 2014-02-03 1.852077 0.992634
2532 2015-01-11 1.206086 0.000000
2533 2015-01-12 1.852077 0.000000
2901 2016-01-17 1.206086 0.000000
2902 2016-01-18 1.852077 0.000000
2908 2016-01-24 1.206086 0.000000
2909 2016-01-25 1.852077 0.000000
2922 2016-02-07 1.206086 0.964914
2923 2016-02-08 1.852077 0.992634

与之前相比,假期效应的幅度已经降低,特别是对于超级碗的影响,因为超级碗的观测数据较少。类似地,还有一个参数 seasonality_prior_scale,它调整了季节性模型对数据拟合的程度。

可以通过在假期数据框中包含一个 prior_scale 列来单独设置每个假期的先验规模。对于单个季节性,可以将先验规模作为参数传递给 add_seasonality。例如,可以使用以下方式设置仅适用于周季节性的先验规模:
通过将 prior_scale 的值设置为适当的大小,可以调整特定假期或季节性对模型的影响程度。较小的值会减小对应假期或季节性的影响,使其更加平滑,而较大的值则会增加其影响,使其更加突出。根据需要,可以针对每个假期或季节性调整先验规模,以得到更符合实际情况的模型和预测结果。

# 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)

image

NFL周末也可以使用上述介绍的 "holidays" 接口来处理,通过创建过去和未来的NFL周末的列表。add_regressor函数提供了一个更通用的接口来定义额外的线性回归变量,特别是不需要回归变量是二进制指标。可以使用另一个时间序列作为回归变量,尽管需要知道它的未来值。这使得可以将其他相关时间序列的信息引入模型中,以帮助解释和预测目标时间序列的变化。

这个notebook展示了在自行车使用预测中使用天气因素作为额外的回归变量的示例,并且提供了一个很好的说明,展示了如何将其他时间序列包含为额外的回归变量。该示例演示了如何将天气数据与自行车使用数据进行关联,以探索它们之间的相关性,并在预测模型中利用这些信息来提高预测准确性。

add_regressor函数有一些可选参数,用于指定先验比例(默认使用假日先验比例)以及回归变量是否被标准化。你可以在Python中使用help(Prophet.add_regressor)来查看文档字符串。需要注意的是,在模型拟合之前必须添加回归变量。如果回归变量在历史数据中保持不变,Prophet将引发错误,因为它无法从中进行拟合。

额外的回归变量必须对历史数据和未来日期都是已知的。因此,它必须是具有已知未来值的变量(如nfl_sunday),或者是在其他地方进行了独立预测的变量。上面链接的笔记本中使用的天气回归变量就是一个很好的例子,它具有可以用于未来值的预测结果。你还可以将其他已经使用时间序列模型(如Prophet)进行预测的时间序列作为回归变量。例如,如果将r(t)作为y(t)的回归变量,在预测y(t)时可以使用Prophet对r(t)进行预测,然后将该预测结果作为预测y(t)时的未来值。需要注意的是,这种方法可能只在r(t)相对于y(t)更容易预测时才有用。这是因为对r(t)的预测误差会导致对y(t)的预测误差。这种方法在层级时间序列中可以很有用,其中存在一个具有更高信噪比且因此更容易预测的顶层预测,它的预测可以包含在每个较低层级系列的预测中。

额外的回归变量被放置在模型的线性部分中,因此基本模型是时间序列依赖于额外回归变量,可以是加法或乘法关系(关于乘性的内容请参见下一节)。

其他回归因子影响

要使用额外回归器的 beta 系数,可以使用 regressor_coefficients 工具函数(在 Python 中为 from prophet.utilities import regressor_coefficients)应用于已拟合的模型。每个回归器的估计 beta 系数大致表示在回归器值增加一个单位时预测值的增加量(请注意,返回的系数始终处于原始数据的比例)。如果指定了 mcmc_samples,还会返回每个系数的可信区间,这有助于确定每个回归器是否具有“统计显著性”。

posted @ 2023-05-17 11:30  明天OoO你好  阅读(681)  评论(0编辑  收藏  举报