文章目录
- 1. Transformer结构
- 2. Encoder结构
- 2.1 Transformer输入
- 2.2 相对位置编码
- 2.3 Self-Attention
- 2.4 Multi-Head Attention
- 2.5 Encoder 整体
- 3. Decoder结构
- 3.1 带Mask的Multi-Head Attention
- 3.2 Multi-Head Attention
- 4. 预测层
1. Transformer结构
Transformer的结构如下所示:
左边是编码器结构,负责将信息编码为向量,右边是解码器结构,将向量解码成需要的信息,该结构可以抽象为:
2. Encoder结构
2.1 Transformer输入
Transformer 中单词的输入表示 x由单词 Embedding 和位置 Embedding 相加得到。
其中单词的 Embedding 有很多种方式可以获取,例如可以采用 Word2Vec、Glove 等算法预训练得到,也可以在 Transformer 中训练得到。
Transformer 中除了单词的 Embedding,还需要使用位置 Embedding 表示单词出现在句子中的位置。因为 Transformer 不采用 RNN 的结构,而是使用全局信息,不能利用单词的顺序信息,而这部分信息对于 NLP 来说非常重要。 所以 Transformer 中使用位置 Embedding 保存单词在序列中的相对或绝对位置。
该过程如下:
位置编码的方法由很多,接下来我们介绍几种常用的。
-
方法一
这个方法的分配方式是,将0-1这个范围的,将第一个token分配0,最后一个token分配去1,其余的token按照文章的长度平均分配。具体形式如下:
我喜欢吃洋葱 【0 0.16 0.32…1】
我真的不喜欢吃洋葱【0 0.125 0.25…1】问题:我们可以看到,如果句子长度不同,那么位置编码是不一样,所以无法表示句子之间有什么相似性。
-
方法二
这个方法比较直观,就是按照输入的顺序,一次分配给token所在的索引位置。具体形式如下:
我喜欢吃洋葱 【1,2,3,4,5,6】
问题:往往句子越长,后面的值越大,数字越大说明这个位置占的权重也越大,这样的方式无法凸显每个位置的真实的权重。
过去的方法总有这样或者那样的不好,所以Transformer对于位置信息的编码做了改进。
一种好的位置编码方案需要满足以下几条要求:
- 它能为每个时间步输出一个独一无二的编码;
- 不同长度的句子之间,任何两个时间步之间的距离应该保持一致;
- 模型应该能毫不费力地泛化到更长的句子。它的值应该是有界的;
- 它必须是确定性的。
2.2 相对位置编码
相对位置即关注一个token与另一个token距离差几个token。比如:位置1和位置2的距离比位置3和位置10的距离更近,位置1和位置2与位置3和位置4都只相差1。
还是按照上面"我喜欢吃洋葱"中的“我”为例,看看相对位置关系是什么样子的:
我们可以看到,使用相对位置的方法,我们可以清晰的知道单词之间的距离远近的关系。
Transformer的作者们提出了一个简单但非常创新的位置编码方法,能够满足上述所有的要求。首先,这种编码不是单一的一个数值,而是包含句子中特定位置信息的 d 维向量(非常像词向量),向量如下:
p i → = [ sin ( ω 1 ⋅ t ) cos ( ω 1 ⋅ t ) sin ( ω 2 ⋅ t ) cos ( ω 2 ⋅ t ) ⋮ sin ( ω d / 2 ⋅ t ) cos ( ω d / 2 ⋅ t ) ] \overrightarrow{p_i}=\left[\begin{array}{c}\sin(\omega_1\cdot t)\\\cos(\omega_1\cdot t)\\\sin(\omega_2\cdot t)\\\cos(\omega_2\cdot t)\\\vdots\\\sin(\omega_{d/2}\cdot t)\\\cos(\omega_{d/2}\cdot t)\end{array}\right] pi= sin(ω1⋅t)cos(ω1⋅t)sin(ω2⋅t)cos(ω2⋅t)⋮sin(ωd/2⋅t)cos(ωd/2⋅t)
其中,频率 w k w_k wk 定义如下:
ω k = 1 1000 0 2 k / d \omega_{k}=\frac{1}{10000^{2k/d}} ωk=100002k/d1
d d d 表示向量维度,这里的 t t t 就是每个 t o k e n token token的位置,比如说是位置1,位置2,以及位置n。
将这个向量与模型的嵌入词向量 ψ ( w t ) \psi\left(w_{t}\right) ψ(wt) 直接相加喂给模型: ψ ′ ( w t ) = ψ ( w t ) + p t ′ → \psi'\left(w_t\right)=\psi\left(w_t\right)+\overrightarrow{p_t^{\prime}} ψ′(wt)=ψ(wt)+pt′
为了保证这种相加操作正确,让位置向量(PE)的维度等于词向量(WE)的维度。
问题:这样的方式虽说可以表示出相对的距离关系,但是也是有局限的。其中一个比较大的问题是:只能的到相对关系,无法得到方向关系。所谓的方向关系就是,对于两个token谁在谁的前面,或者谁在谁的后面是无法判断的。
2.3 Self-Attention
Transformer中编码器和解码器都含有Self-Atteention的结构,在这里我们就先介绍Self-Attention的计算。
Self-Attention的结构如下:
在计算的时候需要用到矩阵 Q(查询), K(键值), V(值)。在实际中,Self-Attention 接收的是输入(单词的表示向量 x组成的矩阵 X) 或者上一个 Encoder block 的输出。而 Q, K, V 正是通过 Self-Attention 的输入进行线性变换得到的。
首先,我们有一个由输入单词组成的矩阵 X ,其每一行都代表每一个单词的表示,然后将其使用线性变换矩阵WQ, WK, WV 计算得到 Q, K, V,如下如所示。
得到矩阵 Q, K, V之后就可以计算出 Self-Attention 的输出了,计算的公式如下:
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V \mathrm{Attention}(Q,K,V)=\mathrm{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
其中 d k d_k dk 是 Q, K 矩阵的列数,即向量维度,为了防止内积过大,因此除以 d k \sqrt{d_k} dk ,得到的矩阵 Q K T QK^T QKT 行列数都为 n,n 为句子单词数,这个矩阵可以表示单词之间的 attention 强度。
得到 Q K T QK^T QKT之后,使用 Softmax 计算每一个单词对于其他单词的 attention 系数,公式中的 Softmax 是对矩阵的每一行进行 Softmax,即每一行的和都变为 1。
得到 Softmax 矩阵之后可以和 V相乘,得到最终的输出矩阵 Z。
上图中 Softmax 矩阵的第 1 行表示单词 1 与其他所有单词的 attention 系数,最终单词 1 的输出 Z1 等于所有单词 i 的值 Vi 根据 attention 系数的比例加在一起得到,如下图所示:
2.4 Multi-Head Attention
Multi-Head Attention 是由多个 Self-Attention 组合形成的,其结构如下:
从上图可以看到 Multi-Head Attention 包含h个 Self-Attention 层,首先将输入 X分别传递到 h 个不同的 Self-Attention 中,计算得到 h 个输出矩阵 Z。下图是 h=8 时候的情况,此时会得到 8 个输出矩阵 Z。
得到 8 个输出矩阵 Z1 到 Z8 之后,Multi-Head Attention 将它们拼接在一起 (Concat),然后传入一个 Linear层,得到 Multi-Head Attention 最终的输出 Z。
可以看到 Multi-Head Attention 输出的矩阵 Z与其输入的矩阵 X 的维度是一样的。
2.5 Encoder 整体
因为每个Encoder的结构都是一样的,所以我们单独看一个Encoder的结构,单独的Encoder结构如下图红框所示:
可以看到Encoder是由Multi-Head Attention, Add & Norm, Feed Forward, Add & Norm 组成的,Add & Norm 层由 Add 和 Norm 两部分组成,其计算公式如下:
LayerNorm ( X + MultiHeadAttention ( X ) ) LayerNorm ( X + FeedForward ( X ) ) \begin{aligned}\text{LayerNorm}&\big(X+\text{MultiHeadAttention}(X)\big)\\\text{LayerNorm}&\big(X+\text{FeedForward}(X)\big)\end{aligned} LayerNormLayerNorm(X+MultiHeadAttention(X))(X+FeedForward(X))
Add指 X+MultiHeadAttention(X),是一种残差连接,通常用于解决多层网络训练的问题,可以让网络只关注当前差异的部分,在 ResNet 中经常用到。
Norm指 Layer Normalization,通常用于 RNN 结构,Layer Normalization 会将每一层神经元的输入都转成均值方差都一样的,这样可以加快收敛。
Feed Forward 层比较简单,是一个两层的全连接层,第一层的激活函数为 Relu,第二层不使用激活函数,对应的公式如下:
max ( 0 , X W 1 + b 1 ) W 2 + b 2 \max(0,XW_1+b_1)W_2+b_2 max(0,XW1+b1)W2+b2
X是输入,Feed Forward 最终得到的输出矩阵的维度与 X 一致。
3. Decoder结构
上图红色部分为 Transformer 的 Decoder block 结构,与 Encoder block 相似,但是存在一些区别:
- 包含两个 Multi-Head Attention 层。
- 第一个 Multi-Head Attention 层采用了 Masked 操作。
- 第二个 Multi-Head Attention 层的 K, V 矩阵使用 Encoder 的编码信息矩阵 C 进行计算,而 Q 使用上一个 Decoder block 的输出计算。
- 最后有一个 Softmax 层计算下一个翻译单词的概率。
3.1 带Mask的Multi-Head Attention
如果像encoder的注意力机制那里一样没有mask,那么在训练decoder时,如果要生成预测结果you,就需要用到下面整个句子的所有词。但是在真正预测的时候,并看不到未来的信息。
Decoder block 的第一个 Multi-Head Attention 采用了 Masked 操作,因为在翻译的过程中是顺序翻译的,即翻译完第 i 个单词,才可以翻译第 i+1 个单词。通过 Masked 操作可以防止第 i 个单词知道 i+1 个单词之后的信息。下面以 “我有一只猫” 翻译成 “I have a cat” 为例,了解一下 Masked 操作。那么在预测第 i 个输出时,就要将第 i+1 之后的单词掩盖住,注意 Mask 操作是在 Self-Attention 的 Softmax 之前使用的,下面用 0 1 2 3 4 5 分别表示 “<Begin> I have a cat <end>”。
输入矩阵包含 “<Begin> I have a cat” (0, 1, 2, 3, 4) 五个单词的表示向量,Mask 是一个 5×5 的矩阵。在 Mask 可以发现单词 0 只能使用单词 0 的信息,而单词 1 可以使用单词 0, 1 的信息,即只能使用之前的信息。
接下来的操作和之前的 Self-Attention 一样,通过输入矩阵 X计算得到 Q, K, V 矩阵。然后计算 Q 和 KT 的乘积 Q K T QK^T QKT。
在得到
Q
K
T
QK^T
QKT 之后需要进行 Softmax,计算 attention score,我们在 Softmax 之前需要使用 Mask矩阵遮挡住每一个单词之后的信息,遮挡操作如下:
得到 Mask QKT 之后在 Mask QKT 上进行 Softmax,每一行的和都为 1。但是单词 0 在单词 1, 2, 3, 4 上的 attention score 都为 0。
使用 Mask Q K T QK^T QKT 与矩阵 V相乘,得到输出 Z,则单词 1 的输出向量 Z1 是只包含单词 1 信息的。
通过上述步骤就可以得到一个 Mask Self-Attention 的输出矩阵 Zi,然后和 Encoder 类似,通过 Multi-Head Attention 拼接多个输出 Zi 然后计算得到第一个 Multi-Head Attention 的输出 Z,Z与输入 X 维度一样。
3.2 Multi-Head Attention
这里的多头注意力的具体细节和encoder是相同的,唯一的区别就是,encoder的多头注意力里的Q、K、V是初始化多个不同的 矩阵得到的。而decoder的K、V是来自于encoder的输出,Q是上层Masked Self-Attention的输出。
如果解码部分的多头注意力有多层,那么输入到每层多头注意力里的K、V都来自于encoder。除了第一层的Q来自于masked Multi-Head Attention的输出,其余的Q都来自于上层dncoder的输出。
4. 预测层
最后使用一个线性层和Softmax层对下一个单词的概率进行预测。
我们假设自己的模型从训练数据集中共学会了10,000个不同的英语单词(我们模型的“输出词汇表”)。这将使线性层的宽度变为10,000个单元,每个单元对应各个单词的得分。我们将会通过这样的方式来解释模型的输出。
然后,softmax层将会把这些分数转换为概率(全部为正数,各项相加和为1.0)。概率最高的单元被选中,且与该单元相关联的单词将成为该步的输出。