(PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测

目录

  • I. 前言
  • II. TCN
  • III. TCN-RNN/LSTM/GRU
    • 3.1 TCN-RNN
    • 3.2 TCN-LSTM
    • 3.3 TCN-GRU
  • IV. 实验结果

I. 前言

前面已经写了一系列有关LSTM时间序列预测的文章:

  1. 深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)
  2. PyTorch搭建LSTM实现时间序列预测(负荷预测)
  3. PyTorch中利用LSTMCell搭建多层LSTM实现时间序列预测
  4. PyTorch搭建LSTM实现多变量时间序列预测(负荷预测)
  5. PyTorch搭建双向LSTM实现时间序列预测(负荷预测)
  6. PyTorch搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
  7. PyTorch搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  8. PyTorch搭建LSTM实现多变量多步长时间序列预测(三):多模型单步预测
  9. PyTorch搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  10. PyTorch搭建LSTM实现多变量多步长时间序列预测(五):seq2seq
  11. PyTorch中实现LSTM多步长时间序列预测的几种方法总结(负荷预测)
  12. PyTorch-LSTM时间序列预测中如何预测真正的未来值
  13. PyTorch搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)
  14. PyTorch搭建ANN实现时间序列预测(风速预测)
  15. PyTorch搭建CNN实现时间序列预测(风速预测)
  16. PyTorch搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)
  17. PyTorch搭建Transformer实现多变量多步长时间序列预测(负荷预测)
  18. PyTorch时间序列预测系列文章总结(代码使用方法)
  19. TensorFlow搭建LSTM实现时间序列预测(负荷预测)
  20. TensorFlow搭建LSTM实现多变量时间序列预测(负荷预测)
  21. TensorFlow搭建双向LSTM实现时间序列预测(负荷预测)
  22. TensorFlow搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
  23. TensorFlow搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  24. TensorFlow搭建LSTM实现多变量多步长时间序列预测(三):多模型单步预测
  25. TensorFlow搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  26. TensorFlow搭建LSTM实现多变量多步长时间序列预测(五):seq2seq
  27. TensorFlow搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)
  28. TensorFlow搭建ANN实现时间序列预测(风速预测)
  29. TensorFlow搭建CNN实现时间序列预测(风速预测)
  30. TensorFlow搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)
  31. PyG搭建图神经网络实现多变量输入多变量输出时间序列预测
  32. PyTorch搭建GNN-LSTM和LSTM-GNN模型实现多变量输入多变量输出时间序列预测
  33. PyG Temporal搭建STGCN实现多变量输入多变量输出时间序列预测
  34. 时序预测中Attention机制是否真的有效?盘点LSTM/RNN中24种Attention机制+效果对比
  35. 详解Transformer在时序预测中的Encoder和Decoder过程:以负荷预测为例
  36. (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测

时间卷积网络TCN和CNN都是一种利用卷积操作提取特征的模型,CNN是通过卷积层来提取图像中的特征,而TCN则通过时序卷积层来处理时间序列数据。TCN强调如何使用非常深的网络(residual)和膨胀卷积的组合来扩大感受野进而捕捉更广泛的上下文信息。

有关TCN的原理部分不做过多讲解,原理比较简单,下面直接讲解代码。

II. TCN

class Chomp1d(nn.Module):def __init__(self, chomp_size):super(Chomp1d, self).__init__()self.chomp_size = chomp_sizedef forward(self, x):"""裁剪的模块,裁剪多出来的padding"""return x[:, :, :-self.chomp_size].contiguous()class TemporalBlock(nn.Module):def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, padding, dropout=0.2):"""相当于一个Residual block:param n_inputs: int, 输入通道数:param n_outputs: int, 输出通道数:param kernel_size: int, 卷积核尺寸:param stride: int, 步长,一般为1:param dilation: int, 膨胀系数:param padding: int, 填充系数:param dropout: float, dropout比率"""super(TemporalBlock, self).__init__()self.conv1 = weight_norm(nn.Conv1d(n_inputs, n_outputs, kernel_size,stride=stride, padding=padding, dilation=dilation))# 经过conv1,输出的size其实是(Batch, input_channel, seq_len + padding)self.chomp1 = Chomp1d(padding)  # 裁剪掉多出来的padding部分,维持输出时间步为seq_lenself.relu1 = nn.ReLU()self.dropout1 = nn.Dropout(dropout)self.conv2 = weight_norm(nn.Conv1d(n_outputs, n_outputs, kernel_size,stride=stride, padding=padding, dilation=dilation))self.chomp2 = Chomp1d(padding)  # 裁剪掉多出来的padding部分,维持输出时间步为seq_lenself.relu2 = nn.ReLU()self.dropout2 = nn.Dropout(dropout)self.net = nn.Sequential(self.conv1, self.chomp1, self.relu1, self.dropout1,self.conv2, self.chomp2, self.relu2, self.dropout2)self.downsample = nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else Noneself.relu = nn.ReLU()self.init_weights()def init_weights(self):"""参数初始化:return:"""self.conv1.weight.data.normal_(0, 0.01)self.conv2.weight.data.normal_(0, 0.01)if self.downsample is not None:self.downsample.weight.data.normal_(0, 0.01)def forward(self, x):""":param x: size of (Batch, input_channel, seq_len):return:"""out = self.net(x)res = x if self.downsample is None else self.downsample(x)return self.relu(out + res)class TCN(nn.Module):def __init__(self, num_inputs, channels, kernel_size=2, dropout=0.2):""":param num_inputs: int, 输入通道数:param channels: list,每层的hidden_channel数,例如[25,25,25,25]表示有4个隐层,每层hidden_channel数为25:param kernel_size: int, 卷积核尺寸:param dropout: float, drop_out比率"""super(TCN, self).__init__()super().__init__()layers = []num_levels = len(channels)for i in range(num_levels):dilation_size = 2 ** i  # 膨胀系数:1,2,4,8……in_channels = num_inputs if i == 0 else channels[i - 1]  # 确定每一层的输入通道数out_channels = channels[i]  # 确定每一层的输出通道数layers += [TemporalBlock(in_channels, out_channels, kernel_size, stride=1, dilation=dilation_size,padding=(kernel_size - 1) * dilation_size, dropout=dropout)]self.network = nn.Sequential(*layers)def forward(self, x):""":param x: size of (Batch, input_channel, seq_len):return: size of (Batch, output_channel, seq_len)"""x = self.network(x)return x

