Luozm +

NLP Related Topics

Notes about the LSTM, GRU, Word2vec, seq2seq, and Attention

原创文章,转载请注明:转自Luozm's Blog

1. RNN

1.1 GRU

门控循环神经网络(gated recurrent neural networks)的提出,是为了更好地捕捉时序数据中间隔较大的依赖关系。其中,门控循环单元(gated recurrent unit,简称GRU)是一种常用的门控循环神经网络。它由Cho、van Merrienboer、 Bahdanau和Bengio在2014年被提出。

1.1.1 Gates

门控循环单元的隐含状态只包含隐含层变量$\mathbf{H}$。假定隐含状态长度为$\mathbf{h}$,给定时刻$\mathbf{t}$的一个样本数为$\mathbf{n}$特征向量维度为$\mathbf{x}$的批量数据 $\mathbf{X}t\in\mathbb{R}^{n\times x}$ 和上一时刻隐含状态 $\mathbf{H}{t-1} \in \mathbb{R}^{n \times h}$ ,重置门(reset gate) $\mathbf{R}_t \in \mathbb{R}^{n \times h}$ 和更新门(update gate) $\mathbf{Z}_t \in \mathbb{R}^{n \times h}$ 的定义如下:

其中的$\mathbf{W}{xr}, \mathbf{W}{xz} \in \mathbb{R}^{x \times h}$和$\mathbf{W}{hr}, \mathbf{W}{hz} \in \mathbb{R}^{h \times h}$是可学习的权重参数,$\mathbf{b}_r, \mathbf{b}_z \in \mathbb{R}^{1 \times h}$是可学习的偏移参数。函数$\sigma$自变量中的三项相加使用了广播。

1.1.2 Proposed Hidden State

我们可以通过元素值域在[0,1]的更新门和重置门来控制隐含状态中信息的流动:这通常可以应用按元素乘法符⊙。门控循环单元中的候选隐含状态$\tilde{\mathbf{H}}_t \in \mathbb{R}^{n \times h}$使用了值域在[−1,1]的双曲正切函数tanh做激活函数:

其中的$\mathbf{W}{xh} \in \mathbb{R}^{x \times h}$和$\mathbf{W}{hh} \in \mathbb{R}^{h \times h}$是可学习的权重参数,$\mathbf{b}_h \in \mathbb{R}^{1 \times h}$是可学习的偏移参数。

需要注意的是,候选隐含状态使用了重置门来控制包含过去时刻信息的上一个隐含状态的流入。如果重置门近似0,上一个隐含状态将被丢弃。因此,重置门提供了丢弃与未来无关的过去隐含状态的机制。

1.1.3 Hidden State

隐含状态$\mathbf{H}t \in \mathbb{R}^{n \times h}$的计算使用更新门$\mathbf{Z}_t$来对上一时刻的隐含状态$\mathbf{H}{t-1}$和当前时刻的候选隐含状态$\tilde{\mathbf{H}}_t$做组合,公式如下:

需要注意的是,更新门可以控制过去的隐含状态在当前时刻的重要性。如果更新门一直近似1,过去的隐含状态将一直通过时间保存并传递至当前时刻。这个设计可以应对循环神经网络中的梯度衰减问题,并更好地捕捉时序数据中间隔较大的依赖关系。

1.1.4 Summary

门控循环单元的提出是为了更好地捕捉时序数据中间隔较大的依赖关系。

1.2 LSTM

本节将介绍另一种常用的门控循环神经网络,长短期记忆(long short-term memory,简称LSTM)。它由Hochreiter和Schmidhuber在1997年被提出。事实上,它比门控循环单元的结构稍微更复杂一点。

我们先介绍长短期记忆的构造。长短期记忆的隐含状态包括隐含层变量$\mathbf{H}$和细胞$\mathbf{C}$(也称记忆细胞)。它们形状相同。

1.2.1 Gates

