我的编程空间,编程开发者的网络收藏夹
学习永远不晚

PyTorch搭建双向LSTM实现时间序列负荷预测

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

PyTorch搭建双向LSTM实现时间序列负荷预测

I. 前言

前面几篇文章中介绍的都是单向LSTM,这篇文章讲一下双向LSTM。

系列文章:

PyTorch搭建LSTM实现多变量多步长时序负荷预测

PyTorch搭建LSTM实现多变量时序负荷预测

PyTorch深度学习LSTM从input输入到Linear输出

PyTorch搭建LSTM实现时间序列负荷预测

II. 原理

关于LSTM的输入输出在深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)中已经有过详细叙述。

关于nn.LSTM的参数,官方文档给出的解释为:

总共有七个参数,其中只有前三个是必须的。由于大家普遍使用PyTorch的DataLoader来形成批量数据,因此batch_first也比较重要。LSTM的两个常见的应用场景为文本处理和时序预测,因此下面对每个参数我都会从这两个方面来进行具体解释。

  • input_size:在文本处理中,由于一个单词没法参与运算,因此我们得通过Word2Vec来对单词进行嵌入表示,将每一个单词表示成一个向量,此时input_size=embedding_size。
  • 比如每个句子中有五个单词,每个单词用一个100维向量来表示,那么这里input_size=100;
  • 在时间序列预测中,比如需要预测负荷,每一个负荷都是一个单独的值,都可以直接参与运算,因此并不需要将每一个负荷表示成一个向量,此时input_size=1。
  • 但如果我们使用多变量进行预测,比如我们利用前24小时每一时刻的[负荷、风速、温度、压强、湿度、天气、节假日信息]来预测下一时刻的负荷,那么此时input_size=7。
  • hidden_size:隐藏层节点个数。可以随意设置。
  • num_layers:层数。nn.LSTMCell与nn.LSTM相比,num_layers默认为1。
  • batch_first:默认为False,意义见后文。

Inputs

关于LSTM的输入,官方文档给出的定义为:

可以看到,输入由两部分组成:input、(初始的隐状态h_0,初始的单元状态c_0)​

其中input:

input(seq_len, batch_size, input_size)
  • seq_len:在文本处理中,如果一个句子有7个单词,则seq_len=7;在时间序列预测中,假设我们用前24个小时的负荷来预测下一时刻负荷,则seq_len=24。
  • batch_size:一次性输入LSTM中的样本个数。在文本处理中,可以一次性输入很多个句子;在时间序列预测中,也可以一次性输入很多条数据。
  • input_size:见前文。

(h_0, c_0):

h_0(num_directions * num_layers, batch_size, hidden_size)
c_0(num_directions * num_layers, batch_size, hidden_size)

h_0和c_0的shape一致。

  • num_directions:如果是双向LSTM,则num_directions=2;否则num_directions=1。
  • num_layers:见前文。
  • batch_size:见前文。
  • hidden_size:见前文。

Outputs

关于LSTM的输出,官方文档给出的定义为:

可以看到,输出也由两部分组成:otput、(隐状态h_n,单元状态c_n)

其中output的shape为:

output(seq_len, batch_size, num_directions * hidden_size)

h_n和c_n的shape保持不变,参数解释见前文。

batch_first

如果在初始化LSTM时令batch_first=True,那么input和output的shape将由:

input(seq_len, batch_size, input_size)
output(seq_len, batch_size, num_directions * hidden_size)

变为:

input(batch_size, seq_len, input_size)
output(batch_size, seq_len, num_directions * hidden_size)

即batch_size提前。

输出提取

假设最后我们得到了output(batch_size, seq_len, 2 * hidden_size),我们需要将其输入到线性层,有以下两种方法可以参考:

(1)直接输入

和单向一样,我们可以将output直接输入到Linear。在单向LSTM中:

self.linear = nn.Linear(self.hidden_size, self.output_size)

而在双向LSTM中:

self.linear = nn.Linear(2 * self.hidden_size, self.output_size)

模型:

class BiLSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size):
        super().__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.output_size = output_size
        self.num_directions = 2
        self.batch_size = batch_size
        self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True, bidirectional=True)
        self.linear = nn.Linear(self.num_directions * self.hidden_size, self.output_size)
    def forward(self, input_seq):
        h_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
        c_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
        # print(input_seq.size())
        seq_len = input_seq.shape[1]
        # input(batch_size, seq_len, input_size)
        input_seq = input_seq.view(self.batch_size, seq_len, self.input_size)
        # output(batch_size, seq_len, num_directions * hidden_size)
        output, _ = self.lstm(input_seq, (h_0, c_0))
        # print(self.batch_size * seq_len, self.hidden_size)
        output = output.contiguous().view(self.batch_size * seq_len, self.num_directions * self.hidden_size)  # (5 * 30, 64)
        pred = self.linear(output)  # pred()
        pred = pred.view(self.batch_size, seq_len, -1)
        pred = pred[:, -1, :]
        return pred

