首页 > 其他分享 >《动手学深度学习 Pytorch版》 8.1 序列模型

《动手学深度学习 Pytorch版》 8.1 序列模型

时间:2023-10-08 23:11:33浏览次数:36  
标签:8.1 loss tau epoch Pytorch train steps 序列 net

到目前为止,我们遇到的数据主要是表格数据和图像数据,并且所有样本都是独立同分布的。然而,大多数的数据并非如此。比如语句中的单词、视频中的帧以及音频信号,都是有顺序的。

简言之,如果说卷积神经网络可以有效地处理空间信息,那么本章的循环神经网络(recurrent neural network,RNN)则可以更好地处理序列信息。循环神经网络通过引入状态变量存储过去的信息和当前的输入,从而可以确定当前的输出。

8.1.1 统计工具

处理序列数据需要统计工具和新的深度神经网络架构。以下以富时100指数为例,用 \(x_t\) 表示价格,即在时间步(time step) \(t\in\Z^+\) 时,观察到的价格 \(x\)。需要注意的是,\(t\) 对于本文中的序列通常是离散的,并在整数或其子集上变化。可以通过以下途径预测股市中表现良好的时间 \(t\) 日:

\[x\sim P(x_t|x_{t-1},\dots,x_1) \]

image

自回归模型

如果依然使用类似 3.3节的线性模型。最主要的问题就是输入数据的数量,输入数据的数量会随着我们遇到的数据量的增加而增加,因此需要一个近似方法来使这个计算变得容易处理。

评估 \(P(x_t|x_{t-1},\dots,x_1)\) 有以下两种策略:

  • 自回归模型:

    序列 \(x_{t-1},\dots,x_1\) 可能不是必要的,可以取一个时间跨度 \(\tau\),使用观测序列 \(x_{t-1},\dots,x_{t-\tau}\) 作为输入数据。自回归指的是对自己执行回归。

  • 隐变量自回归模型:

    保留一些对过去观测的总结 \(h_t\),并且同时更新预测 \(\hat{x}_t\) 和总结 \(h_t\)。即使用 \(\hat{x}_t=P(x_t|h_t)\) 估计 \(x_t\),使用 \(h_t=g(h_{t-1},x_{t-1})\) 更新模型。隐变量指的是 \(h_t\) 从未被观察测到。

    image

上述两个方法的整个序列的估计值都将通过以下的方式获得:

\[P(x_1,\dots,x_T)=\prod^T_{t=1}P(x_t|x_{t-1},\dots,x_1) \]

马尔可夫模型

在自回归模型的近似法中使用时间跨度 \(\tau\) 而不是全部序列来估计 \(x_t\)。只要这种是近似精确的,就可以说序列满足马尔可夫条件。

如果 \(\tau=1\) 则得到一个一阶马尔可夫模型,\(P(x)\) 由下式给出:

\[P(x_1,\dots,x_T)=\prod^T_{t=1}P(x_t|x_{t-1})\ \ \ 当 P(x_1|x_0)=P(x_1) \]

当 \(x_t\) 仅是离散值时,使用动态规划可以沿着马尔可夫链精确地计算结果。如,我们可以高效地计算 \(P(x_{t+1}|x_{t-1})\):

\[\begin{align} P(x_{t+1}|x_{t-1})&=\frac{\sum_{x_t}P(x_{t+1},x_t,x_{t-1})}{P(x_{t-1})}\\ &=\frac{\sum_{x_t}P(x_{t+1}|x_t,x_{t-1})P(x_t,x_{t-1})}{P(x_{t-1})}\\ &=\sum_{x_t}P(x_{t+1}|x_t)P(x_t|x_{t-1}) \end{align} \]

因果关系

原则上,将 \(P(x_1,\dots,x_T)\) 倒序展开也没什么问题。事实上,基于一个马尔可夫模型还可以得到一个反向的条件概率分布。然而,在许多情况下,数据存在一个自然的方向,即在时间上是前进的。很明显,未来的事件不能影响过去。即如果我们改变 \(x_t\) 可能会影响未来发生的事情 \(x_{t+1}\),但不能反过来。也就是说,如果我们改变 \(x_t\),基于过去事件得到的分布不会改变。因此,解释 \(P(x_{t+1}|x_t)\) 比解释 \(P(x_t|x_{t+1})\) 更容易。

