【Prophet快速入门】

概念

Prophet是Facebook开源的时间序列预测框架,它特别适合处理日级别(‌或以上频率)‌的时间序列数据,‌设计考虑了业务场景中的时间序列特点,‌如季节性变化、‌假日效应和趋势变化。
Prophet能够自动检测数据中的趋势和季节性,‌并将它们组合在一起以获得预测值。‌它基于加法模型,‌将时间序列分解成趋势项、‌周期项、‌节假日项/特殊事件影响项以及残差项的组合,‌从而实现对时间序列的有效预测。此外,‌Prophet还提供了强大的可视化分析辅助工具,‌便于分析趋势、‌不同周期、‌不同节假日/特殊事件各自的贡献,‌使得模型解释性较强。

模型原理

Prophet模型既可以使用加法模型,也可以使用乘法模型

加法模型

y(t)=g(t)+s(s)+h(t)+e(t)
g(t)表示时间序列的趋势,用来拟合非周期性变化的。
s(t)用来表示时间序列的季节性。
h(t)表示时间序列的假期效应,节日等特殊原因等造成的变化。
e(t)为误差项,用他来表示随机无法预测的波动。

乘法模型

在Prophet模型的乘法模型中,时间序列的预测值是趋势、季节性和假期效应的乘积
y(t)=g(t)∗s(t)∗h(t)∗e(t)
加法模型和乘法模型都有各自的优缺点,适用于不同类型的时间序列。通常情况下,加法模型适用于时间序列的趋势和季节性与数据规模无关的情况,例如气温和降雨量;而乘法模型适用于时间序列的趋势和季节性与数据规模相关的情况,例如商品销售量和股票价格。在使用Prophet模型进行时间序列预测时,需要根据具体情况选择合适的模型。

快速开始

官网文档:

https://facebook.github.io/prophet/docs/quick_start.html#python-api

github:

https://github.com/facebook/prophet

安装

#python windows安装,pip版本太低可能会安装失败,升级即可(pip install --upgrade pip )。
#prophet自v1.1版本,需要在 Python 3.7及以上支持。
python -m  pip install prophet

Prophet的输入始终是一个包含两列的数据帧:ds和y。
ds(日期戳)列应为Pandas所期望的格式,理想情况下,YYYY-MM-DD表示日期,YYYY-MM-DD HH:MM:SS表示时间戳。
y列必须是数字,并且表示我们希望预测的度量。

import pandas as pd
from prophet import Prophet
from prophet.plot import add_changepoints_to_plot
import numpy as np

# 1、读取数据源df(excel数据) 
df = pd.read_csv('https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv')
#可打印数据源数据
df.head()
#如果数据源中不含ds, y这两列,需要转换,修改列名
#live_df = df[['recordtime','live']].copy()
#live_df = live_df.rename(columns={'recordtime':'ds','live':'y'})

# 2、建立模型,通过实例化一个新的Prophet对象来拟合模型。将任何预测程序的设置传递给构造函数。
#Prophet 参数:
#growth:模型的趋势函数,有linear(分段线性函数)和logistic两种,默认为linear函数
#changepoint_prior_scale:设定自动突变点选择的灵活性,值越大越容易出现changepoint
pm=Prophet()
# 3、训练模型,调用其fit方法并传入历史数据框。拟合应该需要1-5秒的时间
pm.fit(live_df)
#4、预测。在一个包含列ds的dataframe上进行预测,该列包含需要进行预测的日期。
#调用make_future_dataframe()来获得扩展到未来指定时间,根据freq以及periods,创建未来日期的数据帧。
#freq可以为'30s', 'T'(每分钟),默认为'D'(每天)
#(例如本文中指定48个时间点周期,间隔30分钟)的dataframe。默认情况下,它还将包括历史数据中的日期(include_history=true),因此我们将看到模型的拟合情况。
#future = model.make_future_dataframe( periods=48, freq='30min', include_history=False) 
#简写成只指定30个周期点,即预测30天
future = pm.make_future_dataframe(periods=30)
#查看预测数据详情
future.tail()
#5、预测未来的数据。predict方法将为未来的每一行分配一个预测值,并将其命名为yhat。如果您传入历史日期,它将提供样本内拟合。
pm_forecast = pm.predict(future)
#yhat:表示模型对未来值的预测结果。它是根据历史数据和模型的参数计算得出的对未来趋势和季节性的估计。'yhat’列提供了每个时间点的预测值。
#yhat_lower: 是预测值的下限,表示在给定置信水平下的最低预测值。
#yhat_upper: 是预测值的上限,表示在给定置信水平下的最高预测值。
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()

# 6、可视化。绘制预测图
fig1 = pm.plot(pm_forecast)
#可视化预测组件。默认情况下,看到的是时间序列的趋势、年度季节性和每周季节性。如果算上节假日,也会在这里看到
fig2 = pm.plot_components(pm_forecast)

pm.plot(pm_forecast)结果图解释:
黑点为历史数据
蓝线为拟合曲线
蓝色范围为预测区间

1、饱和预测配置

rom prophet import Prophet
from prophet.plot import add_changepoints_to_plot
import numpy as np

