Transformer 架构
这篇文章不错:Transformer模型详解(图解最完整版) - 知乎
论文《Attention is All You Need》提出。Transformer 由 Encoder 和 Decoder 两个部分组成。(注意,当前一些主流的 LLM 比如 Claude, ChatGPT, Gemini, DeepSeek-V3 等等都已经抛弃了 encoder,成为了 Decoder-Only 的架构了)。
输入:
每一个 Encoder block 输出的矩阵维度与输入完全一致。
上图可以看出来,Decoder 有两个输入,编码矩阵和 Masked 矩阵(表示当前已经翻译好的内容)。然后进行多轮输入,每一轮根据编码矩阵和已经翻译好的内容翻译下一个单词。
Transformer 架构应用在机器翻译和大语言模型问答上的区别
Transformer 刚开始研发出来应该是做机器翻译的,
Encoder in Transformer
是由 Multi-Head Attention, Add & Norm, Feed Forward, Add & Norm 组成的。
Decoder in Transformer
解码生成时都是自回归 auto-regressive 的方式。也就是,Decoder 的输出(已翻译的内容)会变为下一次的输入。刚开始都 mask,随着翻译的进行,逐渐 mask 的越来越少。
形式化来表达一下:也就是,解码的时候,先根据当前输入 ,生成下一个 ,然后把新生成的 拼接在 后面,获得新的输入 ,再用 生成 ,依此迭代,直到生成结束。
与 Encoder block 相似,但是存在一些区别:
- 包含两个 Multi-Head Attention 层。
- 第一个 Multi-Head Attention 层采用了 Masked 操作。
- 第二个 Multi-Head Attention 层的 K, V 矩阵使用 Encoder 的编码信息矩阵 C 进行计算,而 Q 使用上一个 Decoder block 的输出计算。
- 最后有一个 Softmax 层计算下一个翻译单词的概率。
第一个 Multi-Head Attention 层采用了 Masked 操作:
Decoder block 的第一个 Multi-Head Attention 采用了 Masked 操作,因为在翻译的过程中是顺序翻译的,即翻译完第 个单词,才可以翻译第 个单词。通过 Masked 操作可以防止第 i 个单词知道 i+1 个单词之后的信息。下面以 " 我有一只猫 " 翻译成 "I have a cat" 为例,了解一下 Masked 操作。
第二个 Multi-Head Attention 层的 K, V 矩阵使用 Encoder 的编码信息矩阵 C 进行计算,而 Q 使用上一个 Decoder block 的输出计算:
Decoder block 第二个 Multi-Head Attention 变化不大, 主要的区别在于其中 Self-Attention 的 矩阵不是使用 上一个 Decoder block 的输出计算的,而是使用 Encoder 的编码信息矩阵 计算的。
根据 Encoder 的输出 计算得到 ,根据上一个 Decoder block 的输出 计算 (如果是第一个 Decoder block 则使用输入矩阵 进行计算),后续的计算方法与之前描述的一致。
这样做的好处是在 Decoder 的时候,每一位单词都可以利用到 Encoder 所有单词的信息 (这些信息无需 Mask)。
Add & Norm
由 Add 和 Norm 两部分组成,其计算公式如下:
或者:
其中 表示 Multi-Head Attention 或者 Feed Forward 的输入, 和 表示输出 (输出与输入 维度是一样的,所以可以相加)。
Add 指 ,是一种残差连接,通常用于解决多层网络训练的问题,可以让网络只关注当前差异的部分,在 ResNet 中经常用到。
Norm 指 Layer Normalization,通常用于 RNN 结构,Layer Normalization 会将每一层神经元的输入都转成均值方差都一样的,这样可以加快收敛。
Feed Forward in Transformer
比较简单,是一个两层的全连接层,第一层的激活函数为 ,第二层不使用激活函数。
是输入,Feed Forward 最终得到的输出矩阵的维度与 一致。
各种 Attention 机制
Self-Attention, MHA, MQA, GQA, MLA。
MQA、GQA、MLA,都是围绕“如何减少 KV Cache 同时尽可能地保证效果”这个主题发展而来的产物。
[缓存与效果的极限拉扯:从MHA、MQA、GQA到MLA - 科学空间 | Scientific Spaces](https://spaces.ac.cn/archives/10091) |
Self-Attention
需要用到三个矩阵:(查询), (键值), (值)。记住 和 ,KV Cache 指的就是这两者。
Self-Attention 接收的输入是:
- (单词的表示向量组成的矩阵 (注意是表示不是编码)) 或者
- 上一个 Encoder block 的输出。
Self-attention 的输出和输入矩阵的格式是一样的。
而 , , 正是通过 Self-Attention 的输入进行线性变换得到的。Self-Attention 的输入用矩阵 进行表示,则可以使用线性变阵矩阵 , , 计算得到 , , 。注意 , , , 的每一行都表示一个单词。
可以看到 , , 三个矩阵具有相同的格式,单词个数没有变(行数没有变),但是每一个单词的表示向量的长度(列数)变了。
得到矩阵 , , 之后就可以计算出 Self-Attention 的输出了,计算的公式如下:
我们可以把这个公式分成三部分:
下面分开进行解释。第一部分:
公式中计算矩阵 和 每一行向量的内积,为了防止每一个内积的值过大,因此除以 ,这个是矩阵的列数,表示每一个单词向量的维度(用了多少维来表示这个向量) 。 乘以 后,得到的矩阵行列数都为 , 为句子单词数,这个矩阵可以表示单词之间的 attention 强度。也就是矩阵的 项其实表示第 个单词和第 个单词之间的 attention 强度。
我们知道向量相乘表示一个向量在另一个向量上的投影。投影越大,说明向量相关性越高。因为两个向量的内积是两个向量的相关度,那矩阵计算 就是每一个单词向量和其他单词向量的相关性。词 A 和 B 之间相关度高表示什么?是不是在一定程度上(不是完全)表示,在关注词 A 的时候,应当给予词 B 更多的关注?
第二部分:
softmax 的意义在于归一化,softmax 之后,得到的数之和就是 1 ,这样代表了权重。这就是 attention 的核心加权求和的由来。当我们关注 " 早 " 这个字的时候,我们应当分配 0.4 的注意力给它本身,剩下 0.4 关注 " 上 ",0.2 关注 " 好 ",这就是注意力机制。
第三部分:
得到 Softmax 矩阵之后可以和 相乘,得到最终的输出 。最终单词 1 的输出 等于所有单词 的值 根据 attention 系数的比例加在一起得到:
这一步的物理意义可以这么解释:
这个新的行向量就是 " 早 " 字词向量经过注意力机制加权求和之后的表示。其实也可以这样理解:之前各个向量是独立存在的(也就是 V 向量),经过 attention 之后(和注意力向量相乘之后),每个向量的表示融入了一些注意力的因素在里面做了变换。这一步还有一个意义就是用来保持 self-attention 算子的输入和输出格式保持一致。
最后,为什么这三个矩阵起 (查询 Query), (键 Key), (值 Value) 这些名称呢?
表示的就是与我这个单词相匹配的单词的属性, 就表示我这个单词的本身的属性, 表示的是我这个单词的包含的信息本身。
举个例子来说,假如你有一个问题 ,去数据库里面搜,数据库存了很多文章,每个文章的标题是 ,内容是 ,然后搜索的过程就是用你的问题 去和数据库内所有的标题 进行一个相关度的计算,然后将每个文章的内容 根据其标题 与查询 的相关度和做个加权和,得到了最终的结果,这个结果融合了相关性强的文章 更多信息,而融合了相关性弱的文章 较少的信息。这就是注意力机制,注意力度不同,重点关注(权值大)与你想要的东西相关性强的部分(文章内容 ),稍微关注(权值小)相关性弱的部分(文章内容 )。所以你能看到, 就表示了单词之间的相关性。因为相当于拿 里面的每一个 token 所对应的行向量作为一个 query 来查询 K 里面的相关性,这样就得到了所有 query 和所有其他 token 的的相关性。然后乘以 就可以根据 和 的相关性取出所有的值。
深度学习Attention中的Q,K,V为什么不叫A,B,C或者X,Y,Z? - 知乎
整个 self-attention 的计算过程可以汇总为下面这张非常直观的图:
MHA (Multi-Head Attention)
对于 self-attention,由于 , , 都来自输入 ,在计算 时,模型很容易关注到自身的位置上,也就是 对角线上的激活值会明显比较大。这样的情况其实不是很好,因为这会削弱模型关注其他高价值位置的能力,也就限制模型的理解和表达能力。MHA 对这个问题会有一些缓解作用。
我们希望多个头能够在训练中学会注意到不同的内容。例如在翻译任务里,一些 attention head 可以关注语法特征,另一些 attention head 可以关注单词特性。这样模型就可以从不同角度来分析和理解输入信息,获得更好的效果了。
头的数量不是越多越好(毕竟头的数量多了,各个子空间小了,子空间能表达的内容就少了)。
MHA 在 2017 年就随着《Attention Is All You Need》一起提出,都是在同一篇论文里的。主要干的就是一个事:把原来一个 attention 计算,拆成多个小份的 attention,并行计算,分别得出结果,最后再合回原来的维度。其实就是在原来的 attention 下,, , 的维度都是比较长(行数和输入矩阵 是一样的,但是列数不一定),然后做一次 attention,而 MHA 相当于把每一个 , , 都拆成了列数比较少的多个矩阵,然后做多次 attention,最后再拼起来。
Multi-Head Attention 是由多个 Self-Attention 组合形成的。首先将输入 分别传递到 个不同的 Self-Attention 中,计算得到 个输出矩阵 。比如当 的时候,此时会得到 8 个输出矩阵 。
得到 8 个输出矩阵 到 之后,Multi-Head Attention 将它们拼接在一起 (Concat),然后乘以一个 Linear 层,得到 Multi-Head Attention 最终的输出 Z。
可以看到,之所以叫做 Multi-Head Attention,是因为是由多个 self-attention 组成的,最后的输出。
理论上来说,可以看到 MHA 的输入和输出格式不一定是一样的,这取决于最后线性变换矩阵的列数。但是实际上 Multi-Head Attention 输出的矩阵 与其输入的矩阵 的维度是一样的。
参考文献:
MLA
算子(Multi-query Latent Attention)
MLA(Multi-query Latent Attention) 是国内创业公司 deepseek 在 24 年 5 月份发布的 DeepSeek-V2 大模型中用到的 KV Cache 压缩技术,正是在该技术的加持下 DeepSeek-V2 可以大幅压缩 KV Cache 的大小,进而大幅提升吞吐量。
缓存与效果的极限拉扯:从MHA、MQA、GQA到MLA - 科学空间|Scientific Spaces