8.1.2 训练

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

首先使用正弦函数和一些可加性噪声来生成序列数据,时间步为 \(1,2,\dots,1000\)。

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

image

接下来将这个序列转换为模型的特征-标签对。

tau = 4  # 时间步长为4,即使用前四个状态预测第五个状态
features = torch.zeros((T - tau, tau))
for i in range(tau):  # features内容 0,1,2,3; 1,2,3,4; 4,5,6,7; ......
    features[:, i] = x[i: T - tau + i]
labels = x[tau:].reshape((-1, 1))  # labels内容 4; 5; 6;......
# 最终效果4->0,1,2,3; 5->1,2,3,4; 6->4,5,6,7; ......

batch_size, n_train = 16, 600  # 只用前600个样本训练

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, 5, 0.01)
epoch 1, loss: 0.060140
epoch 2, loss: 0.056048
epoch 3, loss: 0.054582
epoch 4, loss: 0.050818
epoch 5, loss: 0.052746

8.1.3 预测

进行单步预测,用模型根据前面四个真实值预测后面一个值,效果不错,即使时间超过了 604 预测结果依然可信。

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

image

不使用真实值进行预测,而是使用前次预测的预测值进行预测。可以看到 604 以后的数据纯纯瞎搞。可能是由于预测误差一步步累积的结果。

multistep_preds = torch.zeros(T)
multistep_preds[: n_train + tau] = x[: n_train + 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))

image

进行 k 步预测,即只给四个真实值,然后预测接下来 k 个点。下面分别用 k = 1, 4, 16, 64进行测试。可以看到1到16预测基本可信,虽然也是步长越大越不准。到64步时完全就是瞎预测了。

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

image

练习

(1)改进本节实验中的模型。

a. 是否包含了过去 4 个以上的观测结果?真实值需要是多少个?

b. 如果没有噪音,需要多少个过去的观测结果?提示:把 sin 和 cos 写成微分方程。

c. 可以在保持特征总数不变的情况下合并旧的观察结果吗?这能提高正确度吗?为什么?

d. 改变神经网络架构并评估其性能。

a. 这什么鬼翻译啊,明明就是让你试试不同的 tau,以下面的结果来看, tau稍大点有好处,但也不是越大越好

def test(tau):
    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 get_net():
        net = nn.Sequential(nn.Linear(tau, 10),
                            nn.ReLU(),
                            nn.Linear(10, 1))
        net.apply(init_weights)
        return net

    net = get_net()
    print(f'tau={tau}')
    train(net, train_iter, loss, 5, 0.01)

    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))
test(4)  # tau=4
tau=4
epoch 1, loss: 0.064608
epoch 2, loss: 0.054984
epoch 3, loss: 0.051668
epoch 4, loss: 0.051454
epoch 5, loss: 0.050462

image

test(8)  # tau=8
tau=8
epoch 1, loss: 0.070842
epoch 2, loss: 0.059001
epoch 3, loss: 0.052746
epoch 4, loss: 0.051375
epoch 5, loss: 0.045521

image

test(64)  # tau=64
tau=64
epoch 1, loss: 0.091182
epoch 2, loss: 0.105368
epoch 3, loss: 0.057070
epoch 4, loss: 0.052301
epoch 5, loss: 0.057420

image

test(16)  # tau=16
tau=16
epoch 1, loss: 0.062968
epoch 2, loss: 0.056878
epoch 3, loss: 0.047163
epoch 4, loss: 0.044272
epoch 5, loss: 0.047251

image

b. 没有噪音岂不是只要前一个就行了?


(2)一位投资者想要找到一种好的证券来购买。他查看过去的回报,以决定哪一种可能是表现良好的。这一策略可能会出什么问题呢?

证券需要考虑的特征可太多了,只看过去哪个回报高而不考虑复杂的影响因素所得的预测结果可能和抛硬币没啥区别。


(3)时间是向前推进的因果模型在多大程度上适用于文本呢?

文本的因果性应该更复杂些,比如某些文学性比较高的文章,倒叙、插叙、乱序之类的手法会很大的影响时间是向前推进的因果模型


(4)举例说明什么时候可能需要隐变量自回归模型来捕捉数据的动力学模型。

