第100+33步 ChatGPT学习:时间序列EMD-ARIMA-LSTM模型
基于Python 3.9版本演示
一、写在前面
上一节,我们学了经验模态分解(Empirical Mode Decomposition,EMD)。
如同结尾所说,“那么,做这些分解有什么作用呢?有大佬基于这些分解出来的序列分别作预测,然后再次合并,达到提升预测性能的作用。”
二、EMD&LSTM-ARIMA组合策略
该组合策略主要是将传统的经验模态分解(EMD)方法和现代的机器学习技术(LSTM 和 ARIMA 模型)相结合,用于增强时序数据的预测能力。下面是这个策略的具体描述:
(1)经验模态分解 (EMD):
1)首先,使用 EMD 方法处理原始时序数据,将其分解为多个内模函数(IMF)和一个剩余信号。这一步骤的目的是提取数据中的不同频率成分,每个 IMF 代表原始信号的不同频率层次,而剩余信号包含了趋势信息。
2)EMD 是一种自适应方法,适用于非线性和非平稳时间序列数据分析,可以揭示隐藏在复杂数据集中的简单结构和成分。
(2)LSTM 和 ARIMA 模型的应用:
1)将不同的 IMF 成分分配给不同的预测模型:选定的IMF由 LSTM 模型处理,通常选择那些更具高频和复杂动态的成分;而趋势性较强的成分(包括剩余信号)则交由 ARIMA 模型进行分析。
2)LSTM (长短期记忆网络):适合处理和预测时间序列数据中的长期依赖关系,因此用于捕捉和预测时序数据中的非线性模式和复杂关系。
3)ARIMA (自回归积分滑动平均模型):擅长处理线性关系和趋势变化,适用于具有明显趋势或季节性的时间序列数据。
三、EMD&LSTM-ARIMA组合策略代码Pyhton实现
下面,我使用的是之前分享过的肺结核的数据做演示:

Pyhon代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import CubicSpline
import torch
import torch.nn as nn
import torch.optim as optim
from statsmodels.tsa.arima.model import ARIMA
from sklearn.metrics import mean_absolute_error, mean_squared_error# 读取数据
file_path = 'pone.0277314.s006.xlsx'
data = pd.read_excel(file_path)# 提取时间和PTB病例数
time_series = data['Time']
ptb_cases = data['PTB cases']# 将时间转换为数值形式
time_numeric = np.arange(len(time_series))def get_envelope_mean(signal):"""计算信号的上包络线和下包络线的均值"""maxima = np.where(np.r_[True, signal[1:] > signal[:-1]] & np.r_[signal[:-1] > signal[1:], True])[0]minima = np.where(np.r_[True, signal[1:] < signal[:-1]] & np.r_[signal[:-1] < signal[1:], True])[0]if len(maxima) < 2 or len(minima) < 2:return np.zeros_like(signal)upper_env = CubicSpline(maxima, signal[maxima])(time_numeric)lower_env = CubicSpline(minima, signal[minima])(time_numeric)return (upper_env + lower_env) / 2def sift(signal, max_iter=1000, tol=1e-6):"""对信号进行sifting操作,提取IMF"""h = signalfor _ in range(max_iter):m = get_envelope_mean(h)h1 = h - mif np.mean(np.abs(h - h1)) < tol:breakh = h1return hdef emd(signal, max_imfs=6):"""进行EMD分解"""residual = signalimfs = []for _ in range(max_imfs):imf = sift(residual)imfs.append(imf)residual = residual - imfif np.all(np.abs(residual) < 1e-6):breakreturn np.array(imfs), residual# 执行EMD分解
imfs, residual = emd(ptb_cases.values)# 绘制分解结果
num_imfs = imfs.shape[0]
plt.figure(figsize=(12, 9))
for i in range(num_imfs):plt.subplot(num_imfs + 1, 1, i + 1)plt.plot(time_series, imfs[i], label=f'IMF {i + 1}')plt.legend()plt.subplot(num_imfs + 1, 1, num_imfs + 1)
plt.plot(time_series, residual, label='Residual')
plt.legend()
plt.tight_layout()
plt.show()# LSTM模型
class LSTMModel(nn.Module):def __init__(self, input_size=1, hidden_layer_size=50, output_size=1):super(LSTMModel, self).__init__()self.hidden_layer_size = hidden_layer_sizeself.lstm = nn.LSTM(input_size, hidden_layer_size)self.linear = nn.Linear(hidden_layer_size, output_size)self.hidden_cell = (torch.zeros(1,1,self.hidden_layer_size),torch.zeros(1,1,self.hidden_layer_size))def forward(self, input_seq):lstm_out, self.hidden_cell = self.lstm(input_seq.view(len(input_seq) ,1, -1), self.hidden_cell)predictions = self.linear(lstm_out.view(len(input_seq), -1))return predictions[-1]def train_lstm_model(train_data, n_steps):model = LSTMModel()loss_function = nn.MSELoss()optimizer = optim.Adam(model.parameters(), lr=0.001)epochs = 200for epoch in range(epochs):for seq in range(len(train_data) - n_steps):model.hidden_cell = (torch.zeros(1, 1, model.hidden_layer_size),torch.zeros(1, 1, model.hidden_layer_size))seq_train = torch.FloatTensor(train_data[seq:seq + n_steps])label = torch.FloatTensor(train_data[seq + n_steps:seq + n_steps + 1])optimizer.zero_grad()y_pred = model(seq_train)single_loss = loss_function(y_pred, label)single_loss.backward()optimizer.step()if epoch % 50 == 0:print(f'Epoch {epoch+1} loss: {single_loss.item()}')return modeldef arima_model(train_data, order):model = ARIMA(train_data, order=order)model_fit = model.fit()return model_fitn_steps = 10
imfs_lstm = [3, 4] # 分配给LSTM的IMFs索引
imfs_arima = [0, 1, 2] # 分配给ARIMA的IMFs索引lstm_predictions = np.zeros(len(time_numeric))
arima_predictions = np.zeros(len(time_numeric))# LSTM预测
for idx in imfs_lstm:print(f'Training LSTM for IMF {idx+1}')train_data = imfs[idx].flatten()model = train_lstm_model(train_data, n_steps)for i in range(n_steps, len(train_data)):seq = torch.FloatTensor(train_data[i-n_steps:i])with torch.no_grad():lstm_predictions[i] += model(seq).item()print(f'LSTM predictions for IMF {idx+1} completed')# ARIMA预测
for idx in imfs_arima:print(f'Training ARIMA for IMF {idx+1}')train_data = imfs[idx]model_fit = arima_model(train_data, order=(5, 1, 0))arima_predictions += model_fit.predict(start=0, end=len(train_data) - 1)print(f'ARIMA predictions for IMF {idx+1} completed')# 合并预测结果
final_predictions = lstm_predictions + arima_predictions# 计算误差
mae = mean_absolute_error(ptb_cases, final_predictions)
mse = mean_squared_error(ptb_cases, final_predictions)
rmse = np.sqrt(mse)
mape = np.mean(np.abs((ptb_cases - final_predictions) / ptb_cases)) * 100# 打印误差
print(f'MAE: {mae}')
print(f'MSE: {mse}')
print(f'RMSE: {rmse}')
print(f'MAPE: {mape}')# 绘制预测结果
plt.figure(figsize=(12, 6))
plt.plot(time_numeric, ptb_cases, label='Original Data')
plt.plot(time_numeric, final_predictions, label='Predicted Data')
plt.legend()
plt.show()
输出:

跟原图对比:
发现了没,似乎是整体向下偏移了一波。让GPT帮忙优化一下算法。
五、优化后
根据每个模型的误差(MAE)微调一下试试:
Pyhon代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import CubicSpline
import torch
import torch.nn as nn
import torch.optim as optim
from statsmodels.tsa.arima.model import ARIMA
from sklearn.metrics import mean_absolute_error, mean_squared_error# 读取数据
file_path = 'pone.0277314.s006.xlsx'
data = pd.read_excel(file_path)# 提取时间和PTB病例数
time_series = data['Time']
ptb_cases = data['PTB cases']# 将时间转换为数值形式
time_numeric = np.arange(len(time_series))def get_envelope_mean(signal):"""计算信号的上包络线和下包络线的均值"""maxima = np.where(np.r_[True, signal[1:] > signal[:-1]] & np.r_[signal[:-1] > signal[1:], True])[0]minima = np.where(np.r_[True, signal[1:] < signal[:-1]] & np.r_[signal[:-1] < signal[1:], True])[0]if len(maxima) < 2 or len(minima) < 2:return np.zeros_like(signal)upper_env = CubicSpline(maxima, signal[maxima])(time_numeric)lower_env = CubicSpline(minima, signal[minima])(time_numeric)return (upper_env + lower_env) / 2def sift(signal, max_iter=1000, tol=1e-6):"""对信号进行sifting操作,提取IMF"""h = signalfor _ in range(max_iter):m = get_envelope_mean(h)h1 = h - mif np.mean(np.abs(h - h1)) < tol:breakh = h1return hdef emd(signal, max_imfs=6):"""进行EMD分解"""residual = signalimfs = []for _ in range(max_imfs):imf = sift(residual)imfs.append(imf)residual = residual - imfif np.all(np.abs(residual) < 1e-6):breakreturn np.array(imfs), residual# 执行EMD分解
imfs, residual = emd(ptb_cases.values)# 绘制分解结果
num_imfs = imfs.shape[0]
plt.figure(figsize=(12, 9))
for i in range(num_imfs):plt.subplot(num_imfs + 1, 1, i + 1)plt.plot(time_series, imfs[i], label=f'IMF {i + 1}')plt.legend()plt.subplot(num_imfs + 1, 1, num_imfs + 1)
plt.plot(time_series, residual, label='Residual')
plt.legend()
plt.tight_layout()
plt.show()# LSTM模型
class LSTMModel(nn.Module):def __init__(self, input_size=1, hidden_layer_size=50, output_size=1):super(LSTMModel, self).__init__()self.hidden_layer_size = hidden_layer_sizeself.lstm = nn.LSTM(input_size, hidden_layer_size)self.linear = nn.Linear(hidden_layer_size, output_size)self.hidden_cell = (torch.zeros(1,1,self.hidden_layer_size),torch.zeros(1,1,self.hidden_layer_size))def forward(self, input_seq):lstm_out, self.hidden_cell = self.lstm(input_seq.view(len(input_seq) ,1, -1), self.hidden_cell)predictions = self.linear(lstm_out.view(len(input_seq), -1))return predictions[-1]def train_lstm_model(train_data, n_steps):model = LSTMModel(hidden_layer_size=100) # 调整隐藏层大小loss_function = nn.MSELoss()optimizer = optim.Adam(model.parameters(), lr=0.001) # 调整学习率epochs = 300 # 增加训练轮数for epoch in range(epochs):for seq in range(len(train_data) - n_steps):model.hidden_cell = (torch.zeros(1, 1, model.hidden_layer_size),torch.zeros(1, 1, model.hidden_layer_size))seq_train = torch.FloatTensor(train_data[seq:seq + n_steps])label = torch.FloatTensor(train_data[seq + n_steps:seq + n_steps + 1])optimizer.zero_grad()y_pred = model(seq_train)single_loss = loss_function(y_pred, label)single_loss.backward()optimizer.step()if epoch % 50 == 0:print(f'Epoch {epoch+1} loss: {single_loss.item()}')return modeldef arima_model(train_data, order):model = ARIMA(train_data, order=order)model_fit = model.fit()return model_fitn_steps = 10
imfs_lstm = [3, 4] # 分配给LSTM的IMFs索引
imfs_arima = [0, 1, 2] # 分配给ARIMA的IMFs索引lstm_predictions = np.zeros(len(time_numeric))
arima_predictions = np.zeros(len(time_numeric))# LSTM预测
for idx in imfs_lstm:print(f'Training LSTM for IMF {idx+1}')train_data = imfs[idx].flatten()model = train_lstm_model(train_data, n_steps)for i in range(n_steps, len(train_data)):seq = torch.FloatTensor(train_data[i-n_steps:i])with torch.no_grad():lstm_predictions[i] += model(seq).item()print(f'LSTM predictions for IMF {idx+1} completed')# ARIMA预测
for idx in imfs_arima:print(f'Training ARIMA for IMF {idx+1}')train_data = imfs[idx]model_fit = arima_model(train_data, order=(5, 1, 0))arima_predictions += model_fit.predict(start=0, end=len(train_data) - 1)print(f'ARIMA predictions for IMF {idx+1} completed')# 合并预测结果
final_predictions = lstm_predictions + arima_predictions# 计算LSTM和ARIMA模型的误差
lstm_error = np.mean(ptb_cases - lstm_predictions)
arima_error = np.mean(ptb_cases - arima_predictions)# 根据误差平移预测结果
final_predictions += (lstm_error + arima_error) / 2# 计算误差
mae = mean_absolute_error(ptb_cases, final_predictions)
mse = mean_squared_error(ptb_cases, final_predictions)
rmse = np.sqrt(mse)
mape = np.mean(np.abs((ptb_cases - final_predictions) / ptb_cases)) * 100# 打印误差
print(f'MAE: {mae}')
print(f'MSE: {mse}')
print(f'RMSE: {rmse}')
print(f'MAPE: {mape}')# 绘制预测结果
plt.figure(figsize=(12, 6))
plt.plot(time_numeric, ptb_cases, label='Original Data')
plt.plot(time_numeric, final_predictions, label='Predicted Data')
plt.legend()
plt.show()
看看结果:

效果也不是太好。
六、最后
下一期,我们来测试一下其他矫正方法。
相关文章:
第100+33步 ChatGPT学习:时间序列EMD-ARIMA-LSTM模型
基于Python 3.9版本演示 一、写在前面 上一节,我们学了经验模态分解(Empirical Mode Decomposition,EMD)。 如同结尾所说,“那么,做这些分解有什么作用呢?有大佬基于这些分解出来的序列分别作…...
(C语言)双向链表
目录 链表的分类 双向链表的实现 1)定义链表 2)初始化双向链表 3)申请节点 4)尾插 5)头插 6)打印链表 7)尾删 8)头插 9)查找 10)指定位置删除 11…...
青少年编程与数学 02-004 Go语言Web编程 04课题、接收和处理请求
青少年编程与数学 02-004 Go语言Web编程 04课题、接收和处理请求 课题摘要:一、构建WEB服务器1. 安装Go语言2. 创建项目结构3. 编写代码4. 运行WEB服务器5. 访问WEB服务器 二、接收请求1. 定义处理函数(Handler)2. 将处理函数与路由关联3. 启动服务器4. …...
Unity全局光照详解
之前就学过但是太久没用又忘了,因此用最简洁易懂的语言做个记录。 全局光照分为两个系统,分别是实时光照和混合光照。(点击window/Rendering/Lighing打开此面板) 其中全局光照对于我来说都是新技术了,上一次学…...
计算机网络知识点全梳理(三.TCP知识点总结)
目录 TCP基本概念 为什么需要TCP 什么是TCP 什么是TCP链接 如何唯一确定一个 TCP 连接 TCP三次握手 握手流程 为什么是三次握手,而不是两次、四次 为什么客户端和服务端的初始序列号 ISN 不同 既然 IP 层会分片,为什么 TCP 层还需要 MSS TCP四…...
ELK Stack 安装、配置以及集成到 Java 微服务中的使用
ELK Stack 是由 Elasticsearch、Logstash 和 Kibana 组成的日志管理解决方案。以下是详细的安装、配置步骤以及如何将其集成到 Java 微服务中。 1. 安装 ELK Stack 1.1 安装 Elasticsearch 在 Ubuntu 上安装 Elasticsearch: bash wget -qO - https://artifacts…...
list_
1.对象创建 // // Created by 徐昌真 on 2024/12/12. // #include <iostream> #include <list>using namespace std;void Print(list<int> &my_list) {for ( list<int>::iterator iter my_list.begin(); iter ! my_list.end(); iter ){cout <…...
电机驱动,为什么不需要变速器?
在现代汽车和工业应用中,电机驱动的技术愈发成熟,其核心优势之一是能够省去传统机械变速器的需求。 一、电机驱动的基本原理 电机驱动又被称为电动机驱动,其基本原理是将电能转化为机械能。通过控制电机的输入电压和电流,电机能…...
how to write 述职pptx as a tech manager
As a technical manager, crafting an effective 述职 (performance review) PPT requires you to highlight your leadership, team accomplishments, technical contributions, challenges faced, and future plans. Heres a structured approach to design your PPT: 1. Cov…...
关于QMessageBox的一些使用总结和避坑指南
参考学习 Qt中QMessageBox的用法—看这一篇就够了 Qt:使用QMessageBox弹出标准对话框 QMessageBox模态与非模态及QT中的exec() 如何调整QMessageBox的大小 QSS 自定义QMessageBox python QMessageBox设置标签和按钮居中、中文按钮 使用建议 经过查看多方的资料&…...
C语言预处理详解
1.预定义符号 C语言设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编译的时间 __STDC__ //如果编译器遵循ANSI C&#…...
大语言模型画图(流程图、框架图)
第一步:向随意大语言模型,描述内容,推荐豆包 豆包 加上下面Prompt 通过Mermaid语法,描述上面流程图 第二步:将生成Mermaid输入流程图生成网站 中文Mermaid - 流程图、关系图在线画图、生成和编辑器...
2024年API接口发展趋势:智能化、自动化引领潮流
随着信息技术的飞速发展,应用程序编程接口(API)已成为现代软件开发的核心组成部分。API作为不同系统之间的桥梁,使得数据、功能和服务能够在各种平台和设备之间无缝流动。在2024年,API接口正经历着一系列显著的变革和发…...
数据挖掘与机器学习DMML(part 8)K近邻(KNN)
K Nearest Neighbours KNN Definition KNN 是一种简单的算法,它存储所有可用案例,并根据相似度量对新案例进行分类。 KNN 不同名称: K-Nearest Neighbors • Memory-Based Reasoning基于记忆的推理 • Example-Based Reasoning基于实例的…...
Fortify 24.2.0版本最新版 win/mac/linux
工具介绍: Fortify SCA作为一款业内主流的静态代码扫描工具,被广泛应用于白盒测试中。与其他静态代码扫描工具相比,Fortify SCA的突出优势主要在于更加广泛地支持的语言和开发平台、更全面和权威的安全规则库使扫描更加全面、更加智能化的自定…...
突破时间与空间限制的富媒体百宝箱——智能工具箱:让云上内容生产更easy
“这是你的同款日常吗?老是在赶deadline,苦练PS还未出师,premiere、达芬奇真的好难,学python脑容量确实不够~打工人太难了~~” 来试试智能工具箱吧!即来即用,一键实现办公自由。图片工具、视频工具、音频工…...
MacOs使用Wine 安装UaExpert与UaExpert的使用
要在 macOS 上使用 Wine 安装和运行 UaExpert,可以按照以下步骤操作: 安装 Wine 在 macOS 上,你可以通过 Homebrew 来安装 Wine。如果你还没有安装 Homebrew,可以先安装 Homebrew,然后使用它来安装 Wine。 bash /bin…...
【Prompt Engineering】3.文本概括
一、引言 文本信息量大,LLM在文本概括任务上展现出强大能力。本章介绍如何通过编程方式调用API接口实现文本概括功能。 首先,我们需要引入 zhipuAI 包,加载 API 密钥,定义 getCompletion 函数。 from zhipuai import ZhipuAIke…...
力扣-图论-14【算法学习day.64】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…...
redis 架构详解
Redis架构详解可以从以下几个方面进行阐述: 一、部署架构 Redis有多种部署架构,适用于不同的应用场景和需求,主要包括以下几种: 单机模式(Standalone Mode) 特点:部署简单,配置方便…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
