【学习笔记】transformer是什么?专给非计算机专业看的超直观解读

写在前面:作者本是个计算机小白,因为最近对chatGPT产生了兴趣,开始尝试了解背后的算法,因此有了这篇文章。因为作者是计算机小白(只在学过一点C语言,交完大作业就忘了个干净),所以写出来文章应该没啥门槛,希望可以帮助和我一样不懂计算机但感兴趣的朋友了解什么是transformer模型,即chatGPT中的"T"。

本文主要以我和chatGPT一问一答的形式进行(这部分完全没有门槛,中学数学就可以理解)。因为GPT有胡说八道之嫌,所以我很少直接让GPT介绍某个概念,而是我先看别人的文章形成对某概念的理解,再向GPT确认理解是否准确。当然,这也无法排除GPT仍然胡说八道,因此,如果有错误,还请各位大佬不吝赐教。注意本文是解释这个模型是什么,不涉及具体的实操过程,因此有些地方可能和实际情况有些出入。


transformer的整体架构如下,可以分为四个部分:输入,Encoder,Decoder,输出。我先只把它当一个目录,一步步解释每个框的含义是什么,最后再串起来解释整个架构。

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第1张图片

 

输入和输出

1.1 输入(Inputs & Embedding)

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第2张图片

 

拆开transformer这个黑盒子之前,我们先看它的输入和输出是什么。transformer的输入是一个形状为(batch_size, sequence_length, embedding_dim) 的张量。其中 batch_size 表示批次大小(有几句话),sequence_length 表示序列长度(一句话有多少个词)(实际上我们是需要用零填充同意长度的,详见3.1节),embedding_dim 表示词向量的维度(一个词用几维向量表示)(是一个超参数,也写作d_model,实际模型中一般为512)。

下面涉及第一个概念:词向量。简单地说,电脑无法直接理解我们的语言,词向量就是把单词翻译成了它能听得懂的语言。很容易想到,我们可以用单词在字典中出现的顺序进行编码。例如字典中只有”我“,”吃“,”苹果“三个单词,那么”我吃苹果“就可以编码为”123“。但从数学上看,1和2之间的欧式距离是1,1和3之间的欧氏距离是2;而从语义上看,“我”和“吃”之间语义的差异并不比“我”和“苹果”之间更小。因此,这种编码方式不利于理解。那么如何根据语义编码呢?可以这样操作:首先,字典序只是一个数字,其能储存的信息有限,因此可以先通过“独热编码”(one-hot encoding)对单词进行升维;然后再通过机器学习,将独热编码转化为它所"理解"的语义信息。看下面的对话。

我:请把”我吃苹果“转化为独热编码。

GPT:独热编码是一种将离散特征转换为向量的方法,每个特征对应一个唯一的向量,其中只有一个元素为 1,其他元素都为 0。以“我吃苹果”为例,如果我们将这个句子中的单词进行独热编码,可以得到如下的结果:

- 我:[1, 0, 0,]

- 吃:[0, 1, 0 ]

- 苹果:[0, 0, 1]

这种编码方式可以保留单词的语义信息,同时便于计算和处理。在 Transformer 模型中,输入的单词通常会被转换为对应的词向量,而不是独热编码。

我:关于词向量,我可否这么理解,它其实就是根据语义对单词进行分门别类,每个维度表示特定特征——当然,这些特征每次训练可能都不一样,是一种抽象的特征,未必具有人类能理解的含义。

GPT:您的理解是正确的。词向量是一种用来表示单词的向量,每个维度表示的是抽象的特征,这些特征是通过机器学习算法从大规模文本数据中学习得到的,通常不具有人类能理解的含义。这些特征的选择和权重是根据语义和上下文来确定的,因此词向量可以捕捉单词之间的语义关系,如近义词和反义词之间的相似性和差异性。

我:我可否理解成电脑计算词向量类似于人在进行分类任务,比如假设词向量是五维的,我可以把第一个维度表示词性(是名词还是形容词等),第二个维度表示(如果是名词)名词是动物还是植物;第三个维度表示是脊椎动物还是无脊椎动物,第四个维度表示颜色等等。如此,可以将五个单词,”马“,”狗“,”蜗牛“,”“苹果”,“红色”,分类成:马[1,1,1,1],狗[1,1,1,0],蜗牛[1,1,0,0],苹果[1,0,0,1],红色[0,0,0,1]。

