LSTM-多变量-单时间步-pytorch-负荷预测(多时间步采用滚动预测)

问题描述

使用LSTM做负荷预测问题,数据共计456行,每一行3个特征,用过去N个时间段特征,预测未来第N+1个时间点的特征,数据格式如下,用00:00:00-04:00:00的[feature1,feature2,feature3],预测第05:00:00的[feature1,feature2,feature3]。本问题属于多变量预测,输入是多变量-多时间步,输出也是多变量,只不过输出是一个时间点,可以使用循环的方式预测多个时间步。
在这里插入图片描述

模块导入

import pandas as pd
import matplotlib.pyplot as plt
import torch.nn as nn
import torch
import time
import numpy as np
import random

2 数据处理

2.1 数据导入以及可视化

data = pd.read_csv("负荷-3变量.csv")
data.plot()
plt.show()

在这里插入图片描述

2.2 划分测试集和训练集

data = data.iloc[:, [1, 2, 3]].values  # 获取数值 456 *3
p = 48 # 预测未来48个小时的数据
train_data = data[:-p]
test_data = data[-p:]
  • train_data 维度:408*3
  • test_data 维度:48*3

2.3 数据归一化

每一列都需要单独归一化,所以axis的值为0

min_data = np.min(train_data, axis=0)
max_data = np.max(train_data, axis=0)
train_data_scaler = (train_data - min_data) / (max_data - min_data)

2.4 将一个序列划分为x和y

制作数据集,对应的x和y,假设用前12个时间步预测第13个时间点,则:

  • x 维度:12 *3
  • y 维度:1 *3
    假设用前24个时间步预测第25个时间点,则:
  • x 维度:24 *3
  • y 维度:1 *3
def get_x_y(data, step=12):
    # x : 12*3
    # y: 1 *3
    x_y = []
    for i in range(len(data) - step):
        x = data[i:i + step, :]
        y = np.expand_dims(data[i + step, :], 0)
        x_y.append([x, y])
    return x_y

2.5 生成mini_batch数据

假设batch_size = 16, 则生成的数据维度为:

  • x:16* 12 * 3
  • y: 16 * 1 * 3
def get_mini_batch(data, batch_size=16):
    # x: 16 * 12 *3
    # y :16 * 1 *3
    for i in range(0, len(data) - batch_size, batch_size):
        samples = data[i:i + batch_size]
        x, y = [], []
        for sample in samples:
            x.append(sample[0])
            y.append(sample[1])
        yield np.asarray(x), np.asarray(y)

3 模型搭建和训练

3.1 搭建模型

在处理多变量预测时,我们将lstm输出分别连接3个fc层,每个变量都单独计算loss,再把loss进行相加作为总的loss,示意图如下所示:
在这里插入图片描述

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
class LSTM(nn.Module):  # 注意Module首字母需要大写
    def __init__(self, hidden_size, num_layers, output_size, batch_size):
        super().__init__()
        self.hidden_size = hidden_size  # 隐含层神经元数目 100
        self.num_layers = num_layers  # 层数 通常设置为2
        self.output_size = output_size  # 48 一次预测下48个时间步
        self.num_directions = 1
        self.input_size = 3
        self.batch_size = batch_size
        # 初始化隐藏层数据
        self.hidden_cell = (
            torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device),
            torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device))

        self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True).to(device)
        self.fc1 = nn.Linear(self.hidden_size, self.output_size).to(device)
        self.fc2 = nn.Linear(self.hidden_size, self.output_size).to(device)
        self.fc3 = nn.Linear(self.hidden_size, self.output_size).to(device)

    def forward(self, input):
        output, _ = self.lstm(torch.FloatTensor(input).to(device), self.hidden_cell)
        pred1, pred2, pred3 = self.fc1(output), self.fc2(output), self.fc3(output)
        pred1, pred2, pred3 = pred1[:, -1, :], pred2[:, -1, :], pred3[:, -1, :]
        pred = torch.stack([pred1, pred2, pred3], dim=2)
        return pred

3.2 训练模型

epochs = 200
for i in range(epochs):
    start = time.time()
    for seq_batch, label_batch in get_mini_batch(train_x_y, batch_size):
        optimizer.zero_grad()
        y_pred = model(seq_batch)
        loss = 0
        for j in range(3):
            loss += loss_function(y_pred[:,:, j], torch.FloatTensor(label_batch[:, :, j]).to(device))
        loss /= 3
        loss.backward()  # 调用loss.backward()自动生成梯度,
        optimizer.step()  # 使用optimizer.step()执行优化器,把梯度传播回每个网络
        # 查看模型训练的结果
    print(f'epoch:{i:3} loss:{loss.item():10.8f} time:{time.time() - start:6}')

