Coggle数据科学 | Kaggle 知识点:时序模型 Prophet

本文来源公众号“Coggle数据科学”,仅用于学术分享,侵权删,干货满满。

原文链接:Kaggle 知识点:时序模型 Prophet

Prophet 算法

在时间序列中Prophet是Facebook开源的时间序列预测算法,可以有效处理节假日信息,并按周、月、年对时间序列数据的变化趋势进行拟合。

https://facebook.github.io/prophet/

# pip
python -m pip install prophet

# conda
conda install -c conda-forge prophet

截至2023年1月,这个Python包通过PyPI已被下载超过1600万次,每月下载量仍保持在100万次。

Prophet对具有强烈周期性特征的历史数据拟合效果很好,不仅可以处理时间序列存在一些异常值的情况,也可以处理部分缺失值的情形。

模型定义

Prophet使用了可分解的时间序列模型,模型包含三个主要组件:趋势、季节性和假日。它们通过以下方程组合在一起:

  • 是趋势函数,用于模拟时间序列值的非周期性变化

  • 表示周期性变化(例如每周和每年的季节性变化)

  • 表示假日效应,这些假日在一个或多个不规则时间安排的日子内发生

  • 误差项表示模型未能捕捉的变化

Prophet适用场景

  • 有至少几个月(最好是一年)的每小时、每天或每周观察的历史数据;

  • 有多种人类规模级别的较强的季节性趋势:每周的一些天和每年的一些时间;

  • 有事先知道的以不定期的间隔发生的重要节假日(比如国庆节);

  • 缺失的历史数据或较大的异常数据的数量在合理范围内;

  • 有历史趋势的变化(比如因为产品发布);

Prophet出发点

Prophet 的出发点是提供一种灵活的、可解释的回归模型,该模型可以直观地由具有时间序列知识的分析师调整。这种模型的设计考虑了以下几个关键点:

  1. 易于使用Prophet 旨在使没有时间序列方法训练的大量人员也能进行预测。

  2. 灵活性:它能够适应具有潜在特殊特征的多种预测问题。

  3. 自动化与人工干预相结合Prophet 通过自动化的方式进行预测,同时在模型性能不佳或需要人工干预时,允许分析师进行调整。

  4. 大规模评估:在创建大量预测时,需要有效、自动化的方法来评估和比较预测结果,并检测可能表现不佳的情况。

  5. 可解释性Prophet 的参数具有直观的解释,使得即使非专家也能根据领域知识进行模型配置。

Prophet 模型的设计允许它捕捉时间序列数据中的多种特征,如趋势、季节性、假日效应等,同时提供了一种机制来评估预测性能并根据需要进行调整。

Prophet使用案例

案例 1:拟合基础模型

import pandas as pd
from prophet import Prophet

# 需要有两列,ds 列和 y 列
df = pd.read_csv('https://mirror.coggle.club/prophet/example_wp_log_peyton_manning.csv')

# 定义模型,并训练
m = Prophet()
m.fit(df)

# 推理未来的日期,并镜像预测
future = m.make_future_dataframe(periods=365)
forecast = m.predict(future)
  • 模型预测结果

  • 模型分解结果

案例2:自动识别趋势变化

实际的时间序列经常会在轨迹上发生突然变化。默认情况下,Prophet 会自动检测这些变化点,并允许趋势适当调整。

Prophet 通过首先指定大量潜在的变化点来检测变化点,在这些点上允许速率变化。默认情况下,Prophet 指定了 25 个潜在的变化点,这些变化点均匀地分布在时间序列的前 80% 部分。

import pandas as pd
from prophet import Prophet

df = pd.read_csv('https://mirror.coggle.club/prophet/example_wp_log_peyton_manning.csv')
m = Prophet()

fig = m.plot(forecast)
a = add_changepoints_to_plot(fig.gca(), m, forecast)

案例 3:自定义节假日

如果你有假期或其他重复出现的事件需要建模,必须为它们创建一个数据框。数据框包含两列(holiday 和 ds),每行对应一次假期的发生。数据框必须包括假期的所有发生时间,既包括过去的(从历史数据开始)也包括未来的(预测范围内)。如果假期在未来不会重复,Prophet 会对其进行建模,但不会将其纳入预测中。

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,
})

special_days = pd.DataFrame({
    'holiday': ['Christmas', 'Christmas Eve', 'Black Friday'],
    'ds': ['2023-12-25', '2023-12-24', '2023-11-24'],
    'lower_window': [0, -1, 0],
    'upper_window': [0, 0, 1],
    'prior_scale': [10, 5, 3]
})

holidays = pd.concat((playoffs, superbowls, special_days))

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

案例4:多元回归

Prophet使用 add_regressor 方法或函数将额外的回归变量添加到模型的线性部分。需要在拟合和预测的数据框中都包含一个带有回归变量值的列。

添加的额外回归因子必须对于历史数据和未来日期都是已知的。这意味着它要么是已知未来值的变量(,要么是在其他地方已经预测过的变量。

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)

案例5:兼容缺失值

df = pd.read_csv('https://mirror.coggle.club/prophet/example_wp_log_R_outliers1.csv')
m = Prophet()
m.fit(df)

future = m.make_future_dataframe(periods=1096)
forecast = m.predict(future)
fig = m.plot(forecast)

处理异常值的最佳方法是将其从数据中移除。Prophet 可以很好地处理缺失数据。 Prophet 能够通过拟合趋势变化来处理历史数据中的异常值。不确定性模型可能会预期未来也会出现类似幅度的趋势变化,这可能导致预测区间变宽。

df.loc[(df['ds'] > '2010-01-01') & (df['ds'] < '2011-01-01'), 'y'] = None
model = Prophet().fit(df)
fig = model.plot(model.predict(future))

