👀
前言
Transformer中编码器的构造和运行位置如下图所示,其中编码器内部包含多层,对应下图encoder1…encoder N,每个层内部又包含多个子层:多头自注意力层、前馈神经网络层、归一化层,而最关键的是多头自注意力层。
👀
自注意力是什么?
当人类的视觉系统察觉到一个物体时,通常不会从头到尾地扫视整个场景;一般会根据个人的需求集中关注特定的部分。比如下面这张图,我们第一眼应该是看到一只动物,然后,眼睛会先注意到动物的脸,然后得出初步结论,这应该是一只狼;就像右边注意力图所示,颜色更深的部分表示一般是我们人类最先看见(注意)的。
注意力最早应用在机器视觉领域(CV,Computer Vision),后来才应用到 NLP 和 LLM 领域。
自注意力(Self-Attention) 是一种机制,允许模型在处理一个输入序列时,关注该序列中任意位置的其他元素。自注意力计算每个元素(如一个词语)与序列中其他元素的相关性,并根据这些相关性动态调整每个元素的表示。这使得模型能够捕捉长距离依赖关系,不受距离的影响,尤其适用于自然语言处理等需要理解上下文的任务。
假设有一句话:’小明和小花、小丽是好朋友,其中小花很漂亮,小明很喜欢她’。在传统的语言模型中,模型可能会依赖于顺序来处理每个词。但在自注意力机制下,模型会计算每个词与其他词的关联度,比如’小明’和’喜欢’之间的关联,以及’她’和’小花’之间的联系。通过这种机制,模型能够在理解一个词时同时参考整个句子中的其他词,尤其是长距离的依赖关系,从而捕捉到更复杂的语义信息,例如通过句子上下文就能很好理解“她”指的是“小花”而不是“小丽”。
好处:
-
捕捉长距离依赖:自注意力允许模型在不增加复杂度的情况下,捕捉输入序列中不同位置之间的依赖关系。这对于自然语言处理非常有用,因为语言中的词语依赖可能出现在很远的地方。例如,句子的主语和谓语可能相距甚远。
-
上下文敏感:每个元素的表示在每个自注意力层都会更新,逐渐包含更多的上下文信息,使模型能更准确地理解语义。
👀
在 Transformer 中编码器是如何运作的?
当输入一句话(如 ‘I love ai’)到大模型中进行翻译时,经过多个层次的处理,包括自注意力层(Self-Attention),模型逐渐生成输出。以下详细描述这一过程的步骤,从输入到自注意力层如何处理,直至生成翻译结果。
1、输入嵌入与位置编码首先,输入的句子 ‘I love ai’ 通过词嵌入层将每个单词转换为向量表示。
假设我们有以下输入向量:
-
‘I’ → E_I
-
‘love’ → E_love
-
‘ai’ → E_ai
这些嵌入表示了单词的语义信息,此外还会加上位置编码(Positional Encoding),因为 Transformer 没有内置的序列处理能力(如 RNN)。位置编码会为每个位置加上唯一的标识,这样模型能够区分不同的单词顺序。
2、在自注意力层生成 Q、K、V 向量每个嵌入向量经过线性变换,生成 Query、Key 和 Value 向量:
Query (Q):表示当前单词需要从其他单词中获取的信息。
Key (K):表示每个单词的特征,用于与 Query 进行匹配。
Value (V):表示每个单词最终提供的信息,用于计算输出。假设我们对 ‘I love ai’ 的三个单词分别生成了 Q、K 和 V 向量:
Q:Q_I, Q_love, Q_ai
K:K_I, K_love, K_ai
V:V_I, V_love, V_ai
说明:
-
在生成Query (Q)、Key (K) 和 Value (V) 向量的过程中,“线性变换”指的是使用矩阵乘法来转换原始的词嵌入向量。这种变换本质上是对输入向量的一个线性投影,目的是为了使Query、Key 和 Value 向量具有特定的属性,以便更好地服务于注意力机制的任务,可以简单理解为抽取出多不同维度的信息。
-
权重矩阵(Wq、Wk、Wv)是大模型在训练过程中生成的,当一个模型训练结束以后就固定了,只有后续微调训练才会发生变化。
3、计算注意力权重接下来在自注意力机制中,模型计算每个单词之间的注意力权重。这一步的核心是利用 Query 和 Key 之间的点积来确定当前单词与其他单词的相关性。对于句子中的每个单词(例如 ‘I’),模型将该单词的 Query 与句子中所有单词的 Key 进行点积运算:
score(QI,Kall) = [QI·KI ,QI· KIove,QI · Kai]
对每个单词都进行类似的计算,结果形成一个注意力分数矩阵。为了避免大数值问题,通常会对分数除以 d_k 的平方根(Key 向量的维度)进行缩放,并通过 softmax 函数归一化,使每个单词的注意力分数之和为 1
这个过程为每个单词计算它对其他单词的关注程度,形成注意力权重矩阵。假设在这句话中,’I’ 更关注 ‘love’ 而不是 ‘ai’。
说明:
向量点积运算(dot product),是可以衡量两个向量之间的相似程度。点积的结果越大,说明这两个向量越相似或越接近同一方向。反之,结果越小,说明它们相差越大,甚至方向相反。在自注意力机制中,模型会将输入的每个词转化为一个向量(如查询向量、键向量、值向量)。通过计算查询词向量和键向量之间的点积,模型可以得到每个词与其他词的相似度。这些相似度值决定了模型在生成输出时该“关注”哪些词,以及“关注”的程度。
计算it与这句话里的其他单词的关联度
4、加权求和生成新的表示,使用计算出的注意力权重对 Value 向量进行加权求和。每个单词的输出表示是所有单词的 Value 向量的加权求和:
output for ‘Love’ =(weightI· VI + weightlove· Vlove + weightai· Vai
这意味着每个单词在新的表示中不只是自身的信息,还包含了其他单词的信息,这帮助模型捕捉输入序列中的依赖关系。
5、多头注意力机制自注意力 通常会扩展为多头注意力(Multi-Head Attention),即多个 Q、K、V 头并行运行,每个头学习不同的特征或依赖关系。最终,这些不同头的输出会被拼接在一起并通过线性变换进行整合。
为什么需要多头注意力机制?相比单一的自注意力,多头注意力提供了几个优势:
多样性:学习不同的模式
每个头都有自己独立的线性变换矩阵 W_Q, W_K, W_V,这意味着不同的头可以学习到不同的语义特征。例如:
-
一个头可能关注的是句子中的长距离依赖关系,比如句子的主语和动词的关系。
-
另一个头可能专注于短距离依赖关系,比如形容词和名词之间的联系。
通过多个头并行学习,模型能够在不同的特征维度上捕捉丰富的上下文信息。
信息并行处理
由于每个头的计算是并行进行的,模型可以高效地处理大规模输入。相比于顺序处理的 RNN,注意力机制本身支持并行,而多头机制进一步增强了这一点。这样可以在不增加计算复杂度的情况下提升表达能力。
防止信息丢失
如果只有一个头,可能会错过某些重要的依赖关系或特征。多头注意力可以从不同的角度分析同一个输入,从而降低了忽略重要信息的风险。例如:
-
一个头可能从词汇级别捕捉依赖,而另一个头可能关注句子结构或语义层面。
举例说明:生活场景类比
想象你在听一场演讲,但你邀请了几位朋友一起来,他们每个人都有不同的特长或关注点。你们每个人在听演讲时,都会关注不同的方面:
-
朋友A 对演讲者的语音语调感兴趣,专注于分析说话方式。
-
朋友B 专注于演讲内容的逻辑性,思考信息是否一致和有条理。
-
朋友C 关注演讲中的背景数据,试图理解数据的来源和合理性。
最终,你们会汇总每个人的理解,整合成对演讲的全面认识。
在这个例子中,每个朋友代表多头注意力中的一个头。每个朋友关注的点不同,但都是对同一个演讲的信息进行处理。最后,你将不同的意见和见解整合起来,形成对演讲的完整理解,这类似于多头注意力机制中不同头的输出拼接后,再通过线性变换生成最终的结果。
多头注意力机制通过并行运行多个注意力头,使得模型能够从多个角度分析输入序列,捕捉丰富的特征和依赖关系。每个头学习不同的语义特征,从长距离到短距离依赖关系都能得到有效建模。多头注意力的设计使 Transformer 模型在处理自然语言任务时既高效又具备强大的表达能力,这也是 Transformer 相比于传统序列模型的重要优势之一。
6、多层编码器串行
在 Transformer 模型中,编码器(Encoder) 是由多个串行的编码器层(Encoder Layers)堆叠而成的。每个编码器层内部包含自注意力机制、多头注意力、前馈网络等模块。那么,为什么我们需要将多个这样的编码器层串联起来,而不是使用单一层来完成任务呢?
原因:逐层构建更复杂的表示
多个串行编码器层的堆叠使得模型能够逐步构建输入的表示,这个过程类似于逐层“精炼”和“抽象”输入的信息。每一层编码器都在输入的基础上捕捉到更多的上下文信息,并将更复杂的特征传递给下一层,从而使得模型能够处理复杂的依赖关系和特征。这种逐层构建的方式有几个关键的原因:
捕捉更长距离的依赖关系
单层的自注意力机制可以帮助捕捉句子中不同位置的依赖关系,但是经过多层的堆叠,这种能力进一步增强。例如,在较低层次时,模型可能只捕捉到短距离的依赖关系,如名词与其形容词之间的联系;而在更高层,模型可以捕捉到更长距离的依赖关系,如主语和动词之间的联系。
-
低层次捕捉局部特征:底层编码器层倾向于捕捉输入的局部特征,比如单词的基础含义和相邻单词之间的简单关系。
-
高层次捕捉全局语义:越往高层,模型会逐渐捕捉到句子中整体语义和长距离依赖。这对于复杂的语言现象,如嵌套的从句、跨段落的联系,尤为重要。
信息的逐层处理与抽象
多层编码器堆叠类似于传统深度神经网络的多层抽象。每层编码器可以看作是对输入数据进行不同级别的抽象和处理,逐层提取出更高层次的特征。例如:
-
在前几层,编码器可能处理的是较为具体的词汇信息,如单词的词义。
-
随着层数增加,模型可能开始关注更复杂的句法结构,甚至语义信息。
这种逐层抽象的过程类似于人类的理解方式:我们首先通过观察具体的词句,接着再逐步理解它们的意思,并将这些信息整合到对全文的理解中。
提升模型的表达能力
通过增加编码器层的深度,Transformer 模型的表达能力显著增强。深层网络比浅层网络具有更强的非线性表达能力,能够学习到更复杂的数据模式。多层编码器能够捕捉更加多样化的特征,使得模型能够应对更多样的任务和数据集。
例如,在语言翻译任务中:
-
浅层编码器 可能专注于逐字翻译或简单的短语解析。
-
深层编码器 则可以处理更复杂的语义转换,跨越多个单词或短语进行重新组织以符合目标语言的语法和逻辑。
信息的逐步聚合与精炼
每层编码器都会从上一层获得输入,将其通过自注意力机制、多头注意力和前馈网络处理后,输出更加“精炼”的表示。多个编码器层的堆叠相当于对输入信息的逐步过滤和聚合,类似于通过多次迭代来找到最相关的信息和特征。
比如在句子“I love AI because it is revolutionary”中:
-
第1层编码器 可能只关注到单词的局部关系,如“love”和“AI”之间的联系。
-
第3层编码器 可能会识别到整个句子的逻辑关系,如“because”引导的因果关系。
-
第6层编码器 则可能完全理解到句子的语义层次:AI 被认为是革命性的原因。
处理复杂依赖关系
自然语言中的依赖关系往往是复杂的,不仅存在于局部短距离的词与词之间,还可能存在于整个句子或段落之间的长距离依赖。通过堆叠多层编码器,模型可以逐层从局部信息扩展到全局信息,逐步理解语言中的复杂结构和语义。
例如,在长句子中,主语和谓语动词可能相隔很远,单层的注意力机制可能难以捕捉这种长距离的依赖关系。多层编码器能够更好地捕捉这些复杂的关系,通过逐层信息传递,使模型能够建模语言中的层次结构。
生活中的类比
想象你正在学习一个新技能,比如打网球。刚开始学时,你可能会专注于简单的任务:如何握拍、如何站位。这类似于 Transformer 的低层编码器,处理简单的、局部的任务。
随着你逐渐熟悉基础操作,你开始学习如何控制球的方向、力度,并且开始注意到如何与对手互动。这类似于模型中的中层编码器,逐渐学会处理更复杂的关系。
最后,当你成为一名经验丰富的球员时,你不仅能够控制每一个动作,还能预判对手的行为,调整自己的策略。这相当于 Transformer 的高层编码器,处理的是全局的、高层次的策略和行为。
通过逐层训练和信息处理,你从最基础的技能一步步提升,直到能够处理最复杂的情况。这正是多层编码器在 Transformer 中的作用——逐层处理并聚合信息,从简单到复杂,逐步构建对输入序列的深层次理解。