不愧是Prophet 模型 ,太强了!!

文摘   2024-09-14 18:15   北京  

哈喽,我是kk~

Prophet 是由 Facebook 开发的一种用于时间序列预测的模型,主要应用于预测具有显著趋势和季节性变化的时间序列数据。它的设计目的是应对商业预测中的复杂情况,比如数据中的假期、非线性趋势、多个季节性效应等。其主要优点是灵活性强,能够自动处理各种典型的时间序列问题。

核心思想

Prophet 是基于加性模型的时间序列模型,即预测值由多个分量加在一起。模型的基本形式为:

  • 趋势,用于捕捉时间序列的长期增长或下降趋势。
  • 季节性,用于建模年周期的季节性波动。
  • 假期效应,用于处理特殊的事件或假期对时间序列的短期影响。
  • 误差项,捕捉噪声或其他无法解释的随机成分。

Prophet 的优势在于它将每个分量单独建模,从而可以灵活地适应复杂的时间序列数据。

Prophet 的分量模型详解

1. 趋势模型 

Prophet 提供了两种建模趋势的方式:分段线性趋势饱和增长曲线

a. 分段线性趋势

分段线性趋势模型允许时间序列在多个不同时间点(称为“转折点”)处发生变化。假设我们有  个转折点,定义为 ,则分段线性趋势的模型为:

其中:

  •  是初始的斜率。
  •  是初始的截距。
  •  是每个转折点后的趋势变化幅度。
  •  是指示函数,表明当时间  大于或等于转折点时,函数取值为 1。
b. 饱和增长模型(Logistic Growth)

饱和增长模型适用于具有增长极限的数据,如人口增长或市场饱和。其模型形式为:

其中:

  •  是增长极限,表示时间序列值的饱和值。
  •  控制增长的速率。
  •  是转折点,表示增长速度最快的时刻。

2. 季节性模型 

季节性成分用于捕捉周期性的变化,比如一年中的季节性或一周中的周期波动。季节性被建模为傅里叶级数的展开:

其中:

  •  是周期的长度,例如  表示年周期。
  •    是傅里叶级数的系数,通过拟合数据进行估计。
  •  是傅里叶项的数量,控制季节性的灵活性。  越大,模型越复杂,可以捕捉更多的细节变化。

3. 假期效应 

假期效应用于建模短期内由特定事件(如节假日)引起的时间序列波动。它通常以离散的形式表示:

其中:

  •  是每个假期的影响幅度。
  •  是指示函数,表示在假期  时,函数取值为 1,否则为 0。

误差项 

误差项  是模型中未能捕捉的随机波动,通常假设为高斯白噪声,即:

Prophet 的建模允许通过调整参数来控制噪声项的大小,从而避免过拟合。

参数估计与模型拟合

Prophet 采用了马尔可夫链蒙特卡罗(MCMC)最大后验估计(MAP)两种技术来进行参数估计。具体而言,它使用的是 Stan(贝叶斯编程框架)来进行模型拟合,处理多元的趋势和季节性参数。

  1. 先验分布:Prophet 为不同参数设定了合理的先验分布,以反映商业数据中常见的变化模式。例如,趋势变化的斜率  可以设置一个较小的先验分布,从而避免趋势剧烈波动。
  2. 最大后验估计:通过最大化后验分布来估计参数,Prophet 可以结合先验信息与数据的似然函数来拟合最优模型。

Prophet 模型的优点

  1. 简单易用:Prophet 的界面设计非常直观,用户只需提供时间序列数据和一些可选的假期数据即可快速生成预测。
  2. 可解释性强:由于 Prophet 是加性模型,每个分量都有明确的经济或统计学意义,易于解释各个分量对预测的贡献。
  3. 应对复杂场景:Prophet 可以处理常见的时间序列问题,如缺失数据、异常值、假期效应、变化的趋势等。

总结

Prophet 模型的核心是将时间序列分解为趋势、季节性、假期效应和噪声四个主要部分,并为每个部分单独建模。通过组合不同的模型组件,Prophet 能够捕捉到复杂的时间序列模式,特别是在商业场景中的应用。

在实际案例中,Prophet 经常被用于解决诸如销售预测、用户增长分析等问题。我们将在这个案例中模拟一个公司的销售数据,使用 Prophet 进行时间序列预测,并生成多个复杂且美观的图形来展示数据趋势、季节性效应、假期效应等方面的分析。

案例背景

假设我们有一家公司,它希望预测未来 2 年的销售额,了解其业务的趋势、季节性波动、以及节假日对销售的影响。为了演示 Prophet 模型的强大功能,我们将生成一个虚拟的时间序列数据集,其中包含一些明显的趋势、季节性变化以及假期效应。

模型步骤

  1. 生成虚拟数据集
  2. 使用 Prophet 进行模型训练和预测
  3. 分析模型趋势和季节性
  4. 绘制复杂的分析图形
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from prophet import Prophet
from datetime import timedelta, datetime

# 设置随机种子,保证结果可复现
np.random.seed(42)

