
先来个猜词游戏“今天天气真_”, 这句话,如果是你后面会接什么词呢? 你可能会接“好”,“不错”,而对于AI大模型来说,它也是这么想的,其本质就是一个接词机器,它会将这句话后所有可能出现的词都列举出来,并且按照这些词可能出现概率,从大到小进行排序,然后选择可能出现词填上去(不一定是概率最大的,这个后面会讲为什么)。这篇文章,我们不直接讲公式而是跟着一个 token看它怎么从今天天气真一路漂到真好的。第 1 站文本划分——模型先要切 token什么是 tokentoken,中文叫词元,它是AI大模型处理文本时的最小单位可以是一个词、一个汉字、一个词组、甚至半个词,比如「人工智能」可能被分为成「人工智」「能」两个token。文本划分(tokenize)大模型本身不认识字,也不认识词,它只认识 token,所以当大模型接收到一段文本时,首先要做的第一件事就是将文本划分为token,比如:“今天天气真”, 这句话可能被划分为 「今天」「天气」「真」,也有可能是 「今天天」「气真」,大模型划分token并不会按照人类的阅读习惯来进行划分,一切取决于模型内部的具体实现,不同的厂商的大模型划分法都各不相同,而这并不是我们今天要讨论的重点。假设划分后,整句话变成了「今天」「天气」「真」这三个token, 这样大模型就认识了吗答案是否定的,因为此时的token本质上还是字或词,而我们前文说的认识 token,其实指的是认识tokenID。 当我们将token划分好过后,每一个token会被映射成 对应的一个tokenID,即一个数字,比如 :「今天」「天气」「真」— [1234, 5678, 9012 ]。那么,这个tokenID又是什么呢其实它就是token对应的在词表中的索引,当然这些都是后话了。第 2 站词向量——token ID 变成一串数字什么是词向量词向量(token Embedding),就是用向量的形式来描绘一个词语(即token),向量的维度表示该词语(token)的特征(即特点)的个数。向量上的每一位都代表一个特征,该位上存放的数字,代表该特征的权重,数字越大该特征在对应词语上显现就越明显,比如 「机器人」,它对应的词向量在科技这个特征的位置上其存放的数字就会相对的比较大,而在吃饭这个特征位置上数字就会相对的比较小。什么是潜空间假设有一个可以包含所有词向量的高维空间(即潜空间),在这个高维空间内,根据向量各个维度存放的数字大小将这些词向量放在对应的位置上,两个词向量距离越近,就代表这它们的特征越相似,即对应的词语语义越近,如下图所示(这里我们用二维向量来代替高维向量演示):「苹果」与「香蕉」都是水果语义相近因此距离更近,「喜欢」与「苹果」区别太大,因此距离更远。如何去确定两个词向量在 潜空间的 距离远近呢当然是通过 两个向量之间的 点积或余弦相似度的大小来确定,点积越大,说明距离越近,即两个词向量语义更近。什么是 嵌入矩阵词表(vocabulary)就是模型认识的所有token的集合,该表的每一行就表示一个词向量有多少行就表示有多少个词向量,每一列就表示一个特征,有多少列就表示词向量的维度是多少。模型内部的所有的词向量的维度是相同的,这个可以人为的进行规定。前面所说的tokenID就是词表的索引,即词表的行下标,大模型通过tokenID就能获取到 该token对应的词向量在词表的第几行,从而拿到对应的词向量,这就是 大模型认识的由来。将整个词表对应形成的矩阵就叫嵌入矩阵(Embedding Matrix)。词嵌入(token Embedding )回到我们前面的今天天气真这个例子,我们现在拿到了 「今天」「天气」「真」这三个token对应的tokenID,即[1234, 5678, 9012 ],我们从嵌入矩阵(Embedding Matrix)中获取到这三个tokenID对应的词向量,将它们组成一个新的小矩阵,这就是词嵌入(token Embedding)。第 3 站Transformer——token 们开始开会什么是神经网络从函数到神经网络函数,想必大家都很熟悉,y2x,yx^23……,通用格式就是yf(x);如果我们将x看作是输入,y看作是输出,那么其实世界上几乎所有东西都可以用函数来解释,Functions describe the world:这就是神经网络的理论基础,给定一组输入x和一组输出y,找到它们之间的关系,即找到一个函数来表示,而这个寻找的过程,就被称为训练,所以神经网络本质上可以理解为一个大的函数,所谓多层神经网络,就是不同函数之间的嵌套。关于神经网络,或者说深度学习,我后面会有相应的文章来详细解释这里就不作深入地讲解,只需要大概了解相关概念即可。前向传播如上图所示,假设现在有一个两层神经网络,x为输入,y为输出h为中间结果,w1与w2为每一层的参数,则有hx * w1,yh * w2;L为理论值与实际输出值的差平方,我们称其为损失(图中理论值为10,平方也只是损失的众多算法之一,其消除了正负号)。输入x,经过两层神经网络,最终变成了输出y,然后计算出损失L,这整个过程就叫前向传播。反向传播与梯度下降前向传播算出了 最终输出值y和损失L,那么反向传播与梯度下降就是为了降低损失L,这也是训练的目的。如何降低损失L呢? 我们通过调整每层的参数w1和w2来实现。实现的前提是找到参数与损失之间的关系,根据前面的内容,通过函数嵌套我们能够得到参数与最终输出的关系,而将最终输出作为输入代入损失L的表达式,从而我们可以得到损失L与参数之间的关系:L(w1 * x * w2-10)^2。函数找到了,我们就要确定 各个参数的变化对损失L的影响这就要引出 数学中 导数与函数单调性的关系,当导数0,函数单调递增;当导数0,函数单调递减;导数L △L/△y, 通过链式法则,我们能够确定L与各个参数的导数关系,当导数大于0时,意味着 想要损失L变小,参数就要调小 ,当导数小于0时,想要损失L变小,参数就要调大。确定各层参数与损失L的导数关系,这个是从损失开始向输入方向逐层确定的,这个过程就叫反向传播。确定好每层参数的导数后,根据导数结果调整对应的参数大小,这个过程就叫梯度下降。以w1为例,每次调整的公式为w1w1-(△L/△w1)* K,K叫 学习率,表示每次调整的幅度。残差连接为了能处理更复杂的关系,神经网络的嵌套层数越来越多,结果你发现最终的效果反而越来越差,这种现象就叫退化,原因就是随着嵌套层数的增加,反向传播的难度越来越大,因为层数增多,导数最终可能越来越小,到后面对参数的影响都可以忽略不计了,这种现象就叫梯度消失。为了缓解梯度消失的现象,残差连接,也叫残差网络就此诞生了。每一层的输出由原来的f1(x)变为了f2(x)x,其中f2(x)f1(x)-x,从每一层上来看,每次都是 在求在原来输入x的基础上,增加的内容f2(x),这个增加的内容f2(x)就叫残差。从上面这个角度来看,每层的输入输出好像并没有发生什么改变,但是实际上,残差连接有以下两个好处:前向传播时,因为x的存在,能够将每层输入都完整的传递。反向传播时,因为x的存在,每层导数都会有个1存在,其使得前一层的导数能够通过这个1完整无损地传递到下一层,大大缓解了梯度消失的现象。归一化(Normalization)在真实的场景中,数据之间的大小差距往往是不可预测的,为了防止个别极端数据导致结果波动过大,我们往往会采用归一化(Normalization),将结果中的所有数据 等比放缩到指定数据范围,如[0-1]之间,从而保证系统稳定。FFN前馈神经网络如上图所示,在真正的transformer架构中,神经网络往往可以同时输出多个向量,即你可以等效的将一个神经网络看成多个相同的神经网络,每个神经网络只处理一个输入向量,并且输出其对应的下一个向量。然而大模型本质是个接词游戏,即预测下一个token,这意味着我们只需要关心最后一个输入向量即可,「真」–「好」。因为我们只关心最后一个输入向量,因此我们以最后一个输入向量为例如下图:我们将输入向量先进行一个升维,从而可以在潜空间中学到有用的特征,然后再进行降维,对输入向量维度进行还原。什么是学到有用特征呢?其实就是根据语句中该token的具体含义,拉高相关特征的数字,降低不相关特征的数字,使得二者差距更加明显。将维度还原后的向量进行投影,投影为向量维度是词表大小的输出向量。纵观整个过程,前面升维上采样和降维下采样,这部分就叫FFN前馈神经网络,也叫FC或MLP,后面投影这部分就叫线性投影(Linear),也叫Projection。在实际情况中,FFN前馈神经网络会堆叠很多层,这也正是输入输出向量维度一致的好处。注意力机制(attention)前文提到,我们只需要关心最后一个输入向量即可,「真」–「好」。这并不是说通过输入token「真」就可以直接预测出下一个token「好」,因为仅仅通过一个token「真」的相关信息是不足以预测出下一个token「好」的,实际上,token「好」的预测,是由前面所有token(「今天」「天气」「真」)的相关信息共同作用的结果,将前面所有token加起来产生的新向量作为输入向量,通过神经网络从而预测出下一个token「好」如下图所示:但是,直接加起来,忽略了token之间的差异,即token与token之间的相关性或重要程度各不相同,对此,我们可以根据token之间的相关性,为每个token赋予一个权重,相关性越高,权重越大,然后进行加权求和,得到新向量作为神经网络的输入向量,如下图所示:如何确定每个token的权重呢这就轮到注意力机制(attention)发挥作用了。注意: 我前文说token之间的相关性指的就是所有token包括最后一个token自身与 最后一个token之间的相关性。前面所有token的信息全部汇聚到了一起,结合最后一个token信息自身,从而产生了一个加强版 token,它包含所有token的信息,可以用来预测下一个token,这也就是为什么我们只关心它的原因。由前面潜空间内容可知,两个向量之间的相关性,我们可以用两个向量之间的点积来表示,如上图所示,我们将所有的token对应的词向量通过与三个不同的矩阵相乘,各自映射成三个向量:查询向量(Query),键向量(Key),值向量(Value),简称QKV,其中Q就是用来专门与其他向量作点积的向量,K就是用来专门被其他向量做点积的向量,V就是用来作加权求和的向量,比如「今天」「天气」「真」,针对 最后一个token「真」,它的Q就要与「今天」「天气」「真」的K对应相乘,得到的三个值就是各自的权重,权重再乘上对应的token的V,再依次相加,就得到了包含全部信息的新向量「真」, 如下图所示:以上就是注意力机制(attention),我们往往将它跟FFN前馈神经网络放在一起,合成一个新的层级,叫Transformer Block,同样地,它可以嵌套很多层。在实际的transformer架构中,一个词向量往往会对应多组QKV,每组的信息侧重点各不相同,将每组的QKV分别通过注意力机制处理后,得到的结果再进行汇总相加,这样得到的信息会更加全面预测的效果也会更好,我们将每组的QKV称为一个head,这就叫多头注意力(MHA),如下图所示:流程图更新下:位置编码如上图所示,「真」已经具有全部信息,但是在我们日常交流中,只有语义信息是不够的,比如我咬狗与狗咬我这两个句子,字相同,但表达的意思完全不同,因此为了保证信息正确,我们还需要每个token的位置信息,即它们各自在句子中的位置,这就是位置编码干的事情了。如上图所示,每个token对应一个位置向量,记录其位置信息,所有位置向量组成一个矩阵,这个矩阵就是位置编码。在现在大模型当中,计算注意力的时候都会添加上位置信息,以保证信息的完整。现代 大语言模型LLM 很多都是用 RoPE算法在 Q/K 向量上做旋转从而来得到或包含位置信息。残差连接与归一化如上文所说的那样,每层FFN前馈神经网络在输出结果前,基本都会经过残差连接和归一化,残差连接保证反向传播,归一化防止 参数对损失L的影响过大,保证系统稳定,同时在每一层计算token注意力时,也会有归一化,来保证所有计算出的权重在[0-1]之间。第 4 站预测下一个 token——算出概率分布预填充阶段(prefill)当用户向AI大模型发送一句话后,大模型会对这句话中的每一个token进行并行处理,计算它们各自的注意力,并送入神经网络中处理,然后将每一层的每个token的注意力计算产生的KV向量保存为KV Cache,供后续生成阶段复用,这个过程就是预填充阶段(prefill),也叫Prompt 处理阶段,它每轮对话只执行一次。在每一层计算每个token的注意力时,每个token只能看到它自己前面的内容,即在加权求和的时候,只加自己以及自己前面的内容,比如:「今天」「天气」「真」,在计算权重时,所有token相互之间都会计算,但是在加权求和时,我们会用mask隐藏后面内容,「天气」只能和「今天」相加,无法与「真」相加, 保证了token只能携带当前所有已知信息,不能预知未来。如何实现mask隐藏 其实就是将对应的token的权重换成了负无穷大-∞,当权重计算完毕后,进行归一化,exp(-∞)0,这样对应token最终的权重就变成0,实现了隐藏。推理生成阶段(Decode)每层的token的注意力计算完毕并保存为KV Cache后,取最后一个位置的向量,经过线性投影(Linear),投影到整个词表上,即输出一个词表大小维度的向量,向量上的每个位置都表示下一个token是该位置对应的词向量的分数(logits),这是神经网络的直接输出结果,该结果可读性不高,于是我们会使用归一化,将所有分数等比放缩到[0-1]之间,放缩过后,每个分数我们都可以将其看作是概率,并且它们的和变为了而这个将分数转换为概率的方法,我们将其称为softmax。以上这个利用最后一个位置的向量预测下一个token的过程就被称为推理生成阶段。如何从向量映射为词表每个位置的对应的分数? 其实很简单, 最后一个位置的向量包含了当前的所有信息,将其直接放入潜空间,看它与哪个向量距离最近,即点积最大,而这个点积结果就是分数(logits)。第 5 站采样——怎么从概率里选一个回到我们的最初的那个例子,如上图,将所有可能的token各自对应的概率算出来后,在众多概率当中,选择哪一个,这就是采样,而采样的策略有以下几种:贪心每次都直接选概率最高的token。这样做,会使得每次生成的内容固定,对于小说,诗歌的创作而言,缺乏发散性思维。温度(temperature)温度低更保守温度高更随机,其本质就是调整概率分布的平滑度,温度越低,各个候选token的概率差距就会越大,原来的高概率越高,原来的低概率越低,概率分布越尖锐,反之概率分布越平滑(温度的范围[0-2])。top-k按照概率分布,从大到小排序,只从前 k 个候选token里筛选,然后把这 k 个token的概率重新归一化再从中随机采样。top-p按概率从高到低排序从高到低累加概率直到累计概率达到或超过p为止,将入选的token重新归一化后采样。其特点就是 候选token数量不固定而是由概率质量决定会自适应分布。第 6 站循环——一个 token 接一个 token预测生成第一个token后,系统会将这个新token作为输入重新计算它的每层注意力,同时将它的计算结果也存入KV Cache中,结合前面KV Cache中保存的原来所有token的注意力对应的KV向量从而拿到一个新的包含全部信息的最后位置的向量,再次将其映射至词表上预测下一个token,如此循环。比如,当我们预测出「好」后, 生成并没有结束。模型会把今天天气真好重新作为输入继续预测下一个token,这个过程叫自回归生成,一次只生成一个token然后拼回去再生成下一个,理论上,每一次都要将所有token的注意力重新计算一遍但是在实际工程上,为了避免重复计算,我们引入了KV Cache,保存已经计算好的token注意力对应的向量,下一次要使用时,直接获取,无需重新计算。第 7 站训练——它学会接龙的关键如何获取 嵌入矩阵与QKV向量矩阵从前面的内容,我们可以看到,预测下一个token准不准,关键在于嵌入矩阵和QKV向量对应的矩阵的值,那么如何得到嵌入矩阵和QKV矩阵的值呢首先我们从嵌入矩阵讲起,即如何为词向量的每个维度定义对应的特征含义并给予相应的数字呢如果是人手动来一个一个定义,显然是不可能的因为一个词语的含义实在太丰富了。独热编码(one-hot)每一个词向量的维度就是整个词表的大小,即与词表的总行数大小一致,每个词只有一个位置是1,其余位置是0,这种编码方式就是独热编码(one-hot)。以上这种编码方式属于典型的苏式美学,力大砖飞。它的缺点如下:如果词表太大,就会导致词向量的维度太大。词向量之间的点积均为0,无法判断词语之间的语义关系。综上所述,独热编码(one-hot) out。遇事不决,神经网络既然 人工来定义词向量的每个维度 的特征含义 太麻烦,那么就干脆不定义了。直接给词向量的每个位置存放一个随机的数字,每个位置的具体特征含义不管,将整个词表拼接成一个矩阵,直接喂给 神经网络,让神经网络根据指定的任务进行训练,在训练中,自行调整每个词向量的每个位置的数字大小。至于最后每个位置具体的特征含义,那就只有天知道了,我们也不需要关心只要最后每个词向量能实现 潜空间的效果就行了。下图便是喂给神经网络的矩阵即嵌入矩阵(Embedding Matrix),矩阵里面的初始值都是随机的。如何训练我们准备大量的 文本,就拿我们前面的例子:今天天气真,文本被划分为三个token: 「今天」「天气」「真」选定「天气」为中间词,「今天」和 「真」 为上下文词,我们的目标就是让中间词与上下文词之间的点积 越大越好,同时 添加一些不相关的词,比如 「皇帝」和 「吃饭」,这些词语与中间词之间的点积 越小越好。最终在大量文本 训练后,这个喂给神经网络的矩阵就被训练好了。实际的训练中,中间词和上下文词各自单独一个矩阵神经网络调整中间词矩阵,将调整结果映射到上下文矩阵对应位置这就是Word2Vec训练方法。现代大模型预训练主要是预测下一个 token通过交叉熵损失函数来 训练嵌入矩阵embedding、Transformer和输出层中各自对应的参数。如上图所示这就是交叉熵损失函数的公式当模型预测的概率与真实的概率相差越近损失越小反之越大这个损失函数不仅能判断大模型预测的对不对还能判断大模型预测的好不好比如两个模型A对同一段内容预测的下一个token它们的答案都是好与正确答案一致但是模型给好的概率为模型给好的概率为很明显虽然预测结果一致但是模型预测得更好。如何检验训练效果?一个好的词表矩阵,在潜空间中,能够实现「皇帝」-「男性」 约等于「女皇」-「女性」QKV向量对应的矩阵如何产生?注意力计算的每个向量对应的QKV向量,前文说是原词向量通过与三个不同的矩阵相乘得到的,而这三个不同的矩阵与上文嵌入矩阵的获取方式一致,同样是先随机赋值,然后再通过神经网络的前向传播,反向传播和梯度下降,不断地调整每个位置的值,最终获得正确的QKV矩阵。预训练与自监督学习我们在训练大模型的时候,首先是获取到海量的文本数据,然后将这些文本中的句子错位拆分为两部分,一部分作为训练数据,一部分作为预测值,根据实际结果与预测值的差距来调整参数,包括FFN前馈神经网络的参数,QKV向量对应的矩阵的值,嵌入矩阵的值。如上图所示,这种只需要错位拆分,就能形成一次训练,让数据自己给自己当标准答案,这就叫自监督学习(Self-Supervised Learning),而这种通过海量文本数据训练,让大模型具备初步的语言和知识能力的阶段,叫作预训练(Pre-trained Learning),ChatGPT中的GPT就是Generative Pre-trained Transformer,翻译过来就是生成式预训练Transformer。后训练与监督微调预训练的大模型,一般是一个通才,什么都能干,但是在实际的工作中,我们并不需要大模型什么都会,反而我们需要它在指定领域内特别精通,即需要一个专才,为此,我们会对大模型进行后训练,通过向大模型投喂指定领域的大量数据 来进行训练,从而使得 大模型 在指定领域的能力更加突出,我们将这种 使用人工筛选过的数据对大模型进行二次训练的方式称为监督微调(Supervised Fine-Tuning),简称SFT。第 8 站: token漂流的结局一个token的奇幻漂流从今天天气真开始先被切成token再变成词向量进入Transformer开会算出概率被采样选中好最后拼成今天天气真好。然后下一个token的漂流马上又开始…………