(2)处理后再输入

在LSTM中,经过线性层后的output的shape为(batch_size, seq_len, output_size)。假设我们用前24个小时(1 to 24)预测后2个小时的负荷(25 to 26),那么seq_len=24, output_size=2。根据LSTM的原理,最终的输出中包含了所有位置的预测值,也就是((2 3), (3 4), (4 5)…(25 26))。很显然我们只需要最后一个预测值,即output[:, -1, :]。

而在双向LSTM中,一开始output(batch_size, seq_len, 2 * hidden_size),这里面包含了所有位置的两个方向的输出。简单来说,output[0]为序列从左往右第一个隐藏层状态输出和序列从右往左最后一个隐藏层状态输出的拼接;output[-1]为序列从左往右最后一个隐藏层状态输出和序列从右往左第一个隐藏层状态输出的拼接。

如果我们想要同时利用前向和后向的输出,我们可以将它们从中间切割,然后求平均。比如output的shape为(30, 24, 2 * 64),我们将其变成(30, 24, 2, 64),然后在dim=2上求平均,得到一个shape为(30, 24, 64)的输出,此时就与单向LSTM的输出一致了。

具体处理方法:

output = output.contiguous().view(self.batch_size, seq_len, self.num_directions, self.hidden_size)
output = torch.mean(output, dim=2)

模型代码:

class BiLSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size):
        super().__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.output_size = output_size
        self.num_directions = 2
        self.batch_size = batch_size
        self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True, bidirectional=True)
        self.linear = nn.Linear(self.hidden_size, self.output_size)
    def forward(self, input_seq):
        h_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
        c_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
        # print(input_seq.size())
        seq_len = input_seq.shape[1]
        # input(batch_size, seq_len, input_size)
        input_seq = input_seq.view(self.batch_size, seq_len, self.input_size)
        # output(batch_size, seq_len, num_directions * hidden_size)
        output, _ = self.lstm(input_seq, (h_0, c_0))
        output = output.contiguous().view(self.batch_size, seq_len, self.num_directions, self.hidden_size)
        output = torch.mean(output, dim=2)
        pred = self.linear(output)
        # print('pred=', pred.shape)
        pred = pred.view(self.batch_size, seq_len, -1)
        pred = pred[:, -1, :]
        return pred

III. 训练和预测

数据处理、训练以及预测同前面几篇文章。

这里对单步长多变量的预测进行对比,在其他条件保持一致的情况下,得到的实验结果如下所示:

方法LSTMBiLSTM(1)BiLSTM(2)MAPE7.439.299.29

可以看到,仅针对我所使用的数据而言,单向LSTM的效果更好。对于前面提到的两种方法,貌似差异不大。

IV. 源码及数据

源码及数据我放在了GitHub上,LSTM-Load-Forecasting

以上就是PyTorch搭建双向LSTM实现时间序列负荷预测的详细内容,更多关于双向LSTM时序负荷预测的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

PyTorch搭建双向LSTM实现时间序列负荷预测

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Pytorch怎么实现LSTM时间序列预测

小编给大家分享一下Pytorch怎么实现LSTM时间序列预测,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!开发环境说明:Python 35Pytorch 0.2CPU/GPU均可1、LSTM简介人类在进行学习时,往往不总是
2023-06-15

PyTorch+LSTM实现单变量时间序列预测

时间序列是指在一段时间内发生的任何可量化的度量或事件。这篇文章主要为大家介绍了PyTorch+LSTM实现单变量时间序列预测的相关资料,需要的可以参考一下
2023-02-22

Python怎么实现LSTM时间序列预测

本篇内容主要讲解“Python怎么实现LSTM时间序列预测”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python怎么实现LSTM时间序列预测”吧!参考数据:数据一共两列,左边是日期,右边是乘
2023-06-02

PyTorch怎么搭建ANN实现时间序列风速预测

这篇文章主要介绍了PyTorch怎么搭建ANN实现时间序列风速预测的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇PyTorch怎么搭建ANN实现时间序列风速预测文章都会有所收获,下面我们一起来看看吧。数据集数据
2023-06-30

怎么使用PyTorch和LSTM实现单变量时间序列预测

这篇“怎么使用PyTorch和LSTM实现单变量时间序列预测”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用PyTor
2023-07-05

多维时序 | Matlab实现LSTM-Adaboost和LSTM多变量时间序列预测对比

多维时序 | Matlab实现LSTM-Adaboost和LSTM多变量时间序列预测对比 目录 多维时序 | Matlab实现LSTM-Adaboost和LSTM多变量时间序列预测对比预测效果基本介绍模型描述程序设计参考资料
2023-08-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录