假定隐含状态长度为h,给定时刻t的一个样本数为n特征向量维度为x的批量数据$\mathbf{X}t \in \mathbb{R}^{n \times x}$和上一时刻隐含状态$\mathbf{H}{t-1} \in \mathbb{R}^{n \times h}$,输入门(input gate)$\mathbf{I}_t \in \mathbb{R}^{n \times h}$、遗忘门(forget gate)$\mathbf{F}_t \in \mathbb{R}^{n \times h}$和输出门(output gate)$\mathbf{O}_t \in \mathbb{R}^{n \times h}$的定义如下:

其中的$\mathbf{W}{xi}, \mathbf{W}{xf}, \mathbf{W}{xo} \in \mathbb{R}^{x \times h}$和$\mathbf{W}{hi}, \mathbf{W}{hf}, \mathbf{W}{ho} \in \mathbb{R}^{h \times h}$是可学习的权重参数,$\mathbf{b}_i, \mathbf{b}_f, \mathbf{b}_o \in \mathbb{R}^{1 \times h}$是可学习的偏移参数。函数$\sigma$自变量中的三项相加使用了广播。

和门控循环单元中的重置门和更新门一样,这里的输入门、遗忘门和输出门中每个元素的值域都是[0,1]。

1.2.2 Proposed Cell

和门控循环单元中的候选隐含状态一样,长短期记忆中的候选细胞$\tilde{\mathbf{C}}_t \in \mathbb{R}^{n \times h}$也使用了值域在[−1,1]的双曲正切函数tanh做激活函数:

其中的$\mathbf{W}{xc} \in \mathbb{R}^{x \times h}$和$\mathbf{W}{hc} \in \mathbb{R}^{h \times h}$是可学习的权重参数,$\mathbf{b}_c \in \mathbb{R}^{1 \times h}$是可学习的偏移参数。

1.2.3 Cell

我们可以通过元素值域在[0,1]的输入门、遗忘门和输出门来控制隐含状态中信息的流动:这通常可以应用按元素乘法符⊙⊙。当前时刻细胞$\mathbf{C}_t \in \mathbb{R}^{n \times h}$的计算组合了上一时刻细胞和当前时刻候选细胞的信息,并通过遗忘门和输入门来控制信息的流动:

需要注意的是,如果遗忘门一直近似1且输入门一直近似0,过去的细胞将一直通过时间保存并传递至当前时刻。这个设计可以应对循环神经网络中的梯度衰减问题,并更好地捕捉时序数据中间隔较大的依赖关系。

1.2.4 Hidden State

有了细胞以后,接下来我们还可以通过输出门来控制从细胞到隐含层变量$\mathbf{H}_t \in \mathbb{R}^{n \times h}$的信息的流动:

需要注意的是,当输出门近似1,细胞信息将传递到隐含层变量;当输出门近似0,细胞信息只自己保留。(这个操作GRU没有)

1.3 Multi-layer RNN

对于一个多层循环神经网络,当前时刻隐含层的输入来自同一时刻输入层(如果有)或上一隐含层的输出。每一层的隐含状态只沿着同一层传递。

把单层循环神经网络中隐含层的每个单元当做一个函数f,这个函数在t时刻的输入是$\mathbf{X}t, \mathbf{H}{t-1}$,输出是$\mathbf{H}_t$:

假设输入为第0层,输出为第L+1L+1层,在一共LL个隐含层的循环神经网络中,上式中可以拓展成以下的函数:

如下图所示。

multi-layer RNN

2. Word2vec

2013年,Google团队发表了word2vec工具。word2vec工具主要包含两个模型:跳字模型(skip-gram)和连续词袋模型(continuous bag of words,简称CBOW),以及两种高效训练的方法:负采样(negative sampling)和层序softmax(hierarchical softmax)。值得一提的是,word2vec词向量可以较好地表达不同词之间的相似和类比关系。

