Ai-8循环神经网络

本章的循环神经网络(recurrent neural network,RNN)可以更好地处理序列信息。 循环神经网络通过引入状态变量存储过去的信息和当前的输入,从而可以确定当前的输出。许多使用循环网络的例子都是基于文本数据的,因此我们将在本章中重点介绍语言模型。

8.1. 序列模型

为了实现对下一时间某数值的预测,我们需要引入新的模型:自回归模型,马尔可夫模型以及因果关系模型。

对于直到时间步t的观测序列,其在时间步k+t的预测输出是“k步预测”。随着我们对预测时间k值的增加,会造成误差的快速累积和预测质量的极速下降。

 

练习:

  • 改进本节实验中的模型。

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

设置为4时,模型中包含了四个过去的观测结果,真实值在代码中规定了

batch_size, n_train = 16, 600
# 只有前n_train个样本用于训练
    • 如果没有噪音,需要多少个过去的观测结果?提示:把sincos写成微分方程。

      需要一个

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

     答:可以采用滑动窗口的方式生成特征矩阵feature,这种方式在原有特征矩阵中移动窗口的起始位置,并没有增加新的特征维度。通过利用过去的观察结果作为输入特征,通过合并旧的观察结果,可以提供更丰富的特征信息,使得模型可以捕捉到序列数据中的时间相关性,从而有效提高预测准确度。

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

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

  答:因为影响证券回报的不只是时间因素,未来一段时间该证券相关的政治经济事件都会对其收益产生影响。

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

   文本存在较多的不确定性。

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

  答:隐变量自回归模型是一种用于建模时间序列数据中的动态变化的自回归模型。动力学模型则是一种描述系统状态随时间变化的数学模型,在该模型中,系统的状态可以用一组状态变量来表示,并且这些状态变量随着时间的推移而发生变化。

8.2. 文本预处理

每个文本序列又被拆分成一个词元列表,词元(token)是文本的基本单位。 最后,返回一个由词元列表组成的列表,其中的每个词元都是一个字符串(string)。文本被分割为词元。

词元的类型是字符串,而模型需要的输入是数字,因此这种类型不方便模型使用。 现在,让我们构建一个字典,通常也叫做词表(vocabulary), 用来将字符串类型的词元映射到从0开始的数字索引中。

对它们的唯一词元进行统计, 得到的统计结果称之为语料(corpus)。 然后根据每个唯一词元的出现频率,为其分配一个数字索引。 很少出现的词元通常被移除,这可以降低复杂性。

练习:

1词元化是一个关键的预处理步骤,它因语言而异。尝试找到另外三种常用的词元化文本的方法。

BPE(Byte-Pair Encoding),WordPiece和SentencePiece

2在本节的实验中,将文本词元为单词和更改Vocab实例的min_freq参数。这对词表大小有何影响?

8.3. 语言模型和数据集

为了训练语言模型,我们需要计算单词的概率, 以及给定前面几个单词后出现某个单词的条件概率。 这些概率本质上就是语言模型的参数。

一种常见的策略是执行某种形式的拉普拉斯平滑(Laplace smoothing), 具体方法是在所有计数中添加一个小常量。 用n表示训练集中的单词总数,用m表示唯一单词的数量,然而,这样的模型很容易变得无效,首先,我们需要存储所有的计数; 其次,这完全忽略了单词的意思。 例如,“猫”(cat)和“猫科动物”(feline)可能出现在相关的上下文中, 但是想根据上下文调整这类模型其实是相当困难的。 最后,长单词序列大部分是没出现过的, 因此一个模型如果只是简单地统计先前“看到”的单词序列频率, 那么模型面对这种问题肯定是表现不佳的。

读取长序列的主要方式是随机采样和顺序分区。在迭代过程中,后者可以保证来自两个相邻的小批量中的子序列在原始序列上也是相邻的,这种策略在基于小批量的迭代过程中保留了拆分的子序列的顺序,因此称为顺序分区。

练习;

1假设训练数据集中有100,000个单词。一个四元语法需要存储多少个词频和相邻多词频率?

1e5各词频,相邻多词频,需要P(A|B),P(C|A,B),P(D|A,B,C)即1e10+1e15+1e20

2我们如何对一系列对话建模?

当成一段文本?

3一元语法、二元语法和三元语法的齐普夫定律的指数是不一样的,能设法估计么?

齐普夫定律认为,排名与频率之间存在的负相关的关系。即对于大规模文本,将其中每个词的词频进行统计,并由高到低排序标号,则这些单词的频数和这些单词的序号之间存在一个常数,满足

4想一想读取长序列数据的其他方法?

5考虑一下我们用于读取长序列的随机偏移量。

为什么随机偏移量是个好主意?它真的会在文档的序列上实现完美的均匀分布吗?要怎么做才能使分布更均匀?

答:如果固定偏移量,则会导致迭代后,每次迭代所获取到的子序列均只覆盖有限的序列范围,无法保证全部序列的覆盖性。

不能实现完美的均匀分布,因为加入偏移量后无法保证每个采样点的采样概率完全相等。

6如果我们希望一个序列样本是一个完整的句子,那么这在小批量抽样中会带来怎样的问题?如何解决?

答:小批量采用也许会导致句子完整性被破坏,解决方案是手动控制采用方式,防止句子被阶段。

8.4. 循环神经网络

循环神经网络需要记录变量在时间序列上的变化,与多层感知机不同的是, 我们在这里保存了前一个时间步的隐藏变量Ht−1, 并引入了一个新的权重参数Whh∈Rh×h, 来描述如何在当前时间步中使用前一个时间步的隐藏变量。 从相邻时间步的隐藏变量Ht和 Ht−1之间的关系可知, 这些变量捕获并保留了序列直到其当前时间步的历史信息, 就如当前时间步下神经网络的状态或记忆, 因此这样的隐藏变量被称为隐状态(hidden state)。 由于在当前时间步中, 隐状态使用的定义与前一个时间步中使用的定义相同, 因此 隐状态计算是循环的(recurrent)

值得一提的是,即使在不同的时间步,循环神经网络也总是使用这些模型参数。 因此,循环神经网络的参数开销不会随着时间步的增加而增加。

如何度量语言模型的质量? 如果想要压缩文本,我们可以根据当前词元集预测的下一个词元。 一个更好的语言模型应该能让我们更准确地预测下一个词元。 因此,它应该允许我们在压缩序列时花费更少的比特。 所以我们可以通过一个序列中所有的n个词元的交叉熵损失的平均值来衡量:

自然语言处理的科学家更喜欢使用一个叫做困惑度(perplexity)的量,他是交叉熵平均值的指数。

 

练习:

1如果我们使用循环神经网络来预测文本序列中的下一个字符,那么任意输出所需的维度是多少?

答:对于一个批量大小为,时间步为维采样数据,经过one-hot编码后转换为三维张量(时间步,批量大小,词表大小),假设词表大小为,此时循环神经网络的输入维度为

2为什么循环神经网络可以基于文本序列中所有先前的词元,在某个时间步表示当前词元的条件概率?

答:在循环神经网络中,通过引入隐状态的概念,使得RNN模型可以通过隐状态保留了直到当前时间步的历史信息,根据这些过去历史信息,循环神经网络可以预测出当前时间步,某词语出现的条件概率。

3如果基于一个长序列进行反向传播,梯度会发生什么状况?

答:链式求导时,序列太长,可能会导致梯度消失或爆炸。

 

8.5. 循环神经网络的从零开始实现

从头开始基于循环神经网络实现字符级语言模型。

train_iter中,每个词元都表示为一个数字索引, 将这些索引直接输入神经网络可能会使学习变得困难。 我们通常将每个词元表示为更具表现力的特征向量。 最简单的表示称为独热编码(one-hot encoding)。简言之,将每个索引映射为相互不同的单位向量: 假设词表中不同词元的数目为N(即len(vocab)), 词元索引的范围为0N−1。 如果词元的索引是整数i, 那么我们将创建一个长度为N的全0向量, 并将第i处的元素设置为1

为了定义循环神经网络模型, 我们首先需要一个init_rnn_state函数在初始化时返回隐状态。 这个函数的返回是一个张量,张量全用0填充, 形状为(批量大小,隐藏单元数)

让我们首先定义预测函数来生成prefix之后的新字符, 其中的prefix是一个用户提供的包含多个字符的字符串。 在循环遍历prefix中的开始字符时, 我们不断地将隐状态传递到下一个时间步,但是不生成任何输出。 这被称为预热(warm-up)期。

