动手学习深度学习(总结梳理)——19. 序列模型

目录

1. 背景介绍

1.1 统计工具

1.2 自回归模型

1.3 马尔可夫模型

1.4 因果关系

2. 训练

3. 预测

4. QA

4.1 在常规范围内tau是不是越大越好,像刚才的例子是不是tau取5要比4好?


1. 背景介绍

1.1 统计工具

1.2 自回归模型

1.3 马尔可夫模型

1.4 因果关系

2. 训练

在了解了上述统计工具后,让我们在实践中尝试一下! 首先,我们生成一些数据:使用正弦函数和一些可加性噪声来生成序列数据, 时间步为1,2,…,1000。

%matplotlib inline
import torch
from torch import nn
from d2l import torch as d2l

T = 1000  ''' 总共产生1000个点 '''
time = torch.arange(1, T + 1, dtype=torch.float32)
x = torch.sin(0.01 * time) + torch.normal(0, 0.2, (T,))
d2l.plot(time, [x], 'time', 'x', xlim=[1, 1000], figsize=(6, 3))

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
''' 只有前n_train个样本用于训练 '''
train_iter = d2l.load_array((features[: n_train], labels[:n_train]), batch_size, 
                                is_train = True)

在这里,我们使用一个相当简单的架构训练模型: 一个拥有两个全连接层的多层感知机,ReLU激活函数和平方损失。

''' 初始化网络权重的函数 '''
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)

3. 预测

由于训练损失很小,因此我们期望模型能有很好的工作效果。 让我们看看这在实践中意味着什么。 首先是检查模型预测下一个时间步的能力, 也就是单步预测(one-step-ahead prediction)。

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))

'''这里 T 代表我们最开始的自变量X的取值范围1000'''
multistep_preds = torch.zeros(T)
multistep_preds[: n_train + tau] = x[: n_train + tau]

'''从n_train + tau开始预测,每次预测使用它之前tau的时间特征值,化成(1,tau)向量训练'''
for i in range(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))

max_steps = 64

features = torch.zeros((T - tau - max_steps + 1, tau + 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))

 以上例子清楚地说明了当我们试图预测更远的未来时,预测的质量是如何变化的。 虽然“4步预测”看起来仍然不错,但超过这个跨度的任何预测几乎都是无用的。

4. QA

4.1 在常规范围内tau是不是越大越好,像刚才的例子是不是tau取5要比4好?

当然比4好,一般确实观察到更长更好,但是你tau大一方面样本数量少,另外一方面你特征多了,模型复杂了,其次一个时间序列越早的事物对后面的影响应该是越小,tau大了未必就一定能增加模型准确度。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值