word2vec自提出后被广泛应用在自然语言处理任务中。它的模型和训练方法也启发了很多后续的词向量模型。本节将重点介绍word2vec的模型和训练方法。

2.1 Why not one-hot

我们在循环神经网络中介绍过one-hot向量来表示词。假设词典中不同词的数量为$N$,每个词可以和从0到$N-1$的连续整数一一对应。假设一个词的相应整数表示为$i$,为了得到该词的one-hot向量表示,我们创建一个全0的长为$N$的向量,并将其第$i$位设成1。

然而,使用one-hot词向量并不是一个好选择。一个主要的原因是,one-hot词向量无法表达不同词之间的相似度。例如,任何一对词的one-hot向量的余弦相似度都为0。

2.2 Model

2.2.1 Skip-gram

在跳字模型中,我们用一个词来预测它在文本序列周围的词。例如,给定文本序列”the”, “man”, “hit”, “his”, 和”son”,跳字模型所关心的是,给定”hit”,生成它邻近词“the”, “man”, “his”, 和”son”的概率。在这个例子中,”hit”叫中心词,“the”, “man”, “his”, 和”son”叫背景词。由于”hit”只生成与它距离不超过2的背景词,该时间窗口的大小为2。

我们来描述一下跳字模型。

假设词典大小为$ \mathcal{V} $,我们将词典中的每个词与从0到$ \mathcal{V} -1$的整数一一对应:词典索引集$\mathcal{V} = {0, 1, \ldots, \mathcal{V} -1}$。一个词在该词典中所对应的整数称为词的索引。给定一个长度为$T$的文本序列中,$t$时刻的词为$w^{(t)}$。当时间窗口大小为$m$时,跳字模型需要最大化给定任一中心词生成背景词的概率(MLE):

上式的最大似然估计与最小化以下损失函数等价

我们可以用$\mathbf{v}$和$\mathbf{u}$分别代表中心词和背景词的向量。换言之,对于词典中一个索引为$i$的词,它在作为中心词和背景词时的向量表示分别是$\mathbf{v}_i$和$\mathbf{u}_i$。而词典中所有词的这两种向量正是跳字模型所要学习的模型参数。为了将模型参数植入损失函数,我们需要使用模型参数表达损失函数中的中心词生成背景词的概率。假设中心词生成各个背景词的概率是相互独立的。给定中心词$w_c$在词典中索引为$c$,背景词$w_o$在词典中索引为$o$,损失函数中的中心词生成背景词的概率可以使用softmax函数(Use the similarity of the word vectors for $c$ and $o$ to calculate the probability of o given c (or vice versa))定义为

Why Softmax?

The softmax function maps arbitrary values $x_i$ to a probability distribution $p_i$. Dot product compares similarity of $o$ and $c$.

当序列长度$T$较大时,我们通常随机采样一个较小的子序列来计算损失函数并使用随机梯度下降优化该损失函数。通过微分,我们可以计算出上式生成概率的对数关于中心词向量$\mathbf{v}_c$的梯度为:

而上式与下式等价:

通过上面计算得到梯度后,我们可以使用随机梯度下降来不断迭代模型参数$\mathbf{v}_c$。其他模型参数$\mathbf{u}_o$的迭代方式同理可得。最终,对于词典中的任一索引为$i$的词,我们均得到该词作为中心词和背景词的两组词向量$\mathbf{v}_i$和$\mathbf{u}_i$。

2.2.2 CBOW

连续词袋模型与跳字模型类似。与跳字模型最大的不同是,连续词袋模型中用一个中心词在文本序列周围的词来预测该中心词。例如,给定文本序列”the”, “man”, “hit”, “his”, 和”son”,连续词袋模型所关心的是,邻近词“the”, “man”, “his”, 和”son”一起生成中心词”hit”的概率。

