Transformer

2025-05-27 195714(1).jpg

参考资料:

  1. Transformer模型详解(图解最完整版) – 知乎
  2. Transformer是什么?2017年那篇“无人问津”的论文,为何成了今天AI爆炸的起点?10分钟速通AI论文天花板《Attention is all you_哔哩哔哩_bilibili

前言

Transformer由论文《Attention is All You Need》提出,现在是谷歌云TPU推荐的参考模型。论文相关的Tensorflow的代码可以从GitHub获取,其作为Tensor2Tensor包的一部分。哈佛的NLP团队也实现了一个基于PyTorch的版本,并注释该论文。

在本文中,我们将试图把模型简化一点,并逐一介绍里面的核心概念,希望让普通读者也能轻易理解。

Attention is All You Need:Attention Is All You Need

1.Transformer 整体结构

首先介绍 Transformer 的整体结构,下图是 Transformer 用于中英文翻译的整体结构:


(Transformer 的整体结构,左图Encoder和右图Decoder)

可以看到 Transformer 由 Encoder 和 Decoder 两个部分组成,Encoder 和 Decoder 都包含 6 个 block。Transformer 的工作流程大体如下:

第一步:获取输入句子的每一个单词的表示向量 XX 由单词的 Embedding(Embedding就是从原始数据提取出来的Feature) 和单词位置的 Embedding 相加得到。


(Transformer 的输入表示)

第二步:将得到的单词表示向量矩阵 (如上图所示,每一行是一个单词的表示 x) 传入 Encoder 中,经过 6 个 Encoder block 后可以得到句子所有单词的编码信息矩阵 C,如下图。单词向量矩阵用  表示, n 是句子中单词个数,d 是表示向量的维度 (论文中 d=512)。每一个 Encoder block 输出的矩阵维度与输入完全一致。


(Transformer Encoder 编码句子信息)

第三步:将 Encoder 输出的编码信息矩阵 C传递到 Decoder 中,Decoder 依次会根据当前翻译过的单词 1~ i 翻译下一个单词 i+1,如下图所示。在使用的过程中,翻译到单词 i+1 的时候需要通过 Mask (掩盖) 操作遮盖住 i+1 之后的单词。


(Transofrmer Decoder 预测)

上图 Decoder 接收了 Encoder 的编码矩阵 C,然后首先输入一个翻译开始符 "<Begin>",预测第一个单词 "I";然后输入翻译开始符 "<Begin>" 和单词 "I",预测单词 "have",以此类推,即每一步都是在已有的结果上预测下一个最合理的英文词。这是 Transformer 使用时候的大致流程,接下来是里面各个部分的细节。

image.png

注意,解码器/生成过程中有大量的self-attention机制,这些机制的过程也是理解,所以大语言模型,如GPT,只需要解码器即可。

2.Transformer 的输入

2.0 Token和向量

将一句话切分成多个词块,每个词块叫一个token

假设有一个多维坐标轴,每个坐标轴表示一种语义,比如:是否跟交通相关,这样的空间就是语义空间。

image.png

随着维度的增多,世界上已知词汇的token都能在这个多维坐标系里找到自己的位置

image.png

除此之外,词与词之间的关系可以通过数学方式计算出来,比如下面:国王-男人+女人 会很接近 王后。

image.png

对于有多种意思的token/词块,则一般是在多个坐标轴的平均位置,根据上下文,会将位置向某几个语义轴靠近。

image.png

这些Token都可以在这样的多维坐标系有确定的位置,那么每个token就可以有一组数字(即向量)来表示,也即embedding。

image.png

除了语义信息,还有位置信息,所以有了单词Embedding 和 位置Embedding

Transformer 中单词的输入表示 x单词 Embedding 和位置 Embedding (Positional Encoding)相加得到。


(Transformer 的输入表示)

2.1 单词 Embedding

单词的 Embedding 有很多种方式可以获取,例如可以采用 Word2Vec、Glove 等算法预训练得到,也可以在 Transformer 中训练得到。

2.2 位置 Embedding

Transformer 中除了单词的 Embedding,还需要使用位置 Embedding 表示单词出现在句子中的位置。**因为 Transformer 不采用 RNN 的结构,而是使用全局信息,不能利用单词的顺序信息,而这部分信息对于 NLP 来说非常重要。**所以 Transformer 中使用位置 Embedding 保存单词在序列中的相对或绝对位置。

