Python 数学建模——Prophet 时间序列预测

文章目录

    • 前言
    • 原理
    • 使用方法(初级)
    • 代码实例
    • Prophet 高级应用
      • add_seasonality 添加自定义周期性
      • add_regressor 添加外生变量
      • 交叉检验

前言

  Prophet 是 Facebook 团队开发的一个时间序列分析工具,相比传统的 ARMA 时间序列分析,能够综合考虑节假日、季节等因素的影响,非常适合现实生活中具有相应特点的数据。适用背景:和现实生活联系紧密,时间跨度比较长,具有一定周期性和偶然性的时间序列。往往涉及到经济、商业等方面的问题。
  这一篇 CSDN 博客已经对 Prophet 作出了较为完整的一个阐述,包括原理和应用等方面,本文会深入 Python 代码介绍 Prophet 库的另一些重要参数,相当于是 Prophet 的拓展应用,对原理则简单介绍。
  附上 Prophet 论文的网址:Forecasting at scale (peerj.com)。数学建模的时候若使用 Prophet,可以在原论文中摘取一些原理的介绍。

原理

  给定一系列 (日期,值) 或者说 ( t i , y i ) (t_i,y_i) (ti,yi) 的序列,直接调用 Prophet 模型即可直接拟合出未来日期的结果。Prophet 适用于具有明显的内在规律的商业行为数据。prophet 模型将 y ( t ) y(t) y(t) 拆解为:
y ( t ) = g ( t ) + s ( t ) + h ( t ) + ε ( t ) y(t)=g(t)+s(t)+h(t)+\varepsilon (t) y(t)=g(t)+s(t)+h(t)+ε(t)

  其中:

  • g ( t ) g(t) g(t) 表示趋势项,它表示时间序列在非周期上面的变化趋势。
  • s ( t ) s(t) s(t) 表示周期项,或者称为季节项,一般来说是以周或者年为单位。
  • h ( t ) h(t) h(t) 表示节假日项,表示时间序列中那些潜在的具有非固定周期的节假日对预测值造成的影响。
  • ε ( t ) \varepsilon (t) ε(t) 即误差项或者称为剩余项,表示模型未预测到的波动,服从高斯分布。

使用方法(初级)

注意:数据中的异常点直接赋值为None即可,因为Prophet的设计中可以通过插值处理缺失值。但是 Prophet 对异常值比较敏感。

  Prophet 方法的常见参数有:

  • growth:模型的增长趋势,默认值growth = 'linear',但是如果认为是 Logistic 增长,可以使用growth = 'logistic'。使用 Logistic 模型需要设置容量值 capacity 参数,具体怎么设置可以查看相关文章。
  • changepoints:如果知道某些日期肯定是转折点,那么可以人为地添加。
  • yearly_seasonality:是否分析年季节性,即是否画相应的图。同理还有参数weekly_seasonalitydaily_seasonality
  • holidays:有的时候,add_country_holidays导入的未必是完整的节日,一些洋节也会在中国产生影响,此时需要手动添加。可以有这样的holidays
# 下面的 playoffs 添加的节假日包括:
#    2024-01-13    2024-01-14    2024-01-15
#    2024-05-13    2024-05-14    2024-05-15
playoffs = pd.DataFrame({'holiday': 'playoff','ds': pd.to_datetime(['2024-01-14', '2024-05-14']),'lower_window': -1,'upper_window': 1,
})
  • mcmc_samples:一个非常神奇的参数。默认的mcmc_samples=0,当传入这个参数为非零值时,分解图开始出现置信区间。
  • changepoint_prior_scale:控制 Prophet 模型对转折点的敏感程度,默认值 0.05 0.05 0.05。其值越大时,模型更容易检测到时间序列中的转折点,但是缺点是容易过拟合;其值越小时,不太容易过拟合,但是对一些转折点的识别能力较差。具体可看下面两张图对比:
    在这里插入图片描述在这里插入图片描述
    参考文献:Facebook Prophet使用与调参实践 – 标点符

代码实例