GPT:可以说是类似的思路。词向量是将单词映射到一个高维向量空间中,而这些维度可以表示单词的不同语义或属性。例如,一个表示动物的维度可以使得“马”和“狗”的词向量在该维度上更加接近,而表示颜色的维度可以使得“红色”和“橙色”的词向量在该维度上更加接近。在训练过程中,模型会自动学习到哪些维度对于正确的预测输出更加重要。

(拓展:那么“通过机器学习,让电脑将位置信息转化为它所能理解的语义信息”是如何实现的?

GPT:word2vec是一种用于将单词映射到向量空间的高效算法,它可以在大规模语料库上进行训练,从而得到高质量的词向量。word2vec算法的核心思想是利用单词在上下文中的共现关系来学习单词的向量表示。具体来说,word2vec算法有两个模型:CBOW模型和Skip-gram模型。CBOW模型的目标是根据上下文中的单词预测当前单词,而Skip-gram模型的目标则是根据当前单词预测上下文中的单词。这两个模型都是基于神经网络的,通过学习神经网络的参数来得到单词的向量表示。)

—————

1.2 位置编码(Positional Embedding)

Positional Embedding就是根据单词所在的位置产生一个与词向量维数相同的位置向量,并将该向量与词向量相加,从而把位置信息补充到原始的词向量中

(不想看具体怎么计算的可以跳过这一段)假如某单词在句子中的位置为pos,则该单词词向量的第2i/2i+1个维度的PE值为:

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第3张图片

 

(有一个疑问,PE是储存位置信息的,词向量(WE)是储存语义信息的,直接把它俩的元素相加不就分不出来源了吗?我简要查了一下,大概的解释可能是:词向量的维度足够丰富,而PE的信息主要储存在靠前的一小部分维度,因此即便相加也不会引起混淆)

1.3 输出 (output probabilities)

 

transformer的输出为output probabilities,即输出的token是各个词的概率分别是多少。具体而言:

我:output probabilities是几维的?

GPT:这个概率分布的维度通常等于词汇表的大小,即输出序列中可能出现的单词数。例如,如果词汇表中有10,000个单词,则输出概率分布的维度为10,000。每个维度上的值表示该单词在该位置上的概率

我:也就是说,transformer输入和输出单词不是同一个形式,单词是以词向量的形式输入的,但却是以概率分布的形式输出的

GPT:是的,Transformer模型的输入是经过词嵌入(word embedding)处理后的词向量序列,而输出则是每个位置上单词的概率分布。在训练过程中,我们希望模型能够根据输入序列预测出正确的输出序列,因此在输出端需要将每个位置上的词汇表中的所有单词都考虑到,并计算出对应的概率分布。在训练过程中,我们会根据预测输出与真实输出之间的差异来更新模型参数,以便模型能够更好地预测正确的输出序列。在推理阶段,我们则可以根据模型输出的概率分布来选择最有可能的单词作为模型的预测输出。

————

2. Encoder

2.1 多头注意力(Multihead Attention)

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第4张图片

将输入的语句转化为词向量并加入位置信息后,下一步就是计算注意力了。啥是注意力?有点类似于普通神经网络中的“权重”,即对于某个输入单词,我们应该给予其多大的关注。

(不关心具体计算方法的可以跳过这一段)multi-head attention具体的计算方式不难,attention is all you need的原文写的很清楚了。简单说下,假设只有一个序列,那么本层的输入是一个加入位置信息的词向量序列,形状为(seq_len, d_model) ,其先被线性变换为同形状的Q,K,V(具体怎么变换通过学习得到);然后将QKV依次与每个注意力头的W_Q,W_K和W_V相乘并进行注意力计算,产生h个形状为(seq_len, d_v)的序列,将这些序列拼在一起,然后与一个形状为(h*d_v,d_model)的矩阵W_O相乘,得到一个形状为(seq_len, d_model)(即与input形状相同)的输出。W_Q,W_K,W_V和W_O也都通过学习得到。(想详细了解推荐这篇文章:超详细图解Self-Attention - 知乎 (zhihu.com),稍微有一点数学内容,但写的也非常直观。)

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第5张图片

 

这里我们主要关注的不是计算方式,而是”注意力“和”多头“具体起到什么作用,看下面的对话:

我:关于语言模型的”注意力“机制,我是否可以这样理解:注意力集中在哪个词,就主要依据哪个单词判断接下来要输出的内容?例如,对”爱因斯坦是科学家,贝多芬是__“这句话,如果注意力全部集中在”爱因斯坦“上,则__的位置更可能被填入”科学家“,如果注意力集中在”贝多芬“上,则__更可能被填入”音乐家“?

GPT:您的理解是正确的。在语言模型中,注意力机制可以帮助模型在生成下一个单词时,更加关注输入序列中与当前单词相关的部分,以提高模型的生成准确性。在您的例子中,如果注意力机制集中在“爱因斯坦”上,模型会更有可能生成与“科学家”相关的单词,而如果注意力机制集中在“贝多芬”上,模型则更有可能生成与“音乐家”相关的单词。

我:但如果只把注意力集中在”贝多芬“一个词上,则输出”男人“似乎也对,但整体看这显然不是最合理的答案。因此要选取合理的注意力分配方式?

GPT:您的理解是正确的。在实际应用中,注意力机制并不是单纯地只关注当前单词,而是会综合考虑前文、当前单词等多个因素,以分配合理的注意力权重。在您的例子中,如果只关注“贝多芬”一个词,输出“男人”似乎也是合理的,但如果综合考虑前文,就可以发现应该类比前文的“爱因斯坦是科学家”,因此更合理的答案应该是“音乐家”或者“作曲家”。因此,选择合理的注意力分配方式对于语言模型的生成结果至关重要。

我:何为”多头注意力“机制?

GPT:多头注意力机制可以进一步提高模型对于输入序列和上下文信息的建模能力。它通过将输入序列分成多个子序列,然后对每个子序列进行单独的注意力计算,最后将所有子序列的注意力结果合并起来,从而得到更加全面、准确的注意力表示。举个例子,如果将注意力头数设置为8,那么就会得到8组不同的查询、键和值的线性变换结果。对于每组结果,都会计算一个注意力权重向量,然后将这8个注意力权重向量拼接在一起,再进行一次线性变换得到最终的输出向量。因此,“多头”指的是在注意力机制中使用了多组查询、键和值的线性变换结果,从而增强了模型的表达能力。通过使用多头注意力,模型可以同时关注不同的语义信息,从而更好地捕捉输入序列的语义信息,提高模型的性能。

我:如此说来,注意力头,有点类似于CNN中的卷积核?

GPT:在某种程度上,可以将多头注意力中的注意力头类比为CNN中的卷积核。不同之处在于,卷积核在卷积操作中是对输入数据进行局部的线性变换,而注意力头则是对输入数据进行全局的权重计算。在多头注意力中,每个注意力头都是由不同的查询、键和值组合计算得到的,可以自适应地计算不同位置之间的权重,从而实现对输入数据的全局关注。因此,虽然注意力头和卷积核在实现细节上有所不同,但都是用来提高模型表达能力的重要组件。

——————

接下来的两层更像是构建深度网络的技巧,对理解transformer本身的帮助不大,不关心具体计算方法的可以跳过,只需要知道它们都不改变输入的形状就好。

2.2 加和并归一化(Add & LayerNorm)

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第6张图片

 

上面已经说过,Multi-Head Attetion层的输入和输出是同形状的,因此可以直接相加。这一层就其实是把MHA层的输入和输出相加(残差连接),并进行归一化。这一步不改变输入的形状。不了解残差连接的朋友可以看下面的对话:

我:简单地说,残差连接就是跨层连接,目的是让梯度更加平滑,对吗?

GPT:您的理解基本正确。残差连接是一种跨层连接技术,其目的是解决深层神经网络中的梯度消失和梯度爆炸问题,从而使得网络更容易训练和优化。具体来说,残差连接的基本思想是在网络中添加跨层连接,这样可以使得网络更容易学习到残差函数,从而更好地优化网络。在训练过程中,梯度可以通过跨层连接反向传播到前面的层,从而避免了梯度消失和梯度爆炸问题,使得梯度更加平滑。除了平滑梯度之外,残差连接还有其他一些好处。例如,它可以加速模型的训练,提高模型的准确性和泛化能力,以及减少模型的参数量等。

——————

2.3 前馈传播(Feed Forward)

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第7张图片

(不关注具体实现方法可直接跳过)这部分是先用一个全连接处理上一层的输出,然后进行ReLU激活,再跟第二个全连接层。这样可以提升模型拟合能力,同样引入了残差连接机制。这一步不改变输入的形状,没什么好说的。

