进阶篇 第 5 篇:现代预测方法 - Prophet 与机器学习特征工程
进阶篇 第 5 篇:现代预测方法 - Prophet 与机器学习特征工程

(图片来源: ThisIsEngineering RAEng on Pexels)
在前几篇中,我们深入研究了经典的时间序列统计模型,如 ETS 和强大的 SARIMA 家族。它们在理论上成熟且应用广泛,但有时也面临挑战:模型选择和参数调整可能比较复杂,并且它们本质上是线性模型(或通过变换处理非线性),对于某些复杂模式的捕捉能力有限。
幸运的是,时间序列分析领域也在不断发展,涌现出许多现代的预测方法。本篇,我们将聚焦于两种截然不同但都非常强大的现代思路:
- Facebook Prophet: 一个开源的、易于使用且对商业数据特别友好的自动化预测库。
- 机器学习方法 (特征工程视角): 一种思维上的转变,将时间序列预测重新表述为监督学习问题,核心在于如何巧妙地构建能捕捉时间信息的特征。
我们将探索这两种方法的原理、实践和适用场景,为你的时间序列工具箱增添更多利器。
Part 1: Facebook Prophet - 自动化预测“瑞士军刀”
当你需要快速、稳健地预测具有强季节性(可能包含年、周、日等多种周期)、节假日效应,并且可能存在趋势变化的业务时间序列(如销售额、网站流量、用户增长)时,Facebook 开源的 Prophet 库是一个非常值得考虑的选择。
Prophet 的设计哲学
Prophet 的设计围绕几个核心原则:
- 易用性 (Tunable): 提供直观的参数,即使非时间序列专家也能进行合理调整。默认设置通常效果不错。
- 自动化 (Fully automatic): 尽可能自动化地处理季节性、趋势变化点等,减少手动干预。
- 稳健性 (Robust): 对缺失值和异常值有较好的鲁棒性。
- 可解释性 (Interpretable): 模型结构清晰,易于理解趋势、季节性和节假日各自的贡献。
Prophet 的模型结构:解构预测
Prophet 本质上是一个基于加法模型的时间序列分解方法:
y(t) = g(t) + s(t) + h(t) + ε(t)
其中:
g(t)- 趋势项 (Trend):- 默认使用分段线性模型 (Piecewise Linear Model) 来拟合非线性趋势。Prophet 会自动检测趋势中的变化点 (Changepoints)。
- 也可以选择饱和增长模型 (Logistic Growth),当你预期增长有上限(或下限)时非常有用(需要提供
cap或floor值)。
s(t)- 季节性项 (Seasonality):- 使用傅立叶级数 (Fourier Series) 来拟合周期性模式。
- 能够同时拟合多种季节性,如年度 (
yearly_seasonality)、周度 (weekly_seasonality)、日度 (daily_seasonality)。 - 可以添加自定义的季节性周期。
h(t)- 节假日效应项 (Holidays):- 允许你指定节假日列表及其可能影响的时间窗口(例如,圣诞节不仅影响当天,可能还影响前后几天)。
- 可以轻松加入特定国家的内置节假日。
ε(t)- 误差项 (Error): 假设为正态分布的随机噪声。
Prophet 实战:快速上手
使用 Prophet 非常直接:
# 需要先安装: pip install prophet
import pandas as pd
from prophet import Prophet
import matplotlib.pyplot as plt
import statsmodels.api as sm # 借用 CO2 数据# 1. 数据准备 (必须包含 'ds' 和 'y' 列)
co2_data = sm.datasets.co2.load_pandas().data['co2']
co2_data = co2_data.interpolate().resample('M').mean().reset_index() # 重置索引
co2_data.rename(columns={'index': 'ds', 'co2': 'y'}, inplace=True) # 重命名列print("Prophet input data (head):")
print(co2_data.head())# 2. 实例化并拟合模型
# 可以调整参数,如 changepoint_prior_scale (趋势灵活性), seasonality_prior_scale (季节性强度)
model = Prophet(yearly_seasonality=True, # 开启年度季节性weekly_seasonality=False, # 关闭周季节性 (月度数据无意义)daily_seasonality=False) # 关闭日季节性
# (可选) 添加节假日
# model.add_country_holidays(country_name='US')model.fit(co2_data)# 3. 创建未来日期的数据框
# 预测未来 3 年 (36个月)
future_dates = model.make_future_dataframe(periods=36, freq='M')
print("\nFuture dates dataframe (tail):")
print(future_dates.tail())# 4. 进行预测
forecast = model.predict(future_dates)
print("\nForecast dataframe (tail with components):")
# forecast 包含预测值 'yhat', 置信区间 'yhat_lower', 'yhat_upper' 及各成分
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper', 'trend', 'yearly']].tail())# 5. 可视化预测结果
fig1 = model.plot(forecast)
plt.title('Prophet Forecast for CO2 Data')
plt.xlabel('Date')
plt.ylabel('CO2 Concentration')
plt.show()# 6. 可视化成分
fig2 = model.plot_components(forecast)
plt.show()# 7. (可选) 模型评估 - 交叉验证
# from prophet.diagnostics import cross_validation, performance_metrics
# df_cv = cross_validation(model, initial='730 days', period='180 days', horizon = '365 days')
# df_p = performance_metrics(df_cv)
# print("\nPerformance Metrics (example):")
# print(df_p.head())



解读与定制:
plot():展示历史数据点、预测值yhat以及置信区间。plot_components():分别展示拟合出的趋势、年度季节性、周度季节性(如果开启)等成分,非常有助于理解模型的判断。- 调整参数:
changepoint_prior_scale: 增大它使趋势更灵活,减小它使趋势更平滑。seasonality_prior_scale: 增大它使季节性幅度更大。holidays: 通过pd.DataFrame提供自定义节假日。growth='logistic': 使用饱和增长,需提供cap列。
Prophet 的优缺点
优点:
- 易用性高,自动化程度好: 对新手友好,能快速得到不错的基线预测。
- 擅长处理强季节性与节假日: 这是其核心优势。
- 对趋势变化点鲁棒: 自动检测变化点。
- 结果可解释性强: 成分图清晰展示各部分贡献。
- 处理缺失值和异常值能力较好。
缺点:
- “黑盒”感相对较强: 虽然可解释,但内部细节(如傅立叶级数阶数选择)对用户不透明。
- 不直接提供 AR/MA 部分: 它不显式地对短期自相关性(如 ARMA 模型所做的)进行建模,可能在某些高度自相关的序列上表现不如 ARIMA。
- 需要特定数据格式 (
ds,y)。 - 预测区间可能偏窄: 有时对不确定性的估计可能过于乐观。
何时选择 Prophet? 当你的数据符合其设计初衷(强季节性、节假日、趋势变化),且你需要快速、稳健、易于解释的结果时,Prophet 是一个极佳的选择。
Part 2: 思维转变 - 时间序列作为机器学习问题
与 Prophet 这种“端到端”的预测工具不同,另一种强大的现代方法是将时间序列预测重新构建为一个标准的监督学习问题。这种方法的核心在于特征工程 (Feature Engineering),而不是直接对时间依赖性建模。
范式转换:从 y(t) ~ f(y(t-k), ε(t-k)) 到 y_hat(t) = f(X(t))
- 传统统计模型 (如 ARIMA): 试图直接找到
y(t)与其过去值y(t-k)和过去误差ε(t-k)之间的数学关系。 - 机器学习方法: 我们不再直接寻找这种时序关系,而是为每个时间点
t构建一个特征向量X(t),然后训练一个机器学习模型f来学习从X(t)到y(t)的映射。
这个 X(t) 必须能够捕捉到所有与预测 y(t) 相关的时间信息。
特征工程的艺术:从时间中提取信息
构建有效的特征向量 X(t) 是这种方法成功的关键。以下是一些最常用的时间序列特征类别:
-
滞后特征 (Lag Features):
- 是什么: 直接使用过去的观测值作为特征。例如,用
y(t-1), y(t-2), y(t-3)来预测y(t)。 - 作用: 捕捉短期的自相关性(类似于 AR 部分)。
- 选择: 滞后多少阶?可以基于 PACF 图的截尾阶数获得启发,或作为超参数进行调整。
- Python 实现 (Pandas
shift()):
# 假设 df 是包含 'y' 列的 DataFrame,索引是时间 df = co2_data.set_index('ds') # 假设已有 Prophet 格式数据,转回时间索引 for i in range(1, 4): # 创建 lag 1, 2, 3df[f'lag_{i}'] = df['y'].shift(i) df.dropna(inplace=True) # 滞后操作会产生 NaN,需要处理 print("\nDataFrame with Lag Features (head):") print(df.head()) - 是什么: 直接使用过去的观测值作为特征。例如,用
-
窗口特征 / 滚动统计量 (Window Features / Rolling Statistics):
- 是什么: 计算过去一段时间窗口内的统计量。例如,过去 3 个月、6 个月或 12 个月的平均值、标准差、最大/最小值等。
- 作用: 捕捉近期的趋势、波动性或水平。
- 选择: 窗口大小是关键参数。
- Python 实现 (Pandas
rolling()):
window_size = 12 # 例如,12个月滚动窗口 # 注意:rolling 计算的是包含当前点在内的窗口,预测时常用 shift 后的滞后窗口 df[f'rolling_mean_{window_size}'] = df['y'].shift(1).rolling(window=window_size).mean() df[f'rolling_std_{window_size}'] = df['y'].shift(1).rolling(window=window_size).std() df.dropna(inplace=True) print(f"\nDataFrame with Rolling Features (head, window={window_size}):") print(df[['y', f'rolling_mean_{window_size}', f'rolling_std_{window_size}']].head()) -
日期/时间特征 (Date/Time Features):
- 是什么: 从时间索引中提取信息。
- 作用: 捕捉季节性、周期性、日历效应。
- 常见特征:
- 年份 (
year) - 月份 (
month) - 星期几 (
dayofweek) - 一年中的第几天 (
dayofyear) - 一年中的第几周 (
weekofyear) - 季度 (
quarter) - 是否周末 (
is_weekend) - 周期性编码: 对于像月份、星期几这样的周期性特征,直接用数字(如 1-12)可能无法让模型理解其周期性(12月和1月是相邻的)。常用正弦/余弦变换 (Sine/Cosine Transformation) 来编码:
df['month_sin'] = np.sin(2 * np.pi * df.index.month / 12)
df['month_cos'] = np.cos(2 * np.pi * df.index.month / 12)
- 年份 (
- Python 实现 (Pandas DatetimeIndex attributes):
df['month'] = df.index.month df['year'] = df.index.year df['dayofweek'] = df.index.dayofweek # ... 其他日期特征 ...# Sine/Cosine for month df['month_sin'] = np.sin(2 * np.pi * df['month'] / 12) df['month_cos'] = np.cos(2 * np.pi * df['month'] / 12) print("\nDataFrame with Date Features (head):") print(df[['y', 'month', 'year', 'month_sin', 'month_cos']].head()) -
扩展特征 (Expansion Features):
- 特征之间的交互项(如
lag_1 * rolling_mean_12)。 - 滞后特征的差分(如
lag_1 - lag_2)。
- 特征之间的交互项(如
为什么选择机器学习方法?
- 灵活性: 可以使用任何监督学习模型(线性模型、树模型、神经网络等),选择最适合数据复杂度的模型。
- 易于加入外生变量: 将其他时间序列(如广告支出、天气)作为额外特征列加入
X(t)非常自然。 - 捕捉非线性: 许多 ML 模型(如树模型、神经网络)能很好地捕捉复杂的非线性关系和特征交互。
- 无需严格平稳性假设: 像基于树的模型对数据的平稳性要求不像 ARIMA 那样严格(尽管平稳化有时仍有助于特征工程)。
下一步(预告)
本篇我们重点展示了如何创建适用于机器学习的特征。真正的下一步是:
- 选择并训练 ML 模型: 将
X(t)作为输入,y(t)作为目标,训练如 RandomForestRegressor, XGBoost, LightGBM 等模型。 - 处理时间序列交叉验证: 使用 Walk-Forward Validation 或
TimeSeriesSplit来可靠地评估模型性能。 - 超参数调优: 结合时间序列 CV 进行模型调优。
这部分内容将在后续文章中深入探讨(或者可以作为你自行探索的方向)。
总结:现代方法的选择
今天我们探索了两种强大的现代时间序列预测方法:
- Prophet: 一个专注于易用性、自动化和处理特定业务场景(强季节性、节假日)的优秀工具库。当你需要快速、稳健、可解释的结果时,它是一个首选。
- 机器学习特征工程: 一种更通用的方法论,将预测问题转化为监督学习。其核心在于构建能够捕捉时间信息的特征,然后可以利用整个机器学习生态系统的强大模型。这种方法提供了极大的灵活性,特别适合处理复杂关系和融入多源信息。
这两种方法并非相互排斥,有时甚至可以结合使用(例如,用 Prophet 的成分作为 ML 模型的特征)。理解它们的原理、优势和局限性,将使你能够根据具体问题选择最合适的工具。
下一篇预告:
既然我们已经学会了如何为机器学习模型准备时间序列特征,下一篇我们将深入探讨如何实际应用这些模型(如 Random Forest, Gradient Boosting),并特别关注在时间序列场景下进行可靠的模型评估和验证所必须的时间序列交叉验证技术。
准备好看机器学习模型如何在时间序列上大显身手了吗?敬请期待!
(你认为 Prophet 更适合解决你遇到的哪类问题?对于机器学习方法,你觉得哪种特征工程技巧最有潜力?欢迎在评论区分享你的想法!)
相关文章:
进阶篇 第 5 篇:现代预测方法 - Prophet 与机器学习特征工程
进阶篇 第 5 篇:现代预测方法 - Prophet 与机器学习特征工程 (图片来源: ThisIsEngineering RAEng on Pexels) 在前几篇中,我们深入研究了经典的时间序列统计模型,如 ETS 和强大的 SARIMA 家族。它们在理论上成熟且应用广泛,但有…...
ubuntu 交叉编译 macOS 库, 使用 osxcross 搭建 docker 编译 OS X 库
1. ubuntu 交叉编译 macOS 库, 使用 osxcross 搭建 docker 编译 OS X 库 1. ubuntu 交叉编译 macOS 库, 使用 osxcross 搭建 docker 编译 OS X 库 1.1. 安装依赖1.2. 安装 osxcross 及 macOS SDK 1.2.1. 可能错误 1.3. 编译 cmake 类工程1.4. 编译 configure 类工程1.5. 单文件…...
JavaScript 中的单例模式
单例模式在 JavaScript 中是一种确保类只有一个实例,并提供全局访问点的方式。由于 JavaScript 的语言特性(如对象字面量、模块系统等),实现单例有多种方式。 常见实现方式 1. 对象字面量(最简单的单例) …...
深度学习基石:神经网络核心知识全解析(一)
神经网络核心知识全解析 一、神经网络概述 神经网络作为机器学习领域的关键算法,在现代生活中发挥着重要作用,广泛应用于图像识别、语音处理、智能推荐等诸多领域,深刻影响着人们的日常生活。它通过模拟人类大脑神经系统的结构和功能&#…...
java的反编译命令
1. javap -c: 显示方法中的字节码 2. javap -p: 显示所有访问级别,包括private 3. Javap -v: verbose模式,全信息,输出的内容包括: 类的访问标志(access_flags) 类名、父类、接口 …...
影刀填写输入框(web) 时出错: Can not convert Array to String
环境: 影刀5.26.24 Win10专业版 问题描述: [错误来源]行12: 填写输入框(web) 执行 填写输入框(web) 时出错: Can not convert Array to String. 解决方案: 1. 检查变量内容 在填写输入框之前,打印BT和NR变量的值ÿ…...
词语关系图谱模型
参数配置说明 sentences, # 分词后的语料(列表嵌套列表) vector_size100, # 每个词的向量维度 window5, # 词与上下文之间的最大距离(滑动窗口大小) min_count5, # 忽略出现次数小于5的…...
《C++ 模板:泛型编程的核心》
C模板详解 模板是C中实现泛型编程的重要特性,它允许你编写与数据类型无关的代码。模板可以分为函数模板和类模板两种。 1. 函数模板 函数模板允许你定义一个可以处理多种数据类型的函数。 基本语法 template <typename T> T functionName(T parameter1, T…...
HTTP的请求消息Request和响应消息Response
一:介绍 (1)定义 service方法里的两个参数 (2)过程 Request:获取请求数据 浏览器发送http请求数据(字符串),字符串被tomcat解析,解析后tomcat会将请求数据放入request对象 Response:…...
解决Python与Java交互乱码问题:从编码角度优化数据流
在现代软件开发中,跨语言系统的集成已经成为日常工作的一部分。特别是当Python和Java之间进行交互时,编码问题往往会成为导致数据传输错误、乱码以及难以调试的主要原因之一。 你是否曾遇到过这种情境:Python脚本通过标准输出返回了正确的数…...
DES、3DES、SM4 加密算法简介
1. DES(Data Encryption Standard) 设计时间:1975 年(IBM 开发,1977 年被 NIST 采纳为美国联邦标准)。 密钥长度:64 位(实际有效 56 位 8 位校验)。 分组长度…...
C++异步操作 - future async package_task promise
异步 异步编程是一种程序设计范式,允许任务在等待耗时操作(如I/O、网络请求)时暂停执行,转而处理其他任务,待操作完成后自动恢复。其核心目标是避免阻塞主线程,提升程序的并发性和响应速度…...
Feign 深度解析:Java 声明式 HTTP 客户端的终极指南
Feign 深度解析:Java 声明式 HTTP 客户端的终极指南 Feign 是由 Netflix 开源的 声明式 HTTP 客户端,后成为 Spring Cloud 生态的核心组件(现由 OpenFeign 维护)。它通过注解和接口定义简化了服务间 RESTful 通信,并…...
08前端项目----升序/降序
升序/降序 vue实现升序/降序服务器处理 vue实现升序/降序 用vue实现升序/降序,以及css绘制三角形 <div class"sui-navbar"><div class"navbar-inner filter"><ul class"sui-nav"><li class"active"&g…...
用Java实现简易区块链:从零开始的探索
📢 友情提示: 本文由银河易创AI(https://ai.eaigx.com)平台gpt-4o-mini模型辅助创作完成,旨在提供灵感参考与技术分享,文中关键数据、代码与结论建议通过官方渠道验证。 区块链技术作为近年来的热门话题&am…...
JavaScript 渲染内容爬取实践:Puppeteer 进阶技巧
进一步探讨如何使用 Puppeteer 进行动态网页爬取,特别是如何等待页面元素加载完成、处理无限滚动加载、单页应用的路由变化以及监听接口等常见场景。 一、等待页面元素加载完成 在爬取动态网页时,确保页面元素完全加载是获取完整数据的关键。Puppeteer…...
数据结构——栈以及相应的操作
栈(Stack) 在维基百科中是这样定义的: 堆栈(stack) 又称为栈或堆叠,是计算机科学中的一种抽象资料类型,只允许在有序的线性资料集合中的一端(称为堆栈顶端,top)进行加入数据(push)和…...
SVG 与 VSCode:高效设计与开发的完美结合
SVG 与 VSCode:高效设计与开发的完美结合 引言 随着互联网技术的飞速发展,网页设计已经成为了一个重要的领域。SVG(可缩放矢量图形)作为一种矢量图形格式,因其独特的优势,在网页设计中得到了广泛应用。而VSCode(Visual Studio Code)作为一款功能强大的代码编辑器,同…...
如何应对政策变化导致的项目风险
应对政策变化导致的项目风险,核心在于:加强政策研判机制、建立动态应对流程、构建合规应急预案、强化跨部门联动、提升项目柔性与调整能力。其中,加强政策研判机制 是所有防范工作中的“前哨哨兵”,可以让项目团队在政策风向转变之…...
ASP.Net Web Api如何更改URL
1.找到appsettings.json 修改如下: 主要为urls的修改填本机私有地址即可 {"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": &q…...
在 Vue 3 中将拆分后的数组合并回原数组
接上文Vue 3 中按照某个字段将数组分成多个数组_vue3怎么进行数组对象--分割对象-CSDN博客 方法一:使用 flat() 方法 // 假设这是拆分后的多维数组 const splitArrays [[{id: 1, category: A}, {id: 3, category: A}],[{id: 2, category: B}, {id: 5, category: …...
【HTTPS协议原理】数据加密、如何防止中间人攻击、证书和签名、HTTPS完整工作流程
⭐️个人主页:小羊 ⭐️所属专栏:Linux网络 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 数据加密常见的加密方式数据摘要方案一:仅使用对称加密方案二:仅使用非对称加密方案三:双…...
Java中链表的深入了解及实现
一、链表 1.链表的概念 1.1链表是⼀种物理存储结构上⾮连续存储结构,数据元素的逻辑顺序是通过链表中的引⽤链接次序实现的 实际中链表的结构⾮常多样,以下情况组合起来就有8种链表结构: 2.链表的实现 1.⽆头单向⾮循环链表实现 链表中的…...
【武汉理工大学第四届ACM校赛】copy
copy 题目描述代码代码解释: 链接:https://ac.nowcoder.com/acm/contest/108683/E 题目描述 小s苦于在不同的窗口之间复制粘贴, 于是他突发奇想,把所有要复制的内容都复制到了一个剪贴板中,但他突然发现由于他复制的…...
植物大战僵尸杂交版v3.6最新版本(附下载链接)
B站游戏作者潜艇伟伟迷于4月19日更新了植物大战僵尸杂交版3.6版本!!!,有b站账户的记得要给作者三连关注一下呀! 不多废话下载链接放上: 夸克网盘链接::https://pan.quark.cn/s/1af9b…...
【Ansible】批量管理 Windows自动化运维
一,前期准备 1,控制端(Linux)的要求 Ansible可以在安装了Python 2(2.7版)或Python 3(3.5及更高版本)的任何机器上运行。控制端计算机不支持Windows。 2,客户端&#x…...
【源码】【Java并发】【ThreadLocal】适合中学者体质的ThreadLocal源码阅读
👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度 👍 欢迎点赞、收藏、关注,跟上我的更新节奏 📚欢迎订阅专栏…...
背包问题模板
文章目录 01背包题意思路代码优化 完全背包题意思路代码优化 多重背包题意思路代码优化 分组背包题意思路代码 01背包 特点:每件物品最多只能用一次 01背包问题 题意 给出每件物品的体积v,价值w,求解能装入背包的的物品的最大价值,并且每件物品只能选一…...
Redis 处理读请求
在前文“Redis 接收连接”中,Redis 将接收的客户端连接加入了 epoll 中监听,同时还设置了读事件处理器 connSocketEventHandler。 假设现在客户端向 Redis 发来一条 set key value 命令。 事件循环 aeProcessEvents 在事件循环 aeProcessEvents 中会调…...
Sentinel源码—8.限流算法和设计模式总结二
大纲 1.关于限流的概述 2.高并发下的四大限流算法原理及实现 3.Sentinel使用的设计模式总结 3.Sentinel使用的设计模式总结 (1)责任链模式 (2)监听器模式 (3)适配器模式 (4)模版方法模式 (5)策略模式 (6)观察者模式 (1)责任链模式 一.责任链接口ProcessorSlot 二.责…...
