在本文中,我们可以深入了解Transformer结构的工作原理。我们将通过实际的矩阵表示来了解数据如何在该结构内流动,并了解每个阶段所需要执行的相关计算。
一、Transformer整体结构
正如我们在第一部分中所看到的,Transformer架构的主要组成如下所示:
观察上述结构,我们知道编码器和解码器的输入,主要包括嵌入层以及位置编码层;同时编码器stack包含多个编码器,其中每个编码器包括一个多头自注意力层以及一个前馈神经网络层;解码器stack包含多个解码器,其中每个解码器包括一个多头自注意力层,一个多头交叉注意力层以及一个前馈神经网络层;右上角的输出head主要包括全连接线性层以及分类softmax层。
为了展示每个组件的功能,让我们以训练Transformer来解决翻译问题的过程中深入探讨一下 Transformer 的工作原理。我们将使用一个训练数据样本进行讲解,该样例包括一个输入序列(英语’You are welcome’)和一个目标序列(西班牙语’De nada’)。
二、嵌入层
与任何 NLP 模型一样,Transformer 需要了解每个单词的两个方面–单词的含义及其在序列中的位置。
- 嵌入层对单词的词义进行编码。
- 位置编码层表示单词在句子中的位置。
Transformer将这两种编码表示进行相加操作,从而将二者结合在一起。
我们首先来学习嵌入层,Transformer有两个嵌入层,如上图所示:输入序列被送入第一个嵌入层,即输入嵌入层。将目标序列右移一个位置,并在第一个位置插入一个开始标记后,将目标序列送入第二个嵌入层。
请注意,在推理过程中,我们没有目标序列,我们将输出序列循环送到第二个嵌入层,这就是它被称为 "输出嵌入"的原因。
如上图所示,使用我们的词汇表可以将文本序列映射为数字单词 ID。然后,嵌入层将每个输入词映射为嵌入向量Embeddings,嵌入向量是该单词更丰富的语义表示。
三、位置编码层
由于 RNN 实现了一个循环,每个单词都是按顺序输入的,因此它隐含地知道每个单词的位置。然而,Transformer架构并不使用 RNN,序列中的所有单词都是并行输入的。这是它相对于 RNN 架构的主要优势,但这也意味着位置信息会丢失,必须重新单独进行添加。
与两个嵌入层一样,Transformer架构中也有两个位置编码层。位置编码的计算与输入序列无关。这些都是固定常数值,只取决于序列的最大长度。这些常数的计算公式如下:
上述公式中:
- pos 是单词在输入序列中的位置
- d_model 是编码矢量的长度(与嵌入矢量长度相同)
- i 是位置编码向量中的索引值
换句话说,位置编码层交织了一条正弦曲线和一条余弦曲线,所有偶数索引都有正弦值,所有奇数索引都有余弦值。举例来说,如果我们对一个包含 40 个单词的序列进行编码,我们可以在下面看到一些组合的编码值。
蓝色曲线表示所有40个单词位置的第 0 个索引的编码情况,橙色曲线表示所有 40 个单词位置的第1个索引的编码情况。其余的索引值也有类似的曲线。
四、矩阵计算
我们知道,深度学习模型一次处理一批训练样本。嵌入层和位置编码层对表示一批序列样本的矩阵进行处理。嵌入层采用(samples,seq_len)形状的单词矩阵。它将每个单词ID编码成单词向量,单词向量的长度为embedding_size,从而得到一个(samples,seq_len,embedding_size)形状的输出矩阵。位置编码层使用的编码大小等于嵌入大小。因此,它产生的矩阵形状与嵌入矩阵相似。
嵌入层和位置编码层产生的(samples,seq_len,embedding_size)矩阵形状在整个Transformer结构中都会保持不变,因为数据会流经编码器Stack和解码器Stack,直到最后的输出层对其进行reshape。
这样我们就掌握了Transformer中的三维矩阵维度。不过,为了简化可视化效果,从现在起我们将去掉第一个维度(samples),而使用单个样本的二维表示法:
输入嵌入将其输出送入编码器。同样,输出嵌入也会输入到解码器。