Seq2Seq与注意力机制
-
在基于词语的语言模型中,我们使用了循环神经网络。它的输入是一段不定长的序列,输出却是定长的,例如输入:They are,输出可能是watching或者sleeping。然而,很多问题的输出是不定长的序列。以机器翻译为例,输入是一段英文,输出是一段法语,输入和输出皆不定长,例如
英语:The are watching
法语:lls regardent
当输入输出序列都是不定长时,我们可以使用编码器-解码器(encoder-decoder)或者seq2seq。它们分别是基于2014年的两个工作:
- Cho et al., Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation
- Sutskever et al., Sequence to Sequence Leaerning with Neural Networks
以上两个工作本质上都用到了两个循环神经网络结构,分别叫做编码器和解码器。编码器对应输入序列,解码器对应输出序列
编码器—解码器
编码器和解码器分别对应输入序列和输出序列的两个循环神经网络。我们通常会在输入序列和输出序列后面分别附上一个特殊字符’<eos>‘(end of sequence)表示序列的终止。在测试模型时,一旦输出’<eos>'就终止当前的输出序列
编码器
编码器的作用是把一个不定长的输入序列转化成一个定长的背景词向量c\boldsymbol{c}c。该背景词向量包含了输入序列的信息。常用的编码器是循环神经网络
首先回顾以下循环神经网络的知识。假设循环神经网络单元为fff,在ttt时刻的输入为xt,t=1,…,Tx_t,t=1,…,Txt,t=1,…,T。假设xt\boldsymbol{x}_txt是单个输出在嵌入层的结果,例如xt\boldsymbol{x}_txt对应的ont-hot向量o∈Rx\boldsymbol{o}\in \mathbb{R}^xo∈Rx与嵌入层参数矩阵E∈Rx×h\boldsymbol{E}\in \mathbb{R}^{x\times h}E∈Rx×h的乘积o⊤E\boldsymbol{o}^\top\boldsymbol{E}o⊤E。隐藏层变量
$$
\boldsymbol{h}_t = f(\boldsymbol{x}t, \boldsymbol{h}{t-1})
$$
编码器的背景向量
$$
\boldsymbol{c} = q(\boldsymbol{h}_1, \ldots, \boldsymbol{h}_T)
$$
一个简单的背景向量可以认为是该网络最终时刻的隐藏层变量hT\boldsymbol{h}_ThT。我们将这里的循环神经网络叫做编码器双向循环神经网络
编码器的输入既可以是正向传递,也可以是反向传递的。如果输入序列是x1,x2,…,xT\boldsymbol{x}_1,\boldsymbol{x}_2,…,\boldsymbol{x}_Tx1,x2,…,xT,在正向传递中,隐藏层变量
$$
\overrightarrow {\boldsymbol{h}}_t = f(\boldsymbol{x}t,\overrightarrow {\boldsymbol{h}}{t-1})
$$
而反向传递过程中,隐藏层变量的计算变为
$$
\overleftarrow {\boldsymbol{h}}_t = f(\boldsymbol{x}t,\overleftarrow {\boldsymbol{h}}{t-1})
$$
当我们希望编码器的输入既包含正向传递信息又包含反向传递信息时,我们可以使用双向循环神经网络。例如,给定输入序列x1,x2,…,xT\boldsymbol{x}_1,\boldsymbol{x}_2,…,\boldsymbol{x}_Tx1,x2,…,xT,按正向传递,它们在循环神经网络中的隐藏层变量分别是h⃗1,h⃗2,…,h⃗T\vec {\boldsymbol{h}}_1,\vec {\boldsymbol{h}}_2,…,\vec {\boldsymbol{h}}_Th1,h2,…,hT;按反向传播,它们在循环神经网络中的隐藏层变量分别是h←1,h←2,…,h←T\overleftarrow{\boldsymbol{h}}_1,\overleftarrow{\boldsymbol{h}}_2,…,\overleftarrow{\boldsymbol{h}}_Th1,h2,…,hT。在双向循环神经网络中,时刻iii的隐藏层变量是将h⃗i\vec{\boldsymbol{h}}_ihi和h←i\overleftarrow{\boldsymbol{h}}_ihi拼接起来,例如import numpy as np h_forward = np.array([1, 2]) h_backward = np.array([3, 4]) h_bi = np.concat(h_forward, h_backward, dim=0) # [1, 2, 3, 4]
解码器
编码器最终输出了一个背景向量c\boldsymbol{c}c,该背景向量整合了输入序列x1,x2,…,xT\boldsymbol{x}_1,\boldsymbol{x}_2,…,\boldsymbol{x}_Tx1,x2,…,xT
假设训练数据中的输出序列是y<em>1,y<em>2,…,y</em>T’\boldsymbol{y}<em>1,\boldsymbol{y}<em>2,…,\boldsymbol{y}</em>{T’}y<em>1,y<em>2,…,y</em>T’,我们希望表示每个t’t’t’时刻输出的向量,既取决于之前的输出又取决于背景向量。因为,我们可以最大化输出序列的联合概率
$$
P(\boldsymbol{y}1,\boldsymbol{y}2,…,\boldsymbol{y}{T’})=\prod{t’=1}^{T’}P(\boldsymbol{y}{t’}\mid \boldsymbol{y}1,…,\boldsymbol{y}{t’-1},\boldsymbol{c})
$$
并得到该输出序列的损失函数
$$
-logP(\boldsymbol{y}1,…,\boldsymbol{y}{T’})
$$
为此,我们使用另一个循环神经网络作为解码器。解码器使用函数ppp来表示单个输出y<em>t’\boldsymbol{y}<em>{t’}y<em>t’的概率
$$
P(\boldsymbol{y}{t’}\mid \boldsymbol{y}1,…,\boldsymbol{y}{t’-1},\boldsymbol{c})=p(\boldsymbol{y}{t’-1},\boldsymbol{s}{t’},\boldsymbol{c})
$$
其中的s<em>t’\boldsymbol{s}<em>{t’}s<em>t’为t’t’t’时刻的解码器的隐藏层变量。该隐藏层变量
$$
\boldsymbol{s}{t’}=g(\boldsymbol{y}{t’-1},\boldsymbol{c},\boldsymbol{s}{t’-1})
$$
其中函数g是循环神经网络单元需要注意的是,编码器和解码器通常会使用多层循环神经网络
注意力机制
在以上的解码器设计中,各个时刻使用了相同的背景向量c\boldsymbol{c}c。如果解码器的不同时刻可以使用不同的背景向量呢?
以英语-法语翻译为例,给定一对输入序列"They are watching"和输出序列"lls regardent",解码器在时刻1可以使用更多的编码了"They are"信息的背景向量来生成"lls",而在时刻2可以使用更多编码了"watching"信息的背景向量来生成"regardent"。这看上去就像是在解码器的每一时刻对输入序列中不同时刻分配不同的注意力。这也是注意力机制的由来
现在,对上面的解码器稍作修改。我们假设时刻t’t’t’的背景向量为c<em>t’\boldsymbol{c}<em>{t’}c<em>t’。那么解码器在时刻t’t’t’的隐藏层变量
$$
\boldsymbol{s}{t’}=g(\boldsymbol{y}{t’-1},\boldsymbol{c}{t’},\boldsymbol{s}{t’-1})
$$
令编码器在ttt时刻的隐藏层变量为h<em>t\boldsymbol{h}<em>th<em>t,解码器在t’t’t’时刻的背景向量为
$$
\boldsymbol{c}{t’}=\sum{t=1}^{T}\alpha_{t’t}\boldsymbol{h}t
$$
也就是说,给定解码器的当前时刻t’t’t’,我们需要对编码器中不同时刻的隐藏层变量求加权平均。而权值也称注意力权值。它的计算公式是
$$
\alpha{t’ t} = \frac{\exp(e_{t’ t})}{ \sum_{k=1}^T \exp(e_{t’ k}) }
$$
而et’t∈Re_{t’ t}\in \mathbb{R}et’t∈R的计算公式为
$$
e_{t’ t} = a(\boldsymbol{s}_{t’ - 1}, \boldsymbol{h}t)
$$
其中函数aaa有多种设计方法。在Bahdanau的论文中
$$
\boldsymbol{e}{t’t} = \boldsymbol{v}^\top \tanh(\boldsymbol{W}s \boldsymbol{s}{t’-1} + \boldsymbol{W}_h \boldsymbol{h}_t),
$$
其中v\boldsymbol{v}v、Ws\boldsymbol{W}_sWs、Wh\boldsymbol{W}_hWh和编码器与解码器两个循环神经网络中的各个权重与偏移项以及嵌入层参数等都是需要同时学习的模型参数在Bahdanau的论文的论文中,编码器和解码器均使用了GRU
在解码器中,我们需要对GRU的设计稍作修改,假设y<em>t\boldsymbol{y}<em>ty<em>t是单个输出在嵌入层的结果,例如y<em>t\boldsymbol{y}<em>ty<em>t对应的ont-hot向量o∈Ry\boldsymbol{o}\in \mathbb{R}^yo∈Ry与嵌入层参数矩阵B∈Ry×s\boldsymbol{B}\in \mathbb{R}^{y\times s}B∈Ry×s的乘积o⊤B\boldsymbol{o}^\top\boldsymbol{B}o⊤B。假设时刻t’t’t’的背景向量为c</em>t’\boldsymbol{c}</em>{t’}c</em>t’。那么解码器在时刻t’t’t’的单个隐藏层变量
$$
\boldsymbol{s}{t’} = \boldsymbol{z}{t’} \odot \boldsymbol{s}{t’-1} + (1 - \boldsymbol{z}{t’}) \odot \tilde{\boldsymbol{s}}{t’}
$$
其中,重置门、更新门和候选隐藏状态分别为
$$
\begin{split}\begin{aligned} \boldsymbol{r}{t’} &= \sigma(\boldsymbol{W}{yr} \boldsymbol{y}{t’-1} + \boldsymbol{W}{sr} \boldsymbol{s}{t’ - 1} + \boldsymbol{W}{cr} \boldsymbol{c}{t’} + \boldsymbol{b}r),\ \boldsymbol{z}{t’} &= \sigma(\boldsymbol{W}{yz} \boldsymbol{y}{t’-1} + \boldsymbol{W}{sz} \boldsymbol{s}{t’ - 1} + \boldsymbol{W}{cz} \boldsymbol{c}{t’} + \boldsymbol{b}z),\ \tilde{\boldsymbol{s}}{t’} &= \text{tanh}(\boldsymbol{W}{ys} \boldsymbol{y}{t’-1} + \boldsymbol{W}{ss} (\boldsymbol{s}{t’ - 1} \odot \boldsymbol{r}{t’}) + \boldsymbol{W}{cs} \boldsymbol{c}{t’} + \boldsymbol{b}_s), \end{aligned}\end{split}
$$总结
- 编码器-解码器(seq2seq)的输入和输出可以都是不定长序列
- 在解码器上应用注意力机制可以使解码器的每个时刻使用不同的背景向量。每个背景向量相当于对输入序列的不同部分分配了不同的注意力