本文是对视频【官方双语】直观解释注意力机制,Transformer的核心 | 【深度学习第6章】的整理
1 背景
要解决的问题:接收一段文本,预测下一个词
句子会被切成许多小块,这些小块称为token。token可以是单词也可以是词组。为了简单起见,本文假设所有token是单词。
第一步就是把每个token映射到一个嵌入向量(embedding)
需要了解的是,在这个高维空间中,每个可能的嵌入向量的方向代表了语义。
Transformer的目的是为了不断调整这些嵌入向量,使得他不仅仅对这个单独的单词进行编码,同时还要融入更多的上下文语义。
2 self-attention(单头)
2.1 Q和K,得到注意力模式(attention pattern)
同一个单词在不同的语境中有不同的含义
在第一步切分文本并把每个token映射到嵌入向量后,三个“mole”对应的是同一个向量。初始的token嵌入没有考虑任何上下文信息。
想象一下,在嵌入空间有多个方向,编码了“mole”这个单词的不同含义。
训练好的注意力模块可以计算出需要给初始的泛型嵌入(generic embedding)加上什么向量,才能把它移动到考虑了上下文的对应的方向上。
注意力模块不仅精细化了一个单词的含义,还允许模型相互传递这些嵌入向量所蕴含的信息。
甚至可以传递的很远,而且新的嵌入向量的信息比单个词丰富的多。
所有向量流经网络之后,经历了很多层注意力模块。此时预测下一个token的计算过程,完全基于序列中最后一个向量
举例来说,输入了一整篇文章,最后是“the murderer was”.如果模型要准确预测下一个词,该序列的最后一个向量,也就是“was”对应的向量,必须经过所有注意力模块的更新,已包含远超单个词的信息量。也就是设法编码整个上下文窗口中与预测下一个词相关的所有信息。
举例如下:假设有下面这段话,重点关注形容词对名词的改变。
每个词的初始嵌入是一个高维向量。只编码了这个词的泛型含义,没有考虑上下文。同时也编码了位置信息(位置编码有很多种),告诉模型单词在序列中的位置。
用
E
⃗
\vec{E}
E来表示嵌入向量,最后的目标就是通过计算,产生一组新的,更为精准的嵌入向量(考虑了上下文)。
这个过程的第一步可以想象成“creature”这个单词在问:“我的前面有形容词吗?”
然后fluffy和blue回答:“是的,我们在这里”。
这样的提问被编码成了另外一个向量,称之为查询(Query)
查询向量的维度比嵌入向量的维度要小得多。要计算查询向量,先取一个矩阵
W
Q
W_Q
WQ,乘以嵌入向量
查询向量
Q
4
→
=
W
Q
E
4
→
\overrightarrow{Q_4}=W_Q \overrightarrow{E_4}
Q4=WQE4
把查询矩阵与所有嵌入向量相乘,得到对应的查询向量。
W
Q
W_Q
WQ是从数据中学习得到的。
还需要第二个矩阵,键矩阵
W
K
W_K
WK,也会与每个嵌入向量相乘,产生键向量序列
W
Q
W_Q
WQ与
W
K
W_K
WK都把嵌入向量映射到了低维度空间。在低维度空间,查询向量与键向量方向对齐的时候,认为匹配。对于本例,键矩阵会把fluffy和blue映射到与creature的查询向量高度一致的方向上。
为了衡量每个键向量与每个查询向量的匹配程度,计算所有可能的键向量与查询向量之间的内积。内积越大,键向量与查询向量越对齐(方向一致),
上面形容词的例子就像这样。fluffy和blue的键向量与creature的查询向量高度对齐。fluffy和blue注意到了creature的嵌入.其他的词的键向量与creature的查询向量内积很小,说明他们与他的关联不大。
内积可以是负无穷到正无穷的任何数字。这个内积得分可以看作是每个词与更新其他词的含义有多相关
这些得分最后要当作权重使用,所以要映射到(0,1)之间,而且每列总和为1,就像概率分布。
softmax可以达到这个目的
利用softmax进行归一化后,每一列可以看作权重,表示左侧的键向量与顶部的查询向量的相关程度。
我们称这个网格为attention pattern
论文中把attention写的很简洁,
Q
Q
Q是查询向量,
K
K
K是键向量
V
V
V是值向量。如下:
Q
K
T
QK^T
QKT表达了键向量与查询向量的内积得到的表格,为了数值稳定性,除以键-查询空间的维度的平方根。然后整个表达式的最外层的softmax是逐列进行的。
2.2 掩码
[to DO]
2.3 V,更新语义
算出这个模式,就可以让模型推断出每个词与其他哪些词(在精细化语义上)有关,
然后要做的就是去更新嵌入向量,把各个词的信息传递给与之相关的其他词。
例如要让fluffy这个词的嵌入向量改变creature这个词的嵌入向量,使其移动到这个12000多维的词嵌入空间的另一个方向。从而更具体的表示“fluffy creature”
这会用到第三个矩阵,值矩阵(value matrix)
W
V
W_V
WV,将
W
V
W_V
WV乘以第一个词“fluffy”的嵌入,得到的就是值向量(value vector),这也就是加到后面的“creature”的嵌入向量的向量,所以这个值向量处于与嵌入向量相同的高维空间。
这个过程可以理解为“如果这个词需要调整目标词的含义(这个由attention pattern决定),那么,要使得目标词能反映出语义的变化,需要加上什么向量呢?”
每个嵌入向量乘以
W
V
W_V
WV,得到对应的值向量。拿creature这个词举例,他所对应的attention权重乘以对应的值向量,得到想要引入的变化量,记为
Δ
E
⃗
\Delta \vec{E}
ΔE,然后把他加到原始嵌入向量上。预期是得到一个考虑了上下文的更精准的向量。
当然,需要对所有的词都要做这个操作,得到每个token考虑上下文后更精准的编码。这就是单头注意力机制。
整个过程由三个可学习的矩阵实现:
W
Q
W_Q
WQ、
W
K
W_K
WK、
W
V
W_V
WV
算一下GPT3的总参数量:键矩阵和查询矩阵都有12288个列,对应了嵌入向量空间维度。128行,对应了键-查询空间维度。这样就各有1572864个参数
按照之前说的,值矩阵行和列都是12288维,这就是1.5亿 的参数。可以看到值矩阵的参数数量比查询矩阵和键矩阵多好几个数量级。
有没有更好的处理方式呢?将值矩阵分解成两个矩阵的乘积。
解释1:第一个矩阵把较大的嵌入向量映射到低维度的空间,称为“value down matrix”,另一个矩阵把向量从低维空间映射回高维嵌入空间,称为“value up matrix”
解释2:线性代数术语:对大矩阵的“低秩分解”(low rank transformation)
这样四个矩阵加起来一共约630万个参数。
3 交叉注意力:cross-attention
GPT只需要自注意力机制,不需要交叉注意力机制。交叉注意力机制涉及的模型会处理两种不同类型的数据。比如机器翻译和音频转文字。
交叉注意力和自注意力几乎相同,唯一的区别是:键和查询矩阵作用于不同的数据集。例如机器翻译中,键来自一种语言,而查询来自另一种语言。
而这个注意力模式就可以描述,一种语言中的哪些词对应另一种语言的哪些词。这种情况下通常不会用到掩码。因为不存在后面的token影响前面的token 的问题。
4 多头注意力机制
上面的例子里讲的是形容词影响名词的语义,实际上,上下文中影响词义的方式有多种。每一种不同的上下文更新方式,键矩阵和查询矩阵都会有所变化,以捕捉不同的注意力模式。值矩阵也会不同(要加到嵌入向量上的向量不同)
transformer完整的注意力模块由多头注意力组成,每个头都有不同的键、值、查询矩阵。GPT3每个注意力模块有96个注意力头。
GPT3每个注意力模块有96个注意力头。每个头都有不同的键、值、查询矩阵,产生96个不同的注意力模式。每个注意力头都有不同的值矩阵,产生96个值向量。与对应注意力模式分别加权求和。每个token都会产生96个要加到这个token嵌入向量上的变化量。而你要做的就是把各个头给出的变化量加起来。然后加上初始的嵌入向量。
这个总和就是多头注意力模块输出的一列。得到更精准的向量。
这样一共有6亿个参数。
4.1 额外说明
在论文和实际的实践中,多头注意力机制中,value up矩阵会合到一起,称为output矩阵,与整个多头注意力模块相关联,
而值矩阵就指的是value down矩阵。以下还有其他额外的技巧
多头注意力之后,还要经过MLP模块。然后会多次重复这两个模块。使得所提取的概念从低级走向高级。比如情感,语气,诗意。
96个层,这样GPT3的参数量来到了580亿。很多了,但是只占总参数量1750亿的三分之一。其他参数在MLP。