从0开始的Transformer架构学习:Encoder-Decoder(编码器-解码器)框架流程与相关知识
整个文章的内容涉及Encoder、Decoder的流程以及其中的相关知识点包括:残差链接、层标准化、全连接层、注意力机制等。书写的内容均是我查阅相关资料后的自我理解,受限于学业水平,这其中或有些许错误,或有解释不清的地方,还望指出;如有更好的想法,也欢迎你在评论区交流,一同进步。
写在前面:
Hi!还是我!这次的文章源于我们学术前沿的小组汇报,整个文章的内容涉及Encoder、Decoder的流程以及其中的相关知识点包括:残差链接、层标准化、全连接层、注意力机制等。书写的内容均是我查阅相关资料后的自我理解(来源均已标出),受限于学业水平,这其中或有些许错误,或有解释不清的地方,还望指出;如有更好的想法,也欢迎你在评论区交流,一同进步。
下面,文章正式开始!
目录
Transformer架构:
Transformer是一种用于自然语言处理(NLP)和其他序列到序列(sequence-to-sequence)任务的深度学习模型架构,在2017年由Vaswani等人首次提出,它的结构如下:

可以看到Transformer架构最主要的部分就是这个Ecoder-Decoder (编码器-解码器)框架。你可能会问,什么是Ecoder-Decoder 框架?Ecoder-Decoder 框架是自然语言处理领域通用的框架,它很好的诠释了机器学习的核心思路:“将现实问题转化为数学问题,通过求解数学问题,从而解决现实问题。”而如何转化和求解 或者说 如何设计编码器与解码器,这个就因架构而异了,那么Transformer架构是如何设计的呢?我们马上展开。
Encoder:
首先我们先说Encoder,Encoder中文名编码器,负责将输入序列压缩成指定长度的向量,它的作用就是「将现实问题转化为数学问题」

在Transformer架构中,encoder部分是由六个encoder-block组成的,每个编码块包含两个部分Multi-Head Self-Attention(多头注意力机制)与Position-Wise Feed-Forward Network(全链接前馈网络)

具体来讲,每一个编码块的组成可以用这个等式表示
=一个 Block 的输出=自注意力机制 + 残差链接 + LayerNorm + FC + 残差链接 + layer Norm ;

这些名词都是什么含义呢?别慌张,我们一一解释。
自注意力机制的具体内容我们与解码器中的多头注意力机制等一道一同放到后面的注意力机制部分去讲解,在这里我只需要知道,自注意力机制是为我们筛选输入中的重要信息即可。
ResidualConnections残差连接:
ResidualConnections中文名残差连接,是指将输入数据直接添加到网络某一层输出之上。它描述的就是如下这张图中右边的这个通路。这种设计使得信息可以更自由地流动,并且保留了原始输入数据中的细节和语义信息。 使信息更容易传播到后面的层次,避免了信息丢失。

举个例子,比如我们在图像识别的网络中经常会在卷积层后加入一个池化层来减少特征图的尺寸,降低计算量,但是池化操作本身可能会导致信息丢失。所以我们通过添加一个残差连接,将将原始输入直接与最后一个池化层输出相加或拼接起来,从而保留原始图像中更多的细节与语义信息
参考资料:
残差连接(skip connect)/(residual connections)-CSDN博客
【深度学习 | ResNet核心思想】残差连接 & 跳跃连接:让信息自由流动的神奇之道-CSDN博客
Encoder的部分流程(1):