案例6:模型调参

import itertools
import numpy as np
import pandas as pd

param_grid = {  
    'changepoint_prior_scale': [0.001, 0.01, 0.1, 0.5],
    'seasonality_prior_scale': [0.01, 0.1, 1.0, 10.0],
}

# Generate all combinations of parameters
all_params = [dict(zip(param_grid.keys(), v)) for v in itertools.product(*param_grid.values())]
rmses = []  # Store the RMSEs for each params here

df = pd.read_csv('https://mirror.coggle.club/prophet/example_retail_sales.csv')
# Use cross validation to evaluate all parameters
for params in all_params:
    m = Prophet(**params).fit(df)  # Fit model with given params
    df_cv = cross_validation(m, cutoffs=cutoffs, horizon='30 days', parallel="processes")
    df_p = performance_metrics(df_cv, rolling_window=1)
    rmses.append(df_p['rmse'].values[0])

# Find the best parameters
tuning_results = pd.DataFrame(all_params)
tuning_results['rmse'] = rmses
print(tuning_results)

案例 7:模型微调

使用热启动技术可以在添加新数据时显著加快模型的拟合速度。热启动对于数据的小幅度更新(如例子中一天的数据)效果很好,但如果数据发生了较大变化(例如,添加了很多天的数据),热启动可能不如从头开始拟合模型来得有效。

def warm_start_params(m):
    res = {}
    for pname in ['k', 'm', 'sigma_obs']:
        if m.mcmc_samples == 0:
            res[pname] = m.params[pname][0][0]
        else:
            res[pname] = np.mean(m.params[pname])
    for pname in ['delta', 'beta']:
        if m.mcmc_samples == 0:
            res[pname] = m.params[pname][0]
        else:
            res[pname] = np.mean(m.params[pname], axis=0)
    return res

df = pd.read_csv('https://mirror.coggle.club/prophet/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

%timeit m2 = Prophet().fit(df)  # Adding the last day, fitting from scratch
%timeit m2 = Prophet().fit(df, init=warm_start_params(m1))  # Adding the last day, warm-starting from m1

Prophet参数含义与调参

参数含义

参数名称说明
growth趋势类型,可选值有 'linear', 'logistic', 或 'flat'。
changepoints变化点日期列表。如果未指定,将自动选择潜在变化点。
n_changepoints潜在变化点的数量。如果未指定 changepoints,则在历史数据的前 changepoint_range 比例内均匀选择
changepoint_range用于估计趋势变化点的历史比例。
yearly_seasonality是否拟合年度季节性。可以是 'auto', True, False,或傅里叶项的数量。
weekly_seasonality是否拟合每周季节性。可以是 'auto', True, False,或傅里叶项的数量。
daily_seasonality是否拟合每日季节性。可以是 'auto', True, False,或傅里叶项的数量。
holidays包含假期数据的 pd.DataFrame
seasonality_mode季节性模式,可选值为 'additive'(加性)或 'multiplicative'(乘性)。
seasonality_prior_scale调节季节性模型强度的参数。值越大,模型可以拟合的季节性波动越大;值越小,季节性波动幅度越小。
holidays_prior_scale调节假期组件模型强度的参数,除非在假期输入中被覆盖。
changepoint_prior_scale调节自动变化点选择灵活性的参数。值越大,允许的变化点越多;值越小,允许的变化点越少。
interval_width预测的不确定区间的宽度。
uncertainty_samples用于估计不确定区间的模拟抽样数量。将此值设置为 0 或 False 将禁用不确定性估计并加快计算速度。

超参数调优

主要可调参数
  1. changepoint_prior_scale

    • 作用:确定趋势的灵活性,特别是趋势在变化点的变化幅度。

    • 默认值:0.05

    • 调优范围:[0.001, 0.5]

    • 说明:值越大,趋势变化越灵活,过大可能导致过拟合,过小可能导致欠拟合。

  2. seasonality_prior_scale

    • 作用:控制季节性的灵活性。

    • 默认值:10

    • 调优范围:[0.01, 10]

    • 说明:值越大,季节性变化越大,值越小,季节性幅度越小。

  3. holidays_prior_scale

    • 作用:控制假期效应的灵活性。

    • 默认值:10

    • 调优范围:[0.01, 10]

    • 说明:与季节性灵活性类似,调整假期效应的幅度。

  4. seasonality_mode

    • 作用:季节性的模式,可以选择加性('additive')或乘性('multiplicative')。

    • 默认值:'additive'

    • 说明:商业时间序列中,季节性变化随时间序列幅度变化的情况适合乘性模式。

可能需要调优的参数
  1. changepoint_range

    • 作用:确定趋势变化的历史比例。

    • 默认值:0.8(80% 的历史数据)

    • 调优范围:[0.8, 0.95]

    • 说明:增加该参数可能有助于避免在时间序列末尾过拟合。

一般不需要调优的参数
  1. growth:选择增长模式('linear' 或 'logistic')。

  2. changepoints:手动指定变化点位置。

  3. n_changepoints:自动放置的变化点数量,默认 25。

  4. yearly_seasonality:是否启用年度季节性(默认 'auto')。

  5. weekly_seasonality:是否启用每周季节性(默认 'auto')。

  6. daily_seasonality:是否启用每日季节性(默认 'auto')。

  7. holidays:传入指定假期的数据框。

  8. mcmc_samples:是否使用 MCMC,取决于时间序列的长度和参数不确定性的重要性。

  9. interval_width:指定预测区间的宽度(默认 0.8,对应 80% 置信区间)。

  10. uncertainty_samples:用于计算不确定性区间的样本数量,默认 1000。

THE END !

文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。

  • 26
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值