【LLM】10分钟理解Transformer和Attention

मूल वीडियो सामग्रीवीडियो बड़ा करें
  • 如何理解大语言模型的Transformer架构和Attention机制
  • 我们将一步一步拆解Transformer架构的设计精髓
  • 理解自注意力机制如何影响翻译准确性

在本期视频中,我们不讲复杂的数学计算,
我们直接来看大语言模型是怎样工作的。

在2017年,谷歌团队发表了里程碑论文《Attention is all you need》,
Transformer架构首次被提出。
如果你对这个架构图感到陌生,不用担心,我们会一步一步拆解它的设计精髓。

整个架构的左半部分叫做 Encoder,顾名思义,它负责分析和理解模型的输入信息。
基于这一部分,后续衍生出了encoder-only模型,其中最著名的代表是谷歌的 BERT
BERT的经典应用场景包括分析邮件内容,从而筛选出诈骗邮件,
或者分析用户的评价,判断得到的反馈是正面的还是负面的。

右半部分的 Decoder 则是内容生成的关键。
当前主流的大语言模型如 ChatGPTDeepSeq 均采用 decoder-only 架构,通过自回归方式生成文本。

为了便于理解这个视频,我们将借助一个简单的音译中的翻译模型,
展示完整的 transformer encoderdecoder 的工作流程,并深入解析 Attention 机制的运作原理。

左侧是翻译模型的层级化结构,每一层代表一个计算层。
可以看到它与 Transformer 原版架构图完全对应。
图中每个颜色的方框对应模型中的一组或多组层级,但模型中的这些层级到底是什么呢?

在这里我们需要回溯几个核心概念。
机器学习是人工智能的一个核心领域,
而神经网络是机器学习的一种实现方法。
Transformer 本质上是一种特殊设计的神经网络。

提到神经网络,大家应该见过类似这样的图,把传统神经网络展示为一组箭头和圆圈的组合。
这里的每一条箭头代表着一个数字,我们称为模型的参数。
所谓的模型训练,就是通过调节和优化这些参数,使得模型可以计算出最终的结果。
每个圆圈也是一个数字。
第一层的圆圈就是模型输入的数据,结合参数进行简单的计算,就可以得到第二层的数字。

所以我们可以简单地把神经网络中的层级理解为一个数学黑箱。
它的输入是一串数字,通过一系列计算可以得到一组新的数字,再传递到下一层。
这样层层计算,直到最终的结果。这些计算以加法和乘法为主,
看起来是不是还挺简单的。
但在实际模型中,参数量级可能是百万到万亿的规模,这也是为什么这类模型被称为大模型。

回到我们的架构图,就可以看到数据流进每一层时,
通过当前层的计算,会生成更新后的数值输入到下一层。
但等等,我们不是说这个模型是做英语到中文的翻译吗?
这可都是文字呀,怎么进行数值计算呢?
文字不能直接输入给模型,所以这里就需要用到一个工具,叫 Tokenizer
负责把文字转换为数字。

转换的第一步就是先把文字拆分成 Token
这个例子中,可以看到一个英语单词可能会独立作为一个 Token,也可能会被拆分成多个 Token。
文字的最后还会增加一个特殊的 Token 来标记结尾。
之后每个 token 就可以在模型的词汇表中找到对应的数字编号,即 token id
这样我们的文字就被转换成了模型可以处理的数字了。

但是光一个数字并不足以表达文字所包含的丰富语意。
比如我们理解一个英语单词,会看它在字典中给出的详细介绍。
对应到大模型中,Token ID 可以比作是字典中的索引编号,而真正记录这个 Token 信息的则是一长串的数字存在一个向量中。
具体向量维度因模型而定,这就好像一张高清图片,清晰度越高所能包含的信息就越多。
而把 Token ID 转换为向量的这一步就被称之为 Embedding

当前使用的翻译模型中,向量的维度是 512
GPTDeepSeq 使用的向量则会大得多,至少是数千维。
但到此为止,每个 token 还是相互独立的。
但文字却是有前后观点,
一旦顺序调整,意思可能截然不同。

所以下一步模型又定义了一组相同维度的向量,这些项量所包含的信息不再是 Token 本身的含义,而是它们在句子中所在的位置。
将这两组项量相加得到新的项量,便包含了每个 Token 的信息以及它们所在的位置。
更新后的项量便可以进入下一层,即 Encoder 的 Self-Attention。

在这一层中,每个 Token 会动态关注句子中最相关的其他 Token,并做相应的更新。
所以可以看到,项量每经过一个层级计算和更新的数据的过程,
其实就是给这些向量注入新的信息,使他们能更好、更全面的理解整个输入的文本。

在这个模型中,整个 encoder 层会叠加 6 次,直到最终的向量能够充分涵盖那句输入的英语 I like capes
至此,encoder 的工作结束,这些向量之后会被用于 decoder 的 cross-attention。

说到这里,我们已经发现整个模型其实包含了三种 attention:
encoder 的 self-attentiondecoder 的 self-attentioncross-attention
那么 attention 到底是做什么的呢?我们可以简单理解为它帮助句子中的每个 token 找到与自己最相关的 token,从而更准确地理解自己。

