用pytorch写lstm预测多变量时间序列
时间: 2023-10-01 20:12:41 浏览: 117
首先,你需要准备好你的数据。对于多变量时间序列数据,你需要将每个变量作为一个特征,并将它们放在一起形成一个二维数组 x,每行代表一个时间步骤。另外,你需要一个一维数组 y,代表每个时间步骤的目标值。这些数据需要被划分为训练集和测试集。
接下来,你需要构建一个 LSTM 模型。你可以使用 PyTorch 的 `nn.LSTM` 模块来构建 LSTM 层。然后,你可以使用 `nn.Linear` 模块构建一个全连接层,将 LSTM 层的输出映射到一个具有多个特征的输出空间。
下面是一个简单的 LSTM 模型示例:
```
import torch.nn as nn
class LSTM(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(LSTM, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size, hidden_size, num_layers)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(1), self.hidden_size)
c0 = torch.zeros(self.num_layers, x.size(1), self.hidden_size)
out, _ = self.lstm(x, (h0, c0))
out = self.fc(out[-1, :, :])
return out
```
在这个模型中,我们使用 `nn.LSTM` 构建 LSTM 层,输入大小为 `input_size`,隐藏大小为 `hidden_size`,层数为 `num_layers`。然后我们使用 `nn.Linear` 构建一个全连接层,将 LSTM 输出映射到具有 `output_size` 个特征的输出空间。
接下来,你需要定义损失函数和优化器。对于回归问题,我们可以使用均方误差(MSE)作为损失函数,并使用随机梯度下降(SGD)或者 Adam 作为优化器。
```
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
```
然后,你可以开始训练模型。在每个训练迭代中,你需要将输入数据 x 传递到模型中,得到预测 y_pred。然后计算损失值并进行反向传播,更新模型参数。
```
for epoch in range(num_epochs):
# Forward pass
outputs = model(x_train)
loss = criterion(outputs, y_train)
# Backward and optimize
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch+1) % 100 == 0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))
```
最后,你可以使用训练好的模型进行预测。你需要将测试数据 x_test 传递给模型,得到预测值 y_pred。然后你可以计算预测值与真实值之间的误差,并可视化它们的比较。
```
with torch.no_grad():
y_pred = model(x_test)
loss = criterion(y_pred, y_test)
print('Test Loss: {:.4f}'.format(loss.item()))
plt.plot(y_test.numpy(), label='True')
plt.plot(y_pred.numpy(), label='Predicted')
plt.legend()
plt.show()
```
完整的代码示例:
```
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
# Prepare data
# Here we generate a simple time series data with 2 features
def generate_data(num_data):
x = np.random.randn(num_data, 2)
y = np.zeros((num_data, 1))
for i in range(2, num_data):
y[i] = 0.5 * y[i-1] + 0.2 * y[i-2] + 0.1 * x[i-2, 0] + 0.3 * x[i-1, 1] + 0.4
return x, y
x_train, y_train = generate_data(100)
x_test, y_test = generate_data(50)
# Define model
class LSTM(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(LSTM, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size, hidden_size, num_layers)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(1), self.hidden_size)
c0 = torch.zeros(self.num_layers, x.size(1), self.hidden_size)
out, _ = self.lstm(x, (h0, c0))
out = self.fc(out[-1, :, :])
return out
model = LSTM(input_size=2, hidden_size=16, num_layers=2, output_size=1)
# Define loss and optimizer
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
# Train the model
num_epochs = 1000
for epoch in range(num_epochs):
# Convert numpy arrays to torch tensors
inputs = torch.from_numpy(x_train).float()
targets = torch.from_numpy(y_train).float()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, targets)
# Backward and optimize
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch+1) % 100 == 0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))
# Test the model
with torch.no_grad():
x_test = torch.from_numpy(x_test).float()
y_test = torch.from_numpy(y_test).float()
y_pred = model(x_test)
loss = criterion(y_pred, y_test)
print('Test Loss: {:.4f}'.format(loss.item()))
# Visualize the results
plt.plot(y_test.numpy(), label='True')
plt.plot(y_pred.numpy(), label='Predicted')
plt.legend()
plt.show()
```
这是一个简单的 LSTM 模型,你可以根据自己的需求进行修改和扩展。
阅读全文