3.3 预测模型

model.eval()
with torch.no_grad():
   model.hidden_cell = (torch.zeros(1 * num_layers, 1, hidden_size).to(device),
                        torch.zeros(1 * num_layers, 1, hidden_size).to(device))
   # 测试集
   total_test_loss = 0
   test_pred = np.zeros(shape=(p, 3))
   for i in range(len(test_data)):
       x = train_data_scaler[-time_step:, :]
       x1 = np.expand_dims(x, 0)
       test_y_pred_scalar = np.expand_dims(model(x1).cpu().squeeze().numpy(), 0)  # 预测的值0-1
       train_data_scaler = np.append(train_data_scaler, test_y_pred_scalar, axis=0)
       y = test_y_pred_scalar * (max_data - min_data) + min_data
       test_pred[i,:] = y

   x_in = list(range(len(test_pred)))

3.4 结果可视化

loss图像
在这里插入图片描述

最后3个变量的预测结果,看出能预测大体趋势,但是数据集质量不高,导致最后的结果不好,模型也需要继续优化。
在这里插入图片描述

完整代码和数据集,关注公众号:AI学习部 ,发送“时间序列”关键词获取,或联系Q 596520206
  • 2
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
以下是使用 PyTorch 实现 LSTM 时间序列预测的示例代码: 首先,需要导入所需的库: ```python import torch import torch.nn as nn from torch.autograd import Variable import numpy as np ``` 接着,定义 LSTM 模型: ```python class LSTM(nn.Module): def __init__(self, input_size, hidden_size, output_size=1, num_layers=2): super().__init__() self.hidden_size = hidden_size self.num_layers = num_layers 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): h0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size)) c0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size)) out, _ = self.lstm(x, (h0, c0)) out = self.fc(out[:, -1, :]) return out ``` 在这个模型中,我们使用了一个 LSTM 层和一个全连接层,输入是一个序列,输出是一个标量。 接下来,定义训练函数: ```python def train(model, dataloader, criterion, optimizer, num_epochs): for epoch in range(num_epochs): for i, (inputs, targets) in enumerate(dataloader): inputs = Variable(inputs) targets = Variable(targets) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, targets) loss.backward() optimizer.step() if (i+1) % 10 == 0: print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, i+1, len(dataloader), loss.data[0])) ``` 在训练函数中,我们传入模型、数据加载器、损失函数和优化器,以及训练的轮数。在每个轮次中,我们遍历数据加载器,将输入和目标变量转换为张量并将它们包装在变量中。然后,我们将梯度归零,计算模型的输出和损失,反向传播并更新模型参数。每 10 ,我们打印一次损失。 最后,定义测试函数: ```python def test(model, dataloader): model.eval() with torch.no_grad(): for inputs, targets in dataloader: inputs = Variable(inputs) targets = Variable(targets) outputs = model(inputs) loss = criterion(outputs, targets) inputs = inputs.data.numpy() targets = targets.data.numpy() outputs = outputs.data.numpy() plt.plot(inputs[:, :, 0].flatten(), label='input') plt.plot(targets.flatten(), label='target') plt.plot(outputs.flatten(), label='output') plt.legend() plt.show() ``` 在测试函数中,我们将模型设置为评估模式,并遍历数据加载器获取输入和目标变量。然后,我们计算模型的输出和损失,并将输入、目标和输出可视化。 最后,我们可以使用以下代码来加载数据、定义模型、设置损失函数和优化器,并开始训练: ```python # Load data data = np.loadtxt('data.csv', delimiter=',', dtype=np.float32) X = data[:, :-1] y = data[:, -1:] X = np.reshape(X, (X.shape[0], X.shape[1], 1)) # Define hyperparameters input_size = 1 hidden_size = 2 output_size = 1 num_layers = 1 batch_size = 4 num_epochs = 100 # Define model, loss function and optimizer model = LSTM(input_size, hidden_size, output_size, num_layers) criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # Train the model train_dataset = torch.utils.data.TensorDataset(torch.from_numpy(X), torch.from_numpy(y)) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) train(model, train_loader, criterion, optimizer, num_epochs) # Test the model test_dataset = torch.utils.data.TensorDataset(torch.from_numpy(X), torch.from_numpy(y)) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False) test(model, test_loader) ``` 这里假设数据集已经存在于 `data.csv` 文件中,包含输入和目标变量。首先,我们将数据加载到 NumPy 数组中,并将输入重塑为三维数组。接下来,我们定义了一些超参数,包括输入大小、隐藏大小、输出大小、层数、批量大小和训练轮数。然后,我们定义了模型、损失函数和优化器,并使用数据加载器开始训练。最后,我们使用相同的数据加载器测试模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

王小葱鸭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值