假设词典大小为$ \mathcal{V} $,我们将词典中的每个词与从0到$ \mathcal{V} -1$的整数一一对应:词典索引集$\mathcal{V} = {0, 1, \ldots, \mathcal{V} -1}$。一个词在该词典中所对应的整数称为词的索引。给定一个长度为$T$的文本序列中,$t$时刻的词为$w^{(t)}$。当时间窗口大小为$m$时,连续词袋模型需要最大化由背景词生成任一中心词的概率:

上式的最大似然估计与最小化以下损失函数等价

我们可以用$\mathbf{v}$和$\mathbf{u}$分别代表背景词和中心词的向量(注意符号和跳字模型中的不同)。换言之,对于词典中一个索引为$i$的词,它在作为背景词和中心词时的向量表示分别是$\mathbf{v}i$和$\mathbf{u}_i$。而词典中所有词的这两种向量正是连续词袋模型所要学习的模型参数。为了将模型参数植入损失函数,我们需要使用模型参数表达损失函数中的中心词生成背景词的概率。给定中心词$w_c$在词典中索引为$c$,背景词$w{o_1}, \ldots, w{o{2m}}$在词典中索引为$o_1, \ldots, o_{2m}$,损失函数中的背景词生成中心词的概率可以使用softmax函数定义为

当序列长度$T$较大时,我们通常随机采样一个较小的子序列来计算损失函数并使用随机梯度下降优化该损失函数。通过微分,我们可以计算出上式生成概率的对数关于任一背景词向量$\mathbf{v}_{o_i}$($i = 1, \ldots, 2m$)的梯度为:

而上式与下式等价:

通过上面计算得到梯度后,我们可以使用随机梯度下降来不断迭代各个模型参数$\mathbf{v}_{o_i}$($i = 1, \ldots, 2m$)。其他模型参数$\mathbf{u}_c$的迭代方式同理可得。最终,对于词典中的任一索引为$i$的词,我们均得到该词作为背景词和中心词的两组词向量$\mathbf{v}_i$和$\mathbf{u}_i$。

2.3 Training Method

我们可以看到,无论是跳字模型还是连续词袋模型,每一步梯度计算的开销与词典$\mathcal{V}$的大小相关。显然,当词典较大时,例如几十万到上百万,这种训练方法的计算开销会较大。所以,使用上述训练方法在实践中是有难度的。

我们将使用近似的方法来计算这些梯度,从而减小计算开销。常用的近似训练法包括负采样和层序softmax。

2.3.1 Negative Sampling

我们以跳字模型为例讨论负采样。

词典$\mathcal{V}$大小之所以会在目标函数中出现,是因为中心词$w_c$生成背景词$w_o$的概率$\mathbb{P}(w_o \mid w_c)$使用了softmax,而softmax正是考虑了背景词可能是词典中的任一词,并体现在softmax的分母上。

我们不妨换个角度,假设中心词$w_c$生成背景词$w_o$由以下相互独立事件联合组成来近似

我们可以使用$\sigma(x) = 1/(1+\text{exp}(-x))$函数来表达中心词$w_c$和背景词$w_o$同时出现在该训练数据窗口的概率:

那么,中心词$w_c$生成背景词$w_o$的对数概率可以近似为

假设噪声词$w_k$在词典中的索引为$i_k$,上式可改写为

因此,有关中心词$w_c$生成背景词$w_o$的损失函数是

当我们把$K$取较小值时,每次随机梯度下降的梯度计算开销将由$\mathcal{O}( \mathcal{V} )$降为$\mathcal{O}(K)$。

我们也可以对连续词袋模型进行负采样。有关背景词$w^{(t-m)}, \ldots, w^{(t-1)}, w^{(t+1)}, \ldots, w^{(t+m)}$生成中心词$w_c$的损失函数

在负采样中可以近似为

同样地,当我们把$K$取较小值时,每次随机梯度下降的梯度计算开销将由$\mathcal{O}( \mathcal{V} )$降为$\mathcal{O}(K)$。

2.3.2 Hierarchical Softmax