可以看到这里TCN输入的尺寸是(batch_size, input_channel, seq_len),输出尺寸是(batch_size, output_channel, seq_len)。这与前面讲的文章大致类似,如果需要直接利用TCN得到输出,可以取输出的最后一个时间步,然后经过一个nn.Linear即可得到预测结果,即:

self.fc = nn.Linear(channels[-1], output_size)
x = x[:, :, -1]
x = self.fc(x)

III. TCN-RNN/LSTM/GRU

TCN的输出尺寸为(batch_size, output_channel, seq_len),这天然满足了RNN类模型的输入要求,因此将时序数据先经过TCN再经过RNN等模型是很自然的想法。

3.1 TCN-RNN

TCN-RNN模型搭建如下:

class TCN_RNN(nn.Module):def __init__(self):super(TCN_RNN, self).__init__()self.tcn = TCN(num_inputs=7, channels=[32, 32, 32])self.rnn = nn.RNN(input_size=32, hidden_size=64,num_layers=2, batch_first=True)self.fc = nn.Linear(64, 1)def forward(self, x):x = x.permute(0, 2, 1)  # b i sx = self.tcn(x)  # b h sx = x.permute(0, 2, 1)  # b s hx, _ = self.rnn(x)  # b, s, hx = x[:, -1, :]x = self.fc(x)  # b output_sizereturn x

由于我们构建的输入为(batch_size, seq_len, input_size),而TCN要求的输入为(batch_size, input_channel, seq_len),因此首先需要进行一个permute操作。经过TCN后,输出为(batch_size, output_channel, seq_len),其中output_channelchannels=[32, 32, 32]中最后一个数,即32。

