身边依然有很多非技术的朋友 ,搞不清楚大语言模型是什么,以及它们究竟是怎么工作的 。
所以今天,尽量用通俗的语言 ,把一个现代大语言模型从你输入文字到它输出回答的整个过程,拆成一个一个具体的环节,讲清楚为什么需要它 ,它解决了什么问题,以及今天的主流模型在这个部件上做了哪些改进。听完这期,相信大家再去看任何一篇模型论文或者模型介绍,应该都能大致知道在讲模型的哪个部分。我们从头开始说 。
第一步:分词——将文字转换成模型能懂的整数你在对话框里敲了一句话 ,点下发送。模型拿到的第一个东西是什么呢?首先,它不会直接读你写的文字。你看到的是“今天天气怎么样”这七个汉字,但模型看到的是一串整数 。把文字转换成整数序列这个步骤 ,就叫分词,英文是Tokenization。
分词是通过一个叫分词器的程序进行的,它会接收你输入的字符串 ,输出一串数字,每个数字指向一个固定词表里的某个条目。现代大模型的词表通常有几万到几十万个条目不等。
听到这里你可能会问,为什么不直接用完整的单词做词表呢?这其实是个效率权衡的问题 。如果用整词词表 ,词表会变得特别大,而且遇到训练时没见过的新词,就完全没办法处理。那如果反过来 ,用单个字符做词表呢?这样词表确实小了,但模型就得从零开始学习最简单的拼写模式,计算效率极低。
于是,子词分词就相当于取了个中间值 。最常见的字符串片段成为单个token ,罕见词和新词就由更小的片段拼出来。比如说“tokenization ”这个词可能被切成“token”和“ization”两个部分,“running ”可能切成“run”和“ning”。
这个设计取舍会在你意想不到的地方暴露出来 。最经典的例子就是问大模型“strawberry这个单词里有几个字母R ”,早期的模型会经常答错。很多人第一次看到这个的时候会说:“你看 ,大模型连数数都不会。”其实这真不是模型不会数数,而是模型根本就不在字母层面操作 。它看到的只是token ID,而这些ID恰好拼出了一个人类会逐字母拆开的词。对模型来说 ,它处理的是几个子词单元,不是一个个独立的字母,所以数错R的个数再正常不过了。
不同的模型家族用不同的分词器 。GPT系列用的是字节对编码 ,也就是BPE的变体;LLaMA系列常用SentencePiece。分词器的选择会影响计算量,同样一句话分成更少的token就意味着更少的计算,也会影响多语言覆盖能力。但基本形态都是一样的:文本进去 ,整数出来。
第二步:嵌入——为数字赋予意义好了,现在你的提示词已经变成了一串整数 。但是一个像1024这样的token ID,本质上只是一个行号,它本身没有任何含义。赋予这些数字意义的 ,是一张巨大的查找表,叫做嵌入矩阵。
每个模型都有这么一张表,词表里每个条目对应一行 ,每行是一个长长的数字向量 。向量的长度就是模型的隐藏维度,在很多70亿参数级别的模型里,这个数字是4096 ,更大的模型会用更宽的向量。分词器把整数交给模型之后,模型就去嵌入矩阵里查出对应的那一行,之后所有的计算都用这个向量来做 ,不再用那个整数了。这个向量就是这个token的嵌入,也叫Embedding,是模型在海量文本训练过程中学到的 ,这个token意味着什么的内部表示 。
嵌入有个特别有意思的性质:语义相近的token最终会得到在空间中相近的向量。比方说,“国王”的向量靠近“女王”,“巴黎 ”的向量靠近“法国”。这些位置关系没有任何人硬编码进去,完全是模型在训练过程中自发涌现出来的 ,因为这样的几何结构有助于模型更好地预测下一个词 。更有意思的是,你甚至可以对这些嵌入向量做算术,有时候结果真的成立。最著名的例子就是“king”减去“man ”加上“woman” ,结果近似等于“queen”。嵌入空间的几何结构确实承载着真实的语义关系 。
第三步:位置编码——让模型知道词序但说到这里,我要特别提醒你一个很关键的缺口:嵌入只编码了这个token是什么,完全不知道这个token在序列里的位置。打个比方 ,“狗 ”这个字不管出现在你提示词的第一个位置还是第五个位置,它的嵌入向量是一模一样的。这显然是个大问题,因为词序决定意思。“狗咬人”和“人咬狗” ,词完全一样,但是意思天差地别 。这个缺口,就需要下一个部件来填补。
朴素的自注意力机制本身是没有内建的词序概念的 ,没有位置信号的话,模型根本没法直接知道“狗 ”在“咬”前面还是后面。2017年那篇经典的原始Transformer论文,也就是《Attention Is All You Need》,给出的解决方案是给每个位置分配一套独有的数字模式 ,直接加到那个位置token的嵌入上 。位置1是一种模式,位置5是另一种,位置100又是另一种。这些模式来自不同频率的正弦和余弦波。这样一来 ,“狗”在位置1和位置5的最终向量就不一样了 。当时选择正弦编码,有一部分原因是它理论上能外推到训练时没见过的序列长度。
但是这种加法式的位置方案,在模型规模变大之后暴露出两个问题。第一个问题是 ,嵌入向量得在同一组数字里同时承载语义信息和位置信息,容量是有限的 。第二个问题是,学习式的绝对位置嵌入泛化能力不干净 ,如果训练时最长只见过2048个token的提示词,那位置5000的嵌入就从来没有被正经学过。
所以现代模型大多改用了一种叫做旋转位置编码的方案,简称RoPE ,是苏剑林等人在2021年提出来的。现在LLaMA、Mistral 、Gemma、Qwen这些主流开放权重模型,用的全都是RoPE 。它的核心直觉很巧妙:不再往token向量里加位置信息,而是根据token的位置,把Query向量和Key向量旋转一个角度。位置1转一小下 ,位置100转一大圈。之后做注意力比较的时候,真正起作用的是两个token旋转角度的差值,这个差值恰好就编码了它们之间相隔多远。
RoPE的实际优势很明显:第一 ,它天然编码相对位置,这其实更接近注意力机制真正需要的东西;第二,它对长上下文的泛化能力更好;第三 ,它不增加任何新的参数 。
说到这里顺便提一个对大家写提示词很有用的观察。即便有了很好的位置编码,现代大语言模型仍然有一个被学术文献明确记录的现象,叫做中间迷失 ,也就是“lost in the middle ”问题。长提示词开头和结尾的信息被模型利用的可靠程度,远比埋在中间的信息高 。这就是为什么“重要上下文放前面、关键信息在结尾 、重复一遍”等等这类提示词工程技巧真的有用,因为模型并没有均匀地利用你提示词的每一个部分。
第四步:注意力机制——Token间的信息交换token的意义有了 ,位置信息也加上了,接下来就是整个架构最核心的部分,也是给Transformer命名的机制:注意力。
在每一个Transformer层里面,注意力只做一件事:让每个token去查看它被允许看到的其他token ,然后决定哪些token对预测接下来的内容是重要的 。它的实现方式是让每个token同时扮演三个角色,被变换成三个新的向量,分别叫做Query、Key和Value ,简称Q、K 、V。
你可以这么理解:Query是在问“我正在从其他token那里找什么”;Key是在答“我能提供什么给来找我的token”;Value携带的是匹配成功时真正被传递过去的信息。同一个token同时扮演全部三个角色,而Q、K、V的变换矩阵都是模型在训练中学出来的,所以模型会自己摸索出每个token该找什么、该提供什么 。
匹配是通过相似度打分来完成的。每个token的Query和它能看到的所有token的Key ,做一个缩放点积,直觉上就是衡量两个向量的对齐程度。缩放是为了让数值在进入下一步之前保持稳定 。然后用softmax函数把这些原始分数变成总和为1的权重,分数高的拿到大权重 ,分数低的拿到小权重。最后这些权重被用来对Value向量做加权平均。
举个例子,我们来看这句话:“The cat that I saw yesterday was sleeping ”(那只我昨天看到的猫正在睡觉)。模型处理到“was”这个词的时候,需要搞清楚到底是什么在睡觉 。“was”的Query和各个token的Key做比较 ,和“cat ”的点积很高,因为模型在训练中学到了“was”这类动词需要一个主语,而“cat”这类主语产生的Key向量恰好和它对得上;和“yesterday ”的点积就很低。经过softmax之后,“cat”拿到高权重 ,加权求和的时候“cat”的Value就主导了结果。于是“was ”这个词的新表示,主要就由“cat”的信息塑造了 。你看,隔了好几个位置的token ,就这样通过注意力机制完成了指代。
GPT这类自回归语言模型有一个特有的约束,它们是从左到右生成文本的。位置5的token只能注意位置1到5的token,绝对不能看6 、7、8 ,因为那些位置的token还没生成出来 。这就叫因果掩码。实现起来其实很简单,把未来token的匹配分数压到极低,经过softmax之后它们的权重实际就为零了。
注意力这部分还有一个特别有意思的研究发现 ,是Anthropic在2022年的可解释性研究中找到的,叫做归纳头,也就是induction heads 。这是一类特化的注意力头 ,它们学会了识别提示词中“A…B…A”这种形态的模式,然后预测B会接着出现。第二次看到A的时候,归纳头会回看A上次出现的位置,看它后面跟了什么 ,然后照抄下来。这是目前已知的上下文学习能力最清晰的机制之一,也就是模型为什么能从你的提示词里现学一个模式然后继续往下写 。
当然,注意力也有一个很现实的代价。在完整的注意力机制中 ,每个token要和所有可见token做比较。提示词长度翻倍的话,计算量大约要翻四倍。这就是为什么长提示词跑起来贵,也是FlashAttention、稀疏注意力 、线性注意力这些效率优化研究的根本动机 。
第五步:多头注意力——从多个视角理解语言单次注意力只能给模型一种“哪些token对哪些token重要 ”的判断方式 ,但这其实不够。语言里面有太多种关系在同时发生:主谓一致要管,代词和它们指代的名字要连起来,跨句子的长程引用要处理 ,词序和局部短语结构也要照顾。
多头注意力的解决办法就是并行跑很多次注意力,每个并行的通道就叫做一个头 。这里要专门纠正一个连很多教程都讲错的细节:每个头拿到的不是原始token向量的一个字面切片。不是说4096维的向量切成32块,每头拿128维 ,不是这样的。每个头有自己学出来的投影矩阵,把完整的token向量映射到属于它自己的更小的Q、K、V空间 。还是拿4096维 、32个头举例,每个头确实通常在128维空间里工作,但是这128个数字是对完整4096维的学习式投影 ,不是固定切块。你可以理解为是同一个token的不同视角,而不是不同碎块。
每个头独立跑完注意力之后,所有头的输出拼接起来 ,再过一个最终的线性层混合回完整尺寸的向量 。这个混合层也是学出来的。有意思的是,不同的头经常会发展出部分特化。没有人告诉每个头该干什么,这种特化完全是在训练过程中自然涌现的 。研究者已经发现过:有专门追踪语法关系的头 ,把动词连到宾语、把冠词连到名词;有专门分辨代词指代的头;有追踪位置模式的头;还有我们刚才提到的归纳头。一层可能有32个头,前沿模型有几十层,所以一个典型的大语言模型总共有几千个注意力头 ,各自贡献一种学到的视角。
说到多头注意力,就不得不提近年的一个重要架构变化——分组查询注意力,简称GQA。它是由实际成本问题推动的 。每个注意力头需要为所有已经生成的token保留Key向量和Value向量 ,这样生成新token的时候就不必从头重算一遍,这就是KV缓存,也是长上下文推理时最主要的内存开销来源。
现代decoder-only架构的大模型,大多用GQA作为变体。不是每个查询头都有自己独立的K/V ,而是多组查询头共享同一套键值头 。举个例子,LLaMA-2 70B有64个查询头,但只有8个KV头;Mistral 7B是32比8。这样做的效果是精度几乎不损失 ,但内存压力和推理成本能大幅下降。
第六步:前馈网络——Token的深度加工与知识存储注意力让token之间交换完信息之后,每一层其实还有第二个步骤 。它的讨论度远不如注意力,但是重要性一点都不低 ,这就是前馈网络,简称FFN。如果说注意力是token之间互相交谈、交换信息,那前馈网络就是每个token关起门来独自做深加工。它在每个token的向量上独立运行 ,不做任何跨token的混合 。
前馈网络按顺序做三件事:先把token向量扩张到更大的尺寸(原始transformer用的是4倍扩张,现代用SwiGLU的模型扩张比例各有不同),然后施加一个非线性函数 ,最后再压缩回原来的尺寸。
我们重点来说一下中间那个非线性步骤。非线性说白了就是把输入掰弯的函数,最简单的ReLU就是把所有负数归零 、正数原样通过 。为什么非要加非线性呢?因为没有它的话,前馈网络就只是两个线性层叠在一起,而纯线性运算的堆叠是会坍缩的。两个线性层在数学上等价于一个线性层 ,一百个叠上去也还是等价于一个。而非线性阻止了这种坍缩,这是前馈网络能做出比单次矩阵乘法更丰富计算的根本原因。
非线性函数本身也经历了几代演进 。原始transformer用的是ReLU,后来GPT和BERT换成了GELU ,再后来LLaMA、Mistral、PaLM这一代模型用的是SwiGLU。所以,“扩张再压缩”这个大结构一直没变,迭代的一直是中间的非线性函数。
这里有个很重要的事实很多人不知道:稠密Transformer的大部分参数其实是住在前馈网络里的 ,不在注意力里 。而且这些参数不是泛泛的数字,模型存储的事实和语义结构有相当一部分就在这里。研究者通过可解释性工作发现,前馈网络内部某些神经元和特定的概念或事实有强关联。有的神经元对“埃菲尔铁塔”相关的文本强烈激活 ,有的对“编程语言”,还有的对“过去式动词 ” 。模型知道“巴黎是法国的首都”这个事实,就表示在特定层的前馈网络权重和激活模式里。
前馈网络这种存储记忆的性质带来了一个很有趣的推论:你甚至可以不重新训练模型 ,直接编辑里面的某些事实。有一种叫做ROME的方法,也就是“秩一模型编辑”,能够通过对特定前馈网络权重矩阵做一次有针对性的低秩修改,把“埃菲尔铁塔在巴黎 ”改成“埃菲尔铁塔在罗马” 。改完之后模型生成的文本就真的会倾向于和编辑后的关联保持一致。当然这还是比较早期的研究 ,但至少说明我们对模型内部知识存储的理解已经到了可以动手编辑的程度。
第七步:混合专家模型——扩大规模的新范式最后我们说一下混合专家模型,也就是MoE 。一些现代前沿模型开始把稠密的前馈网络,换成多个并行的前馈网络 ,每个叫做一个“专家”,然后由一个很小的路由网络来决定每个token交给哪几个专家处理。以Mixtral 8x7B为例,每层有8个专家 ,每个token只激活其中2个。算下来总参数量是467亿,但是每个token实际只用到大约129亿参数。总参数量可以大幅上升,但每个token的计算量增长慢得多 。这就是在不让推理成本同比例膨胀的前提下 ,继续扩大参数规模的办法。当然MoE也带来了新的工程挑战,怎么在不同设备之间路由专家 、怎么保持训练稳定性都是问题,但它确实已经改变了前沿模型的设计思路。
第八步:残差流与层归一化——深层网络的稳定器讲完注意力和前馈网络 ,我们来说两个听起来不那么光鲜,但实际上至关重要的机械部件:残差流和层归一化 。没有这两个东西,极深的神经网络根本就训不动。
残差流这个机制的核心思想特别朴素,就是让模型做加法而不是做替换。注意力或者前馈网络跑完之后 ,它们的输出通常不会直接替换掉token原来的向量,而是加到原来的向量上面 。逐位置相加,新向量等于旧向量加上子块的输出。这样跨越三十层、五十层、甚至一百层 ,每层的贡献都是累加的,而不是覆盖的。这个运行过程中的累加和就叫残差流 。它有个很奇特的性质:最初的输入嵌入始终有一条直达深层的加法通路,和沿途每个子块的贡献混在一起。
残差连接不是为Transformer发明的 ,它来自2015年何恺明等人提出的残差网络ResNet,最初是用在图像识别上的。当时的动机很直接:因为深层网络根本训不动,训练信号反向传播穿过太多层之后 ,要么变得太弱要么太强,模型没法从自己的错误中学习 。于是,加一条捷径让信号能从输出层直接流回输入层 ,突然之间几百层的网络就能训了。Transformer只是继承了同一个技巧而已。
在现代可解释性研究里,残差流已经成为核心研究对象。你可以把整个模型想象成一条高速公路,每个组件(包括每个注意力头、每个前馈网络 、甚至最后把向量转成token概率的步骤)都从残差流里读取信息,再把处理后的结果写回残差流 。
第二个部件层归一化的存在理由就更实际了:没有它的话残差流会不稳定。数字流过几十次加法之后 ,倾向于要么数值爆炸,要么塌缩到零。两种情况训练都会失败 。层归一化在子块之间把每个token的向量拉回到受控的数值范围。
这里有两个演进值得记一下。一个是归一化的位置 。2017年原始transformer是在每个子块之后做归一化,叫post-norm ,浅模型没问题,模型深了就难训。而现代transformer从GPT-2开始,包括LLaMA、Mistral这些 ,普遍改在子块之前做归一化,叫pre-norm。这是让超深transformer变得好训的关键改动之一 。另一个是归一化函数本身。很多现代开放模型用的是更简单的RMSNorm。原始的层归一化做两件事:先把向量移向零点再缩放大小 。RMSNorm砍掉了移动这一步只留缩放,经验上缩放其实承担了大部分的收益 ,计算还更便宜。
这两个部件确实是整个架构里最不酷炫的部分,但是你要知道,没有残差连接 ,极深的模型几乎训不动;没有层归一化,数值会爆炸或塌缩。两者都有,才有今天我们看到的几十上百层深的大模型。
第九步:生成循环——如何逐词写出回答所有层的注意力和前馈网络处理结束之后,序列里每个token都有了一个最终的向量 。生成文本的时候 ,预测下一个词只取最后一个token的最终向量。这个向量会被转换成每个候选token一个分数的形式,词表有10万个token就有10万个数字。这些数字叫logits,它们还不是概率 ,可以是正数也可以是负数,大小没有限制 。然后还是用我们之前提过的softmax函数,把logits变成对下一个token的概率分布。
模型通常不会每次都死板地选概率最高的那个token。解码参数控制着输出的确定性和多样性 。温度参数(temperature)用来调整概率分布的尖锐程度:温度越高分布越平 ,输出越有创造性;温度越低分布越尖,输出越确定。top-k和top-p则是把候选token限制在最合理的范围内。这就是为什么同一个模型,在某些参数设置下显得特别精确严谨 ,换个设置又能写诗编故事更有创造性 。
选出一个token之后,它会被追加到输入的末尾,模型在更长的序列上跑下一步。这时候通常会复用KV缓存 ,不必从头重算整个前缀。新token、新的注意力计算 、新的前馈网络处理、新的最终向量、新的预测 。这个循环不断持续,直到模型吐出一个终止符或者撞到上下文长度上限。你看到的一整段回答,就是这个循环一次一个token跑出来的。
这里我要特别强调一个很多人忽略的事实:预测下一个token这个单一目标,就是基础大语言模型(base LLM)全部的训练信号。 基础模型没有被直接针对事实准确性 、对话能力、逻辑推理或者写代码来训练 ,它只是在海量文本上训练“给定前面的文字,预测下一个最可能的token ”这一件事 。你感受到的对话能力、遵循指令的能力 、偏好对齐、安全行为,这些全都是后训练阶段 ,在基础模型之上微调出来的,不是预训练阶段就有的。
说到生成循环,顺便提一个重要的效率创新 ,叫投机解码,也就是speculative decoding。它的思路很巧妙:用一个小而快的草稿模型先往前猜若干个token,然后大模型并行验证这些猜测 。猜中的、在大模型看来概率可接受的就直接采纳 ,猜错的地方就回退到大模型自己算。如果猜得准,最终输出的概率分布和单独跑大模型是完全一致的,但生成速度可以快很多。这也是现在很多推理服务在背后用的技术 。
总结:不同模型究竟差在哪里?走到这里 ,我们已经把一个大语言模型从输入到输出的整个流程走完了。最后我们回到一个很多人关心的问题:GPT 、Claude、Gemini、LLaMA,这些名字天天听到,它们到底差在哪?
说实话,公开的细节很有限 ,专有模型不会公布每一个架构选择。但我们大概知道,它们大体都坐落在同一个transformer家族的设计空间里 。包括分词、嵌入 、位置编码、堆叠的transformer层,每层都是多头注意力加前馈网络 ,然后是残差流、层归一化 、下一词预测循环。这些大的骨架都是共通的。
模型之间真正变化的是三样东西:第一是训练出来的权重本身,也就是在不同数据、不同规模配置下学出来的那些具体数字,这当然是最核心的差异;第二是配置选择 ,多少层、词表多大 、多少个注意力头、总参数量多少、用稠密架构还是MoE,这些工程选择差别很大;第三是后训练,怎么做指令微调 、怎么用人类反馈做对齐、安全控制做到什么程度 ,这些对最终用户体验影响极大 。
这里有一个很值得记住的观察:2023到2025年这一波现代transformer技术栈,其实在众多前沿模型和开放权重模型之间收敛到了一组共同选择。pre-norm的归一化位置、RMSNorm归一化函数 、RoPE旋转位置编码、SwiGLU激活函数、GQA分组查询注意力。最大的那些模型再加上MoE混合专家。有意思的是,这些选择不是某一家公司一次性发明出来的 ,而是不同团队各自独立走到了几乎相同的方案上 。这些东西是在2017年原始设计之上,经过大约五年的打磨逐渐累积下来的。
展望:Transformer的未来最后我们说说未来。其实围绕transformer家族的这种技术收敛,在机器学习历史上是挺反常的 。这个领域过去的常态是,每个问题有一种专门的网络结构 ,图像是一种,语言是一种,音频又是一种。做视觉的团队和做语言的团队几乎不共享方法。但是现在transformer式的模型横跨语言、视觉 、音频和各种多模态系统 ,吸收了这个领域的一大块研究力量 。
当然这种局面未来也可能改变。像Mamba这类状态空间模型就是一种很可信的替代方案,尤其在超长序列处理上有天然优势。各种混合架构也在探索中 。MoE其实已经改变了架构这个词在前沿语境下的含义,放在五年前还会被认为是一种相当异类的设计。但是 ,我们今天讲的这些核心机制——包括分词、嵌入、位置信息编码 、注意力式的信息交换、前馈网络式的深度处理、残差连接与归一化 、一步一步预测下一个token——这些都是耐久的部分。即便未来架构换代,这些也是任何序列模型都必须以某种形式解决的问题 。
结语:祛魅,才能更好地理解和运用讲完这一整圈下来 ,你可能会觉得好像也没有那么神秘。其实大语言模型也不是什么魔法,它就是一个一个工程部件堆叠起来的,每个部件解决一个具体问题 ,每个部件都经历了几代迭代改进。当然今天我们讲的是骨架层面的理解,真正的模型训练还有无数工程细节、数据清洗的技巧、对齐的学问,那些是另外的话题。但至少现在你再看到一篇新的模型论文,或者听到别人讨论某个新架构 ,你不会再觉得是在听天书 。你能大致知道他们改动的是哪个部件 、可能在解决什么问题。
本文来自作者[麴智越]投稿,不代表点新号立场,如若转载,请注明出处:https://sc-hx.cn/cshi/202609-11176.html
评论列表(3条)
我是点新号的签约作者“麴智越”
本文概览:非线性函数(非线性函数是什么意思)身边依然有很多非技术的朋友,搞不清楚大语言模型是什么,以及它们究竟是怎么工作的。所以今天,尽量用通俗的语言,把一个现代大语言模型从你输入文字到...
文章不错《非线性函数(非线性函数是什么意思)》内容很有帮助