transformer学习记录


transformer学习记录

1. 注意力机制

重点词嵌入机制(embeddings)

1.1 embeddings机制

image-20250310210751327

对于上述遇到的一些具体歧义的单词时,如Apple,既可以代表水果,也可以代表苹果品牌。传统的embeddings技术如onehot和wordvector很难去进行区分具有歧义的单词,在创建好的词嵌入矩阵中,一个词只能用一个预训练好的向量去表示。

1.2 Attention机制

image-20250310211423751

第一句中的Apple代表水果中的苹果,而第二句中代表的是品牌中的苹果。

image-20250310212005727

第一句中的苹果更倾向于水果类,因此我们将苹果的坐标向水果类移动;第二句中的水果倾向于电子产品类,因此向手机的坐标移动。

Attention的操作就是对句子作一个并行处理。在开始时进行一个初始坐标赋值全部打乱,然后计算句子中的单词相似度来调整坐标,当两个单词意思相近时,他们之间的权重就越大,例如orange和apple。

image-20250310213518916

类似于聚类的感觉,将其向水果类拉近。

多头注意力机制 Multi-head attention:假设我们现在初始化三个embedding矩阵,可以很明显看到第一个矩阵的初始化效果更好,apple这个词在手机和水果分类的中间,apple离两种歧义分的越开,那么他的效果就更好,运行效率更好,多头注意力机制就是找出这样一个最佳的原始词嵌入矩阵,此时我们遇到的新问题就是取多少个矩阵更合适。多头注意力机制并不在纵向上叠加来拉升注意力机制的维度,而在横向添加来进行并行处理。通过拆分特征维度到多个子空间(多头),实现特征学习的多样性和并行化,最后通过线性层进行融合。

image-20250310213752725

我们可以通过线性变换来进行变换

image-20250310214406820

image-20250310214453461

输入线性变换生成Q、K、V拆分多头缩放点积注意力拼接多头结果线性变换输出

左边是多头注意力机制的架构图,右边是上述的过程。我们首先初始化三个词嵌入矩阵,然后通过三个权重矩阵W^Q,W^K,W^V对输入进来的三个词嵌入矩阵进行线性变换得到Q,K,V

image-20250311022221286

Q、K、V是输入向量经过线性变换后的结果,而非直接等于词嵌入或权重矩阵。经过这种变换我们可得Q,K,V,然后输入进线性层,Q和K相乘进行一个线性变换,变换完成后输入缩放点积注意力层,在这层中,使用V矩阵对其进行一个打分image-20250311022854441,如右图中间所示,初始值为1,经过一次线性变换后得到我们想要的结果,然后再使用softmax函数进行一次缩放以防梯度消失,dk为K的维度(如Apple(0, 1, 2, 3),那么dk就为4),随后得到一个注意力权重分布,最后用注意力权重对V加权求和,得到当前头的输出image-20250311023206492,并将其输出到连接层。“注意力权重”是通过Q和K的点积计算得到的(即 image-20250311022414926)。

1.3 结构详解

宏观理解网络架构

image-20250312153936210

transformer网络分为编码器和解码器,以句子翻译为例,当句子输入到网络中,首先经过多层编码器,每一层的编码器输入都是上一层的输出直到最后一层的输出将输入到每一层的解码器中,然后依次类推,最后输出翻译结果。

将每一层的编码器和解码器结构拆开进一步分析的话,如下图所示。

img

每一个编码器 在结构上都是一样的,但它们的权重参数是不同的。每一个编码器里面,可以分为 2 层

  1. Self-Attention Layer
  2. Feed Forward Neural Network(前馈神经网络,缩写为 FFNN)

同理,解码器也具有这两层,但是这两层中间还插入了一个 Encoder-Decoder Attention 层,这个层能帮助解码器聚焦于输入句子的相关部分(类似于 seq2seq 模型 中的 Attention)。

具体结构

image-20250312180847614

编码器部分N个block堆叠组成(自注意+前馈网络),每个block又分为两层:自注意力+残差连接(参考CNN架构)+归一化层/前馈神经网络+残差连接+归一化层。每一个block依次向上传递直到最后第N层,将第N层的block输出到解码器的每一层中(参考上述encoder和decoder图)。