至此,整个Endocder的组成解释完毕。实际模型中是6个Encoder串联的,即第一张图中的N=6。

3. Decoder

Decoder所要进行的计算和Encoder大部分都一样,依然是多头注意力、相加并归一、前馈、残差传播等,因此这里主要讨论几个关键区别。(ps:实际模型中decoder也是有6个串联的)

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第8张图片

3.1 将已有输出作为输入

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第9张图片 

 

和RNN类似,Decoder的输入包括两部分,第一部分是Encoder的输出(输入1),第二部分输入(以下简称输入2)是整个模型上一步的输出,也就是下图中的内容。

需要注意的是,这一部分输入内容在训练时和预测时是不一样的。看下面的对话:

我:关于decoder,如果输入transformer的原句是“你爱吃啥”,那么训练时,输入2处会直接输入答案“我爱吃鱼和肉”(但需要掩盖,下一节细说)。而预测时,最开始输入2=“ ”,然后模型预测“我”(t=0);然后输入2=“我”,模型预测“我爱”(t=1);输入2=“我爱”,模型预测“我爱吃”(t=2)...。显然,这个序列长度一直在变,那怎么避免形状不一致的问题?答案是短补长截。如果输入2过短,则通过补零(zero-pad masking)使得其与原句长度相同(同理,encoder是输入其实也是需要零填充的,不然稍微长一点的句子都无法处理)。即,模型输出的“我”,放到输入2时会变成“我_ _ _“。而如果模型已经预测了”我爱吃鱼和“,则此时这个预测的seq_len = 5,而原句的seq_len = 4,于是此时模型会从预测结果的第二位开始截取,即输入2是”爱吃鱼和“。是这样吗?

GPT:是的,您的理解基本正确。在训练时,输入2会被直接输入答案,并进行掩盖,防止模型在预测时使用到未来的信息。在预测时,输入2会根据模型的预测结果不断变长,如果长度不足,则通过补零的方式进行填充,如果长度过长,则进行截取。这样可以避免形状不一致的问题,使得模型能够正确地处理变长的输入2。

我:所以,论文中shifted right是否可以理解为,当我们把当前输入作为下一步的输入时,每进行一步,长度固定的“输入框”就向右移动一位?

GPT:是的,你可以将shifted right理解为将目标序列向右移动一位,这样解码器在每个时间步都能够看到前一个时间步生成的单词,以便更好地预测下一个单词。你的理解也是正确的,可以将shifted right看作是将"输入框"向右移动一位,以便将前一个时间步生成的单词作为当前时间步的输入。

——————

3.2 遮盖的多头注意力(Masked Multi-Head Attention)

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第10张图片

 

与上文的补零(zero-pad masking)相区别,这里说的mask(sequence mask)只有在训练的时候才需要进行,这是为了避免decoder在训练时直接看到后面的信息。上一小节我们说,如果输入transformer的原句是“你爱吃啥”,那么训练时,输入2直接输入答案“我爱吃鱼和肉“。但如果不进行任何处理,模型就会直接把这个结果输出出去,显然,这样就起不到训练的效果了。因此,我们需要把当前时间步之后的内容全部隐藏起来。

3.3 线性层和Softmax层

 

【学习笔记】transformer是什么?专给非计算机专业看的超直观解读_第11张图片

最后,加入一个单层的全连接神经网络,其输入形状仍然为(batch_size, seq_leng, hidden_size)(注意我们上面提到的注意力、add&norm,feed forward等层都没有改变输入的形状,因此到这里还是这个形状),输出是一个维度为dim_V的向量,”一个“的含义是模型每步只下一个最可能的词是什么,"dim_V"也记作vocab_size,就是词库的大小。经过softmax函数转化,这个向量的每个分量就是用词库中对应单词作为回复的概率(参见1.3节)。至此,大功告成!

总结,我觉得理解transformer的关键,其一在于弄清楚"注意力"到底起到什么作用。这是transformer的核心的,理解了它才能知道transformer回复的内容到底是根据什么生成的。其二是弄清楚在训练和预测的时候,decoder的输入2是不同的,我一开始疑惑了好久,decoder刚回复第一个词的时候,后面不都是零填充的空白吗?为什么要mask起来。

推荐另一篇也很直白的解读文章:(30条消息) 史上最小白之Transformer详解_Stink1995的博客-CSDN博客

 

你可能感兴趣的:(学习,笔记,transformer)