层序softmax利用了二叉树。树的每个叶子节点代表着词典$\mathcal{V}$中的每个词。每个词$w_i$相应的词向量为$\mathbf{v}_i$。我们以下图为例,来描述层序softmax的工作机制。

Hierarchical Softmax

假设$L(w)$为从二叉树的根到代表词$w$的叶子节点的路径上的节点数,并设$n(w,i)$为该路径上第$i$个节点,该节点的向量为$\mathbf{u}_{n(w,i)}$。以上图为例,$L(w_3) = 4$。那么,跳字模型和连续词袋模型所需要计算的任意词$w_i$生成词$w$的概率为:

其中$\sigma(x) = 1/(1+\text{exp}(-x))$,如果$x$为真,$[x] = 1$;反之$[x] = -1$。

由于$\sigma(x)+\sigma(-x) = 1$,$w_i$生成词典中任何词的概率之和为1:

让我们计算$w_i$生成$w_3$的概率,由于在二叉树中由根到$w_3$的路径上需要向左、向右、再向左地遍历,我们得到

我们可以使用随机梯度下降在跳字模型和连续词袋模型中不断迭代计算字典中所有词向量$\mathbf{v}$和非叶子节点的向量$\mathbf{u}$。每次迭代的计算开销由$\mathcal{O}( \mathcal{V} )$降为二叉树的高度$\mathcal{O}(\text{log} \mathcal{V} )$。

3. Seq2seq

在基于词语的语言模型中,我们使用了循环神经网络。它的输入是一段不定长的序列,输出却是定长的,例如一个词语。然而,很多问题的输出也是不定长的序列。以机器翻译为例,输入是可以是英语的一段话,输出可以是法语的一段话,输入和输出皆不定长,例如

英语:They are watching.

法语:Ils regardent.

输入输出都是不定长序列时,我们可以使用编码器—解码器(encoder-decoder)或者seq2seq。它们分别基于2014年的两个工作:

以上两个工作本质上都用到了两个循环神经网络,分别叫做编码器和解码器。编码器对应输入序列,解码器对应输出序列。下面我们来介绍编码器—解码器的设计。

3.1 Encoder-decoder

编码器和解码器是分别对应输入序列和输出序列的两个循环神经网络。我们通常会在输入序列和输出序列后面分别附上一个特殊字符’'(end of sequence)表示序列的终止。在测试模型时,一旦输出''就终止当前的输出序列。

3.1.1 Encoder

编码器的作用是把一个不定长的输入序列转化成一个定长的背景向量$\mathbf{c}$。该背景向量包含了输入序列的信息。常用的编码器是循环神经网络。

我们回顾一下循环神经网络知识。假设循环神经网络单元为$f$,在$t$时刻的输入为$x_t, t=1, \ldots, T$。 假设$\mathbf{x}_t$是单个输出$x_t$在嵌入层的结果,例如$x_t$对应的one-hot向量$\mathbf{o} \in \mathbb{R}^x$与嵌入层参数矩阵$\mathbf{E} \in \mathbb{R}^{x \times h}$的乘积$\mathbf{o}^\top \mathbf{E}$。隐含层变量

编码器的背景向量

一个简单的背景向量是该网络最终时刻的隐含层变量$\mathbf{h}_T$。 我们将这里的循环神经网络叫做编码器。

3.1.2 双向循环神经网络

编码器的输入既可以是正向传递,也可以是反向传递。如果输入序列是$x_1, x_2, \ldots, x_T$,在正向传递中,隐含层变量

而反向传递中,隐含层变量的计算变为

