时序模型中,当前数据与之前观察到的数据有关自回归模型使用自身过去数据预测未来马尔可夫模型假设当前只跟最近少数数据相关,进而简化模型潜变量模型使用潜变量来概括历史信息
导入相关的包
import torch from torch import nn from d2l import torch as d2l import matplotlib.pyplot as plt
使用正弦函数和一些可加性噪声生成序列数据
T = 1000 #总的的点数
x = torch.arange(1,T+1,dtype=torch.float32)
y = torch.sin(0.01*x)+torch.normal(0,0.2,(T,))
plt.figure(figsize=(8,4))
plt.xlim((0,1000))
plt.ylim((-1.5,1.5))
plt.xlabel('time')
plt.ylabel('y')
plt.plot(x,y)
plt.show()
模型预测下一个时间步
#PyTorch数据迭代加载
def load_array(data_arrays,batch_size,is_train=True):
dataset = TensorDataset(*data_arrays)
return DataLoader(dataset,batch_size,shuffle=is_train)
#序列转换为模型的“特征-标签”
tau = 4
features = torch.zeros((T - tau, tau))
for i in range(tau):
features[:, i] = x[i:T - tau + i]
labels = x[tau:].reshape((-1, 1))
batch_size, n_train = 16, 600
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)
#MPL
def get_net():
net = nn.Sequential(
nn.Linear(4,10),
nn.ReLU(),
nn.Linear(10,1)
)
net.apply(init_weights)
return net
def evaluate_loss(net, data_iter, loss):
metric = d2l.Accumulator(2) # 损失的总和,样本数量
for X, y in data_iter:
out = net(X)
y = y.reshape(out.shape)
l = loss(out, y)
metric.add(l.sum(), l.numel())
return metric[0] / metric[1]
#训练
def train(net,train_iter,loss,epochs,lr):
optimilizer = torch.optim.Adam(net.parameters(),lr)
for epoch in range(epochs):
for X,y in train_iter:
optimilizer.zero_grad()
l = loss(net(X),y)
l.sum().backward()
optimilizer.step()
print(f'epoch {epoch + 1}, '
f'loss: {evaluate_loss(net, train_iter, loss):f}')
loss = nn.MSELoss(reduction='none')
net = get_net()
train(net,train_iter,loss,10,0.01)
onestep_preds = net(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))
d2l.plt.show()
多步预测
max_steps = 64
features = torch.zeros((T - tau - max_steps + 1, tau + max_steps))
for i in range(tau):
features[:, i] = x[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))
总结:
对于时间是向前推进的因果模型,正向估计通常⽐反向估计更容易。对于直到时间步t的观测序列,其在时间步t + k的预测输出是“k步预测”。随着我们对预测时间k值的增加,会造成误差的快速累积和预测质量的极速下降。



