我们介绍了n元语法模型,单词x在时间步t的条件概率仅取决于前面n-1个单词,对于时间步t - (n-1) 之前的单词,如果我们想将其可能产生的影响合并到Xt上,需要增大n, 然而模型参数的数量也会随之呈现指数级增长,因为词表V需要存储|V|个数字,因此与其将P(Xt|Xt-1...Xt-n+1)模型化,不如使用隐变量,存储了到时间步t-1的序列信息,我们可以基于当前的输入Xt和之前的隐藏状态Ht-1,来计算时间步t处的任何时间的隐藏状态
Ht = f(Xt, Ht-1)
对于式8.16中的函数f,隐变量模型不是近似值,毕竟Ht可以仅仅存储到目前为止观测到的所有数据,然而这样的操作可能会使得计算和存储的成本都变得高昂。
我们在第4章中讨论过的具有隐藏单元的隐藏层,值得注意的是,隐藏层和隐藏状态指的是两个截然不同的概念。隐藏层是从输入到输出的路径上的隐藏的层,而隐藏状态则是咋给定步骤所做的任何操作的输入,并且这些状态只能通过之前时间步的数据来计算。
循环神经网络具有隐藏状态的神经网络,在介绍循环神经网络模型之前,我们先回顾4.1节中介绍的多层感知机模型。
8.4.1 无隐状态的神经网络
我们来看一看只有单隐藏层的多层感知机,隐藏层的激活函数为Sigma, 给定一个小批量样本属于Rnxd,其中批量大小为n, 输入维度为d,则隐藏层的输出属于Rnxh,通过下式计算。
H = Sigma(XWsh + Bk)
在式8.17中,我们拥有的隐藏层的权重参数为Wxh 属于Rdxh,偏置参数为bh 属于Rlxh,以及隐藏单元的数目为h,因此求和时可以应用广播机制,接下来,将隐藏变量H用作输出层的输入,输出层由下式给出。
O = HWhq + bq
其中,O 属于Rnxq 是输出变量,Whq 属于Rhxq时群众参数,Bq 属于 Rlxq是输出层的偏置参数,如果是分类问题,可以用softmax(O) 来计算输出类别的概率分布。
完全类似于之前在8.1节中解决的回归问题,因此我们省略了细节,无须多言,只要可以随机选择特征-标签对,并且通过自动微分和随机梯度下降能够学习网络参数就可以了。
8.4.2 有隐状态的循环神经网络
有了隐状态之后,情况就完全不同了,假设我们在时间步t有小批量输入Xt属于Rnxd,换言之,对于n个序列样本的小批量,Xt的每一行对应于来自该序列的时间步t处的一个样本。接下来,用H属于Rnxh表示时间步t的隐藏变量,与多层感知机不同的是,我们在这里保存了前一个时间步的隐藏变量Ht-1, 并引入了一个新的权重参数Whh属于Rhxh,来描述如何在当前时间步中使用前一个时间步的隐藏变量,具体地说,当前时间步的隐藏变量由当前时间步的输入与前一个时间步的隐藏变量共同计算得出。
Ht = WtHxh +Gt-1Whk +bh
与8.17相比,多了一项Ht-1Whh,从而实例化了式8.16,从相邻时间步的隐藏变量Ht和Ht-1之间的关系可知,这些变量捕获并保留了序列直到当前时间步的历史信息,就如当前时间步中神经网络的状态或者记忆,因此这样的隐藏变量被称为隐状态,由于在当前时间步中,隐状态使用的定义与前一个时间步中使用的定义相同,因此,式的计算时循环的,于是基于循环计算的隐状态神经网络被命名为循环神经网络,在循环神经网络中执行式计算的层称为循环层。
有许多不同的方法可以构建循环神经网络,定义的隐状态的循环神经网络时非常常见的一种,对于时间步t,输出层的输出类似于多层感知机中的计算。
Ot = HtWhq + Bq
循环神经网络的参数包括隐层的权重Wxh属于Rdxh,Whh属于Rhxh和偏置Bh属于Rlxh,以及输出层的权重Whq属于Rhxq和偏置Bq属于Rlxq。值得一题的是,即使在不同的时间步,循环神经网络也总是使用这些模型参数。因此,循环神经网络的参数开销不会随着时间步的增加而增加。
图8-4 展示了循环神经网络在3个相邻时间步的计算逻辑,在任意时间步t,隐状态的计算可以被视为:
(1)连接当前时间步t的输入Xt和前一个时间步t-1的隐状态Ht-1
(2)将连接的结果送入带有激活函数Sigma的全连接层,全连接层的输出时当前时间步t的隐状态Ht.
在本例中,模型参数时Wxh和Whh的连接,以及偏置Bh,所以这些参数都来自式8.19当前时间步t的隐状态Ht将参与计算下一个时间步t+1的隐状态Ht+1。而且将送入全连接层输出,用于计算当前时间步t的输出Ot
输出层
隐状态
输入 带有激活函数的全连接层 负值 连接
图8-4 有隐状态的循环神经网络
隐状态中XtHxh + Ht-1Whh的计算,相当于Xt和Ht-1的连接与Wxh和Whh的连接的矩阵乘法,虽然这个性质可以通过数学证明,下面我们使用简单的代码说明一下。
我们定义的矩阵X,W_xh和W_hh,他们的形状分别为(3,1) (1,4) (3,4)和(4,1)然后分别将X乘以W_xh,将H乘以W_hh,并将这两个结果相加,得到一个形状为(3,4)的矩阵。
import troch
from d2l import torch as d2l
X, W_xh = torch.normal(0,1,(3,1)), torch.normal(0,1,(1,4))
H,W_hh = torch.normal(0,1,(3,4)),torch.normal(0,1,(4,4))
torch.normal(X,W_xh) + torch.matmul(H,W_hh)
我们沿列连接矩阵X和H,沿行连接矩阵W_xh和W_hh,这两个连接分别产生形状和形状的矩阵,再将这两个连接的矩阵相乘,我们得到与上面形状(3,4)相同的输出矩阵。
torch.normal(torch.cat(X,H),1),torch.cat(W_xh,W_hh, 0)
8.4.3基于循环神经网络的字符语言模型
我们的目标是根据过去和当前的词元预测下一个词元,因此我们将原石序列移位一个词元作为标签。Bengio等人首先提出使用神经网络进行语言建模,接下来,我们看一下如何使用循环神经网络来构建语言模型,设小批量大小为1,批量中的文本序列为machine。为了简化后续部分的训练,我们考虑使用字符级语言模型,将文本词元华为字符而不是单词,图8-5 展示了如何通过基于字符级语言建模的循环神经网络,使用当前的和之前的字符预测下一个字符。
时间步 1 2 3 4 5 6
标签 a c h l n e
输出层 O1, O2,O3,O4,O5,O6
隐藏层 H1,H2,H3,H4,H5,H6
输入 m,a,c,h,l,n
训练过程中,我们对每个时间步的输出层的输出进行softmax操作,然后利用交叉墒损失计算模型输出和标签之间的误差。由于隐藏层中的隐状态的循环计算,图8-5中的第3个时间步的输出O3由文本序列m a c确定,训练数据中这个文本序列的下一个字符是h,因此第3个时间步的损失将取决于下一个字符的概率分布,而下一个字符是基于特征序列m a c和第3个时间步的标签h生成的。
我们使用的批量大小为n > 1,每个词元都由一个d味向量表示,在时间步t的输入Xt将是一个nxd矩阵,这与我们在8.4.2节中的讨论。
8.4.4 困惑度
我们讨论如何度量语言模型的质量,将在后续部分中用于评估基于循环神经网络的模型。一个好的语言模型能够用够用高度准确的词元来预测我们接下来会看到什么,考虑由不同的语言模型给出的对It is rainning的续写。
1 It is rainning outside
2 It is rainning banana tree
3 It is raning piouw
就质量而言,例1显然是最合乎情理,逻辑上连贯的,虽然这个模型可能没有很准确的反应出后续词的语义,但是该模型已经能够捕获到跟在后面的是哪类单词,例2择要更糟糕,因为其他给出了一个无意义的续写。至少模型已经学会了如何拼写单词,以及单词之间的某种程度的相关性,例3表明训练不足的模型是无法正确的你和数据的。
可以通过计算序列的似然概率来度量模型的质量,然而这是一个难以理解,难以比较的数字,毕竟。较短的序列比较长的序列更有可能出现,因此评估模型产生托尔斯泰的巨著 可能性不可避免的产生。
信息论可以派上用场了,引入softmax回归时定义了,惊异和交叉墒。如果想要压缩文本,我们可以根据当前词元集预测的下一个词元,一个更好的语言模型应该能让我们更准确的预测下一个词元,应该允许我们在压缩序列时花费更少的比特,我们可以通过一个序列中的所有的n个词元的交叉墒损失的平均值来衡量。
1/n logP(Xt-1,,,X1)
P由语言模型给出,Xt是在时间步t从该序列中观测到的时间词元,使得不同长度的文本的性能具有了可比性,由于历史原因,自然语言处理的科学家更喜欢使用一个称为困惑度的量,简而言之,是对式8.21 的指数运算结果。
exp(-1/n logP(Xt|,,,T1))
对困惑度的最好的理解是 下一个词元的实际选择数的调和平均数,我们来看一些示例,
在最好的情况下,模型总是完美的估计标签词元的概率为1,这种情况下,模型的困惑度为1
在最坏的情况下,模型总是预测标签词元的概率为0. 在这种情况下,困惑度为正无穷大。
在基线上,该模型的预测时词表所有可用词元上的均匀分布,这种情况下,困惑度等于词表中唯一词元的数量。实际上,如果我们在没有任何压缩的情况下存储序列,这将是我们能做的最好的编码方式,因此,这种方式提供了一个重要的上限,而任何实际模型都无法超越这个上限。
接下来内容中,我们将基于循环神经网络实现字符级语言模型,并使用困惑度来评估这样的模型。
小结:
对隐状态使用循环计算的神经网络称为循环神经网络RNN
循环神经网络的隐状态可以捕获直到当前时间步的序列的历史信息
循环神经网络模型的参数数量不会随着时间步的增加而增加
我们可以使用循环神经网络创建字符级语言模型
我们可以使用困惑度来评估语言模型的质量。