比如按分小组顺序汇报,每个组都会根据前一组的表现和老师点评来修正自己的PPT。

标签:8.1,loss,tau,epoch,Pytorch,train,steps,序列,net
From: https://www.cnblogs.com/AncilunKiang/p/17750444.html

相关文章

  • pytorch(8-1) 循环神经网络 序列模型
    https://zh.d2l.ai/chapter_recurrent-neural-networks/sequence.html     #%matplotlibinlineimporttorchfromtorchimportnnfromd2limporttorchasd2lfromAPI_Drawimport*T=1000#总共产生1000个点#time[0,1...,999]time=torch.arange(......
  • 密码协议学习笔记(8.16):几种特殊的秘密分享体系
    已知两个秘密的碎片,计算秘密的乘积的碎片:已知两个秘密$\alpha_0,\beta_0$分别实现了门限值为$t$的分享记$$f_{\alpha}(x)=\alpha_0+\alpha_1x+\cdots+\alpha_{t-1}x^{t-1}$$$$f_{\beta}(x)=\beta_0+\beta_1x+\cdots+\beta_{t-1}x^{t-1}$$秘密碎片为$$A_1=f_{\alpha}(1),A_2=......
  • Unity 通信方案 - 使用 Google Protobuf 序列化数据
    1.下载和编译1.1下载ProtoBuf源文件从github下载最新的protoBuf库,如下图所示 Releases·protocolbuffers/protobuf(github.com)1.2编译dll和导入解压后打开/scharp/src中的sln工程文件 选择Release,Google.Protobuf,之后在生成中生成文件在......
  • 密码协议学习笔记(8.15):知识证据详解
    在开始前,先回顾以下的知识点:离散对数问题(DiscretelogarithmProblem,DLP)难解性猜想:给定以大素数$p$为阶的循环群$G$,$g,h\inG$是两个生成元(在素数阶群上等价于非恒等元),求解$t$,使得$h^t=g$在计算上是不可行的.Diffie-Hellman的计算难解性(ComputationalDiffie-Hellm......
  • 数据结构的关键码序列的理解概述
    1、关键码序列的理解所谓关键码序列,就是出现在二叉排序树中的,对二叉排序树的各个结点进行排序的一个结点序列。依据左子树的各个结点的值都小于父结点的值,右子树的各个结点的值都大于父结点的值的条件进行排序。2、习题解决一般都是给我们一个二叉排序树的图,让我们去判断选......
  • pytorch训练模版
    train.pyimporttorchimportnumpyasnpimportosimportmathimportsysimportargparseimportpsutilimporttorchimporttorch.optimasoptimimporttorch.optim.lr_scheduleraslr_schedulerfromtorchvisionimporttransformsimporttorchvisionimportd......
  • pytorch 自定义dataset类
    实现模版classour_dataset(Dataset):def__init__(self,···):super(our_dataset,self).__init__()#初始化,可以自定义添加参数def__getitem__(self,index):···returnimg,label#根据索引(0,len(dataset)-1)获取......
  • Mysql 分布式序列算法
    接上文Mysql分库分表1.分布式序列简介在分布式系统下,怎么保证ID的生成满足以上需求?ShardingJDBC支持以上两种算法自动生成ID。这里,使用ShardingJDBC让主键ID以雪花算法进行生成,首先配置数据库,因为默认的注解id是int类型,装不下64位,需要进行修改:#在本地和远端服务器数据......
  • pytorch F.grid_sample
    importtorchfromtorch.nnimportfunctionalasFinp=torch.ones(1,1,4,4)inp=torch.randint(1,10,(1,1,4,4)).float()#目的是得到一个长宽为20的tensorout_h=20out_w=20#grid的生成方式等价于用mesh_gridnew_h=torch.linspace(-1,1,out_h).v......
  • Excel快速下拉填充序列至10000行
    问题:想要下拉输入的数据递增得到1、2、3……10000,但是手动下拉太累解决:1.如在A1单元格输入1,在A2单元格输入22.选中A2单元格,在上方名称框中填写A2:A1000,回车,此时将选中A2:A10003.在编辑栏中填写=A1+1,按Ctrl+回车,便可得到一万条递增数据1、2、3……100004.同上效果,可在编辑栏......