前言
Transformer模型是一个革命性的创新,它推动了深度学习在多个领域的发展。尽管存在一些挑战,但通过不断的改进和优化,Transformer模型已成为当前自然语言处理和其他人工智能领域的主流模型之一。未来,随着研究的深入,Transformer模型及其变体可能会在更多领域展现其强大的潜力。
本文将深度讲解transformer的理论逻辑与数学原理
文章目录
Transformer的数学原理课溯源至注意力机制。
注意力机制简单来讲,就是来原来的基础上多出一个查询向量,用来对序列里的每一个向量进行查询。在此过程中通过注意力打分函数,我们可以得到序列与查询向量点乘后的得分,用以计算出注意力分布。这个注意力分布实际就代表着这个序列里每一个向量所占的权重。如果有需要,我们将其加权平均得到的表示转换为一个总和,这个总和代表了整个句子在一定语境下的总体影响或效应。
我们将Transforme结构分成两个部分:encorder与decorder。
在这里插入图片描述
自注意力机制
理论原理
在Transformer模型中,编码器(Encoder)和解码器(Decoder)中的自注意力机制(Self-Attention)虽然都是用于处理序列数据,但它们在具体实现和功能上存在一些差异:
编码器中的自注意力(Encoder Self-Attention):
上下文理解:编码器的自注意力允许每个标记(例如,单词或token)在生成其表示时考虑输入序列中的所有其他标记。这有助于模型理解整个输入序列的上下文。
多头注意力:在编码器中,自注意力通常以多头注意力(Multi-Head Attention)的形式实现,这意味着自注意力被多次独立地计算,每次关注输入的不同部分,然后将这些结果拼接起来。
位置编码:编码器的自注意力通常会结合位置编码(Positional Encoding),以确保模型能够理解序列中标记的位置信息。
无遮挡:在编码器的自注意力中,每个标记都可以同时看到序列中的所有其他标记,没有任何遮挡。
解码器中的自注意力(Decoder Self-Attention):
遮挡效应:解码器的自注意力具有遮挡效应(Masked Attention),这意味着在生成序列的某个位置时,模型只能attend到该位置之前的所有输出(包括当前步骤的输入),不能attend到未来的输出。这是为了保持自回归性质,即解码器的输出必须按照顺序生成。
多头注意力:与编码器类似,解码器中的自注意力也是以多头注意力形式实现的,但每个头的计算可能受到遮挡效应的影响。
上下文和目标结合:在解码器的自注意力层中,模型不仅要考虑已经生成的输出序列,还要考虑编码器的输出,以生成下一个输出标记。
交叉注意力:除了自注意力,解码器通常还包含一个交叉注意力层(Cross-Attention),它允许解码器attend到编码器的输出,从而获取输入序列的上下文信息。
主要区别:
遮挡效应:解码器中的自注意力具有遮挡效应,以防止模型在生成序列时泄露未来的信息,而编码器中的自注意力没有这种限制。
上下文来源:编码器的自注意力只关注输入序列本身,而解码器的自注意力同时关注已经生成的输出序列和输入序列(通过交叉注意力)。
功能目的:编码器的目的是理解整个输入序列的上下文,而解码器的目的是根据输入序列和已经生成的输出序列生成新的输出。
总的来说,虽然编码器和解码器都使用自注意力机制,但它们在注意力计算的具体方式和目的上有所不同,这些差异使得Transformer能够有效地处理序列到序列的任务,如机器翻译、文本摘要等。
数学原理
自注意力机制的本质是通过添加该机制,使得得到一个权重矩阵。矩阵里每个元素aij表示第i个元素对第j个元素的关注程度。
举例说明一下:假设我们有一个输入序列X,它由4个元素组成:X,[x1, x2, x3, x4]。在自注意力机制中,我们将为这个序列计算注意力权重矩阵。
1.输入序列的嵌入表示:首先,输入序列中的每个词都被转换为一个嵌入向量(embedding vector)。这个嵌入向量是一个稠密、低维的向量,它能够捕捉到词的语义信息。
2.位置编码(Positional Encoding):由于Transformer模型本身不具有处理序列位置信息的能力,因此需要向每个词的嵌入向量中添加位置编码。变成了X’,[x1+p1,x2+p2,x3+p3,x4+p4]。位置编码可以是固定的(例如正弦和余弦函数的线性组合)或者可学习的参数。
3.线性变换:每个带有位置编码的词向量会通过一个线性变换(即矩阵乘法)来生成查询矩阵Q。这个线性变换是通过与一个权重矩阵WQ[a1,a2,a3,a4]相乘来完成的,其中WQ是模型在训练过程中学习到的参数。
最终我们得到了查询向量Q=WQ*X’。
通过带入图片里的公式,我们可以得到一个自注意力权重矩阵。
x1 x2 x3 x4
x1 [0.31 0.08 0.05 0.11]
x2 [0.08 0.31 0.16 0.08]
x3 [0.05 0.16 0.31 0.16]
x4 [0.11 0.08 0.16 0.31]
在这个矩阵中,每个元素aij表示第i个元素对第j个元素的关注程度。它决定了在生成每个元素的表示时,序列中其他元素应该给予多少权重。通过这种方式,模型能够在处理序列时考虑到序列内部的长距离依赖关系。
注意力分布 𝛼𝑛 可以解释为在给定任务相关的查询 𝒒 时,第 𝑛 个输入
向量受关注的程度.我们采用一种“软性”的信息选择机制对输入信息进行汇总,
即
个这样,每个位置的上下文向量都融合了序列中其他所有词的信息,体现了当前词在整个序列中的上下文关系。代表每个词对于这个序列的影响力。它将作为自注意力层的输出,进入下一个残差网络。
Layer normalization。Normalization有很多种,但是它们都有一个共同的目的,那就是把输入转化成均值为0方差为1的数据。我们在把数据送入激活函数之前进行normalization(归一化),因为我们不希望输入数据落在激活函数的饱和区。
编码器里的FFN层
理论原理
在Transformer模型中,编码器(Encoder)内部的FNN(Feed-Forward Neural)层扮演了重要的角色,其主要意义如下:
非线性变换:FNN层引入了非线性激活函数(如ReLU),允许模型学习更复杂的函数映射。这是因为在没有非线性激活函数的情况下,无论神经网络有多少层,其整体仍然是一个线性变换,这限制了模型的表达能力。
增强表示能力:FNN层通过两个线性变换层和一个非线性激活函数,对自注意力层输出的上下文向量进行进一步处理。第一个线性层通常增加隐藏单元的数量(即扩展维度),第二个线性层则将维度还原。这种“扩展-压缩”的操作有助于模型捕捉更复杂的特征和模式。
位置信息的进一步处理:虽然自注意力层可以捕获序列中不同位置的依赖关系,但FNN层可以进一步处理这些信息,使得模型能够更好地理解序列中的位置关系。
参数共享:在Transformer模型中,每个编码器层都包含一个FNN层,但这些FNN层之间不共享参数。每个FNN层都可以学习到不同的特征表示,从而增强模型对不同层次特征的处理能力。
残差连接和层归一化:FNN层通常与残差连接(Residual Connection)和层归一化(Layer Normalization)结合使用。残差连接有助于缓解深层网络训练中的梯度消失问题,而层归一化则有助于稳定训练过程。
数学原理
如此,单一个编码器的所有结构都已经说明了。但是在实际应用的过程里,通常都是多个编码器堆叠,深度增强表达,使模型能够学习更深层次的特征表示。每一层都能够基于前一层的输出学习到更复杂、更抽象的表示,从而增强模型的表达能力。
解码器里的自注意力层
在Transformer模型的解码器中,自注意力层(Self-Attention Layer)的输出将作为输入传递到编码器-解码器注意力层(Encoder-Decoder Attention Layer)。以下是这一过程的详细说明:
自注意力层的输出:
解码器的自注意力层首先处理解码器的前一层的输出,生成当前层的输出。这个输出包含了当前解码器步骤的上下文信息,并且已经通过掩码处理,确保了在生成当前词时不会考虑未来的词。
传递到编码器-解码器注意力层:
自注意力层的输出将作为查询(Query)输入到编码器-解码器注意力层。在这个层中,解码器的每个位置的输出将和编码器的所有位置的输出进行交互,以便获取输入序列的全局上下文信息。
在解码器部分里的encorder-decorder attention
在Transformer模型中,交叉注意力机制通常发生在解码器部分,其中解码器生成的每个目标语言单词都会关注源语言句子中的不同部分,目的是用来生成下一个词语。
编码器-解码器注意力层的运行过程:
查询(Query):来自解码器自注意力层的输出。
键(Key)和值(Value):来自编码器的输出。在标准的Transformer模型中,编码器的最终输出将作为键和值。
计算注意力得分:使用查询和键计算注意力得分,这通常是通过点积操作完成的。
应用softmax函数:将注意力得分通过softmax函数转换为概率分布,称为注意力权重。
加权求和:将注意力权重与值进行加权求和,得到编码器-解码器注意力层的输出。
输出:
编码器-解码器注意力层的输出是解码器当前步骤的上下文向量,它结合了来自编码器的全局信息和解码器已经生成的部分序列的局部信息。
以下是步骤:
1.编码器处理源句子:
源句子 “I have a cat” 经过编码器处理,得到一系列编码后的向量,每个向量对应一个源单词(I, have, a, cat)。
解码器生成目标句子:
解码器开始生成目标句子。假设我们已经生成了 “J’ai” 部分,现在要生成下一个单词 “un”。
2.交叉注意力机制的应用:
在解码器中,当前生成的最后一个目标语言单词的隐藏状态(对应 “ai”)(对应的是自注意力层的输出结果)**将作为查询向量(Query)。
编码器输出的所有向量(对应 “I”, “have”, “a”, “cat”)将作为键(Key)和值(Value)。
3.交叉注意力机制的计算步骤如下:
a. 计算注意力得分:
对于每个源单词的键向量,计算它与查询向量的点积,这会得到一个注意力得分。
得分公式:Score(Q, K) = Q · K^T / √d_k
其中 Q 是查询向量,K 是键向量,d_k 是键向量的维度。
b. 应用softmax函数:
将注意力得分通过softmax函数转换为概率值。
概率公式:Attention weights = softmax(Score)
c. 计算加权值:
使用得到的概率值对值向量进行加权求和。
加权值公式:Weighted Value = Σ(V_i * Attention weights_i)
d. 得到上下文向量:
加权求和的结果就是上下文向量,它代表了模型在当前解码步骤对源句子的关注。
生成目标单词:
解码器将上下文向量与当前目标单词的隐藏状态结合,然后通过一个前馈神经网络来预测下一个目标单词 “un”。
在Transformer模型中,解码器中的查询向量(Query)用于生成下一个目标语言单词的过程如下:
利用最后一个目标语言单词的隐藏状态:
当解码器生成了一系列目标语言单词后,最后一个生成的单词的隐藏状态将作为当前时间步的输出。这个隐藏状态包含了关于到目前为止生成的整个序列的信息。
作为查询向量:
这个隐藏状态将直接作为查询向量(Query)或者通过一个线性变换(即一个可学习的权重矩阵)来生成查询向量。这个线性变换的目的是将隐藏状态的维度转换成与键(Key)和值(Value)向量相同的维度,以便进行注意力计算。
注意力机制:
查询向量与编码器输出的键向量进行点积运算,以计算它们之间的相似度。这些相似度分数随后通过softmax函数转换为概率分布,称为注意力权重。
注意力权重表示了在当前解码步骤中,源语言序列中的每个位置对生成下一个目标单词的重要性。
生成上下文向量:
将注意力权重与编码器输出的值向量相乘,并求和,得到上下文向量。这个上下文向量包含了来自源语言序列的相关信息,这些信息有助于生成下一个目标单词。
如何使用上下文向量来生成下一个词语的步骤(解码器里的FNN)
上下文向量与解码器输出结合:
在Transformer模型的解码器中,当前时间步的解码器输出(即最后一个生成单词的隐藏状态)会与计算得到的上下文向量相结合。这通常是通过简单的向量加法或拼接操作完成的。
前馈神经网络处理:
结合后的向量会通过一个或多个前馈神经网络(Feed-Forward Neural Networks)。这些网络进一步处理这些信息,学习如何从结合了解码器状态和上下文信息的向量中提取特征,以生成下一个词语。
线性变换和Softmax激活:
经过前馈神经网络处理后的向量会通过一个线性变换层,这个层将向量映射到一个维度等于词汇表大小的向量。然后,这个向量会通过softmax激活函数,转换为概率分布,其中每个元素代表了词汇表中对应单词的生成概率。
注意:
1)encoder提供了更多的数据给到decoder,encoder会把所有的节点的hidden
state提供给decoder,而不仅仅只是encoder最后一个节点的hidden state。
2)decoder并不是直接把所有encoder提供的hidden state作为输入,而是采取一种选择机制,把最符合当前位置的hidden state选出来,具体的步骤如下
a:确定哪一个hidden state与当前节点关系最为密切
b:计算每一个hidden state的分数值(具体怎么计算我们下文讲解)
即:把每一个encoder节点的hidden states的值与decoder当前节点的上一个节点的hidden state相乘(如果是第一个decoder节点,需要随机初始化一个hidden state),最后会获得多个值,这几个值就是上文提到的hidden state的分数,这个数值对于每一个encoder的节点来说是不一样的,把该分数值进行softmax计算,计算之后的值就是每一个encoder节点的hidden states对于当前节点的权重,把权重与原hidden states相乘并相加,得到的结果即是当前节点的hidden state。
这样能让相关性高的hidden state的分数值更大,相关性低的hidden state的分数值更低
选择下一个词语:
根据softmax输出的概率分布,可以采用不同的策略来选择下一个词语:
贪婪解码:选择概率最高的单词。
束搜索(Beam Search):维护多个候选序列,选择整体得分最高的序列。
采样:根据概率分布随机采样下一个单词。
更新解码器状态:
选定的下一个词语不仅用于构建输出序列,还会反馈到解码器中,更新解码器的状态。这个过程是迭代的,解码器在每一步都会使用新的状态和更新后的上下文向量来生成下一个词语。
结尾
如果有小伙伴坚持看到这里的话深表感谢,本来要继续写源码分析和具体的实践了。时间关系,等下周再抽时间写源码分析与实践部分吧。本文仅用于笔者自己总结自己transformer学习之路,期间引用很多专家学者的观点思路,深表感谢。第一次驾驭这么长的技术文章,每个知识点都想写点,感觉越写越乱。若有读者在阅读本文期间有不好的阅读体验深表歉意。