import pandas as pd
import numpy as np
from prophet import Prophet
import datetime as dt
import matplotlib.pyplot as plt# 准备数据
np.random.seed(114)
data = pd.DataFrame({'ds': [dt.date(2024,1,1) + dt.timedelta(i) for i in range(100)],'y': 10 + (np.sin(range(100)) * 0.3 + np.arange(100) * 0.2) * np.random.rand(100)
})# 创建模型
model = Prophet(growth='linear',yearly_seasonality=True,weekly_seasonality=True,# changepoints = ['2024-01-03']# 可以添加转折点但是必须是 ds 里面有的日期interval_width=0.95)# 添加传统节日效应
model.add_country_holidays(country_name='CN')# 拟合模型
model.fit(data)# 预测未来值
future = model.make_future_dataframe(periods=50) # period = 50 代表预测未来 50 天的数据
forecast = model.predict(future)# 可视化预测结果
model.plot(forecast)
plt.savefig("预测.pdf")
model.plot_components(forecast)
plt.savefig("分解.pdf")

在这里插入图片描述
  上图是“预测.pdf”。值得一提的是,因为我们设置了年周期性和周周期性分析选项,预测图中在一个月后出现了较大抖动,分解图中也有yearly分量。在取消yearly_seasonality=True,以及weekly_seasonality=True的设置之后,预测图变成下图,分解图中yearly也将消失。
在这里插入图片描述
  下面这张图是“分解.pdf”:
在这里插入图片描述

Prophet 高级应用

 &emsp上面通过Prophet方法得到了模型model,实际上这个model对象还有一些方法可以满足我们一些额外的需求。

add_seasonality 添加自定义周期性

  添加自定义周期性之后,模型的原理是不变的,即 y ( t ) = g ( t ) + s ( t ) + h ( t ) + ε ( t ) y(t)=g(t)+s(t)+h(t)+\varepsilon (t) y(t)=g(t)+s(t)+h(t)+ε(t)。只不过此时的 s ( t ) s(t) s(t) 就会单独考虑添加一个新的周期性分量了。比如我已知存在有一个 T = 14 d T=14\mathrm d T=14d d \mathrm d d 表示天)的影响因子,那么在得到model对象后可以加入下面的代码:

model.add_seasonality('genshin', period=14, fourier_order=2)

  这将带来以下区别:

  • Prophet 模型会考虑你所谓的 T = 14 d T=14\mathrm d T=14d 的周期性分量,提取出这样的成分,画在分解图中。这个周期性分量的表达式为:
    p ( t ) = ∑ n = 1 N [ a n cos ⁡ ( 2 π n t / T ) + b n sin ⁡ ( 2 π n t / T ) ] p(t)=\sum_{n=1}^{N}{[}{{a}_{n}}\cos{(}2\pi nt/T)+{{b}_{n}}\sin{(}2\pi nt/T)] p(t)=n=1N[ancos(2πnt/T)+bnsin(2πnt/T)]

  这里的 N N N 就是上面的fourier_order T T T 就是上面的T

  • 人为加入这一行代码,与不加入相比,预测结果会产生一点偏差。如果你找的规律好,预测当然会更准确。

add_regressor 添加外生变量

  外生变量指的就是和预测变量存在关联关系的变量。比如预测的y的含义是销量,那么就可以将价格作为外生变量传入 Prophet 模型中。
  训练时使用外生变量,只需在传入Prophet方法的 DataFrame 里面加入新的列。例如,如下所示加入价格列price(其长度与其他列相同):

data = pd.DataFrame({'ds': [dt.date(2024,1,1) + dt.timedelta(i) for i in range(100)],'y': 10 + (np.sin(range(100)) * 0.3 + np.arange(100) * 0.2) * np.random.rand(100),'price': [……] # 自己填充数据
})

  其他地方原封不动即可。Prophet模型在训练时会考虑到这些,从而变成多变量时间序列预测模型
  在预测时,我们需要给出外生变量的值,从而让模型能够预测。在上面的代码中我们得到了一个叫做future的 DataFrame:

future = model.make_future_dataframe(periods=50) # period = 50 代表预测未来 50 天的数据

  实际上,我们只需要设置future['price'] = [……](给一个长为 periods = 50 的列表),就可以调用forecast = model.predict(future)进行预测。加入了外生变量的总代码如下:

import pandas as pd
import numpy as np
from prophet import Prophet
import datetime as dt
import matplotlib.pyplot as plt# 准备数据
np.random.seed(114)
data = pd.DataFrame({'ds': [dt.date(2024,1,1) + dt.timedelta(i) for i in range(100)],'y': 10 + (np.sin(range(100)) * 0.3 + np.arange(100) * 0.2) * np.random.rand(100),# 注意这里需要填入外生变量'price': [……]
})# 创建模型
model = Prophet(growth='linear',yearly_seasonality=True,weekly_seasonality=True,# changepoints = ['2024-01-03']# 可以添加转折点但是必须是 ds 里面有的日期interval_width=0.95)# 添加传统节日效应
model.add_country_holidays(country_name='CN')# 拟合模型
model.fit(data)# 预测未来值
future = model.make_future_dataframe(periods=50) # period = 50 代表预测未来 50 天的数据
# 注意这里需要给出预测的 periods = 50 天时间内外生变量 price 的实际值
future['price'] = [……]
forecast = model.predict(future)# 可视化预测结果
model.plot(forecast)
plt.savefig("预测.pdf")
model.plot_components(forecast)
plt.savefig("分解.pdf")

参考文献:【时序分析】Prophet模型中使用外生变量、自定义周期性_prophet如何自定义周期-CSDN博客

交叉检验

参考文献:

  • 掌握时间波动:借助时间序列交叉验证技术提升预测精准度-CSDN博客
  • prophet Diagnostics诊断-腾讯云开发者社区-腾讯云

  Prophet 预测的效果好不好,需要进行交叉检验。Prophet 用下面的方式交叉检验:

# 接着上面的代码
from prophet.diagnostics import cross_validation
df_cv = cross_validation(model, initial='50 days', period='10 days', horizon = '5 days')
# 一般设置参数 initial = 3 * horizon,period = 0.5 * horizon,当然可以调整一下达到最好效果

  交叉检验基于已给的前initial天(可能有一些偏差)的数据,预测紧接着horizon天的数据。然后将initial自增period,重复操作……直到已有数据用完。上面代码生成的数据如下,这个y是实际值,yhat是根据已有数据的估计值。

           ds       yhat  yhat_lower  yhat_upper          y     cutoff
0  2024-02-25  16.388943   14.007529   18.943522  13.804077 2024-02-24
1  2024-02-26  17.330200   14.915873   19.953441  20.031500 2024-02-24
2  2024-02-27  19.368427   16.741796   21.909734  20.663439 2024-02-24
3  2024-02-28  19.180708   16.633248   21.765376  16.081144 2024-02-24
4  2024-02-29  20.501733   17.950074   23.024951  18.069711 2024-02-24
5  2024-03-06  12.081063    9.124616   15.339416  11.955349 2024-03-05
6  2024-03-07  10.326309    7.134838   12.963412  12.771650 2024-03-05
7  2024-03-08   6.582040    3.493560    9.725560  10.321305 2024-03-05
8  2024-03-09   2.564637   -0.545879    5.474141  17.704553 2024-03-05
9  2024-03-10  -2.144653   -5.084986    0.953620  16.517561 2024-03-05
10 2024-03-16  19.026456   15.343248   22.797478  16.060686 2024-03-15
……    ……            ……        ……            ……        ……        ……

  仍然不够直观,调库计算上面的误差

from prophet.diagnostics import performance_metrics
df_p = performance_metrics(df_cv)
"""
结果:horizon         mse       rmse  ...     mdape     smape  coverage
0  1 days   69.840361   8.357055  ...  0.187254  0.354367       0.4
1  2 days   47.651266   6.902990  ...  0.191466  0.385643       0.4
2  3 days   72.913272   8.538927  ...  0.362286  0.529062       0.4
3  4 days  224.096939  14.969868  ...  0.609604  0.999131       0.0
4  5 days  285.191131  16.887603  ...  1.129841  1.205107       0.2
"""

这里的 mse,…,smape 是不同角度的误差衡量方式,显然其值越小越好。均方误差 mse 对异常值非常敏感,故大多都是选择 mape 误差。认为 mape 误差在 20 % 20\% 20% 以内,prophet 的拟合效果就还可以,也即问题适合使用 prophet 模型。
这个 coverage 目前还找到一篇博客说清楚他到底是啥,但知道它越大越好,在 70 % 70\% 70% 以上则说明 prophet 模型较为合适。

  将上面的误差可视化,这里选择 mape 误差:

from prophet.diagnostics import plot_cross_validation_metric
fig = plot_cross_validation_metric(df_cv, metric='mape')

  作出来结果如下。百分比绝对误差达到了 1,说明参数调得非常烂。这是因为我乱生成的数据,实际数据肯定是有点周和年的规律的。在取消yearly_seasonality=True,weekly_seasonality=True的设置之后就好多了。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/54002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常见 HTTP 状态码详解与Nginx 文件上传大小限制

在我们日常使用 Nginx 搭建网站或应用服务时,可能会遇到很多与文件上传和请求响应相关的问题。今天我们就来聊聊 如何限制文件上传的大小,并介绍一些常见的 HTTP 状态码 及其在 Nginx 中的处理方式。 一、文件上传大小限制 有时,我们需要限…

通过覆写 url_for 将 flask 应用部署到子目录下

0. 缘起 最近用 flask 写了一个 web 应用,需要部署到服务器上。而服务器主域名已经被使用了,只能给主域名加个子目录进行部署,比如主域名 example.org ,我需要在 example.org/flask 下部署。这时 flask 应用里的内部连接们就出现…

github远程仓库环境搭建及使用

目录 1、创建一台虚拟机 centos 源的配置 备份源 修改源 重新加载缓存 安装软件 配置epel 2、关闭防火墙和selinux 关闭防火墙 临时关闭SELinux 永久关闭SELinux:编辑SELinux的配置文件 配置文件的修改内容 3、git是本地仓库,linux系统中一…

Qt常用控件——QDateTimeEdit

文章目录 QDateTimeEdit核心属性及信号时间计算器 QDateTimeEdit核心属性及信号 QDateEdit作为日期的微调框QTimeEdit作为时间的微调框QDateTimeEdit作为时间日期的微调框 它们的使用方式都是类似的,本篇以QDateTimeEdit作为示例 核心属性: 属性说明…

【秒达开源】多功能中文工具箱源码:自部署 全开源 轻量级跨平台 GPT级支持+高效UI+Docker

【秒达开源】多功能中文工具箱源码发布:自部署、全开源、轻量级跨平台,GPT级支持高效UI,Docker/便携版任选,桌面友好丰富插件生态 这是一款集大成之作,专为追求高效与便捷的用户量身打造。它不仅支持完全自部署&#…

远程访问电脑共享文件

远程访问电脑共享文件,可以通过多种方法实现,每种方法都有其特点和适用场景。以下是一些常见的方法及其步骤: 一、使用Microsoft远程桌面 启用远程桌面: 在目标电脑上,打开“开始”菜单,选择“设置”>“…

教育培训小程序开发,简单实用的入门指南

教育培训小程序可以帮助教育机构和个人老师提供更灵活的在线教学服务,满足学生的学习需求。对于初学者来说,开发一个功能齐全的教育培训小程序并不复杂,只需掌握一些基础的开发知识和工具即可。本文将带你了解如何使用微信小程序开发工具&…

SpringBoot开发——使用@Slf4j注解实现日志输出

文章目录 1、Lombok简介2、SLF4J简介3、实现步骤3.1 创建SpringBoot项目3.2 添加依赖3.3 使用 Slf4j 注解3.4 输出日志信息 4、结论 在现代Java开发中,日志记录是至关重要的。它不仅帮助开发者调试代码,还便于监控系统运行状态和性能。 Lombok 和 SLF4J …

【Android】Room—数据库的基本操作

引言 在Android开发中,数据持久化是一个不可或缺的部分。随着应用的复杂度增加,选择合适的数据存储方式变得尤为重要。Room数据库作为Android Jetpack架构组件之一,提供了一种抽象层,使得开发者能够以更简洁、更安全的方式操作SQ…

快速搭建最简单的前端项目vue+View UI Plus

1 引言 ‌‌Vue是一套用于构建Web前端界面的渐进式JavaScript框架。‌‌它以其易学易用、性能出色、灵活多变而深受开发者喜爱,并且与其他前端框架(如‌React和‌Angular)相比,在国内市场上受到了广泛的认可和使用。点击进入官方…

AI问答-HTTP:理解 Content-Disposition

一、简介 Content-Disposition是HTTP协议中的一个响应头字段,它主要用于指示如何处理响应的内容以及如何呈现给用户。这个字段是MIME协议类型的扩展,用于指导MIME用户代理(如浏览器)如何显示附加的文件。Content-Disposition的主…

yolo自动化项目实例解析(二)ui页面整理

我们在上一章整理main.py 的if __name__ __main__: 内容还留下面这一段, app QApplication(sys.argv) # 初始化Qt应用ratio screen_width / 2560 # 分辨率比例# 设置全局字体大小# 计算字体大小base_font_size 13# 基准字体大小,适合1920*1080分辨…

【数据结构与算法 | 灵神题单 | 合并链表篇】力扣2, 21, 445, 2816

1. 力扣2:两数相加 1.1 题目: 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可…

vue3 +百度地图 实现 地点检索,输入联想,经纬度,逆地理编码,创建标记,label等

由于百度地图文档确实有点欠缺,在这里记录一下 vue3 百度地图(js api 3.0)实现效果如下实现方式注意事项 vue3 百度地图(js api 3.0) 需求: 地图弹框组件,可以搜索地图点,输入联想…

尚品汇-订单拆单、支付宝关闭交易、关闭过期订单整合(五十)

目录: (1)拆单接口 (2)取消订单业务补充关闭支付记录 (3)支付宝关闭交易 (4)查询支付交易记录 (5)PaymentFeignClient 远程接口 &#xff08…

JMeter脚本开发

环境部署 Ubuntu系统 切换到root用户 sudo su 安装上传下载的命令 apt install lrzsz 切换文件目录 cd / 创建文件目录 mkdir java 切换到Java文件夹下 cd java 输入rz回车 选择jdk Linux文件上传 解压安装包 tar -zxvf jdktab键 新建数据库 运行sql文件 选择sql文件即…

基于51单片机的电饭锅控制系统proteus仿真

地址: https://pan.baidu.com/s/1CGyg6uPhFI0MeaBWwe_HAg 提取码:1234 仿真图: 芯片/模块的特点: AT89C52/AT89C51简介: AT89C52/AT89C51是一款经典的8位单片机,是意法半导体(STMicroelectro…

RedisTemplate操作ZSet的API

文章目录 ⛄概述⛄常见命令有⛄RedisTemplate API❄️❄️ 向集合中插入元素,并设置分数❄️❄️向集合中插入多个元素,并设置分数❄️❄️按照排名先后(从小到大)打印指定区间内的元素, -1为打印全部❄️❄️获得指定元素的分数❄️❄️返回集合内的成员个数❄️❄…

LineageOS刷机教程

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ LineageOS 是一个基于 Android 开源项目(AOSP)的开源操作系统,主要由社区开发者维护。它起源于 CyanogenMod 项目&#xff…

10年Python程序员教你多平台采集10万+电商数据【附实例】

10万级电商数据采集需要注意什么? 在进行10万级电商数据采集时,有许多关键因素需要注意: 1. 采集平台覆盖:确保可以覆盖主流的电商平台,如淘宝、天猫、京东、拼多多等。 2. 数据字段覆盖:检查是否可以对平…