位置 Embedding 用 PE表示,PE 的维度与单词 Embedding 是一样的。PE 可以通过训练得到,也可以使用某种公式计算得到。在 Transformer 中采用了后者,计算公式如下:

其中,pos 表示单词在句子中的位置,d 表示 PE的维度 (与词 Embedding 一样),2i 表示偶数的维度,2i+1 表示奇数维度 (即 2i≤d, 2i+1≤d)。使用这种公式计算 PE 有以下的好处:

  • 使 PE 能够适应比训练集里面所有句子更长的句子,假设训练集里面最长的句子是有 20 个单词,突然来了一个长度为 21 的句子,则使用公式计算的方法可以计算出第 21 位的 Embedding。
  • 可以让模型容易地计算出相对位置,对于固定长度的间距 k,PE(pos+k) 可以用 PE(pos) 计算得到。因为 Sin(A+B) = Sin(A)Cos(B) + Cos(A)Sin(B), Cos(A+B) = Cos(A)Cos(B) – Sin(A)Sin(B)。

将单词的词 Embedding 和位置 Embedding 相加,就可以得到单词的表示向量 xx 就是 Transformer 的输入。

3. Self-Attention(自注意力机制)


(Transformer Encoder 和 Decoder)

上图是论文中 Transformer 的内部结构图,左侧为 Encoder block,右侧为 Decoder block。红色圈中的部分为 Multi-Head Attention,是由多个 Self-Attention组成的,可以看到 Encoder block 包含一个 Multi-Head Attention,而 Decoder block 包含两个 Multi-Head Attention (其中有一个用到 Masked)。Multi-Head Attention 上方还包括一个 Add & Norm 层,Add 表示残差连接 (Residual Connection) 用于防止网络退化,Norm 表示 Layer Normalization,用于对每一层的激活值进行归一化。

因为 Self-Attention是 Transformer 的重点,所以我们重点关注 Multi-Head Attention 以及 Self-Attention,首先详细了解一下 Self-Attention 的内部逻辑。

3.1 Self-Attention 结构


(Self-Attention 结构)

上图是 Self-Attention 的结构,在计算的时候需要用到矩阵Q(查询),K(键值),V(值)。在实际中,Self-Attention 接收的是输入(单词的表示向量x组成的矩阵X) 或者上一个 Encoder block 的输出。而Q,K,V正是通过 Self-Attention 的输入进行线性变换得到的。

3.1.1 QKV

image.png

Key就是句子中的Token,Token的背后含义是Value,理解一个Token时应该重点关注哪些其他Token,相当于拿这个Token去遍历所有Token,相当于用相应Token的Query查询所有Token。

我们现在只有Token一个向量,用一个向量去完成Query,Key,Value不够灵活,所以通过权重矩阵获得每个Token各自具备的Q,K,V,各司其职。

  • 承担查询角色为Q,代表这个Token想关注什么
  • 承担键角色为K,代表这个Token能提供什么信息
  • 承担值角色为V,代表这个Token背后真正的含义

image.png

3.1.2 Attention 注意力

点积,计算两个向量在坐标系里指向是否一致,数值上反映两者相关程度,高者即多关注

3.2 Q, K, V 的计算

Self-Attention 的输入用矩阵X进行表示,则可以使用线性变阵矩阵WQ,WK,WV计算得到Q,K,V。计算如下图所示,注意 X, Q, K, V 的每一行都表示一个单词。

3.3 Self-Attention 的输出

image.png

点积就是在计算两个向量在坐标系里指向是否一致,数值上反映两者相关程度,高者即多关注

image.png

向量维度过大,点积结果会整体偏大,容易导致某一个Token的关注程度被放大的过于极端,为了让不同Token的关注差异更容易被区分,模型会除以维度的开方,这一步称为 Scale。

image.png

image.png

image.png

得到与原先维度一致且融入了上下文信息的向量

image.png

然后对每个Token做以上操作,每个Token都获得了相应融合上下文信息的向量。

image.png

得到矩阵 Q, K, V之后就可以计算出 Self-Attention 的输出了,计算的公式如下:


(Self-Attention 的输出)

公式中计算矩阵QK每一行向量的内积,为了防止内积过大,因此除以  的平方根。Q乘以K的转置后,得到的矩阵行列数都为 n,n 为句子单词数,这个矩阵可以表示单词之间的 attention 强度。下图为Q乘以  ,1234 表示的是句子中的单词。