现在我们就能理解编码器的部分流程了
- 原始的输入向量,一个记过自注意力机制层进行重要信息提取得到向量a,另一个不做任何处理(向量b)与向量a残差连接,得到向量a+b
- 接下来向量a+b通过LayerNorm得到向量c
LayerNorm层标准化:
什么是LayerNorm呢?LayerNorm中文名层标准化,是深度学习中标准化/归一化(Norm)这一技术的实现方法之一。标准化这一技术的提出是为了提高模型的泛化能力,减少模型对输入数据的敏感度。
那么我们为什么要有标准化这种技术?为什么这样做就能减少模型对输入数据的敏感度呢?
相信大家都能明白,特征是目标检测的重中之重。而问题恰恰就出现在特征上,因为特征间的单位尺度或者说变化范围可能是不同的,就比如我们的身高和体重,从出生时十几厘米到现在的一百几十厘米,这个变化范围是百一级的,而体重按照千克来算,变化范围只有十一级。而现实问题的差异往往更加突出,经常有万一级对零点几,如果我们不加处理的将这些数据用于处理,就会出现大变化范围的特征对输出结果的影响明显强于甚至掩盖小范围变化的特征,而这并不是我们希望看到的现象,我们希望这两种特征对输出的影响是相同,于是归一化技术应运而生,它描述一种把样本调整到均值为 0,方差为 1 的缩放平移操作,这样可以最大化消除数据的范围。
而如何应用这种缩放平移操作,便对应着不同的技术路线

比如BatchNorm是对整个 batch 样本内的每个特征做归一化,这消除了不同特征之间的大小关系,但是保留了不同样本间的大小关系。这使它适用于计算机视觉领域,因为可以把各通道特征图的数量级调整到差不多,同时保持不同图片相同通道特征图间的相对大小关系(RGB)。
而LayerNorm是对每一个特征的不同样本做归一化,这消除了不同样本间的大小关系,但是保留了一个样本内不同特征之间的大小关系。这使它适用于自然语言处理,因为它能保留每个 token d 维嵌入内部的相对大小关系,同时拉近了不同 token 对应特征向量间的距离。

参考资料:
详解三种常用标准化:Batch Norm & Layer Norm & RMSNorm-CSDN博客
机器学习/深度学习中为什么要做特征归一化/标准化?_深度学习标准化scale-CSDN博客
Encoder的部分流程(2):

3. 向量c通过FullConnectedLayer得到向量d
FullConnectedLayer全连接层:
什么是FullConnectedLayer呢?(CNN网络中的部分)FullConnectedLayer中文名全连接层,是将最后一层卷积得到的特征图(矩阵)展开成一维向量。展开成一维的过程我们可以理解为一次卷积,比如我们经过卷积层和池化层输出20个 12×12 的图像,那我们用一个12x12x20的卷积运算,最后的输出就是一个值。

通过这样的运算我们可以前面卷积得出的分布式特征(一个通道一个),整合为一个输出。这样做可以大大减少特征位置对分类带来的影响。
比如下面这个猫猫识别/分类任务,我们对输入的猫猫进行卷积运算获得特征图,我们先不讨论卷积核具体如何提取特征,但我相信我们都可以认可位于左上角的猫猫,通过卷积提取出来的特征会大多位于特征矩阵的左上角;位于右下角的猫猫会大多位于右下角。
如果我们就此不加入全连接层的进行下去,我其们实是在做一件很危险的事情,因为我们说特征是图像识别的一切,如果我们喂给计算机的特征就具有位置偏好,那么计算机就很容易把位置也当作一个特征,这显然会带来一个很荒谬的结果——同一只猫换了一个位置,计算机就识别不出来了。这显然不是我们期待的结果,因为我们的任务是一个识别任务,只需要计算机告诉我们图中有没有猫猫,位置并不重要。那么我们如何去除位置信息的干扰呢,这便是全连接层的作用了,还是刚才这两个矩阵,如果我们加入全连接层,通过一个2x2的全1矩阵,输出的值便是相同的1了,这样后续的层只会拿到猫的特征,从而去除了位置信息的干扰。
但在Transformer的编码器中FC层在消除位置影响方面的作用可能并不是那么大,它主要还是其中汇总特征的作用

参考资料: CNN 入门讲解:什么是全连接层(Fully Connected Layer)? - 知乎 (zhihu.com)
FeedForward前馈层:
了解了FullConnectionLayer全连接层,我们再来看FeedForward前馈层。前馈层是建立全连接层之上的,它的整体结构可以如下图所示:

它由两层全连接层组成,第一层后面跟着ReLU激活函数(即图中linear + ReLU),第二层没有激活函数(即图中linear)。通常是将输入映射到更高的维度,再映射回原本的维度(这也是图中第三行token突然变长的原因)
你可能会有疑问,刚刚不还是Full Connection嘛?为什么这里变成了linear?是不是图画错了?答案是否定的,我们不妨去想一想前文中提到的Full Connection layer,无论它想要去实现什么目的,但它的底层仍是卷积运算,也就是矩阵运算,而矩阵运算说到底是一堆加法和乘法运算的集合,也就是“线性计算”或者说“线性变化”,于是全连接层也可以被称为线性层,即图中的linear (layer)。
至于什么是“线性”,什么是“非线性”,希望下面这段话可以帮助你理解:
线性关系是一种简单、直接的关系,遵循着“一因一果”的原则,各部分的贡献是独立且可加的。
非线性关系更为复杂,涉及到多个因素的相互作用,且这些作用不是简单的叠加关系。在非线性关系中,小的变化可能导致大的结果,或者大的变化只引起微小的效应。
通过上面对于“线性”与“非线性”的描述,我们不难看出“非线性关系”是更适于深度学习的,因为我们在复杂任务中使用深度学习所要建模的关系往往是高度非线性,比如文本生成任务中,“我喜欢”之后可能出现的词就是一个很好的非线性关系的例子,这个词是什么并不总与前文或后文有关,可能这次前后文一起才能决定出这个词,如果用线性关系,我们是很难找到一个直线方程能同时表示前后的内容都很重要(直线方程总是有正有负),但如果用非线性关系,一个简单一元二次方程就能轻松表示前后的内容都很重要。【这个例子并不算严谨,但希望还能让你些许感知到非线性关系对深度学习的重要意义】
而这也是我们引入ReLU这个激活函数的原因(在这里要注意,ReLU仅是“激活函数”这一大类中较为常用的一种,而非ReLU的中文译名是“激活函数”。当然,对激活函数的研究也是深度学习领域中的一个课题)——添加非线性关系。因为激活函数这种非线性变换,能够进一步提取特征,从而增强模型的表达能力。
参考资料:
轻松理解 Transformers (3): Feed-Forward Layer部分 - 知乎
对Transformer中FeedForward层的理解_feedforward层的作用-CSDN博客
Encoder的部分流程(3):

4.向量c 与向量d 残差相加 ,得到向量e ;
5.向量e 通过LayerNorm输出向量f;(此时的相量f便是每一个块的输出)
Encoder全部流程:

- 原始的输入向量,一个记过自注意力机制层进行重要信息提取得到向量a,另一个不做任何处理(向量b)与向量a残差连接,得到向量a+b
- 接下来向量a+b通过LayerNorm得到向量c
- 向量c通过FullConnectedLayer得到向量d
- 向量c 与向量d 残差相加 ,得到向量e ;
- 向量e 通过LayerNorm输出向量f;(此时的相量f便是每一个块的输出)
参考资料: 【Transformer系列(1)】encoder(编码器)和decoder(解码器)_encoder和decoder的区别-CSDN博客
Decoder:
说完encoder,我们来说decoder,decoder中文名解码器,负责根据Encoder输出的语义向量来做解码工作,它的作用就是「求解数学问题,并转化为现实世界的解决方案」

在Transformer架构中,decoder部分是由六个decoder-block组成的,每个编码块包含三个部分:Multi-Head Self-Attention(多头注意力机制),Multi-Head Context-Attention(编码器-解码器注意力模块),Position-Wise Feed-Forward Network(全链接前馈网络)

可以看到解码器中最主要的部分是注意力部分,那么什么是注意力机制呢?
Attention注意力机制:
我先来看一张图

