实现单变量时间序列数据预测的
时间: 2024-03-12 21:50:20 浏览: 73
以下是使用PyTorch实现单变量时间序列数据预测的代码:
```python
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
class TimeSeriesDataset(torch.utils.data.Dataset):
def __init__(self, data, sequence_length):
self.data = data
self.sequence_length = sequence_length
def __len__(self):
return len(self.data) - self.sequence_length
def __getitem__(self, index):
x = self.data[index:index+self.sequence_length]
y = self.data[index+self.sequence_length]
return x, y
class TimeSeriesPredictor(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers):
super(TimeSeriesPredictor, self).__init__()
self.lstm = nn.LSTM(input_size, hidden_size, num_layers)
self.linear = nn.Linear(hidden_size, output_size)
def forward(self, x):
lstm_out, _ = self.lstm(x)
y = self.linear(lstm_out[-1])
return y
def train_model(model, dataloader, criterion, optimizer, num_epochs):
model.train()
for epoch in range(num_epochs):
for x, y in dataloader:
optimizer.zero_grad()
x = x.unsqueeze(0)
y_hat = model(x)
loss = criterion(y_hat, y)
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print('Epoch: {}, Loss: {:.5f}'.format(epoch, loss.item()))
def test_model(model, dataloader):
model.eval()
with torch.no_grad():
y_true = []
y_pred = []
for x, y in dataloader:
x = x.unsqueeze(0)
y_hat = model(x)
y_true.append(y.item())
y_pred.append(y_hat.item())
return np.array(y_true), np.array(y_pred)
# load data
data = pd.read_csv('data.csv')
data = data['value'].values.astype(float)
# plot data
plt.plot(data)
plt.show()
# normalize data
data = (data - np.mean(data)) / np.std(data)
# split data into train and test sets
train_data = data[:800]
test_data = data[800:]
# create datasets and dataloaders
train_dataset = TimeSeriesDataset(train_data, sequence_length=30)
test_dataset = TimeSeriesDataset(test_data, sequence_length=30)
train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=1, shuffle=True)
test_dataloader = torch.utils.data.DataLoader(test_dataset, batch_size=1, shuffle=False)
# create model, optimizer, and loss function
model = TimeSeriesPredictor(input_size=1, hidden_size=10, output_size=1, num_layers=1)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.MSELoss()
# train model
train_model(model, train_dataloader, criterion, optimizer, num_epochs=100)
# test model
y_true, y_pred = test_model(model, test_dataloader)
# plot results
plt.plot(y_true, label='true')
plt.plot(y_pred, label='pred')
plt.legend()
plt.show()
```
这里我们定义了一个名为 `TimeSeriesDataset` 的数据集类,用于将原始时间序列数据转换为模型训练所需的输入和输出。类中的 `__len__` 方法返回数据集中样本的数量,`__getitem__` 方法返回给定索引处的样本。
接着,我们定义了一个名为 `TimeSeriesPredictor` 的模型类,它由一个 LSTM 层和一个全连接层组成。在模型的前向传播函数中,我们首先将输入数据传递给 LSTM 层,然后取出最后一个时间步的输出,通过全连接层输出预测结果。
在训练模型时,我们首先创建了一个 `TimeSeriesDataset` 实例和对应的数据加载器。然后,我们定义了一个名为 `train_model` 的函数,用于训练模型。在函数中,我们首先将模型设置为训练模式。然后,对于每个训练批次,我们使用优化器将模型的参数梯度清零,计算模型的预测值和损失,进行反向传播,并使用优化器更新模型的参数。最后,我们每隔一定的周期输出一次当前的训练损失。
在测试模型时,我们首先将模型设置为评估模式,并使用 `torch.no_grad()` 上下文管理器禁用梯度计算。然后,对于每个测试样本,我们使用模型预测输出,并将预测结果和真实标签存储在数组中。
最后,我们使用 `matplotlib` 库绘制了预测结果和真实标签的折线图。
阅读全文