(Q乘以K的转置的计算)

得到 之后,使用 Softmax 计算每一个单词对于其他单词的 attention 系数,公式中的 Softmax 是对矩阵的每一行进行 Softmax,即每一行的和都变为 1.


(对矩阵的每一行进行 Softmax)

得到 Softmax 矩阵之后可以和V相乘,得到最终的输出Z


(Self-Attention 输出)

上图中 Softmax 矩阵的第 1 行表示单词 1 与其他所有单词的 attention 系数,最终单词 1 的输出  等于所有单词 i 的值  根据 attention 系数的比例加在一起得到,如下图所示:


Zi 的计算方法)

3.4 Multi-Head Attention

词与词之间的语义是多样的,有些是语义上的关联,有些事语法结构上的依赖,所以为了全面,所以模型进行多次注意力计算,每次关注不同的侧重点,这些并行计算的结果最终被拼接在一起,这就是多头注意力。
在上一步,我们已经知道怎么通过 Self-Attention 计算得到输出矩阵 Z,而 Multi-Head Attention 是由多个 Self-Attention 组合形成的,下图是论文中 Multi-Head Attention 的结构图。


(Multi-Head Attention)

从上图可以看到 Multi-Head Attention 包含多个 Self-Attention 层,首先将输入X分别传递到 h 个不同的 Self-Attention 中,计算得到 h 个输出矩阵Z。下图是 h=8 时候的情况,此时会得到 8 个输出矩阵Z


(多个 Self-Attention)

得到 8 个输出矩阵  到  之后,Multi-Head Attention 将它们拼接在一起 (Concat),然后传入一个Linear层,得到 Multi-Head Attention 最终的输出Z


(Multi-Head Attention 的输出)

可以看到 Multi-Head Attention 输出的矩阵Z与其输入的矩阵X的维度是一样的。

4. Encoder 结构


(Transformer Encoder block)

上图红色部分是 Transformer 的 Encoder block 结构,可以看到是由 Multi-Head Attention, Add & Norm, Feed Forward, Add & Norm 组成的。刚刚已经了解了 Multi-Head Attention 的计算过程,现在了解一下 Add & Norm 和 Feed Forward 部分。

4.1 Add & Norm

将注意力的记过和原始输入相加,这一步即 add,这样,就能让网络只关注到差异部分:
比如残差结构

H(x)=F(x)+x

  • x输入(已经掌握的信息)。
  • F(x)残差(Residual),也就是你说的**“差异部分”**。
  • H(x)输出(最终目标)。
    当你把 x 直接跳接到输出端(通过 Add 操作),网络层 F(x) 就不再需要从零开始构建 H(x) 的所有信息了。它被迫去学习 H(x)x,即“目标与现状之间的缺口”。如果当前层发现输入 x 已经很完美了,它只需要把 F(x) 的权重训练趋近于 0,信息就能无损通过。

image.png

接着做归一化,避免数值在多层计算后失控。

image.png

Add & Norm 层由 Add 和 Norm 两部分组成,其计算公式如下:

其中 X表示 Multi-Head Attention 或者 Feed Forward 的输入,MultiHeadAttention(X) 和 FeedForward(X) 表示输出 (输出与输入 X 维度是一样的,所以可以相加)。

Add指 X+MultiHeadAttention(X),是一种残差连接,通常用于解决多层网络训练的问题,可以让网络只关注当前差异的部分,在 ResNet 中经常用到:

残差连接

Norm指 Layer Normalization,通常用于 RNN 结构,Layer Normalization 会将每一层神经元的输入都转成均值方差都一样的,这样可以加快收敛。

4.2 Feed Forward

Add & Norm 的过程映射关系仍然是线性的

image.png

image.png

为了能够处理非线性的映射,使用前馈神经网络(FFN)

image.png

并且处理后再次进行 Add & Norm。

image.png

Feed Forward 层比较简单,是一个两层的全连接层,第一层的激活函数为 Relu,第二层不使用激活函数,对应的公式如下。


(Feed Forward)

X是输入,Feed Forward 最终得到的输出矩阵的维度与X一致。

4.3 组成 Encoder

通过上面描述的 Multi-Head Attention, Feed Forward, Add & Norm 就可以构造出一个 Encoder block,Encoder block 接收输入矩阵,并输出一个矩阵。通过多个 Encoder block 叠加就可以组成 Encoder。

