深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)

39 篇文章 209 订阅
36 篇文章 150 订阅

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结合实现时间序列预测
  37. PyTorch搭建Informer实现长序列时间序列预测
  38. PyTorch搭建Autoformer实现长序列时间序列预测
  39. PyTorch搭建GNN(GCN、GraphSAGE和GAT)实现多节点、单节点内多变量输入多变量输出时空预测

LSTM参数

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

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

案例

简单搭建一个LSTM如下所示:

class LSTM(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 = 1 # 单向LSTM
        self.batch_size = batch_size
        self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True)
        self.linear = nn.Linear(self.hidden_size, self.output_size)

    def forward(self, input_seq):
        batch_size, seq_len = input_seq.shape[0], input_seq.shape[1]
        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)
        # output(batch_size, seq_len, num_directions * hidden_size)
        output, _ = self.lstm(input_seq, (h_0, c_0)) # output(5, 30, 64)
        pred = self.linear(output)  # (5, 30, 1)
        pred = pred[:, -1, :]  # (5, 1)
        return pred

其中定义模型的代码为:

self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True)
self.linear = nn.Linear(self.hidden_size, self.output_size)

我们加上具体的数字:

self.lstm = nn.LSTM(self.input_size=1, self.hidden_size=64, self.num_layers=5, batch_first=True)
self.linear = nn.Linear(self.hidden_size=64, self.output_size=1)

再看前向传播:

def forward(self, input_seq):
    batch_size, seq_len = input_seq.shape[0], input_seq.shape[1]
    h_0 = torch.randn(self.num_directions * self.num_layers, batch_size, self.hidden_size).to(device)
    c_0 = torch.randn(self.num_directions * self.num_layers, batch_size, self.hidden_size).to(device)
    # input(batch_size, seq_len, input_size)
    # output(batch_size, seq_len, num_directions * hidden_size)
    output, _ = self.lstm(input_seq, (h_0, c_0))  # output(5, 30, 64)
    pred = self.linear(output) # (5, 30, 1)
    pred = pred[:, -1, :]  # (5, 1)
    return pred

假设用前30个预测下一个,则seq_len=30,batch_size=5,由于设置了batch_first=True,因此,输入到LSTM中的input的shape应该为:

input(batch_size, seq_len, input_size) = input(5, 30, 1)

经过DataLoader处理后的input_seq为:

input_seq(batch_size, seq_len, input_size) = input_seq(5, 30, 1)

然后将input_seq送入LSTM:

output, _ = self.lstm(input_seq, (h_0, c_0))  # output(5, 30, 64)

根据前文,output的shape为:

output(batch_size, seq_len, num_directions * hidden_size) = output(5, 30, 64)

全连接层的定义为:

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

然后将output送入全连接层:

pred = self.linear(output)  # pred(5, 30, 1)

得到的预测值shape为(5, 30, 1),由于输出是输入右移,我们只需要取pred第二维度(time)中的最后一个数据:

pred = pred[:, -1, :]  # (5, 1)

这样,我们就得到了预测值,然后与label求loss,然后再反向更新参数即可。

时间序列预测的一个真实案例请见:PyTorch搭建LSTM实现时间序列预测(负荷预测)

下面是一个使用PyTorch搭建LSTM进行多变量输入多变量输出时间序列预测的示例代码,其包含数据预处理、模型搭建、训练和预测部分。 首先,假设我们有一个包含多个变量的时间序列数据集,每个变量都有多个时间步。我们需要将数据集分成训练集和测试集,并对数据进行标准化处理,这里使用scikit-learn库的MinMaxScaler进行归一化操作。 ```python import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler # 读取数据 data = pd.read_csv('data.csv', header=None) data = data.values # 分割数据集 train_size = int(len(data) * 0.8) train_data = data[:train_size] test_data = data[train_size:] # 标准化数据 scaler = MinMaxScaler(feature_range=(0, 1)) train_data = scaler.fit_transform(train_data) test_data = scaler.transform(test_data) ``` 接下来,我们需要将数据转换为输入输出对的形式,其每个样本的输入包含多个时间步的多个变量,输出为多个时间步的多个变量。我们可以定义一个函数来实现这个转换过程。 ```python def create_dataset(dataset, lookback=1, lookahead=1): X, Y = [], [] for i in range(len(dataset)-lookback-lookahead+1): X.append(dataset[i:(i+lookback), :]) Y.append(dataset[(i+lookback):(i+lookback+lookahead), :]) return np.array(X), np.array(Y) # 转换数据 lookback = 10 lookahead = 5 trainX, trainY = create_dataset(train_data, lookback, lookahead) testX, testY = create_dataset(test_data, lookback, lookahead) ``` 接下来,我们可以使用PyTorch搭建LSTM模型。这里使用两层LSTM,每层有64个隐藏单元。注意,输入输出的形状需要与数据集的形状相匹配。 ```python import torch import torch.nn as nn class LSTM(nn.Module): def __init__(self, input_size, output_size, hidden_size, num_layers): super().__init__() self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True) self.fc = nn.Linear(hidden_size, output_size) def forward(self, x): out, _ = self.lstm(x) out = self.fc(out[:, -1, :]) return out # 定义模型 input_size = trainX.shape[-1] output_size = trainY.shape[-1] hidden_size = 64 num_layers = 2 model = LSTM(input_size, output_size, hidden_size, num_layers) ``` 然后,我们需要定义损失函数和优化器。这里使用均方误差损失函数和Adam优化器。 ```python criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) ``` 现在,我们可以开始训练模型了。训练过程,我们使用批量梯度下降来更新模型参数。在每个epoch结束时,我们对模型在测试集上的表现进行评估。 ```python # 训练模型 num_epochs = 100 batch_size = 64 train_loss = [] test_loss = [] for epoch in range(num_epochs): # 训练模型 model.train() for i in range(0, len(trainX), batch_size): optimizer.zero_grad() inputs = torch.tensor(trainX[i:i+batch_size]).float() targets = torch.tensor(trainY[i:i+batch_size]).float() outputs = model(inputs) loss = criterion(outputs, targets) loss.backward() optimizer.step() train_loss.append(loss.item()) # 测试模型 model.eval() with torch.no_grad(): inputs = torch.tensor(testX).float() targets = torch.tensor(testY).float() outputs = model(inputs) loss = criterion(outputs, targets) test_loss.append(loss.item()) # 打印损失 print('Epoch [{}/{}], Train Loss: {:.4f}, Test Loss: {:.4f}' .format(epoch+1, num_epochs, train_loss[-1], test_loss[-1])) ``` 最后,我们可以使用训练好的模型进行预测。注意,预测过程需要将标准化后的输出重新还原为原始数据。 ```python # 预测模型 model.eval() with torch.no_grad(): inputs = torch.tensor(testX).float() outputs = model(inputs) preds = scaler.inverse_transform(outputs.numpy()) ``` 这就是使用PyTorch搭建LSTM进行多变量输入多变量输出时间序列预测的完整过程。
评论 89
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cyril_KI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值