梯度裁决:使用η>0作为学习率时,在一次迭代中, 我们将x更新为x−ηg。 如果我们进一步假设目标函数f表现良好, 即函数f在常数L下是利普希茨连续的(Lipschitz continuous)。 这意味着我们不会观察到超过Lη‖g‖的变化。 这既是坏事也是好事。 坏的方面,它限制了取得进展的速度; 好的方面,它限制了事情变糟的程度,尤其当我们朝着错误的方向前进时。一个流行的替代方案是通过将梯度g投影回给定半径 (例如θ)的球来裁剪梯度g

梯度裁剪可以防止梯度爆炸,但不能应对梯度消失。

练习:

1尝试说明独热编码等价于为每个对象选择不同的嵌入表示。

  可视为单位向量

2通过调整超参数(如迭代周期数、隐藏单元数、小批量数据的时间步数、学习率等)来改善困惑度。

困惑度可以降到多少?用可学习的嵌入表示替换独热编码,是否会带来更好的表现?如果用H.G.Wells的其他书作为数据集时效果如何, 例如*世界大战*

困惑度最小为1;若采用可学习嵌入表示对one-hot编码进行替换,会带来更好的表现,因为可学习的嵌入表示可以将相似近义词映射到相似嵌入向量中,而不是one-hot中相互独立的向量基。

3修改预测函数,例如使用采样,而不是选择最有可能的下一个字符。,会发生什么?调整模型使之偏向更可能的输出,例如,当α>1,从q(xt∣xt−1,…,x1)∝P(xt∣xt−1,…,x1)α中采样。

改变采样方式,会提高随机性,但可能生成文本不稳定。

4在不裁剪梯度的情况下运行本节中的代码会发生什么?

不裁剪梯度的情况下,会出现数值不稳定的现象。困惑度不平滑

5更改顺序划分,使其不会从计算图中分离隐状态。运行时间会有变化吗?困惑度呢?

答:对顺序划分进行修改,先对输入和标签进行设备变换和形状变换,再进行前向计算和反向传播,因此可以避免隐状态从计算图中分离的问题。

6用ReLU替换本节中使用的激活函数,并重复本节中的实验。我们还需要梯度裁剪吗?为什么?

答:而ReLU作为激活函数时,其梯度在输入为正时恒为1,输入为负时恒为0,因此在反向传播时通常不会出现数值不稳定现象,无需进行梯度裁剪。

 

8.6. 循环神经网络的简洁实现

 

练习:

1尝试使用高级API,能使循环神经网络模型过拟合吗?

答:在高级API中,针对循环神经网络进行了一系列优化,例如nn.RNN源码中增加了可开启的Dropout模块,以及可选的ReLU激活函数,d2l.train_ch8函数中也默认开启了梯度裁剪。

2如果在循环神经网络模型中增加隐藏层的数量会发生什么?能使模型正常工作吗?

模型训练速度减慢,模型可能会过拟合。

隐藏层为1                                                                         3

 

8.7. 通过时间反向传播

通过时间反向传播(backpropagation through time,BPTT) (Werbos, 1990)实际上是循环神经网络中反向传播技术的一个特定应用。 

通过链式法则来求梯度会导致出现非常长的梯度链,因此需要想办法解决此问题。

我们可以在τ步后截断中的求和计算。 这会带来真实梯度的近似。这样做导致该模型主要侧重于短期影响,而不是长期影响。

练习:

1假设我们拥有一个对称矩阵M∈Rn×n,其特征值为λi,对应的特征向量是vii=1,…,n)。通常情况下,假设特征值的序列顺序为|λi|≥|λi+1|

证明Mk拥有特征值λik。证明对于一个随机向量x∈RnMkx将有较高概率与M的特征向量v1在一条直线上。形式化这个证明过程。上述结果对于循环神经网络中的梯度意味着什么?

答:可将上述公式中的理解为权重矩阵,当循环神经网络中,权重矩阵的特征向量与输入向量满足:  其中根据在特征向量上投影的大小所决定,的变化会导致权重矩阵的变化,进而使得其在反向传播时的梯度受到影响。这种变化会随着序列长度的增加不断加剧,使得梯度不断放大或缩小,导致梯度爆炸或梯度消失的问题。

2除了梯度截断,还有其他方法来应对循环神经网络中的梯度爆炸吗?

答:还有长短期记忆,改变激活函数等方法。

posted @ 2023-07-22 21:45  浪矢-CL  阅读(280)  评论(0编辑  收藏  举报