解码器部分中Output Embedding输入是我们已知的句子翻译结果再输入(以句子翻译为例就是假设Iuputs输入为我是学生,那么最后的输出结果为I am a student,那么这里的Output Embedding就是翻译结果),每个block层又分为如上图右边的结构:掩码自注意力层+残差+归一化/自注意力层+残差+归一化/前馈神经网络+残差+归一化层。这里需要特别注意的是,中间的自注意力层的输入来自编码器最后一层的输出以及来自掩码注意力层的输出共同组合。

最后解码器的输出会经过一个线性层和softmax函数激活后输出我们词表中所有词的概率,选择概率最大的一个作为我们最后的结果输出。

词嵌入(Word Embedding)

我们首先将每个输入单词通过词嵌入算法转换为词向量。在transformer中,通常转换为256 或者 512 维。

所有的编码器都有一个相同的特点,即它们接收一个向量列表,列表中的每个向量大小特定维度,在Transformer中是512维。词嵌入过程只发生在最底层的编码器中。在底层(最开始)编码器中它就是词向量,但是在其他编码器中,它就是下一层编码器的输出(也是一个向量列表)。

向量列表大小是我们可以设置的超参数:一般是我们训练集中最长句子的长度。

位置编码(Positional Encoding)

首先我们回顾RNN,RNN隐藏层的每一次计算都会包含上一时刻的信息,而transformer并没有这个结构,因此我们需要用到位置编码来告诉网络当前这个单词在整个句子中的位置,他通过和input embedding相加来得到一个同样为512维度的向量作为编码器的输入。

image-20250312212410515

pos指当前词在整个句子中的位置,范围是0到整个句子的长度(左闭右开)。i指位置编码的维度,范围是0到2/dmodel(左闭右开,通常为512维)。

当维数为偶数时输入到sin函数,维数为奇数时输入到cos函数。

编码过程(宏观)

Transformer的一个核心特性,在这里输入序列中每个位置的单词都有自己独特的路径流入编码器。在自注意力层中,这些路径之间存在依赖关系。而前馈(feed-forward)层没有这些依赖关系。因此在前馈(feed-forward)层时可以并行执行各种路径。

image-20250312220353012

以下图为例,其中的“it”这个句子是指什么呢?它指的是street还是这个animal呢?这对于人类来说是一个简单的问题,但是对于算法则不是。当模型处理这个单词“it”的时候,自注意力机制会允许“it”与“animal”建立联系。随着模型处理输入序列的每个单词,自注意力会关注整个输入序列的所有单词,帮助模型对本单词更好地进行编码。

如果你熟悉RNN(循环神经网络),回忆一下它是如何维持隐藏层的。RNN会将它已经处理过的前面的所有单词/向量的表示与它正在处理的当前单词/向量结合起来。而自注意力机制会将所有相关单词的理解融入到我们正在处理的单词中。

当我们在编码器#5(栈中最上层编码器)中编码“it”这个单词的时,注意力机制的部分会去关注“The Animal”,将它的表示的一部分编入“it”的编码中。

注意力机制的精髓就体现在这些深浅不一的橙色背景色中。

为了让大家更好地理解注意力的作用,再举个计算机视觉中的例子,假设我们要对一张图片进行分类,注意力的作用就在于帮助我们指出图片中的哪些区域是值得关注的。可以看到经过自注意力机制已经很明显地将兔子的轮廓及其标志性的地方用热力图框选出来了。

image-20250312220517870

编码过程(微观)

第一步,生成 Q、K、V,辅助计算注意力机制

image-20250312221807056

通过将X1,X2向量分别与权重矩阵W^Q^, W^K^, W^V^相乘,为每个单词都创建一个查询向量Q,一个键向量K,值向量V。

第二步,计算当前单词的Q与候选单词的K的点积,得到注意力分数。假设我们在为这个例子中的第一个词“Thinking”计算自注意力向量,我们需要拿输入句子(Thinking Machines)中的每个单词对“Thinking”打分。这些分数决定了在编码单词“Thinking”的过程中有多重视句子的其它部分。这些分数是通过打分单词(所有输入句子的单词)的键向量与“Thinking”的查询向量相点积来计算的。所以如果我们是处理位置最靠前的词的自注意力的话,第一个分数是q1和k1的点积,第二个分数是q1和k2的点积。