# 1、读取数据源df(excel数据) 
df = pd.read_csv('https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv')
# 设置饱和上限
df['cap'] = 20
# 设置饱和下限
df['floor'] = 10
# 初始化并拟合模型,指定增长为逻辑增长,这是必要的步骤以使用饱和趋势
pm = Prophet(growth='logistic')
# 3、训练模型,调用其fit方法并传入历史数据框。拟合应该需要1-5秒的时间
pm.fit(df)
#4、预测。# 创建未来日期的数据帧,需要包括饱和上限
future = pm.make_future_dataframe(periods=30)
future['cap'] = 20
#5、预测未来的数据
pm_forecast = pm.predict(future)

forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
# 6、可视化。绘制预测图
fig1 = pm.plot(pm_forecast)
#可视化预测组件。默认情况下,看到的是时间序列的趋势、年度季节性和每周季节性。如果算上节假日,也会在这里看到
fig2 = pm.plot_components(pm_forecast)

2、假期配置

自定义假期
holiday_event = pd.DataFrame({
    'holiday': 'holiday_event',
    'ds': pd.to_datetime(['2015-04-03', '2015-04-04', '2015-04-05',
                          '2016-04-23', '2016-04-24', '2016-04-25']),
    'lower_window': -1,  # 节假日前一天的影响
    'upper_window': 1,   # 节假日后一天的影响
})

holiday_event2 = pd.DataFrame({
  'holiday': 'holiday_event2',
  'ds': pd.to_datetime(['2015-04-07', '2016-04-07', '2016-04-22']),
  'lower_window': 0,  # 节假日前0天的影响, 即不提前
  'upper_window': 1,  # 节假日后一天的影响
})
holidays = pd.concat((holiday_event, holiday_event2))

# 初始化并配置Prophet模型
# holidays_prior_scale参数是影响了模型对于节假日(包括特殊事件)所假设的重要性程度,可以被视为节假日组件的灵活性
m = Prophet(holidays=holidays, holidays_prior_scale=10.0)
m.fit(df).predict(future)
国家假期

可以使用add_country_holidays方法(Python)来使用一个内置的国家特定假日集合。指定国家的名称,然后除了通过上面描述的holidays参数指定的任何假日之外,该国家的主要假日将被包括在内。
每个国家的假期由Python中的holidays包提供。
可用的国家列表和使用的国家名称可在页面上找到:https://github.com/vacanza/python-holidays/
在Python中,大多数假期都是确定性计算的,因此可以用于任何日期范围;如果日期超出该国支持的范围,则会发出警告。如果需要更大的日期范围,可以使用此脚本将该文件替换为不同的日期范围:https://github.com/facebook/prophet/blob/main/python/scripts/generate_holidays_file.py。

m = Prophet(holidays=holidays)
#CN表示中国
m.add_country_holidays(country_name='CN')
m.fit(df)
#可以通过查看模型的train_holiday_names (Python)属性来查看包含哪些假期:
m.train_holiday_names

3、季节配置

内置季节性的配置

rophet可以自动检测并适配年度(yearly)、周度(weekly)和日度(daily)季节性,默认情况下都是’auto’,如果已经确认想让模型拟合哪个维度就可以直接设置为True,关闭就是False。

m = Prophet(yearly_seasonality=True,
            weekly_seasonality='auto',
            daily_seasonality=False,
            seasonality_prior_scale=10.0)
m.fit(df)

除了设置为True以外,还可以指定用傅里叶级数。

#yearly_seasonality=10 表示模型会使用10个傅立叶级数来拟合年度季节性。
#傅立叶级数越多,季节性曲线越灵活,可以拟合更复杂的季节性模式
m = Prophet(yearly_seasonality=10)
m.fit(df)
自定义季节

add_seasonality一次只能添加一个季节性配置,name 参数是季节性的名称,period 参数指周期的长度(以天为单位),fourier_order 参数指傅立叶级数的数量。

m = Prophet()
m.add_seasonality(name='monthly', period=30.5, fourier_order=5)  # 添加月度季节性
m.add_seasonality(name='quarterly', period=91.25, fourier_order=7)  # 添加季度季节性
乘法季节模型
from prophet import Prophet

# 初始化Prophet模型,使用加性季节性模式
m_additive = Prophet(seasonality_mode='additive')

# 初始化Prophet模型,使用乘性季节性模式
m_multiplicative = Prophet(seasonality_mode='multiplicative')

4、不确定性区间配置

趋势的不确定性

通过interval_width参数,默认值是80%,表示不确定性区间的宽度,如果该值变大,表示不确定性越大

forecast = Prophet(interval_width=0.95).fit(df).predict(future)

季节的不确定性

默认情况下,Prophet只会返回趋势和误差项中的不确定性。为了获得季节性的不确定性,可以使用参数mcmc.samples(默认为0)完成。

m = Prophet(mcmc_samples=300)
forecast = m.fit(df, show_progress=False).predict(future)

异常

趋势预测可能存在不确定性区间太宽的可能性。Prophet能够处理历史中的异常值,但只能通过将其与趋势变化相匹配来处理。然后,不确定性模型预计未来的趋势变化幅度相似。
处理异常值的最佳方法是删除它们——Prophet对缺失数据没有问题。如果在历史上将它们的值设置为NA,但将日期留在未来,那么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))
  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值