# 1. 生成虚拟时间序列数据
# 创建日期范围:从2015-01-01开始,每天的数据,持续到2023年底
dates = pd.date_range(start='2015-01-01', end='2023-12-31')

# 创建基本趋势:线性增长+周期性变化(如月度、年度)
trend = 0.05 * np.arange(len(dates))  # 模拟线性增长的趋势
seasonal = 10 * np.sin(2 * np.pi * dates.dayofyear / 365.25)  # 年季节性变化
monthly_seasonal = 5 * np.sin(2 * np.pi * dates.day / 30)  # 月度波动

# 加入一些随机噪声
noise = np.random.normal(02, len(dates))

# 生成销售数据
sales = 100 + trend + seasonal + monthly_seasonal + noise

# 创建 DataFrame
df = pd.DataFrame({'ds': dates, 'y': sales})

# 2. 引入假期效应
holidays = pd.DataFrame({
    'holiday''company_event',
    'ds': pd.to_datetime(['2016-12-25''2017-12-25''2018-12-25''2019-12-25''2020-12-25',
                          '2021-12-25''2022-12-25''2023-12-25']),
    'lower_window'0,
    'upper_window'1,
})

# 3. 创建 Prophet 模型,添加假期
model = Prophet(holidays=holidays, yearly_seasonality=True, weekly_seasonality=False)
model.add_seasonality(name='monthly', period=30.5, fourier_order=5)

# 4. 模型拟合
model.fit(df)

# 5. 生成未来的预测数据,预测未来2年的销售额
future = model.make_future_dataframe(periods=365*2)
forecast = model.predict(future)

# 6. 绘制预测图
plt.figure(figsize=(106))
model.plot(forecast)
plt.title("Sales Forecast with Prophet", fontsize=18, fontweight='bold')
plt.xlabel('Date', fontsize=14)
plt.ylabel('Sales', fontsize=14)
plt.grid(True)
plt.show()

# 7. 绘制趋势、季节性和假期效应的分解图
plt.figure(figsize=(108))
model.plot_components(forecast)
plt.suptitle("Trend, Seasonality, and Holiday Effect Decomposition", fontsize=18, fontweight='bold')
plt.show()

# 8. 绘制复杂图形:实际值 vs 预测值 + 残差分析
plt.figure(figsize=(128))

# (a) 绘制实际值 vs 预测值
plt.subplot(211)
plt.plot(df['ds'], df['y'], label='Actual Sales', color='blue', linewidth=2)
plt.plot(forecast['ds'], forecast['yhat'], label='Forecasted Sales', color='red', linestyle='--', linewidth=2)
plt.fill_between(forecast['ds'], forecast['yhat_lower'], forecast['yhat_upper'], color='red', alpha=0.3)
plt.title("Actual vs Forecasted Sales", fontsize=16, fontweight='bold')
plt.xlabel('Date', fontsize=12)
plt.ylabel('Sales', fontsize=12)
plt.legend()
plt.grid(True)

# (b) 绘制残差
plt.subplot(212)
residuals = df['y'] - forecast.loc[:len(df)-1'yhat']
plt.plot(df['ds'], residuals, label='Residuals', color='green', linewidth=2)
plt.axhline(0, color='black', linestyle='--', linewidth=1)
plt.title("Residuals (Actual - Forecast)", fontsize=16, fontweight='bold')
plt.xlabel('Date', fontsize=12)
plt.ylabel('Residuals', fontsize=12)
plt.grid(True)
plt.tight_layout()
plt.show()

虚拟数据生成:我们生成了一个从 2015 年到 2023 年的虚拟销售数据,包含线性增长、年季节性、月度波动以及随机噪声。这样模拟了一个典型的商业时间序列数据集。

Prophet 模型创建:使用 Prophet 创建了模型,并加入了假期(例如每年圣诞节的假期效应)。此外,我们还添加了月度季节性,以捕捉月度波动。

模型拟合:使用 model.fit() 方法对数据进行训练。

未来预测:使用 model.make_future_dataframe() 创建未来两年的预测数据,并使用 model.predict()生成预测结果。

  1. 销售预测图:第一张图展示了未来两年的销售预测,红色虚线代表预测值,蓝色线代表实际值,阴影部分为置信区间。

  2. 趋势、季节性和假期效应分解图:这张图清楚地展示了时间序列的主要组成部分,包括长期趋势、年度季节性波动和假期效应。它帮助我们理解每个因素对预测的影响。

实际值 vs 预测值 + 残差分析:这张复杂图展示了模型的预测能力。第一部分显示了实际值和预测值的对比,第二部分展示了残差图,帮助我们判断模型是否存在系统性误差。

通过 Prophet 模型,我们成功地预测了未来两年的销售额,并对数据的趋势、季节性和假期效应进行了深入的分析。从图形中可以看出,Prophet 能够有效地捕捉到长期趋势和季节性波动,且假期效应明显。此外,通过残差分析可以看到,模型的预测误差较小,表明拟合效果较好。

kk机器学习算法
机器学习基础、计算机视觉…
 最新文章