接着RNN的输入应该为(batch_size, seq_len, output_channel),因此还需要经过一个permute。最后利用一个nn.Linear得到这个batch的预测结果。

3.2 TCN-LSTM

相比TCN-RNN,TCN-LSTM只是进行了简单替换:

class TCN_LSTM(nn.Module):def __init__(self):super(TCN_LSTM, self).__init__()self.tcn = TCN(num_inputs=7, channels=[32, 32, 32])self.lstm = nn.LSTM(input_size=32, hidden_size=64,num_layers=2, batch_first=True)self.fc = nn.Linear(64, 1)def forward(self, x):x = x.permute(0, 2, 1)  # b i sx = self.tcn(x)  # b h sx = x.permute(0, 2, 1)  # b s hx, _ = self.lstm(x)  # b, s, hx = x[:, -1, :]x = self.fc(x)  # b output_sizereturn x

3.3 TCN-GRU

TCN-GRU类似:

class TCN_GRU(nn.Module):def __init__(self):super(TCN_GRU, self).__init__()self.tcn = TCN(num_inputs=7, channels=[32, 32, 32])self.gru = nn.GRU(input_size=32, hidden_size=64,num_layers=2, batch_first=True)self.fc = nn.Linear(64, 1)def forward(self, x):x = x.permute(0, 2, 1)  # b i sx = self.tcn(x)  # b h sx = x.permute(0, 2, 1)  # b s hx, _ = self.gru(x)  # b, s, hx = x[:, -1, :]x = self.fc(x)  # b output_sizereturn x

IV. 实验结果

数据集依然选择前边的负荷预测数据集,前24小时的负荷+其余6个变量,预测未来1小时的负荷。由于TCN耗时较长,这里只使用了前5000条数据。

模型效果比较:

模型TCNTCN-RNNTCN-LSTMTCN-GRU
MAPE / %6.915.607.796.75

可以发现TCN-RNN的效果稍好一点,不过以上结果只针对本实验的数据集,并且没有经过调参,因此不具备太多参考性。

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

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

相关文章

算法训练第五十二天|300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

300. 最长递增子序列: 题目链接 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组…

Arduino驱动VL53L0X ToF激光测距传感器(距离传感器)