这么说可能有点抽象,我们来看一些具体的例子。
比如我们要翻译一句句子 She sat by the river bank, letting the cool breeze and the sound of flowing water calm her thoughts
这里的 bank 在英语中可以指银行,也可以是河岸。
那么模型是怎么知道应该翻译成“她坐在河岸边”而不是“她坐在银行里”呢?
因为 encoder 在计算 self-attention 时,bank 会去查看句子中的其他 token,发现 river 与它最相关,
而通过 river 的信息让它确定自己是河岸而不是银行。

类似的,每个 token 都会去寻找与自己相关的 token。
比如与 letting 最相关的是 calm,符合英语语法的 let somebody do something
既然这里的 calm 是个动词,它的作用对象是谁呢?就是 thoughts
通过这样的 self-attention 过程,让句子中的每个 token 都可以找到与自己最相关的其他 token,并相应的调整自己的 embedding,更好地诠释文本内容。

类似的,decoder 中也会有一个 self-attention。
但是由于 decoder 每次只会输出一个 token,所以这里的 token 只会观察自己左侧的其他 token,
因为右侧的内容对于它来说是还未生成的未来。
我们之后在讲解 decoder 时会更详细地解释 token 的生成方式。
只要记住,encoded self-attention 是帮助模型充分理解用户输入的句子,而 decoded self-attention 则是让模型记得自己已经说了什么,
保证之后输出的内容不会和已有信息自相矛盾或有语法错误。

最后我们来看 cross-attention
这里的每个中文 token 都会去找它相关的英语 token,比如 河岸 最相关的就是 river bank,而 流水 对应的就是 flowing water
中文中的句子是连接在流水之后,但英语中的 sound 却是在 flowing water 之前,这也体现了中英语之间语法的不同。
而 cross-attention 保证了即使两种语言差别巨大,模型最终还是能完成准确的翻译。

我们再来看一个例子 A bird can fly and so can a fly
这个句子中两个 fly 前者表示飞行,后者表示苍蝇。
我们来看看模型的 attention 机制是怎么理解它们的。
在 encoder 的 self-attention 中,第一个 fly 找到最相关的 token 是 birdcan,所以它知道自己是一个动词,表示鸟的飞翔。
而后一个 fly 关注到的是它前方的 a,从而知道自己是一个名词。
而在 decoder 的 self-attention 中,token 也能意识到自己也能做的事情是飞。

而回到 cross-attention 中,苍蝇 这几个 token 都顺利地找到了自己对应的 fly
最后回到我们最初的例子 I like cakes
动词 like 注意到了它的主语是 I,同时 cake 也注意到了它的复数 s

decoder 中 蛋糕 注意 我喜欢,在 cross-attention 中 我喜欢 对应着 I like
那么这些 Attention 的数值是哪里得到的呢?
我们说了这个视频不讨论复杂的数学,但以下这个 Attention 的计算公式还是一个绕不开的话题。

这里的 Q, K, V 分别代表了 Query, Key 和 Value,每个 Token 通过这三组项量参与计算。
所以可以简单地把公式的前半部分理解为衡量 Token 之间的关联强度。
Softmax 参数则负责把这些相关性的数值转换成一个概率分布,即所有的数值相加之和为一。
这样便得到了我们刚才例子中的数值,称为 Attention 的权重。

了解完了 Attention,我们就可以继续回到 Decoder 的部分来生成对应的中文了。
Decoder 的第一步同样需要一个输入,这个输入是模型提供了一个特殊的起始 Token。
之后的 embedding 过程与 encoder 中的类似,直到进入 attention 层。
这里因为只有一个向量,所以它也只能和自己相关,而在 cross-attention 中,
则是在关联 encoder 输出的英语向量,
好让模型知道自己在翻译什么。

整个 decoder 层同样需要叠加 6 次。
之后进入了线性层,输出的限量维度达到了 6万多,这个长度正是之前 Tokenizer 所引用的词汇表的长度。
这样再经过一个 softmax,我们得到的实际就是一个概率分布,对应着词汇表中每一个 token 作为当前输出结果的概率。

一旦找到概率最高的 token id,它将被作为 decoder 新一轮的输入,
与其 token 一起去计算下一个 token id
整个计算过程还是与上一轮一致,只是这一次我们有了两个向量对应着两个输入值。
在完成了所有 decoder 层的计算后,第二个向量此时不仅包含它本身 token 的信息,
也通过 attention 而充分接收了它之前向量所代表的 token 的信息。

因而只需要用第二个 token 作为线性层的输入,最终计算出第三个 token ID。
同样的过程会一直重复,直到模型输出一个特殊的 token id 标记结束。
这里的 0 会告诉模型所有的输出已经完成。

这样我们就得到了整个模型从输入到输出的过程。
下一步我们要把这些 token id 转换为文字。
这里我们再一次使用 Tokenizer,只是这一次是去寻找数字对应的 token,
再把这些 token 组合成最终的结果,就得到了英语到中文的翻译。

至此,我们跟随 Transformer 理解了它的工作原理和 Attention 机制。
我是认真工作的家,如果这个视频对你有帮助的话,请一键三连支持一下,
祝各位前尘似锦。