背景
还是以I am good(我很好)为例。
在RNN模型中,句子是逐字送入学习网络的。换言之,首先把I作为输入,接下来是am,以此类推。通过逐字地接受输入,学习网络就能完全理解整个句子。然而,Transformer网络并不遵循递归循环的模式。因此,我们不是逐字地输入句子,而是将句子中的所有词并行
地输入到神经网络中。并行输入有助于缩短训练时间,同时有利于学习长期依赖。
不过,并行地将词送入Transformer,却不保留词序,它将如何理解句子的意思呢?要理解一个句子,词序(词在句子中的位置)不是很重要吗?
当然,Transformer也需要一些关于词序的信息,以便更好地理解句子。但这将如何做到呢?现在,让我们来解答这个问题。
位置编码
对于给定的句子I am good,我们首先计算每个单词在句子中的嵌入值。嵌入维度可以表示为 d m o d e l d_{model} dmodel。比如将嵌入维度 d m o d e l d_{model} dmodel设为4,那么输入矩阵的维度将是[句子长度×嵌入维度],也就是[3 × 4]。
同样,用输入矩阵X(嵌入矩阵)表示输入句I am good。假设输入矩阵X如图所示。
如果把输入矩阵X直接传给Transformer,那么模型是无法理解词序的。因此,需要添加一些表明词序(词的位置)的信息,以便神经网络能够理解句子的含义。所以,我们不能将输入矩阵直接传给Transformer。这里引入了一种叫作位置编码的技术,以达到上述目的。顾名思义,位置编码是指词在句子中的位置(词序)的编码。
位置编码矩阵P的维度与输入矩阵X的维度相同。在将输入矩阵直接传给Transformer之前,我们将使其包含位置编码。我们只需将位置编码矩阵P添加到输入矩阵X中,再将其作为输入送入神经网络,如图所示。这样一来,输入矩阵不仅有词的嵌入值,还有词在句子中的位置信息。
位置编码矩阵究竟是如何计算的呢?如下所示,Transformer论文“Attention Is All You Need”的作者使用了正弦函数来计算位置编码:
P ( p o s , 2 i ) = s i n ( p o s 1000 0 2 i / d m o d e l ) P(pos,2i) = sin(\frac{pos}{10000^{2i/d_{model}}}) P(pos,2i)=sin(100002i/dmodelpos)
P ( p o s , 2 i + 1 ) = c o s ( p o s 1000 0 2 i / d m o d e l ) P(pos,2i+1) = cos(\frac{pos}{10000^{2i/d_{model}}}) P(pos,2i+1)=cos(100002i/dmodelpos)
在上面的等式中,pos表示该词在句子中的位置, i i i表示在输入矩阵中的位置。下面通过一个例子来理解以上等式,如图所示。
可以看到,在位置编码中,当 i i i是偶数时,使用正弦函数;当 i i i是奇数时,则使用余弦函数。通过简化矩阵中的公式,可以得出下图所示的结果。
我们知道I位于句子的第0位,am在第1位,good在第2位。代入pos值,我们得到结果。
最终的位置编码矩阵P如图所示。
只需将输入矩阵X与计算得到的位置编码矩阵P进行逐元素相加,并将得出的结果作为输入矩阵送入编码器中。
让我们回顾一下编码器架构。下图是一个编码器模块,从中我们可以看到,在将输入矩阵送入编码器之前,首先要将位置编码加入输入矩阵中,再将其作为输入送入编码器。
其他补充
前馈网络层
前馈网络层在编码器模块中的位置如下图所示。
前馈网络由两个有ReLU激活函数的全连接层组成。前馈网络的参数在句子的不同位置上是相同的,但在不同的编码器模块上是不同的。
叠加和归一组件
在编码器中还有一个重要的组成部分,即叠加和归一组件。它同时连接一个子层的输入和输出,如下图所示(虚线部分)
- 同时连接多头注意力层的输入和输出。
- 同时连接前馈网络层的输入和输出。
叠加和归一组件实际上包含一个残差连接与层的归一化。层的归一化可以防止每层的值剧烈变化,从而提高了模型的训练速度。
至此,我们已经了解了编码器的所有部分。
编码器总览
下图显示了叠加的两个编码器,但只有编码器1被展开,以便查看细节。
通过上图,我们可以总结出以下几点。
(1) 将输入转换为嵌入矩阵(输入矩阵),并将位置编码加入其中,再将结果作为输入传入底层的编码器(编码器1)。
(2) 编码器1接受输入并将其送入多头注意力层,该子层运算后输出注意力矩阵。
(3) 将注意力矩阵输入到下一个子层,即前馈网络层。前馈网络层将注意力矩阵作为输入,并计算出特征值作为输出。
(4) 接下来,把从编码器1中得到的输出作为输入,传入下一个编码器(编码器2)。
(5) 编码器2进行同样的处理,再将给定输入句子的特征值作为输出。
这样可以将N个编码器一个接一个地叠加起来。从最后一个编码器(顶层的编码器)得到的输出将是给定输入句子的特征值。让我们把从最后一个编码器(在本例中是编码器2)得到的特征值表示为R。
我们把R作为输入传给解码器。解码器将基于这个输入生成目标句。现在,我们了解了Transformer的编码器部分。后续将详细分析解码器的工作原理。