目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序 VL53L0X激光测距传感器是一款基于意法半导体(STMicroelectronics&#

python实现简易的flask后端接口

先安装插件pip install flask 新建py脚本文件编码: # -*- coding: utf-8 -*- from flask import Flask from flask_cors import CORS # 跨域依赖,通过pip install flask-cors安装app Flask(__name__) cors CORS(app) # 跨域设置,这样设置…

WPF容器的背景对鼠标事件的影响

背景:在实现鼠标拖动窗口的过程中发现对父容器设置了鼠标拖动窗口的事件MouseLeftButtonDown private void DragWindow(object sender, MouseButtonEventArgs e) {if (e.LeftButton MouseButtonState.Pressed)DragMove(); } 问题:非常困惑的是&#x…

C# windows服务程序开机自启动exe程序

我们使用传统的Process.Start(".exe")启动进程会遇到无法打开UI界面的问题,尤其是我们需要进行开启自启动程序设置时出现诸多问题,于是我们就想到采用windows服务开机自启动来创建启动一个新的exe程序,并且是显式运行。 首先是打开…

软件测试入门(知识汇总)

1、黑盒测试、白盒测试、灰盒测试 1.1 黑盒测试 黑盒测试又叫功能测试、数据驱动测试 或 基于需求规格说明书的功能测试。该类测试注重于测试软件的功能性需求。 采用这种测试方法,测试工程师把测试对象看作一个黑盒子,完全不考虑程序内部的逻辑结构和…

clickhouseSQL日期相关

1. 毫秒级时间戳转日期/小时 --13位时间戳转具体时间 toDateTime(report_time / 1000) as _c00 -- 获取时间戳对应的时间点整点(结果:%Y-%m-%d %H:00:00.0) eg:2022-09-28 23:00:00.0 toStartOfHour(toDateTime(report_time / 1000)) AS _10-- 获取时间…

Rust使用gRPC

需要先安装protoc(Protocol Buffers Compiler),可据此Protobuf Compiler Installation下载 第一步:创建项目 创建两个新的Rust项目,分别作为服务端与客户端: cargo new rust_grpc_servercargo new rust_grp…

简单的数组移动问题

https://leetcode.cn/problems/move-zeroes/?envTypestudy-plan-v2&envIdprogramming-skills 思路: 1.在原数组上直接操作,采用双指针的思想,每次移动r,当r不为0时交换num中的值 class Solution {public void moveZeroes(in…

超级解压馆帮助与支持

游戏目标: 将相同颜色的筹码移动到同一排,当一排筹码颜色相同并装满时,你可以合成新数字。挑战你的智力,看你能拼出的最大数字是多少! 游戏玩法: 将相同颜色的数字币移动到相同颜色的数字币槽中。 观察所…

【操作系统习题】处理机调度与死锁

一、单选题 FCFS算法的就绪队列是按照进程的()排列。 B A、等待时间 B、到达时间 C、响应时间 D、运行时间设有4个作业同时到达,每个作业的执行时间均为2个小时,它们在一台处理机上按单道方式执行,则平均周转时间为&a…

LeetCode2413. Smallest Even Multiple

文章目录 一、题目二、题解 一、题目 Given a positive integer n, return the smallest positive integer that is a multiple of both 2 and n. Example 1: Input: n 5 Output: 10 Explanation: The smallest multiple of both 5 and 2 is 10. Example 2: Input: n 6 O…

PAT 乙级 1042 字符统计

请编写程序,找出一段给定文字中出现最频繁的那个英文字母。 输入格式: 输入在一行中给出一个长度不超过 1000 的字符串。字符串由 ASCII 码表中任意可见字符及空格组成,至少包含 1 个英文字母,以回车结束(回车不算在内…

Winform中使用Fleck实现Websocket服务端并读取SQLite数据库中数据定时循环群发消息

场景 Winform中使用Websocket4Net实现Websocket客户端并定时存储接收数据到SQLite中: Winform中使用Websocket4Net实现Websocket客户端并定时存储接收数据到SQLite中-CSDN博客 Winform中操作Sqlite数据增删改查、程序启动时执行创建表初始化操作: Wi…

Vue3 结合typescript 组合式函数(2)

安装axios:npm install axios 1、hooks文件夹下新建useURLLoader 在APP.VUE中使用useURLLoader 使用Dog API 2、使用对象中的属性,必须使用toRefs,否则Reactive响应失效 3、使用泛型 结果:

Linux iptables地址转换

一.SNAT场景配置 实现内网主机通过防火墙访问公网,需要使用SNAT(源地址转换POSTROUTING) 1、指定从哪个ip地址转换出去(静态公网地址) SNAT配置:必须使用nat表;iptables -t nat -I POSTROUTING -s 172.16.1.0/24 -j SNAT --to 10.0.0.200 ip…

C++不懂就问:std::vector的push_back和emplace_back函数的差别?

欢迎关注公众号(20YC编程),视频号也有免费视频课程哦! -今日内容- 1 emplace_back介绍 std::vector的emplace_back(包括emplace)函数是C11引入的新特性,用于在容器中直接构造元素,而不是先构造元素再插入…

拧巴的 tcp

本来想说说 tcp fastopen(tfo),但没什么意义,看 rfc7413 好了,还是 tcp 的惯常套路,引入一个新特性,解决了某个问题,带来一些新问题,然后就是各种 tradeoff,哪里适用哪里不适用。久而…

3 - 字段约束|MySQL索引|MySQL用户管理

字段约束|MySQL索引|MySQL用户管理 字段约束主键外键 MySQL索引索引介绍优缺点索引使用规则索引的分类索引的管理 用户管理用户授权权限撤销 用户权限追加user表的使用 字段约束 设置在表头上,用来限制字段赋值 包括: 是否允许给…

基于深度学习的交通标志图像分类识别系统

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文详细探讨了一基于深度学习的交通标志图像识别系统。采用TensorFlow和Keras框架,利用卷积神经网络(CNN)进行模型训练和预测,并引入VGG16迁移学习…