51序列模型
import torch
from torch import nn
from d2l import torch as d2l
import matplotlib.pyplot as pltT = 1000 # 总共产生1000个点
time = torch.arange(1, T + 1, dtype=torch.float32)
x = torch.sin(0.01 * time) + torch.normal(mean=0, std=0.2, size=(T,))
d2l.plot(time, [x], 'time', 'x', xlim=[1, 1000], figsize=(6, 3))
plt.show()tau = 4
features = torch.zeros((T - tau, tau)) # torch.Size([996, 4])
for i in range(tau):# features 矩阵的每一行将包含时间序列中连续 tau 个时间步的数据features[:, i] = x[i: T - tau + i]
"""
x = [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ...]
features = [[x0, x1, x2, x3],[x1, x2, x3, x4],[x2, x3, x4, x5],[x3, x4, x5, x6],[x4, x5, x6, x7],[x5, x6, x7, x8],...
]
"""
labels = x[tau:].reshape((-1, 1))batch_size, n_train = 16, 600
# 只有前n_train个样本用于训练
train_iter = d2l.load_array((features[:n_train], labels[:n_train]),batch_size, is_train=True)# 初始化网络权重的函数
def init_weights(m):if type(m) == nn.Linear:nn.init.xavier_uniform_(m.weight)# 一个简单的多层感知机
def get_net():net = nn.Sequential(nn.Linear(4, 10),nn.ReLU(),nn.Linear(10, 1))net.apply(init_weights)return net# 平方损失。注意:MSELoss计算平方误差时不带系数1/2
loss = nn.MSELoss(reduction='none')def train(net, train_iter, loss, epochs, lr):trainer = torch.optim.Adam(net.parameters(), lr)for epoch in range(epochs):for X, y in train_iter:trainer.zero_grad()l = loss(net(X), y)l.sum().backward()trainer.step()print(f'epoch {epoch + 1}, 'f'loss: {d2l.evaluate_loss(net, train_iter, loss):f}')net = get_net()
train(net, train_iter, loss, 10, 0.01)
# epoch 8, loss: 0.044640
# epoch 9, loss: 0.045863
# epoch 10, loss: 0.045066# 单步预测
onestep_preds = net(features) #对输入特征 features 进行单步预测。
d2l.plot([time, time[tau:]],[x.detach().numpy(), onestep_preds.detach().numpy()], 'time','x', legend=['data', '1-step preds'], xlim=[1, 1000],figsize=(6, 3))
"""
[time, time[tau:]]:表示 x 轴的数据。time 是完整的时间序列,time[tau:] 是从第 tau 个时间步开始的时间序列,长度为 T - tau。
[x.detach().numpy(), onestep_preds.detach().numpy()]:表示 y 轴的数据。x 是实际的时间序列数据,onestep_preds 是神经网络的预测结果。使用 detach().numpy() 将 PyTorch 张量转换为 NumPy 数组,以便绘图函数可以处理。
'time':x 轴的标签,表示时间。
'x':y 轴的标签,表示时间序列数据的值。
legend=['data', '1-step preds']:图例,分别标记实际数据和单步预测。
xlim=[1, 1000]:设置 x 轴的范围,从 1 到 1000。
figsize=(6, 3):设置图的大小,宽度为 6 英寸,高度为 3 英寸。
"""
plt.show()# 多步预测
multistep_preds = torch.zeros(T) # 用于存储多步预测的结果
multistep_preds[: n_train + tau] = x[: n_train + tau]
# 将 x 的前 n_train + tau 个元素复制到 multistep_preds 的对应位置。
# 这样做是为了在进行多步预测之前,保留训练集和前 tau 个时间步的数据。
for i in range(n_train + tau, T): # 从 n_train + tau 开始到 T,逐步进行预测。multistep_preds[i] = net(multistep_preds[i - tau:i].reshape((1, -1)))d2l.plot([time, time[tau:], time[n_train + tau:]],[x.detach().numpy(), onestep_preds.detach().numpy(),multistep_preds[n_train + tau:].detach().numpy()], 'time','x', legend=['data', '1-step preds', 'multistep preds'],xlim=[1, 1000], figsize=(6, 3))
plt.show()# 生成特征矩阵进行多步预测
max_steps = 64 # 最大预测步数为64
features = torch.zeros((T - tau - max_steps + 1, tau + max_steps))# tau 列是时间序列 x 的观测数据,而后 max_steps 列是基于前面列的预测结果。
# 列i(i<tau)是来自x的观测,其时间步从(i)到(i+T-tau-max_steps+1)
for i in range(tau):features[:, i] = x[i: i + T - tau - max_steps + 1]
# 列i(i>=tau)是来自(i-tau+1)步的预测,其时间步从(i)到(i+T-tau-max_steps+1)
for i in range(tau, tau + max_steps):features[:, i] = net(features[:, i - tau:i]).reshape(-1)steps = (1, 4, 16, 64)
d2l.plot([time[tau + i - 1: T - max_steps + i] for i in steps],[features[:, (tau + i - 1)].detach().numpy() for i in steps], 'time', 'x',legend=[f'{i}-step preds' for i in steps], xlim=[5, 1000],figsize=(6, 3))
plt.show()"""
1-step 预测:每一步预测只预测下一个时间步的数据。模型每次使用的是最近的观测数据进行预测。
4-step 预测:每一步预测预测接下来的四个时间步的数据。模型需要预测四步后的数据。
16-step 预测:每一步预测预测接下来的十六个时间步的数据。模型需要预测更远的未来数据。
64-step 预测:每一步预测预测接下来的六十四个时间步的数据。模型需要预测很远的未来数据。
"""
单步预测:
多步预测: