1. 什么是 Transformer
Transformer 是 Google 提出的一种将 Attention 思想发挥到极致的模型。该论文提出了一个全新的架构,抛弃了以往深度学习任务中常用的 CNN 和 RNN。目前大热的 BERT 就是基于 Transformer 构建的,该模型广泛应用于 NLP 领域,例如机器翻译、问答系统、文本摘要和语音识别等方向。
2. Transformer 结构
2.1 总体结构
Transformer 采用了 Encoder-Decoder 架构。相比于传统的 Attention 模型,其结构更为复杂。在原始论文中,Encoder 层由 6 个相同的 Encoder 堆叠而成,Decoder 层同样由 6 个相同的 Decoder 堆叠而成。
每个 Encoder 和 Decoder 的内部结构包含多个子层(Sub-layers)。
- Encoder:包含两层,一个是 Self-Attention 层,另一个是前馈神经网络(Feed Forward Neural Network)。Self-Attention 帮助当前节点不仅仅关注当前的词,从而获取上下文的语义信息。
- Decoder:也包含类似 Encoder 的两层网络,但在中间增加了一层 Masked Multi-Head Attention,帮助当前节点获取到当前需要关注的重点内容,同时防止看到未来的信息。
2.2 Encoder 层结构
首先,模型需要对输入的数据进行 Embedding 操作,类似于 Word2Vec。Embedding 结束后,数据输入到 Encoder 层。Self-Attention 处理完数据后,将其送入前馈神经网络。前馈神经网络的计算可以并行,得到的输出会输入到下一个 Encoder 层。
2.2.1 Positional Encoding
Transformer 模型本身缺乏解释输入序列中单词顺序的方法,这与 RNN 等序列模型不同。为了解决这个问题,Transformer 给 Encoder 层和 Decoder 层的输入添加了一个额外的向量 Positional Encoding,其维度与 Embedding 的维度相同。这个向量采用了一种独特的方式让模型学习位置信息,决定当前词的位置或句子中不同词之间的距离。
论文中的计算方法如下:
$$PE(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$ $$PE(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$
其中 $pos$ 是指当前词在句子中的位置,$i$ 是指向量中每个值的索引。可以看出,在偶数位置使用正弦编码,在奇数位置使用余弦编码。最后将这个 Positional Encoding 与 Embedding 的值相加,作为输入送到下一层。
2.2.2 Self-Attention
Self-Attention 的思想与 Attention 类似,但它是 Transformer 用来将其他相关单词的'理解'转换成正在处理的单词的一种机制。例如在句子 "The animal didn't cross the street because it was too tired" 中,判断 it 指代的是 animal 还是 street。Self-Attention 能够让机器建立这种联系。
处理过程如下:
- 计算三个新的向量:Query (Q)、Key (K)、Value (V)。这三个向量是用 Embedding 向量与随机初始化的矩阵相乘得到的结果。
- 计算 Self-Attention 的分数值,决定了当我们在某个位置 Encode 一个词时,对输入句子的其他部分的关注程度。分数值的计算方法是 Query 与 Key 做点积。
- 将点积结果除以一个常数(通常是 $\sqrt{d_k}$),然后进行 Softmax 计算。得到的结果是每个词对于当前位置的词的相关性大小。
- 将 Value 和 Softmax 得到的值进行加权求和,得到的结果即是 Self-Attention 在当前节点的值。
在实际应用场景中,为了提高计算速度,通常采用矩阵方式直接计算出 Q、K、V 的矩阵,然后将 Embedding 的值与三个矩阵相乘,得到新矩阵 Q 与 K 相乘,乘以常数,做 Softmax 操作,最后乘上 V 矩阵。这种方法被称为 Scaled Dot-Product Attention。
2.2.3 Multi-Headed Attention
为了增强模型的表达能力,论文引入了 Multi-Headed Attention 机制。简单来说,不仅仅是初始化一组 Q、K、V 的矩阵,而是初始化多组。在 Transformer 中通常使用了 8 组多头注意力。这样可以让模型在不同的表示子空间中关注不同的信息,最后将各个头的输出拼接起来。