这张图片中,初见,大家的目光会更多放在哪里?如果我说希望你能记住士兵们的服饰,你又会将注意力放在哪里?如果希望你能记住环境呢?这便是我们人的注意力机制,而深度学习中的注意力机制不过就是使用运算,矩阵等等数学方法与工具去模仿,人的注意力机制。
那么我们该如何实现呢?
我们先来认识几个概念
查询(Query): 指的是查询的范围,自主提示,即主观意识的特征向量
键(Key): 指的是被比对的项,非自主提示,即物体的突出特征信息向量
值(Value) : 则是代表物体本身的特征向量,通常和Key成对出现
注意力机制就是给定一个 Query查询,计算Query查询与 Key值的相关性,然后根据Query与Key的相关性去找到最合适的 Value值,实现对Value的注意力权重分配,生成最终的输出结果。

什么意思呢?就比如我们去淘宝上购物时,我们敲了一个搜素关键词神器,这个关键词就是Query;而后淘宝的搜索系统就会根据这个关键词去查一系列的Key,比如学习神器,切菜神器这种名称,商品图片等等;最后系统再将相应的value(具体神器的商品详情连接)返回给你。
在淘宝这个例子中我们可以感受到,Query,Key,Value虽然各自属于不同的空间,但三者其实有着潜在的关系,也就是说我们能够通过某种变换,使这三者进入到同一个空间中,或者去描述这种关系。
这便进入到了注意力机制的计算的部分:

每个阶段具体的公式在右边,但解释的话第一写起来会没完没了,第二我恨数学。所以在这里就给大家讲每个阶段在做什么了。
第一阶段:据Query和Key计算两者之间的相关性或相似性,得到注意力得分;

第二阶段:对注意力得分进行缩放,再使用softmax函数,一方面可以进行归一化,消除变化范围带来的权重差异;另一方面也可以更加突出重要元素的权重。(统一范围了,数越大越重要嘛)[ Softmax函数是机器学习中用于多类分类问题的激活函数,它将实向量转换为概率分布,每个元素值在0到1之间且总和为1。]

第三阶段:根据权重系数对Value值进行加权求和,得到Attention Value,之所以加权就是为了凸显重要信息,忽略不重要信息(此时的V是具有一些注意力信息的)

现在你已经知道注意力机制了,是时候来理解自注意力机制了!
Self-Attention自注意力机制:
自注意力机制使注意力机制的变体,它的出现是为了让计算机注意每一批输入内部不同部分之前的相关性,这有助于模型更全面地捕捉源语言句子中的上下文信息。就比如英文翻译中特别常见的指代词‘it’,如何找到it指代谁呢?相信大家都能说出答案—前后文关联,而自注意力机制就是来着重实现这个前后文关联的,通过将Q、K、V(query,key,value)同源(来自同一个输入),我们就能实现模型更加关注一个输入内部的信息,从而更关注其中的重要信息。
那么我们该如何从输入内部提取Q、K、V呢?这便是自注意力机制的实现。它的步骤与注意力机制很类似
- 获取Q、K、V的值
对于每一个向量x,分别乘上三个系数,wq,wk,wv,得到的Q,K和V分别表示query,key和value(三个W就是我们需要学习的参数)

- 利用得到的Q和K计算每两个输入向量之间的相关性,一般采用点积计算,为每个向量计算一个score:score =q · k

- 将刚得到的相似度除以维度开根号,再进行Softmax。经过Softmax的归一化后,每个值是一个大于0且小于1的权重系数,且总和为1,这个结果可以被理解成一个权重矩阵。

- 用刚得到的权重矩阵,与V相乘,计算加权求和。

