最强总结,时间序列分析法,Prophet!!

文摘   2024-09-27 11:26   北京  

哈喽,我是小白~

最近,咱们分享了很多关于时间序列的内容,今儿想和大家详细的聊其中一个算法模型:

时间序列分析方法:Prophet

简单来说,Prophet 是由 Facebook(现在的 Meta)开发的一种时间序列预测工具,它非常适合初学者使用,尤其是用来处理具有周期性、趋势性数据的任务,比如预测销售额、网站流量等。Prophet 之所以受欢迎,主要是因为它相对简单易用,而且能够很好地处理常见的时间序列问题,比如节假日影响、周期性波动等。


下面,咱们先简单介绍其核心思想和简单的案例,让大家有一个整体的认识~

1. Prophet 的核心思想

Prophet 的核心模型可以理解为以下三个部分的加和:

  1. 趋势(trend):数据长期的变化趋势,比如一个网站的流量随着时间推移逐步上升。
  2. 季节性(seasonality):数据周期性的波动,比如流量每年圣诞节前后会大幅增加。
  3. 假日影响(holidays):节假日对数据的影响,比如某些特定假期对消费数据的短期刺激作用。

Prophet 的基本公式如下:

  • :趋势模型
  • :季节性模型
  • :假日影响
  • :误差项

2. 简单案例:预测冰淇淋店销售额

假设我们有一家冰淇淋店,它每年夏天的销售额会大幅增加,而冬天的销售额会下降。我们希望用 Prophet 来预测未来几个月的销售额。

数据准备:

我们有过去 3 年每个月的销售数据,类似下面的格式:

日期销售额(元)
2021-01-011000
2021-02-011100
2021-03-011200
......
2023-12-015000

计算与预测步骤:

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': [100011001200, ..., 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 支持两种不同的趋势模型:

  1. 线性趋势模型
  2. 饱和增长趋势模型(即 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 进行时间序列分析~

  1. 图形一:实际销售额 vs 预测销售额对比图,展示预测结果与实际数据的对比。
  2. 图形二:趋势、季节性、假日效应分解图,展示 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(0200, len(dates))  # 季节性波动
sales += np.where((dates.month == 11) & (dates.day >= 20), 50000)  # 加入黑色星期五效应
sales += np.where((dates.month == 12) & (dates.day <= 25), 70000)  # 圣诞季效应

# 创建 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()
  1. 数据生成:创建了一个包含 4 年每日销售数据的 DataFrame。销售数据包括基础趋势和季节性波动(使用正弦函数模拟一年周期的波动),并且加入了黑色星期五和圣诞节效应。
  2. Prophet 模型训练:使用 Prophet 模型拟合数据,并加入美国节假日效应。模型会自动检测趋势、季节性和假日影响。

图形一:实际销售额和预测销售额对比,展示模型的预测精度。

图形二:将 Prophet 模型分解后的趋势、季节性、和假日效应展示为三张子图,便于理解模型是如何处理不同分量的。

总的来说,Prophet 的数学模型可以分解为趋势季节性、和假日效应三部分。趋势可以是线性或饱和增长的,季节性由傅里叶级数拟合,假日效应通过回归捕捉特定时间点的短期波动。Prophet 的推导过程基于最大似然估计和贝叶斯方法,确保其在实际中具有较好的表现,特别是在处理非平稳、复杂的时间序列时。

最后

以上就是今天所有的内容了。
如果对你来说比较有用,记得点赞、收藏,慢慢学习~
下期会有更多干货等着你!~


Python和机器学习初学者
Python和机器学习分享,只写干货,一起学习~
 最新文章