一个编码层如下图,可以完成一次上下文理解:

image.png

多个编码层堆叠起来,加深语义理解。

编码层之间串行,依次输出结果作为下一个编码层的输入,最终得到了所有Token融入丰富的上下文理解的一组向量,这样的整体构成了一个编码器(Encoder)。

第一个 Encoder block 的输入为句子单词的表示向量矩阵,后续 Encoder block 的输入是前一个 Encoder block 的输出,最后一个 Encoder block 输出的矩阵就是编码信息矩阵 C,这一矩阵后续会用到 Decoder 中。


(Encoder 编码句子信息)

5. Decoder 结构


(Transformer Decoder block)

上图红色部分为 Transformer 的 Decoder block 结构,与 Encoder block 相似,但是存在一些区别:

  • 包含两个 Multi-Head Attention 层。
  • 第一个 Multi-Head Attention 层采用了 Masked 操作。
  • 第二个 Multi-Head Attention 层的K, V矩阵使用 Encoder 的编码信息矩阵C进行计算,而Q使用上一个 Decoder block 的输出计算。
  • 最后有一个 Softmax 层计算下一个翻译单词的概率。

5.1 第一个 Multi-Head Attention

场景:中文 -> 英文

问题1:新生成的词怎么和已经写下的英文内容衔接?保证语法和表达连贯

使用注意力机制,查询当前token(翻译中的句子当前token),此时词块数据库为翻译中的句子,拿当前token的Q乘以前面包括自己的token的K,更新上文理解的信息进来,从而更新当前token的向量,接着还需要结合原文的,这个后面会讲。

注意:在最开始翻译的时候,翻译中的句子当前token是下图中的<BOS>,也是后面文中写到的<Begin>,由当前token进行查询更新当前token的向量,结合原文来预测下一个英语单词。

image.png

Decoder block 的第一个 Multi-Head Attention 采用了 Masked 操作,因为在翻译的过程中是顺序翻译的,即翻译完第 i 个单词,才可以翻译第 i+1 个单词。通过 Masked 操作可以防止第 i 个单词知道 i+1 个单词之后的信息。下面以 "我有一只猫" 翻译成 "I have a cat" 为例,了解一下 Masked 操作。

不过很重要的一点,训练的过程中,会输入正确结果给解码器,用于同步计算loss提高训练效率,但是不能原封不动地输入答案。

  • 首先需要翻译的启动,即开头需要有<BOS>,相当于右移
  • 需要掩码,如果没有掩码,即查询当前token,预测下一token时,通过Q乘以所有token的

下面的描述中使用了类似 Teacher Forcing 的概念,不熟悉 Teacher Forcing 的童鞋可以参考以下上一篇文章Seq2Seq 模型详解。在 Decoder 的时候,是需要根据之前的翻译,求解当前最有可能的翻译,如下图所示。首先根据输入 "<Begin>" 预测出第一个单词为 "I",然后根据输入 "<Begin> I" 预测下一个单词 "have"。

Decoder 可以在训练的过程中使用 Teacher Forcing 并且并行化训练,即将正确的单词序列 (<Begin> I have a cat) 和对应输出 (I have a cat <end>) 传递到 Decoder。那么在预测第 i 个输出时,就要将第 i+1 之后的单词掩盖住,注意 Mask 操作是在 Self-Attention 的 Softmax 之前使用的,下面用 0 1 2 3 4 5 分别表示 "<Begin> I have a cat <end>"。

第一步: 是 Decoder 的输入矩阵和 Mask 矩阵,输入矩阵包含 "<Begin> I have a cat" (0, 1, 2, 3, 4) 五个单词的表示向量,Mask 是一个 5×5 的矩阵。在 Mask 可以发现单词 0 只能使用单词 0 的信息,而单词 1 可以使用单词 0, 1 的信息,即只能使用之前的信息。


(输入矩阵与 Mask 矩阵)

第二步: 接下来的操作和之前的 Self-Attention 一样,通过输入矩阵X计算得到Q,K,V矩阵。然后计算 Q 和 KT 的乘积 。


(Q乘以K的转置)

第三步: 在得到  之后需要进行 Softmax,计算 attention score,我们在 Softmax 之前需要使用Mask矩阵遮挡住每一个单词之后的信息,遮挡操作如下:


(Softmax 之前 Mask)

得到 Mask  之后在 Mask 上进行 Softmax,每一行的和都为 1。但是单词 0 在单词 1, 2, 3, 4 上的 attention score 都为 0。

