关于GPT的生成等大语言模型背后的技术原理,一个很常见的说法是,它们是通过预测出现概率最高的下一个词来实现文本生成的,这种效果有点像搜索引擎的自动补全。每当我们输入一个新的字或词,输入框就开始预测后面的文本,概率越高的,排在越上面。但模型具体到底是如何得到各个词出现的概率的?
说起大语言模型的技术原理,就不得不说Transformer架构。自从一篇2017的论文,attention is all you need提出Transformer后,文本领域的大模型,几乎被他一统江湖,OpenAI的GPT,清华的GLM等等,背后无疑都有Transformer的影子在。Attention is all you need论文里它看起来有点复杂,但不需要害怕,它可以被看作有两个核心部分组成,编码器encoder以及解码器decoder。假如我们要这个Transformer做英语翻译法语的任务,给编码器输入一句英语解码器返回对应的法语。这个过程中发生了什么?
我们先看编码器部分输入的文本首先会被token化,也就是先把输入拆分成各个token,token可以被理解为是文本的一个基本单位,取决于不同的token化方法。短单词可能每个词是一个token,长单词可能被拆成多个token。然后每个token会被用一个整数数字表示,这个数字被叫做token ID。这样做是因为计算机内部是无法储存文字的任何字符的,最终都得用数字来表示。有了数字表示的输入文本后再把它传入嵌入层,嵌入层的作用是让每个token都用向量表示,向量可以被简单地看为一串数字。为了能在画面里放下,这里把向量长度简化为3,但实际中项链长度可以非常长。
问题来了,之前明明已经有单个整数表示各个token了,怎么现在又要用一串数字表示各个token,其中一个原因是一串数字能表达的含义是大于一个数字的,能包含更多语法,语义信息等等。
这就好比男人和女人这两个词他们都在描述人类,但性别又是完全相反的。如果只用一个数字表示这两个词之间的距离大小,应该距离很大还是距离很小?但如果有多个数字,我们就可以进行更多维度的表示。就比如说第一个数字可以表示是雌性的程度,第二个表示年龄大的程度,第三个表示社会阶层高低程度。所以,嵌入层的向量不是随便搞出来的,里面包含了词汇之间语法语义等关系,相似的词所对应的嵌入向量在向量空间里距离也更近,而一些没啥关系的词之间的距离就更远。这有助于模型利用数学计算向量空间里的距离去捕捉不同词在语义和语法等方面的相似性。而且,男人与国王的差异和女人与女王的差异可以被看作是相似的,这也可以在多维向量空间里展现。因此,词向量不仅可以帮模型理解词的语义,也可以捕捉词与词之间的复杂关系。那我们这里为了直观是用三维向量空间表示的,把向量长度相应简化成了3。而提出Transformer的论文里向量长度是512GB,所以可以想象能包含多少信息。
通过编码器的嵌入层得到词向量后,下一步是对向量进行位置编码。我们在上个博客提到Transformer这一项关键机制是位置编码。如果你没看上一篇文章也没关系,位置编码就是把表示各个词在文本里顺序的向量和上一步得到的词向量相加,然后把得到的结果传给编码器。这样做的意义是,模型既可以理解每个词的意义,又能够捕捉词在句子中的位置,从而理解不同词之间的顺序关系。
接下来就到了编码器这个核心部分,他的主要任务是把输入转换成一种更抽象的表示形式。这个表示形式也是向量记一串数字,里面既保留了输入文本的词汇信息和顺序关系,也捕捉了语法语义上的关键特征,捕捉关键特征的核心是编码器的自注意力机制。模型在处理每个词的时候,不仅会关注这个词本身和它附近的词,还会关注输入序列中所有其它词。也正如Transformer论文标题所说,attention is all you need,注意力就是你所需要的一切。自注意力机制通过计算每对词之间的相关性来决定注意力权重,如果两个词之间的相关性更强,他们之间的注意力权重就会更高。
比如这个例子,单从语法上来讲,it可以animal。也可以指street,而自注意机制发现了it与animal更强的关联。所以给animal的权重会更大一些,但由于自注意力机制对上下文的全面关注。那在输出的表示结果里不仅包含这个词本身的信息,还融合了上下文中的相关信息。上下文在语言里很重要,也能揭露相同词的不同含义。所以在解码器输出的结果里表示各个词的向量会根据上下文信息进行调整,同一个词根据上下文有不同的抽象表示,自注意力机制涉及到很多计算步骤,这里主要是做个简单的科普,更多细节可以在论文原文里关注一下。
而且Transformer实际上使用了多头自注意力,也就是编码器不只有一个自注意力模块而是有多个,每个头都有它自己的注意力权重,用来关注文本里不同特征或方面。比如有的关注动词,有的关注修饰词,有的关注情感,有的关注命名实体等等,而且他们之间可以做并行运算,也就是计算进展上互不影响。每个字注意力投的权重都是模型,在之前的训练过程中,从大量文本里逐渐学习和调整的。在多头自注意力后面还有一个前馈神经网络,它会对自注意力模块的输出进行进一步的处理,增强模型的表达能力。那编码器在Transformer里不只有一个,实际上是有多个堆叠到一起,每个编码器内部结构一样,但不共享权重。这样模型能更深入的理解数据,处理更复杂的文本语言内容。
看完编码器,接下来看解码器的部分。它是大语言模型生成一个个词的关键,通过前面的编码器。我们有了输入序列里各个token的抽象表示,可以把它传给解码器。解码器还会先接收一个特殊值,这个值表示输出序列的开头。这样做的原因是,解码器不仅会把来自编码器的输入序列的抽象表示作为输入,还会把之前已经生成的文本也作为输入,来保持输出的连贯性和上下文相关性。刚开始的这轮还没有任何已生成的文本,所以把表示开头的特殊值先作为输入,具体的生成过程仍然是要经过多个步骤。
首先和编码器一样,文本要经过我们已经了解过的嵌入层和位置编码,然后被输入进多头自注意力层。但他和编码器里的自注意力层有点不一样,当编码器在处理词的时候,他会关注输入序列里所有其它词。但解码器中自注意力只会关注这个词和它前面的其它词,后面的词要被遮住,不去关注,这样做是为了确保解码器生成文本时遵循正确的时间顺序,不能给他偷看到后面,在预测下一个词时只使用前面的词作为上下文。这种类型的多头自注意力被叫做带掩码的多头自注意力。
带掩码的多头自注意力是针对已生成的输出序列的,而后面解码器还有个多头自注意力层。这里就是前面编码器所输出的输入序列的抽象表示所派上用场的地方,注意力会捕捉编码器的输出和解码器即将生成的输出之间的对应关系,从而将原始输入序列的信息融合到输出序列的生成过程中。解码器里的前馈神经网络作用和编码器里的类似,也是通过额外的计算来增强模型的表达能力,而且和编码器一样,解码器同样是多个堆叠到一起的,这可以增加模型的性能,有助于处理复杂的输入输出关系。
解码器的最后阶段包含一个线性层和一个softmax层,它们俩加一块儿的作用是把解码器输出的表示转换为词汇表的概率分布。这个词汇表的概率分布代表下一个被生成token的概率,那么有些token的概率就会比其他的高。在大多数情况下,模型会选择概率最高的token作为下一个输出,那现在我们知道了解码器本质上是在猜下一个最可能的输出。至于输出是否符合客观事实,某些无从得知。所以我们能经常看到模型一本正经的胡说八道,这种现象也被叫做幻觉。那解码器的一整个流程会重复多次,新的token会持续生成,直到生成的是一个用来表示输出序列结束的特殊token,那现在我们就拥有了来自解码器的完整输出序列。
那以上描述的是attention is all you need里的原始Transformer编码器用来理解和表示输入序列解码器用来生成输出序列。实际上在原始架构的基础上,后续出现了一些变种。主要有三个类别:仅编码器、仅解码器以及编码器解码器。
仅编码器模型也叫自编码器模型,只保留了原始架构里的编码器,Bert就是这种模型的一个例子。此类模型适用于理解语言的任务,比如掩码语言建模:也就是让模型猜文本里被遮住的词是什么,情感分析:让模型判断文本情感是积极还是消极等等。
仅解码器模型也叫自回归模型只保留了原始架构里的解码器,GPT系列都是这种模型的例子。这类模型非常擅长通过预测下一个词来实现文本生成。我们已经在ChatGPT身上见识过了。
编码器解码器模型也叫序列到序列模型,同时保留了原始架构里的编码器和解码器。T5、Bart都是这种模型的例子。
此类模型适用于把一个序列转换成另一个序列的任务,比如翻译总结等等。
那经过这个文章,你对大语言模型背后技术的了解应该已经超过99%的人了。如果你好奇如何炼成ChatGPT的话,请看下一篇博客。