哈喽,我是小白~
最近,咱们分享了很多关于时间序列的内容,今儿想和大家详细的聊其中一个算法模型:
时间序列分析方法:Prophet
简单来说,Prophet 是由 Facebook(现在的 Meta)开发的一种时间序列预测工具,它非常适合初学者使用,尤其是用来处理具有周期性、趋势性数据的任务,比如预测销售额、网站流量等。Prophet 之所以受欢迎,主要是因为它相对简单易用,而且能够很好地处理常见的时间序列问题,比如节假日影响、周期性波动等。
下面,咱们先简单介绍其核心思想和简单的案例,让大家有一个整体的认识~
1. Prophet 的核心思想
Prophet 的核心模型可以理解为以下三个部分的加和:
趋势(trend):数据长期的变化趋势,比如一个网站的流量随着时间推移逐步上升。 季节性(seasonality):数据周期性的波动,比如流量每年圣诞节前后会大幅增加。 假日影响(holidays):节假日对数据的影响,比如某些特定假期对消费数据的短期刺激作用。
Prophet 的基本公式如下:
:趋势模型 :季节性模型 :假日影响 :误差项
2. 简单案例:预测冰淇淋店销售额
假设我们有一家冰淇淋店,它每年夏天的销售额会大幅增加,而冬天的销售额会下降。我们希望用 Prophet 来预测未来几个月的销售额。
数据准备:
我们有过去 3 年每个月的销售数据,类似下面的格式:
日期 | 销售额(元) |
---|---|
2021-01-01 | 1000 |
2021-02-01 | 1100 |
2021-03-01 | 1200 |
... | ... |
2023-12-01 | 5000 |
计算与预测步骤:
1. 安装和导入 Prophet
我们需要用 Python 来运行 Prophet。可以通过以下命令安装:
pip install prophet
2. 导入数据并创建模型 接下来,我们将数据加载到 Pandas 数据框中,然后用 Prophet 进行训练。
import pandas as pd
from prophet import Prophet
# 创建数据框
df = pd.DataFrame({
'ds': ['2021-01-01', '2021-02-01', '2021-03-01', ..., '2023-12-01'],
'y': [1000, 1100, 1200, ..., 5000]
})
# 将日期列转换为日期格式
df['ds'] = pd.to_datetime(df['ds'])
# 创建 Prophet 模型并拟合数据
model = Prophet(yearly_seasonality=True)
model.fit(df)
3. 预测未来几个月的销售额
模型拟合好后,我们可以预测未来的销售额。例如,我们想预测接下来 6 个月的销售情况:
future = model.make_future_dataframe(periods=6, freq='M')
forecast = model.predict(future)
4. 查看预测结果
预测结果中会包含许多列,但最重要的是 yhat
列,它表示预测的销售额。我们可以通过以下命令查看预测数据:
forecast[['ds', 'yhat']].tail(6)
假设输出结果如下:
ds yhat
2024-01-01 5200.45
2024-02-01 5300.12
2024-03-01 5400.76
2024-04-01 5500.25
2024-05-01 5800.36
2024-06-01 6000.12
从预测结果可以看到,未来几个月销售额逐步上升,尤其是从春季到夏季,随着天气变暖,冰淇淋店的销售额逐渐增长。
这个例子展示了如何使用 Prophet 预测一个冰淇淋店的销售额,大家可以根据自己的数据和需求进一步调整模型,比如添加假日效应、调整季节性参数等。
接下来,我们详细分析 Prophet 的数学公式及其推理过程。
Prophet 模型基本公式
Prophet 使用加性模型表示时间序列数据。其基本公式为:
其中:
表示时间 的观察值(例如销售额)。 表示趋势(trend)函数,用于捕捉数据中的长期趋势。 表示季节性(seasonality)函数,用于捕捉周期性的波动。 表示假日效应(holidays)函数,表示特定节假日对时间序列的短期影响。 表示误差项(残差),通常假设为独立同分布的高斯噪声。
1. 趋势函数
Prophet 支持两种不同的趋势模型:
线性趋势模型。 饱和增长趋势模型(即 logistic 回归模型)。
线性趋势模型
线性趋势假设数据随时间以常数速率增长或衰减。趋势函数 表示为:
其中:
是斜率(即线性增长率),初始时不随时间变化。 是截距。 是由模型自动检测的时间段中断(changepoint)引起的斜率变化。 是由于 changepoint 导致的截距变化。
Prophet 自动检测 changepoints,并允许趋势在这些点发生变化,从而提高对非平稳数据的拟合效果。
饱和增长趋势模型
饱和增长模型适用于增长受限的场景,比如人口增长、资源有限的业务增长。使用 Logistic 函数定义的趋势模型为:
其中:
是增长的上限。 是增长速率。 是数据增长达到一半饱和水平的时间点。
2. 季节性函数
季节性函数捕捉数据中的周期性波动,Prophet 假设季节性波动是周期性的,可以用傅里叶级数表示:
其中:
是季节性周期的长度(例如一年为 365.25 天)。 和 是傅里叶系数,由模型拟合。 是傅里叶级数的阶数,控制拟合的季节性复杂度。
Prophet 通过对时间序列进行傅里叶展开来建模季节性。傅里叶级数的高阶部分可以捕捉到更复杂的季节性模式。
3. 假日效应
假日效应是短期波动,特定节假日可能对销售或业务有显著影响。假日效应 可以建模为:
其中:
是第 个节日对销售的影响强度。 是指示函数,当 属于节日 时为 1,否则为 0。
4. 误差项
误差项 通常假设为独立同分布的正态分布噪声:
Prophet 会通过最大化似然估计来拟合模型,确保误差项服从正态分布的假设。
优缺点和适用场景
优点
1. 易用性强
Prophet 的接口设计非常简洁。用户只需要输入日期和观测值,无需对数据做过多预处理或深入的时间序列建模知识,就能得到合理的预测结果。
2. 自动处理趋势和季节性
Prophet 可以自动检测数据中的长期趋势和季节性波动。对于不同时间段的趋势变化(例如突变点),Prophet 能自动检测并进行趋势调整。这在处理非平稳数据时非常有用。
3. 处理节假日效应
Prophet 内置了处理节假日效应的功能,用户可以将特定节日或事件引入模型,从而提升对短期波动的预测精度。
4. 能够处理缺失值与异常值
Prophet 在遇到数据中的缺失值或异常值时表现得较为鲁棒,不会因为少数异常点导致模型失效。此外,它不要求数据必须等间距,适合处理非均匀分布的数据。
5. 支持不定期时间间隔
与 ARIMA 等传统时间序列模型不同,Prophet 可以处理时间间隔不等的数据(如业务运营中断,或者非工作日没有数据的情况)。
6. 可解释性强
Prophet 模型的可解释性很好,可以清晰地将数据分解为趋势、季节性和节假日效应,这有助于理解模型输出背后的原因。
7. 可定制化
Prophet 提供了许多参数让用户调整,例如:
是否使用线性趋势或 logistic 趋势。 自定义季节性周期的长度和复杂度。 添加自定义的节假日。
缺点
1. 对短期预测效果不佳
Prophet 主要针对长期预测,对于短期波动较大的时间序列,模型可能不如传统的时间序列方法(如 ARIMA、SARIMA)精确。
2. 假设趋势是平滑的
Prophet 默认假设趋势是平滑的,且在特定的时间点发生变化。这对于那些具有剧烈变化的时间序列数据(如股票价格等高频交易数据)可能效果较差,因为这些变化难以通过分段线性回归捕捉。
3. 对外部因素敏感性低
Prophet 主要侧重于时间序列数据本身的特征,而对外部变量的敏感性较低。例如,假如某一数据的波动与外部经济指标有关,Prophet 并不能很好地捕捉到这种关联。
4. 没有内置的状态更新机制
Prophet 是基于历史数据进行静态预测的,并不具备自适应更新功能。对于那些依赖于在线实时数据的场景,Prophet 并不能像 Kalman Filter 等方法一样根据新数据更新预测。
5. 预测结果依赖于趋势分割点
Prophet 会自动检测变化点(changepoint),但有时这种自动检测可能不准确,导致模型在趋势发生变化时效果不佳。用户需要手动调整 changepoint 或进行验证,以确保预测的准确性。
适用场景
Prophet 适用于处理具有长期趋势、季节性波动和节假日效应的时间序列。它的设计初衷是为那些不需要精确微调的商业场景服务,尤其是以下场景:
1. 电商销售预测
电商中的销售数据往往具有很强的季节性波动,例如每年圣诞节或黑色星期五销售量会突然激增。Prophet 可以很好地捕捉到这种趋势,并在节假日效应中体现。
2. 网站流量预测
对于网站流量或用户访问量的预测,尤其是具有长期趋势和季节性波动的场景,Prophet 可以有效识别日常波动以及突发事件的影响。
3. 商品库存管理
在零售行业中,商家通常需要根据历史销售数据预测未来的需求,以进行库存管理。Prophet 可以帮助商家根据销售历史和季节性需求做好库存规划。
4. 金融业的长期资产价格预测
虽然 Prophet 不适合处理高频交易数据,但在某些长期的金融资产价格趋势分析中,它可以提供不错的预测结果。
5. 能源消耗预测
能源需求往往受季节性因素(如冬天和夏天的供暖、制冷需求)影响。Prophet 可以帮助能源公司预测未来的需求,优化供应链。
案例 1:电商平台的销售预测
某电商平台希望预测未来几个月的销售情况。历史数据显示,销售额通常在每年 11 月(黑色星期五)大幅上涨,12 月(圣诞季)进一步增长。公司使用 Prophet 模型来预测下一年的销售走势,并制定库存和物流计划。
流程:
利用历史销售数据训练 Prophet 模型。 通过 Prophet 的季节性分量捕捉每年销售高峰期的波动。 利用模型输出的假日效应优化销售策略。
案例 2:网站用户访问量预测
一家新闻网站希望预测未来的访问量变化。该网站的流量通常在节假日或突发事件期间大幅波动。公司使用 Prophet 来预测日常访问量趋势,并根据预测结果优化服务器资源配置。
流程:
使用 Prophet 模型训练过去几年的日流量数据。 模型捕捉到访问量的长期趋势以及季节性波动。 结合节假日效应,优化服务器带宽和资源分配,减少峰值期间的负载问题。
完整案例
我们将使用电商平台销售预测的案例,结合 Prophet 进行时间序列分析~
图形一:实际销售额 vs 预测销售额对比图,展示预测结果与实际数据的对比。 图形二:趋势、季节性、假日效应分解图,展示 Prophet 模型对时间序列数据的趋势、季节性和假日效应分量的分解。
使用集成 Prophet 模型进行数据分析,并利用 Python 的 plotly
库进行可视化。
import pandas as pd
from prophet import Prophet
import numpy as np
import matplotlib.pyplot as plt
import plotly.graph_objs as go
import plotly.subplots as sp
# 1. 创建模拟的电商销售数据
np.random.seed(42)
dates = pd.date_range(start='2019-01-01', periods=365*4, freq='D') # 4年每天的数据
sales = 3000 + 1000 * np.sin(2 * np.pi * dates.dayofyear / 365) + np.random.normal(0, 200, len(dates)) # 季节性波动
sales += np.where((dates.month == 11) & (dates.day >= 20), 5000, 0) # 加入黑色星期五效应
sales += np.where((dates.month == 12) & (dates.day <= 25), 7000, 0) # 圣诞季效应
# 创建 DataFrame
df = pd.DataFrame({'ds': dates, 'y': sales})
# 2. 创建 Prophet 模型并拟合数据
model = Prophet(yearly_seasonality=True, weekly_seasonality=True, daily_seasonality=False, holidays_prior_scale=10)
model.add_country_holidays(country_name='US') # 添加美国节假日效应
model.fit(df)
# 3. 生成未来 1 年的数据并进行预测
future = model.make_future_dataframe(periods=365)
forecast = model.predict(future)
# 4. 创建图形一:实际销售额 vs 预测销售额对比图
fig1 = sp.make_subplots(rows=1, cols=1)
# 实际数据
actual_sales = go.Scatter(x=df['ds'], y=df['y'], mode='lines', name='Actual Sales', line=dict(color='blue', width=2))
# 预测数据
predicted_sales = go.Scatter(x=forecast['ds'], y=forecast['yhat'], mode='lines', name='Predicted Sales', line=dict(color='orange', width=2))
fig1.add_trace(actual_sales)
fig1.add_trace(predicted_sales)
fig1.update_layout(title='Actual Sales vs Predicted Sales',
xaxis_title='Date', yaxis_title='Sales',
template='plotly_dark',
font=dict(size=14),
showlegend=True,
legend=dict(x=0.02, y=0.98),
plot_bgcolor='#111111')
# 5. 创建图形二:趋势、季节性、假日效应分解图
fig2 = sp.make_subplots(rows=3, cols=1, shared_xaxes=True, subplot_titles=['Trend', 'Yearly Seasonality', 'Holidays Effect'])
# 趋势分量
trend = go.Scatter(x=forecast['ds'], y=forecast['trend'], mode='lines', name='Trend', line=dict(color='green', width=2))
fig2.add_trace(trend, row=1, col=1)
# 季节性分量
yearly_seasonality = go.Scatter(x=forecast['ds'], y=forecast['yearly'], mode='lines', name='Yearly Seasonality', line=dict(color='purple', width=2))
fig2.add_trace(yearly_seasonality, row=2, col=1)
# 假日效应分量
holidays_effect = go.Scatter(x=forecast['ds'], y=forecast['holidays'], mode='lines', name='Holidays Effect', line=dict(color='red', width=2))
fig2.add_trace(holidays_effect, row=3, col=1)
fig2.update_layout(title='Trend, Seasonality, and Holidays Effects',
xaxis_title='Date', yaxis_title='Effect',
template='plotly_dark',
font=dict(size=14),
showlegend=False,
plot_bgcolor='#111111')
# 6. 展示图形
fig1.show()
fig2.show()
数据生成:创建了一个包含 4 年每日销售数据的 DataFrame。销售数据包括基础趋势和季节性波动(使用正弦函数模拟一年周期的波动),并且加入了黑色星期五和圣诞节效应。 Prophet 模型训练:使用 Prophet 模型拟合数据,并加入美国节假日效应。模型会自动检测趋势、季节性和假日影响。
图形一:实际销售额和预测销售额对比,展示模型的预测精度。
图形二:将 Prophet 模型分解后的趋势、季节性、和假日效应展示为三张子图,便于理解模型是如何处理不同分量的。
总的来说,Prophet 的数学模型可以分解为趋势、季节性、和假日效应三部分。趋势可以是线性或饱和增长的,季节性由傅里叶级数拟合,假日效应通过回归捕捉特定时间点的短期波动。Prophet 的推导过程基于最大似然估计和贝叶斯方法,确保其在实际中具有较好的表现,特别是在处理非平稳、复杂的时间序列时。
最后