在这里我们可以看到z1这个Attention Value 中还包含了thinking与thinking machine中每个单词和thinking之间的相似度,即蕴含了 thinking machines 这句话对于 thinking 而言哪个更重要的信息。但是如果我们仅使用自注意力机制的话,就会过度将注意力集中于自身,于是多头注意力机制应运而生
Multi-Head Attention多头注意力机制:
简单来说,多头注意力机制就是多个自注意力机制组合在一起,只不过这些自注意力机制关注的范围不同,而当我把这些来自不同范围,又是同一套机制提取出的信息组合在一起时,我们就得了一个丰富且准确的向量了。
那么我们是如何实现的呢?
刚刚我们已经知道Q、K、V是输入向量x分别乘上三个系数得到的。那么,对于同样的x,我们定义多组不同的Wq,Wk,Wv我们就可以得到多组不同的Q、K、V,再应用自注意力机制的流程得到z,再把不同的z拼接在一起乘以权重矩阵w,得到最终结果(attentionhead就是每个权重矩阵Wq,Wk,Wv)

资料来源:【Transformer系列(2)】注意力机制、自注意力机制、多头注意力机制、通道注意力机制、空间注意力机制超详细讲解-CSDN博客
现在我们就可以完全明白decoder了嘛?答案是否定的。你会发现Multi-Head Attention前加了一个masked,还多了一个CrossAttention,这两个是什么呢?
Masked Multi-Head Attention
与多头注意力机制唯一的区别就是加入了masked模块,而它的作用就是使只考虑解码器的当前输入和当前输入的左侧部分, 不考虑右侧部分;举个考试猜词的例子大家就可以明白为什么这样做了,例如我们现在要翻译一个英文句子,其实有一个词我们并不知道它的含义,但通过提前阅读后面的词汇,我们可以联系上下文猜出这个词的意思,这对于要考试的我们自然是好事,但对于我们要训练的大模型来说,这就是坏事一桩了。所以我们加入mask模块,强制它只能考虑已经输入的部分。


但这也会产生一个问题,我们说在masked模块影响下,我解码器只考虑当前的输入和输入的左侧部分,可是起始元素的左侧为空啊,这怎么办呢,这便是Outputs那里shifted right操作的用意,通过将输入右移一位(实质上是给输入添加起始符/结束符),我们就可以通过起始符</s>预测“I”,也就是通过起始符预测实际的第1个输出啦。
Shifted right:
或许眼尖的你还有发现,为什么Outputs的下面有Shifted right?这是什么?
简单来说,Shifted right就是把整个输入序列向右移动的一位
例如:May the force be with you -> ' ' + May the force be with you
这么做的原因也比较容易理解。一方面,通过右移,我们可以给句子加一个起始符号如(</s>)告诉模型,从这开始是新的一句(虽然有点蠢,但是让大模型明白句号是一句话的结束,也是需要训练的)。另一方面,通过前面mask模块的引入,我们已经形成“通过当前位置和当前位置左边的输入,进行预测”的工作流,但这样的工作会有一个问题,它无法处理一句话的开头,还是“May the force be with you”的例子,“May”的左侧是空,模型该怎么凭空预测呢?所以,我们通过右移加入起始符号来补足这个过程,这样我们就可以通过起始符号来预测第一个词了(或者说让大模型明白,现在这种情况是在预测第一个词,不是一个错误状态)
Cross attetion模块:
中文名交叉注意力模块,有这样的名字是因为q , k , v 不是来自同一个模块。它将来自解码器的输出向量q 与来自编码器的输出向量 k , v运算。之后再送到全连接层,得到最终输出。
这样做是为了实现编码器和解码器之间的信息交互,Cross-attention允许解码器在生成输出序列的过程中,根据当前解码位置的上下文信息,对编码器中的所有输入进行加权聚合,从而获取与当前解码位置相关的编码信息。这种机制使得解码器能够充分利用编码器中的丰富上下文信息,生成更加准确的输出序列。

参考资料:【Transformer系列(1)】encoder(编码器)和decoder(解码器)_encoder和decoder的区别-CSDN博客
Encoder-Decoder:
现在我们分别了解了encoder和decoder,而当我们把这二者合在一起时,我们会发现这二者的工作其实很像一个你画我猜,而我们使用大量数据训练的过程便是在培养encoder与decoder之间的“默契“。

参考资料:【Transformer系列(1)】encoder(编码器)和decoder(解码器)_encoder和decoder的区别-CSDN博客
更多推荐


所有评论(0)