当我们希望编码器的输入既包含正向传递信息又包含反向传递信息时,我们可以使用双向循环神经网络。例如,给定输入序列$x_1, x_2, \ldots, x_T$,按正向传递,它们在循环神经网络的隐含层变量分别是$\overrightarrow{\mathbf{h}}_1, \overrightarrow{\mathbf{h}}_2, \ldots, \overrightarrow{\mathbf{h}}_T$;按反向传递,它们在循环神经网络的隐含层变量分别是$\overleftarrow{\mathbf{h}}_1, \overleftarrow{\mathbf{h}}_2, \ldots, \overleftarrow{\mathbf{h}}_T$。在双向循环神经网络中,时刻$i$的隐含层变量可以把$\overrightarrow{\mathbf{h}}_i$和$\overleftarrow{\mathbf{h}}_i$连结起来。

Bi-RNN

3.1.3 Decoder

编码器最终输出了一个背景向量$\mathbf{c}$,该背景向量编码了输入序列$x_1, x_2, \ldots, x_T$的信息。

假设训练数据中的输出序列是$y_1, y_2, \ldots, y_{T^\prime}$,我们希望表示每个$t$时刻输出的既取决于之前的输出又取决于背景向量。之后,我们就可以最大化输出序列的联合概率

并得到该输出序列的损失函数

为此,我们使用另一个循环神经网络作为解码器。解码器使用函数$p$来表示单个输出$y_{t^\prime}$的概率

其中的$\mathbf{s}_t$为$t^\prime$时刻的解码器的隐含层变量。该隐含层变量

其中函数$g$是循环神经网络单元。

需要注意的是,编码器和解码器通常会使用多层循环神经网络

3.2 Attention Mechanism

在以上的解码器设计中,各个时刻使用了相同的背景向量。如果解码器的不同时刻可以使用不同的背景向量呢?

以英语-法语翻译为例,给定一对输入序列“they are watching”和输出序列“Ils regardent”,解码器在时刻1可以使用更多编码了“they are”信息的背景向量来生成“Ils”,而在时刻2可以使用更多编码了“watching”信息的背景向量来生成“regardent”。这看上去就像是在解码器的每一时刻对输入序列中不同时刻分配不同的注意力。这也是注意力机制的由来。它最早由Bahanau等在2015年提出。

现在,对上面的解码器稍作修改。我们假设时刻$t^\prime$的背景向量为$\mathbf{c}_{t^\prime}$。那么解码器在$t^\prime$时刻的隐含层变量

令编码器在$t$时刻的隐含变量为$\mathbf{h}_t$,解码器在$t^\prime$时刻的背景向量为

也就是说,给定解码器的当前时刻$t^\prime$,我们需要对解码器中不同时刻的隐含层变量求加权平均。而权值也称注意力权重。它的计算公式是

而$e_{t^\prime t} \in \mathbb{R}$的计算为:

其中函数$a$有多种设计方法。在Bahanau的论文中,

其中的$\mathbf{v}$、$\mathbf{W}_s$、$\mathbf{W}_h$和编码器与解码器两个循环神经网络中的各个权重和偏移项以及嵌入层参数等都是需要同时学习的模型参数。在Bahanau的论文中,编码器和解码器分别使用了门控循环单元(GRU)。

在解码器中,我们需要对GRU的设计稍作修改。 假设$\mathbf{y}t$是单个输出$y_t$在嵌入层的结果,例如$y_t$对应的one-hot向量$\mathbf{o} \in \mathbb{R}^y$与嵌入层参数矩阵$\mathbf{B} \in \mathbb{R}^{y \times s}$的乘积$\mathbf{o}^\top \mathbf{B}$。 假设时刻$t^\prime$的背景向量为$\mathbf{c}{t^\prime}$。那么解码器在$t^\prime$时刻的单个隐含层变量

其中的重置门、更新门和候选隐含状态分别为

3.3 Summary

References

  1. Word2Vec Tutorial
  2. CS224n: Natural Language Processing with Deep Learning
  3. Efficient Estimation of Word Representations in Vector Space
  4. 自然语言处理(Gluon)
  5. Effective Approaches to Attention-based Neural Machine Translation
© Luozm . All rights reserved. | Top

Life

Theory

Develop