第三步,将上一步结果除以维度的平方根(使梯度更加稳定,这里假设转换为词向量后的维度为64)

第四步,将上一步结果通过softmax函数转换(softmax的作用是使所有单词的分数归一化,得到的分数都是正值且和为1。这个softmax分数决定了每个单词对编码当下位置(“Thinking”)的贡献。显然,已经在这个位置上的单词将获得最高的softmax分数,但有时关注另一个与当前单词相关的单词也会有帮助。)

第五步,将候选单词的每个值向量V乘以softmax后的分数。

第六步,对加权后的值向量V求和,即可得到自注意力层在该位置上的输出(在我们的例子中是对于第一个单词)。得到的输出就可以输入到前馈神经网络中。

image-20250313002553906

核心公式image-20250313004615124

通过矩阵运算实现:

第一步是计算查询矩阵、键矩阵和值矩阵。为此,我们将将输入句子的词嵌入装进矩阵X中,将其乘以我们训练的权重矩阵(WQ , WK, WV)。

X矩阵中的每一行对应于输入句子中的一个单词。我们再次看到词嵌入向量 (512,或图中的4个格子)和q/k/v向量(64,或图中的3个格子)的大小差异。

最后,由于我们处理的是矩阵,我们可以用一个公式来计算自注意力层的输出。

到这里,通过矩阵运算实现自注意力的计算就完成了。这时,我们对于输入句子向量,得到一组Z向量,输入到后续的前馈神经网络中。

但实际情况下,在Transformer中,采用的方式就是多头注意力机制,这里的多头可以理解为不同的QKV(就是在纵向叠加多个注意力层来进行同一个输入并计算,但是权重矩阵的初始化是不同的,因此得到的QKV矩阵也不同,注意力分数也不同)。

image-20250313011014487

多头注意力机制

直观来理解其实就是对于同一个词向量X输入到多个注意力层中进行多次不同的运算,虽然共享同一个输入,但是由于矩阵初始化值的不同会导致其获得不同的QKV矩阵,注意力分数矩阵Z的结果也因此不同。假设这里我们设置了8个注意力头,得到了8个不同的注意力头Z0,…,Z7,我们直接将这8个矩阵进行拼接成一个矩阵Z然后输入到前馈神经网络中。

原论文中说到进行Multi-head Attention的原因是将模型分为多个头,形成多个子空间,可以让模型去关注不同方面的信息,最后再将各个方面的信息综合起来。其实直观上也可以想到,如果自己设计这样的一个模型,必然也不会只做一次attention,多次attention综合的结果至少能够起到增强模型的作用,也可以类比CNN中同时使用多个卷积核的作用,直观上讲,多头的注意力有助于网络捕捉到更丰富的特征/信息。

通过增加一种叫做“多头”注意力(“multi-headed” attention)的机制,论文进一步完善了自注意力层,并在两方面提高了注意力层的性能:

1.它扩展了模型专注于不同位置的能力。在上面的例子中,虽然每个编码都在z1中有或多或少的体现,但是它可能被实际的单词本身所支配。如果我们翻译一个句子,比如“The animal didn’t cross the street because it was too tired”,我们会想知道“it”指的是哪个词,这时模型的“多头”注意机制会起到作用。

2.它给出了注意力层的多个“表示子空间”(representation subspaces)。接下来我们将看到,对于“多头”注意机制,我们有多个查询/键/值权重矩阵集(Transformer使用八个注意力头,因此我们对于每个编码器/解码器有八个矩阵集合)。这些集合中的每一个都是随机初始化的,在训练之后,每个集合都被用来将输入词嵌入(或来自较低编码器/解码器的向量)投影到不同的表示子空间中。

在“多头”注意机制下,我们为每个头保持独立的查询/键/值权重矩阵,从而产生不同的查询/键/值矩阵。和之前一样,我们拿X乘以WQ/WK/WV矩阵来产生查询/键/值矩阵。

如果我们做与上述相同的自注意力计算,只需八次不同的权重矩阵运算,我们就会得到八个不同的Z矩阵。这就类似于在卷积神经网络中使用多个不同尺寸的filter提取多种特征。

image-20250313011242480

image-20250313012013546

image-20250313012034054


文章作者: FeiZao
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 FeiZao !
  目录