PyTorch搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)

2022-10-16 14:38:21

I. 前言

前面已经写了很多关于时间序列预测的文章:

  1. 深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)
  2. PyTorch搭建LSTM实现时间序列预测(负荷预测)
  3. PyTorch搭建LSTM实现多变量时间序列预测(负荷预测)
  4. PyTorch搭建双向LSTM实现时间序列预测(负荷预测)
  5. PyTorch搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
  6. PyTorch搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  7. PyTorch搭建LSTM实现多变量多步长时间序列预测(三):多模型单步预测
  8. PyTorch搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  9. PyTorch搭建LSTM实现多变量多步长时间序列预测(五):seq2seq
  10. PyTorch中实现LSTM多步长时间序列预测的几种方法总结(负荷预测)
  11. PyTorch-LSTM时间序列预测中如何预测真正的未来值
  12. PyTorch搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)
  13. PyTorch搭建ANN实现时间序列预测(风速预测)
  14. PyTorch搭建CNN实现时间序列预测(风速预测)
  15. PyTorch搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)
  16. PyTorch搭建Transformer实现多变量多步长时间序列预测(负荷预测)
  17. PyTorch时间序列预测系列文章总结(代码使用方法)
  18. TensorFlow搭建LSTM实现时间序列预测(负荷预测)
  19. TensorFlow搭建LSTM实现多变量时间序列预测(负荷预测)
  20. TensorFlow搭建双向LSTM实现时间序列预测(负荷预测)
  21. TensorFlow搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
  22. TensorFlow搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  23. TensorFlow搭建LSTM实现多变量多步长时间序列预测(三):多模型单步预测
  24. TensorFlow搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  25. TensorFlow搭建LSTM实现多变量多步长时间序列预测(五):seq2seq
  26. TensorFlow搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)
  27. TensorFlow搭建ANN实现时间序列预测(风速预测)
  28. TensorFlow搭建CNN实现时间序列预测(风速预测)
  29. TensorFlow搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)

上面所有文章都是“单变量输出”,虽然某些文章中提到了“多变量”,但这个多变量只是输入多变量,而不是输出多变量。比如我们利用前24个时刻的[负荷、温度、湿度、压强]预测接下来12个时刻的负荷,此时输入为多变量,虽然有多个输出(多步长),但输出的都是同一变量。

那么有没有办法一次性输出多个变量呢?当然是可以的,在前几篇文章的评论中也有人提到了这个问题,当时我给出的回答是:“这样做效果很不好,不建议这么做”。

II. 多变量输入多变量输出

多变量输入自不必说,不了解的可以去看一下前面几篇文章。

多变量输出是指:我们一次性输出多个变量的预测值。比如我们利用前24小时的[负荷、温度、湿度、压强]预测接下来12个时刻的[负荷、温度、湿度、压强]。实际上,我们可以将多个变量的输出分解开来,看成多个任务,也就是多任务学习,其中每一个任务都是前面提到的多变量输入单变量输出

具体来讲,假设需要预测四个变量,输出在经过LSTM后得到output,我们将output分别通过四个全连接层,就能得到四个输出。得到四个输出后,我们就可以计算出四个损失函数,对这四个损失函数,本文将其简单求平均以得到最终的损失函数。关于如何组合多任务学习中的损失,已经有很多文献探讨过,感兴趣的可以自行了解。

III. 代码实现

3.1 数据处理

本次实验用到了两个数据集:数据集1包含某个地区的负荷、湿度以及能见度三个特征。数据集2中包含三个地区的负荷值。

数据集1:
在这里插入图片描述
数据集2:
在这里插入图片描述

依旧使用前24个时刻的三个变量预测后12个时刻的三个变量,数据处理同前面文章一致。

3.2 模型搭建

多输入多输出LSTM模型搭建如下:

classLSTM(nn.Module):def__init__(self, input_size, hidden_size, num_layers, output_size, batch_size, n_outputs):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
        self.n_outputs= n_outputs
        self.batch_size= batch_size
        self.lstm= nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True)# self.fcs = [nn.Linear(self.hidden_size, self.output_size).to(device) for i in range(self.n_outputs)]
        self.fc1= nn.Linear(self.hidden_size, self.output_size)
        self.fc2= nn.Linear(self.hidden_size, self.output_size)
        self.fc3= nn.Linear(self.hidden_size, self.output_size)defforward(self, input_seq):# print(input_seq.shape)
        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)# print(input_seq.size())# 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))
        preds=[]
        pred1, pred2, pred3= self.fc1(output), self.fc2(output), self.fc3(output)
        pred1, pred2, pred3= pred1[:,-1,:], pred2[:,-1,:], pred3[:,-1,:]# pred = torch.cat([pred1, pred2], dim=0)
        pred= torch.stack([pred1, pred2, pred3], dim=0)# print(pred.shape)return pred

可以看到,由于需要预测三个变量,所以我们在模型中定义了三个全连接层。在得到LSTM的输出后,分别利用三个全连接层得到三个变量的输出,再将三个输出进行拼接,得到最后的pred,pred的shape为:

predict(n_outputs, batch_size, output_size)

其中n_outputs=3,表示一次性预测三个变量,output_size=12表示这里采用了PyTorch搭建LSTM实现多变量多步长时间序列预测(一):直接多输出中的策略,一次性输出接下来12个时刻的预测值,因为是直接多输出,所以这里pred_step_size=output_size。

3.3 模型训练/测试

模型训练中,经过预测后,我们得到的label和pred的shape分别为:

label(batch_size, n_outputs, pred_step_size)
pred((n_outputs, batch_size, pred_step_size))

由于需要对每一个output计算损失然后相加求平均,所以我们的损失函数求解如下:

total_loss=0for kinrange(args.n_outputs):
    total_loss= total_loss+ loss_function(preds[k,:,:], labels[:, k,:])
total_loss/= preds.shape[0]

即每次都取出一个output进行计算求和再平均。

3.4 实验结果

数据集1中包含的是某个地区的负荷、湿度以及能见度三个特征,其预测结果如下所示:

变量负荷湿度能见度
MAPE9.76%6.44%8.49%

在这里插入图片描述
数据集2中包含三个地区的负荷值:

变量负荷1负荷2负荷3
MAPE5.37%8.89%6.29%

在这里插入图片描述

观察上述结果我们可以发现,数据集2上的预测效果明显更好,这可能是因为三个负荷变量之间相关性较强

IV. 源码及数据

后面将陆续公开~

  • 作者:Cyril_KI
  • 原文链接:https://blog.csdn.net/Cyril_KI/article/details/125242049
    更新时间:2022-10-16 14:38:21