第四步: 使用 Mask 与矩阵 V相乘,得到输出 Z,则单词 1 的输出向量  是只包含单词 1 信息的。


(Mask 之后的输出)

第五步: 通过上述步骤就可以得到一个 Mask Self-Attention 的输出矩阵  ,然后和 Encoder 类似,通过 Multi-Head Attention 拼接多个输出 然后计算得到第一个 Multi-Head Attention 的输出ZZ与输入X维度一样。

5.2 第二个 Multi-Head Attention

问题2:原句完整理解好的基础上,此刻翻译最该参考原文中哪部分信息

同样使用注意力机制,查询翻译句子中当前token,此时词块数据库是原文,拿当前token的Q乘以原文token的K,更新上文理解的信息进来,从而更新当前token的向量,结合上面的带掩码的多头注意力,即可有力预测下一个token。

image.png

Decoder block 第二个 Multi-Head Attention 变化不大, 主要的区别在于其中 Self-Attention 的 K, V矩阵不是使用 上一个 Decoder block 的输出计算的,而是使用 Encoder 的编码信息矩阵 C 计算的。

根据 Encoder 的输出 C计算得到 K, V,根据上一个 Decoder block 的输出 Z 计算 Q (如果是第一个 Decoder block 则使用输入矩阵 X 进行计算),后续的计算方法与之前描述的一致。

这样做的好处是在 Decoder 的时候,每一位单词都可以利用到 Encoder 所有单词的信息 (这些信息无需 Mask)。

5.3 Softmax 预测输出单词

Decoder block 最后的部分是利用 Softmax 预测下一个单词,在之前的网络层我们可以得到一个最终的输出 Z,因为 Mask 的存在,使得单词 0 的输出 Z0 只包含单词 0 的信息,如下:


(Decoder Softmax 之前的 Z)

Softmax 根据输出矩阵的每一行预测下一个单词:


(Decoder Softmax 预测)

这就是 Decoder block 的定义,与 Encoder 一样,Decoder 是由多个 Decoder block 组合而成。

image.png

请注意,这里每个解码层都没有预测下一个token,都在更新当前token的向量,经过所有解码层,最后送到线性层(Linear),这里将当前token的向量映射到词表空间(线性层本质是翻译官),然后经过softmax,词表空间每个单词都有一个概率,选取概率最大的token的ID,通过 ID 去 Embedding表 里查询token的原始向量,至此完成下一token的预测。

为什么不直接用向量找向量:
向量空间是连续的,连续空间向连续空间映射,如果没有非常眼睛的函数,是做不到的,因为语言之间的映射本身不严谨(函数高度非线性且),且预测本身是训练拟合一个复杂的条件概率分布(P(TokenNToken1,,TokenN1,中文原文))从而知下一个token大概率是什么,所以没有固定函数,因此选择向量映射ID,即连续映射离散空间。

Embedding表 记录的是token对应的向量,是训练出来的,通过编码器来训练,是语义被数学化的过程,初始苹果,香蕉的向量可能相差很远,但在大量预料训练下,会调整二者的向量,二者向量之间甚至有越来越明确的数学关系,又或者男性与女性这两个token,二者的向量也会慢慢具有明确的数学关系。

BERT模型就是使用Encoder,而现在的大语言模型基本是用Decoder

为什么Decoder可以用作LLM
输入文字,通过Embedding,只是查表,将token映射为相应向量,但没有理解,接着通过Decoder理解,因为Decoder是带掩码多头注意力,从而修改向量,增加理解,此时获得的token向量就是理解了的文字的向量。
也正因如此,Encoder和Decoder都可以作Embedding模型

6. Transformer 总结

  • Transformer 与 RNN 不同,可以比较好地并行训练。
  • Transformer 本身是不能利用单词的顺序信息的,因此需要在输入中添加位置 Embedding,否则 Transformer 就是一个词袋模型了。
  • Transformer 的重点是 Self-Attention 结构,其中用到的 Q, K, V矩阵通过输出进行线性变换得到。
  • Transformer 中 Multi-Head Attention 中有多个 Self-Attention,可以捕获单词之间多种维度上的相关系数 attention score。
标题:Transformer
作者:Echo_Kang
链接:https://echokang.top/transformer/
声明:采用 CC BY-NC-SA 4.0 协议,转载请注明出处。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