引言:一句话的旅程

打开GPT,和它说一句话:

我今天很开心

它通常会给出这样的回应:

听到你今天很开心,真是太好了!✨

有什么特别的事情让你这么高兴吗?愿意和我分享一下吗?

这看起来就像是它明白了“我今天很开心”是什么意思,并且自己做出了什么思考,居然试图进行有来有回的聊天一样。

但是真的如此吗?它真的理解了吗?恐怕并没有,至少不是人类意义上的理解。

那么,它又是怎么做到看上去就和理解了一样做出如此拟人化回应的呢?

这个问题的答案,藏在它接收到自然语言到给出回应之间,一条庞大、精密且明确的推理链路中:

输入文字 → 拆解成片段 → 编码成向量 → 模型内部的模式匹配 → 输出倾向性结果 → 拼接回应

就像 CPU 执行机器码时会经过取指、译码、执行、写回一样,LLM 也有自己的全链条『流水线』处理机制,分阶段地对自然语言进行处理,最终生成了这样看似『有理解』的回应。

接下来,我会逐步分析这条流水线的每个环节,揭开大语言模型表面上『理解』背后的精妙机制。

本系列以「溯源 • 铸理 • 笃行」为经,以语言模型的思与行为纬。

在心潮涌链中,我们追溯大语言模型一次推理的全貌,溯源每一枚符号如何在向量长河中激起涟漪。

在铸理为器中,我们将原理锻造为可复用的工程范式,让抽象的结构落成可触的模型。

至韵染流光,方法与感性交汇,构筑一个能够理解与生成色彩语言的智能体,让“比刚刚柔和一点”在数字世界中绽放。

语言的『碎片化』:从输入到Token,再到编号

我一开始以为AI技术真的开始让计算机理解我们说『今天心情很好』的时候是在表达什么,不然GPT系列怎么会那么强呢?

直到我了解到『ChatGPT』中的GPT是这么三个单词:Generative Pre-trained Transformer,生成式预训练变换器,我就明白事情远远没有那么理想化,我们还没有能力设计出真正能自我成长、主动学习、具备内在意图的自学习逻辑体——某种意义上,相较于制造生命,构建真正意义上的『自学习逻辑体』相当于制造灵魂,我们现在的大模型,或许可以叫做『数据驱动猜谜体』。

那种『理解』,其实只是『有大量前置信息的猜字谜』,只是算法从大量的数据中发现了某种规则,就像是..1 + 1 = 2,于是 10 + 10 = 20

这种规则让模型表现出看上去理解了的表面现象——但实际上,模型并没有理解 1 + 110 + 10背后的数学意义,只是它有一条规则:『1 + 1』之后大概率是一个『2』,仅此而已——当这种规则足够多,多到足以覆盖日常生活中的方方面面,模型就表现出了『人性化』。

目前来说,绝大多数(几乎所有)现代机器学习模型,都不能直接处理原始文本,必须先将自然语言转化为数值序列(如Token ID),才能进行后续计算。

所以,语言模型面对的第一个难题,就是把人类写的文本变成模型可以接受的、结构化的Token,再将Token映射为唯一编号(Token ID)。这个过程叫做Tokenization,也就是分片与编码。

什么是Token?

Token可以理解为『语言的最小可处理单元』,但具体是字、词、子词,甚至单个字符,取决于模型的设定任务和任务目标。

  • 汉语字粒度:"今天很开心" → ["今", "天", "很", "开", "心"]

    • 词表小,覆盖几乎所有文本,除开生僻字。

    • 粒度过细,无法直接理解的语言结构。

    • 小概率因为生僻词产生词表外新词问题(OOV,Out-Of-Vocabulary)。

  • 汉语词粒度:"今天很开心" → ["今天", "很", "开心"]

    • 更贴近语义,但词表极大,容易遇到生僻词组和新词,产生OOV问题。

  • 英语词粒度:"I am happy" → ["I", "am", "happy"]

    • 遇到新词、派生词(happy -> happiness,unhappiness)时词表迅速膨胀,容易OOV。

  • 子词粒度:"happiness" → ["hap", "pi", "ness"];"中华人民共和国" -> ["中华", "人民", "共和国"];"程序猿" → ["程序", "猿"]

    • 自动适应高频整体和低频组合,词表适中,兼顾泛化和效率,单词可被子词有效拼接,OOV少。

    • 英文为主,中文在多语种模型、专有名词等场景时也会用到。

  • 字符级:"happy" -> ["h", "a", "p", "p", "i", "n", "e", "s", "s"];"中华人民共和国" → ["中", "华", "人", "民", "共", "和", "国"]

    • 没有OOV,但粒度极细,缺乏语义表达能力。

    • 中文的更细粒度(拼音/笔画)极罕见,只在特殊任务下出现。

分词算法

综上,一般使用子词粒度,多用如下三种算法:

BPE(Byte Pair Encoding),子词合成的贪心法

  • 核心思想:

    • 一开始把所有文本拆成单个字符/或字。

    • 统计文本中最常见的相邻字符对,将其合并为一个新“子词”,合并时不考虑词义。

    • 不断重复这个“合并高频对”的过程,直到子词表达到预设大小为止。

  • 过程举例:

    • 文本:"happiness happiness happy"。

    • 初始拆分:["h", "a", "p", "p", "i", "n", "e", "s", ...]。

    • 找到频率最高的相邻对,比如"p"+"p",合并为"pp"。

    • 下一轮再合并"pp"+"i"成"ppi"。

    • 最后可能得到子词:["hap", "pi", "ness", "happy"]。

  • 优点:

    • 能自动学到高频词根、后缀、组合,灵活组合新词。

    • 子词表大小可控,易于实现。

  • 缺点:

    • 只能按贪心策略合并,合并顺序决定结果。

    • 子词切分不唯一,对不同文本表现可能有波动。

UnigramLM(Unigram Language Model),概率选择法

  • 核心思想:

    • 先预生成一个“大”子词表(可以随意拆分的所有子词组合)。

    • 认为每个子词在语料中出现是独立的(即“unigram”)。

    • 利用概率模型寻找最优子词切分方式,并逐步删去概率最低的子词,优化词表。

    • 最终留下一个覆盖率高、冗余低的子词表。

  • 过程举例:

    • 文本:"happiness happiness happy"。

    • 初始词表包括所有可能的子词组合,比如 "h", "ha", "hap", ..., "happiness"。

    • 用概率模型对文本做最大似然分解,计算每种子词切分方式的概率。

    • 逐步剔除低概率子词,反复优化,最终确定最佳子词集。

    • 得到的词表可能有["happiness", "happy", "ness", "ha", "p", "y"]等。

  • 优点:

    • 子词表更灵活、切分方式更丰富,效果常常优于 BPE。

    • 可以保留整体高频词和小粒度单位,更适合多语种或杂质文本。

  • 缺点:

    • 算法更复杂,实现和训练成本稍高。

WordPiece

  • 核心思想:

    • 目标和 BPE 类似:构建有限大小的子词表,能覆盖所有文本并支持组合新词。

    • 但它不是简单贪心合并高频对,而是每一步都选择能最大化训练数据似然概率的合并,优先合并让整体分词概率提升最大的子词对。

  • 过程举例:

    • 初始文本:"unhappiness happy"。

    • 拆成单字符序列:["u", "n", "h", "a", ...]。

    • 考察所有可能合并方式,评估每种合并对整体文本分词概率的提升。

    • 每一轮都选提升最大的一对合并为新子词,更新子词表。

    • 重复直到子词表大小满足预设,最终词表可能包含 ["un", "happiness", "happy", "ness"] 等。

  • 优点:

    • 子词切分方式更贴合整体语料统计概率,适合大语料训练。

    • 对英文等结构性强、变化多样的语言有很强泛化能力。

    • 在模型训练和推理阶段都能维持较高一致性,BERT/ERNIE 等主流模型采用。

  • 缺点:

    • 训练阶段算法复杂度高于 BPE(每轮需评估所有合并对的影响),性能略低。

    • 词表依赖训练语料的统计特征,换语料时迁移性略逊于 BPE。

    • 对极端小语料、新语种适配能力有限。

三种算法的选择

BPE

UnigramLM

WordPiece

性能消耗

快速、消耗低

中等~偏高

中等~偏高

分词效果

稳定、结果唯一

通常最佳

对主流英文表现极佳

灵活性/泛化

中等

极强

强,但依赖训练语料

主流应用

GPT、RoBERTa、LLama

mT5、XLNet、ALBERT

BERT、ERNIE、谷歌 NMT

Token的编号从何而来?

有了Token依然是不够的,它们依然是自然语言,需要转换成唯一编号(Token ID)才行:

  • 开心 -> 2458

  • happy -> 1237

模型无法基于"开心"和"happy"进行训练,但2458和1237可以。那么,如何给Token编号?

词表(Vocabulary):编号的基础

所有 Token 的编号都来源于一个预先构建好的词表(Vocabulary)。它是一个“编号字典”,记录了模型能识别的全部 Token 以及它们的对应编号,这也是OOV(Out-Of-Vocabulary)这个词组的来源。

Token

Token ID

开心

2458

天气

1593

happy

1237

today

472

词表通常是在模型训练阶段根据海量语料,通过预定的分词算法(BPE、Unigram)扫描所有出现过的Token,然后按照出现频率或概率设计规则,依次分配编号。常见做法是按出现频率排序,编号从0/1开始递增。

OOV 问题与特殊Token

  • 词表大小受限,无法覆盖所有人类语言。

  • 模型实际运行时,遇到新出现的、不在词表中的Token,会为其统一编码为特殊编号[UNK],unknown token)。

  • 还会有其他特殊Token[PAD](填充)[CLS](句子起始)[SEP](分隔符)[EOS](序列结束)等,预留专门的编号。

词表的生成

  • 确定词表内容

用选定的分词算法(BPE/Unigram/WordPiece)对大语料做一轮统计,确定所有 Token 的集合。

  • 预留特殊Token编号

通常会把 [PAD][UNK][CLS][SEP][EOS] 等特殊 Token 放在词表最前面,分配固定编号(一般是 0, 1, 2, ...)。

  • 依次为普通 Token 编号

剩下的 Token(无论多少),就简单地按某种规则依次编号(常见规则:按频率降序分配(高频词优先获取短编号以提升压缩效率),或者直接按扫描顺序分配)。

0: [PAD]

1: [UNK]

2: [CLS]

3: 开心

4: 天气

5: 很

6: 好

7: happy

8: today

...

实际应用

对于输入文本,分词器(tokenizer)会依次查表,把每个Token替换成词表里的编号,形成一串Token ID,作为模型输入。

比如:

「今天天气很好」→ ["今天", "天气", "很", "好"] → [345, 1593, 876, 442]

小结

Token编号的本质就是把所有语言碎片“哈希”到一个有限空间,查表和唯一性保证了文本片段能在数字世界中有明确归属。

这一步不是理解,而是数据格式的统一——只有编号后的 Token,才真正进入了 LLM 的认知流程。

在实际的 NLP 项目开发中,分词与编号几乎不会手动实现,也不需要为每个 Token 自己编 ID。整个过程通常由分词器(Tokenizer)工具自动完成,比如SentencePiece,它是一种被广泛采用的分词工具,能自动完成切分、编号和词表生成。它支持上面提到的BPE和UnigramLM,依据实际情况选择即可。至于WordPiece,使用HuggingFace的BertTokenizer

向量化:用数字表达文字的『距离』

现在,自然语言已经变成了Token ID的序列...但这还不够。

用一个只处理红绿灯的模型举例,它支持三个Token:

  • 红灯:0

  • 黄灯:1

  • 绿灯:2

那么模型看到的只是单纯的数字,0、1、2本身没有任何语义上的联系,它们只是唯一标识,即使在数学上“红灯”和“黄灯”的差值是1,和“绿灯”的差值是2,这也不能代表“红灯”与“黄灯”更接近,与“绿灯”更远——这不能说明它们之间有任何距离相关性。

这当然远远不够,我们需要模型能够“感觉”到不同符号之间的某种关系——“红灯”和“黄灯”都是代表要停下或者小心的信号,“绿灯”则意味着前进,单纯的编号做不到表达这种“相似”或“相反”的关系。

于是,就需要向量化——三个普通的数字没有联系,但如果把它们转化成空间中的向量,它们之间就有了方向、距离、夹角等概念:

  • 红灯:[1, 0, 0]

  • 黄灯:[0, 1, 0]

  • 绿灯:[0, 0, 1]

当然,这只是最简单的向量化——one-hot编码,每个Token都是一个正交方向。真实模型中的向量化过程(embedding/词嵌入)要复杂得多,通过分词算法(BPE/UnigramLM/WordPiece等)与模型训练,这些向量不再是规整的[1,0,0]或[0,1,0],而是“看上去乱糟糟的点”:

  • 红灯:[0.95, 0.05, 0.90]

  • 黄灯:[0.80, 0.20, 0.85]

  • 绿灯:[0.10, 0.95, 0.85]

这个让向量方向不再正交,可以表达相似关系的过程,就是词嵌入,embedding——当然,词嵌入并不是真的让向量变得乱七八糟,它们是有确切含义的。

想象一个三维坐标系,将每个token的向量看作坐标值,就能得到三个箭头——如此,这三个Token就已经不仅仅是一个数字,它们变成了在空间中具有方向距离的向量,模型可以用它们做加法、减法、算夹角等操作,来描述“谁和谁更像”。

通过训练,模型可能会让“红灯”和“黄灯”的向量距离较近,而“绿灯”距离较远,用来表达它们“语义上更像”的感觉。

语义相似度通常用余弦相似度衡量

// 点积

R·Y = Σ(R_i × Y_i)

// R模长

||R|| = √(ΣR_i²)

// Y模长

||Y|| = √(ΣY_i²)

// RY相似度

sim(R,Y) = (R·Y) / (||R|| × ||Y||)

实际计算流程

||R|| = √(0.95² + 0.05² + 0.90²) = √(0.9025 + 0.0025 + 0.81) = √1.715 ≈ 1.31

||Y|| = √(0.80² + 0.20² + 0.85²) = √(0.64 + 0.04 + 0.7225) = √1.4025 ≈ 1.184

||G|| = √(0.10² + 0.95² + 0.85²) = √(0.01 + 0.9025 + 0.7225) = √1.635 ≈ 1.279

R-Y相似度:

R·Y = (0.95×0.80) + (0.05×0.20) + (0.90×0.85) = 0.76 + 0.01 + 0.765 = 1.535

sim(R,Y) = 1.535 / (1.31 × 1.184) = 1.535 / 1.55104 = 0.99

R-G相似度:

R·G = (0.95×0.10) + (0.05×0.95) + (0.90×0.85) = 0.095 + 0.0475 + 0.765 ≈ 0.9075

sim(R,G) = 0.9075 / (1.31 × 1.279) = 0.9075 / 1.67549 ≈ 0.542

在现实的大模型里,词表常常有几万个甚至数十万Token,每个Token是几百维上万维的向量,它们构成了一个“超高维空间里的语义地图”

这样的高维空间中,模型甚至可以学会复杂的语义结构。

glove-wiki-gigaword-50为例:

  • 找到与『塔』相似的向量,你会发现它们都有某种在概念上接近『塔』的感觉

from gensim import downloader

model = downloader.load("glove-wiki-gigaword-50")

for word, rate in model.most_similar("tower"):

print(f"{rate:.10f}", word)

执行结果

0.8770956397 towers

0.7934194803 gate

0.7872829437 building

0.7803677320 built

0.7780845761 roof

0.7487501502 skyscraper

0.7471459508 constructed

0.7415344119 dome

0.7309735417 facade

0.7280209661 entrance
  • 『国王 - 男 + 女 ≈ 皇后』,于是可以说模型认为国王和皇后的差异类似于男和女,模型在高维空间里自然形成了“性别”这个方向——方向会影响一个token本身的含义

from gensim import downloader

model = downloader.load("glove-wiki-gigaword-50")

for word, rate in model.most_similar(positive=["king", "woman"], negative=["man"]):

print(f"{rate:.10f}", word)

执行结果

0.8523604274 queen

0.7664334178 throne

0.7592144012 prince

0.7473883629 daughter

0.7460220456 elizabeth

0.7424569130 princess

0.7337412238 kingdom

0.7214490771 monarch

0.7184862494 eldest

0.7099431157 widow

需要注意的是:

  • 这种相似和加减的结果,并非模型“设计”出来的功能,而是通过大量文本训练后,词向量在高维空间中自发地组织出了这些方向性关系。

  • glove是一个静态向量模型,其中的向量在训练完成后就不会再变化,这和会在预测中基于上下文动态更新向量值的GPT式模型完全不同,但无伤大雅——此处用它只为了方便演示『高维空间中通过方向表示语义』这个概念。

  • 静态向量模型与GPT式模型的区别不止是向量值的动态变化这么简单,在这种变化下,模型可以存储类似『Michael Jordan -> 蓝球』这样的数据——我们可以说,模型记住了知识。

这样,原本单调的编号被赋予了空间上的方向和距离,模型才能以几何方式模拟“理解”自然语言,为后续所有推理和生成打下基础。

在语言模型的眼中,一句话不是由“词”或“字”组成的,而是由一串嵌入在高维空间中的向量构成的轨迹。每个 token 都被编码为一个向量,而整个句子,就是这些向量在空间中首尾相连所勾勒出的一段路径。

所谓“预测下一个 token”,本质上就像是观察这条轨迹的走势,判断它的下一笔应该延伸向哪个方向。模型并不会孤立地看每一个 token,而是从整体上捕捉路径的形状、弯折与节奏,从而决定最可能接下来的那一“步”该落在何处,这个“落点”对应的就是下一个向量——也就是下一个 token。

接下来,我们进入模型的核心结构部分——Transformer,它将承担预测这条“轨迹走势”的全部任务。

模型的内部机制:Transformer 如何进行『思考』?

经历了碎片化与向量化,输入文本此时已变成一串高维向量,就像一组未经打磨的原料,将被送入一条多层级的语义加工流水线——Transformer。

Transformer 并不只是“变换器”,它更像是一种可微分的语言分析工坊:每一层都尝试重新理解输入向量的含义,提取其中的搭配、结构与抽象意图。模型通过层层递进的建模过程,将原始输入从“表层形式”转化为“结构化语义”。这些处理不是靠单一规则完成的,而是依赖多个功能模块的协同运作。最核心的,是每层内部交替运作的两大结构单元:“QKV注意力机制”与“前馈神经网络”。

它的每一层既是语言感知器,又是语义构造器,最终塑造出模型所谓的“理解”。

向量矩阵:模型思考的操作基础

Transformer 之所以能处理语言,是因为它将语言转化为一种结构可操作的形式——向量矩阵。

训练过程中,模型通过优化自身的参数矩阵(权重),学习如何将输入的向量序列转化为具有语义结构的输出。这些参数矩阵可以被视为模型的“大脑”,定义了它的所有行为模式,每一步运算几乎都可以归结为:

输入向量 × 权重矩阵 → 非线性映射 → 新表示

向量空间使模型得以在数学上操作语言,参数矩阵则定义了这种操作的“风格”与“偏好”。

向量是语言的数值形式,矩阵是思维的操作单元。

就像人通过语法规则组织语言,模型通过参数矩阵操纵向量序列——它遵循的不是显式语法,而是训练中形成的『数值偏好模式』。

解剖:一层 Transformer 的结构剖面图

从更抽象的角度看,Transformer 每一层的运作可以被视为一次『语义感知 → 表达构造』的复合过程:模型先通过 QKV 注意力机制提出“问题”、查询上下文;再通过前馈神经网络结合上下文与自身参数权重生成回应。这个过程不仅建立了上下文关联,也逐步形成对语言内容的内部理解。

进一步来看,这一过程也可以被视作一次神经结构化的“问答”:模型提出问题、查找相关内容、整合答案,再进行表达。

提问(Query) → 检索(Key) → 加权取值(Value) → 响应构造(MLP)

这个流程本质上构成了模型在一层中完成的一次『问题提出—信息整合—语义生成』的内部闭环。

一层标准的 Transformer 可以拆解为如下结构:

输入向量序列

↓

[ Multi-head Attention ]

↓

+ 残差连接(Residual) → LayerNorm

↓

[ Feedforward MLP ]

↓

+ 残差连接(Residual) → LayerNorm

↓

输出向量序列

每一层中都包含两个关键模块:

  • 注意力机制(Multi-head Attention):负责感知输入中各个 token 之间的依赖关系,是模型构建上下文理解的核心结构。

  • 前馈神经网络(Feedforward MLP):将注意力聚焦后的语义信息进一步加工、扩展,构造出更丰富的中间表征。

除此之外,还有两个结构性组件扮演着“理解维稳器”的角色:残差连接(Residual Connection)层归一化(Layer Normalization)

残差连接的作用,是保留前一层的输出并与当前模块的结果融合,避免信息被完全覆盖。它就像一条“语义快车道”,确保原有的语言表达在理解深化过程中不被丢弃。

层归一化则用于控制各 token 表示在数值层面的稳定性,避免因多层叠加造成的表达漂移。可以理解为一种“表达温度调节器”,确保不同 token 的表示仍在相对可比的区间中。

这两个模块虽然不参与语义内容的建构,但它们让 Transformer 能够稳定地深化语言理解。

每一层也不是简单的重复,而是在理解层级上不断升维:从局部片段的识别,到结构关系的捕捉,最终抽象出语义意图

从宏观上看,每一层都在重复一个过程:

聚焦 → 转换 → 传递

最终形成对语义的逐层建模与递进理解。

正是注意力机制与 MLP 的协同作用,让模型在没有规则、标签的前提下,得以构建出形式语言之外的表达能力。

下面我们分别拆解这两大核心模块的内部机制与认知作用:

注意力机制(Multi-head Attention):谁在关注谁?

注意力机制的核心任务是回答一个问题:“当前 token 应该关注上下文中的哪些部分?”

这不是一个固定规则,而是通过三个关键向量的动态计算完成的:

  • Query(查询向量):表示当前 token 想了解什么。

  • Key(键向量):表示每个 token 能提供哪些信息。

  • Value(值向量):表示每个 token 提供的实际内容。

每个输入向量都会被映射为一个三元组(Q, K, V)。模型通过计算 Query 与每个 Key 之间的相似度(点积 → softmax),得到一组权重,进而对 Value 做加权求和,构造出当前 token 的新表示。

然而,这样的一次注意力操作,其实只是在一个特定的理解视角下对上下文进行处理。比如,它可能只关注了句子的主谓宾结构,却忽略了某个词与前文中另一个词之间常见搭配的语义关系。

为了让模型从多个角度理解同一文本,还需要进一步的机制。

在一个注意力头中,Query、Key、Value 都是在特定映射规则下生成的表示,它们只能从某种视角出发去理解 token 之间的关系。例如,它可能更擅长识别搭配模式,却不敏感于语法结构或情感语气。这种单一视角的局限,使得注意力机制需要被扩展为多头结构,以获得更全面的语义覆盖。

因此,Transformer 引入了多头注意力机制(Multi-head Attention):它在多个语义视角中平行地执行注意力操作,每一个头都从不同的角度建模 token 之间的依赖关系。

这些头彼此独立,但最终会将各自的注意力输出拼接在一起,再统一投影为一个新的表示,从而融合多个视角的信息。正是这种机制,让模型能够在同一时刻从多个语义视角并行理解上下文,极大增强了它对复杂语言结构的建模能力。

每个 token 都在多个“理解视角”下,同时向上下文发起并行的语义查询。每个注意力头代表一个独立的视角:一个可能偏向语法结构,一个更关注常用搭配,另一个则擅长情绪色彩。它们各自使用 Query 与上下文中的 Key 进行匹配,从不同角度提取出对应的 Value 信息。最终,这些多视角下聚合出的内容被整合为当前 token 的综合语义理解。

前馈神经网络(Feedforward MLP):构造新的意义空间

在完成注意力计算之后,每个 token 拥有了与上下文整合后的表示,但这只是“感知”阶段。

接下来,模型需要对这些信息进行表达构造——这就是 Feedforward MLP 的任务。它不仅负责对注意力机制的输出进行非线性变换和重构,也在一定程度上扮演着模型的『知识存储器』角色。

Transformer 并没有传统意义上的显式知识库,它的知识是“隐含”在参数权重中的,而 MLP 正是承载这种知识的关键结构之一。我们可以粗略地将注意力机制视为“检索器”,而 MLP 则像“知识库响应器”:当前 token 的语义表示被投射进 MLP 的参数空间,模型根据内在的权重分布生成响应。这些响应不是对外部事实的直接检索,而是对模型经验模式的一种重构——一种隐式、权重驱动的“回应”。

换言之,MLP 的前向传播本质上是一种“向量激活→事实投影”的过程,它将 token 的上下文表示映射到模型所学习到的“语义经验空间”中,形成语义上合适的输出。

它的结构通常是:

线性投影 → 激活函数(GELU) → 线性投影

现代 Transformer 中常使用 GELU(Gaussian Error Linear Unit) 作为激活函数,但早期模型如原始论文则使用了更简单的 ReLU。这两者的核心区别在于:ReLU 是分段线性,而 GELU 是光滑非线性,能够提供更细腻的表达拟合能力。

这一过程就像把感知到的模糊印象,投射到一个新的空间中,生成可以被后续层理解和使用的语义表示。

MLP 的参数定义了模型在处理语义时的“表达风格”与“结构假设”,也让模型具备了对抽象概念的拟合能力。

在整个 Transformer 中,这两个模块不断交替出现,在每一层中构建出更高阶、更抽象、更语义化的中间表示。

从整体视角看,Transformer 的“思考”并不是一次跳跃式的理解,而是由注意力与表达模块交替驱动、层层递进的语义构建过程。它不是在『记住』某些规则,而是在不断『重构』理解本身。

从 logits 到输出:模型如何做出决策?

Transformer 完成内部表征计算之后,接下来的任务是:如何根据这些结果,从词表中选取一个 token,并将其转化为具体的文本输出。

logits:模型对所有词的『偏好打分』

所谓 logits,是语言模型在 decoder 的最后一步中,为当前输出位置生成的一个实数向量,其长度等于整个词表的大小。这个向量中的每个数值,表示模型对对应 token 的“原始偏好”。

需要注意的是:

  • logits 并不是真正的概率,它们可以为负,甚至分布非常不均匀;

  • 绝对值没有语义,只有相对大小才有意义;

  • 它本质上是“语言模型对各个 token 给出的打分”,但这个打分尚未经过归一化。

logits 就像老师在内心对每个学生的印象分:没有标准,也不一定合理,只是个人偏好。但这份偏好是下一步决策的基础。

softmax:将偏好映射为概率

语言模型不能直接依赖 logits 生成词语——它需要将这些“印象分”进一步转换为可以参与下一步选择的结构:概率分布。这一过程由 softmax 完成。

softmax 是一种指数归一化函数,定义为:

softmax(z_i)=\frac {e^{z_i}} {\Sigma_j e^{z_j}}

它有两个关键特性:

  1. 归一化:将所有 logits 转换为 0\~1 之间的概率,并保证总和为 1;

  2. 指数放大:越大的值,其结果增长越快,从而进一步强化偏好之间的差异。

结果是,softmax 会显著突出模型“最自信的几个选项”,而将其余的大量 token 压缩为极小概率。这种决策聚焦性是 softmax 相比其他归一化方式最重要的特征。

softmax 就像老师的印象分转换系统,它会将原本没有明确排序标准的主观打分,转化为一组可排序、可用于排名决策的数值。原始印象越强烈、差异越大,最终排名就越倾向于集中在少数几个学生身上。

熵:模型『犹豫』程度的度量

softmax 得到的是一个概率分布,但这个分布本身也可以被进一步分析。其中最核心的统计量之一就是:熵(Entropy)

熵衡量的是概率分布的『不确定性』程度,定义为:

Entropy(p) = - \sum^n_{i=1} p_i \cdot log p_i

如何解读熵的数值变化:

  • 如果概率高度集中(例如一个 token 占 90% 以上),熵很低 → 表示模型对该位置“信心十足”;

  • 如果概率较为平均(多个 token 拥有接近概率),熵很高 → 表示模型在该位置“难以决断”或“倾向模糊”;

模型在回答“你好吗?”这种句型时,几乎总是选 "fine" 或 "good",此时概率高度集中,熵极低。 而在回答“未来人类会走向___”时,可能出现 "繁荣"、"毁灭"、"星际旅行" 等选项,每个都不低但也不确定,此时熵偏高。

熵不会告诉我们“选项对不对”,但它能告诉我们:模型在这个位置上,判断是否明确、有无偏向

这使熵在以下场景中极具价值:

  • 判断模型当前输出的开放度(创意 vs 稳定性);

  • 拒答机制(不确定时选择放弃回答);

  • 可解释性评估(生成是否存在“含糊段”)。

温度机制:调节模型的『确定性』

softmax 的行为可以通过一个称为 温度(temperature) 的参数进行调节,其作用是在应用 softmax 之前,对 logits 进行缩放处理:

softmax(z_i)=\frac {e^{z_i / T}} {\Sigma_j e^{z_j / T}}

温度控制的是softmax 分布的陡峭程度,即模型输出的“决断力”:

  • T < 1,分布变得更尖锐,高 logits 对应的 token 被赋予更高概率

  • T > 1,分布变得更平缓,所有词的概率趋于接近

  • T \rightarrow \infty 时,softmax 退化为均匀分布;

  • T \rightarrow 0 时,softmax 近似为 argmax(确定性输出)。

因此,温度是控制“确定性 vs 多样性”的主要手段。

温度就像“打分人心态的冷静程度”:越冷静(低温),越果断倾向于只关注印象最深的学生;越浮躁(高温),越缺乏明确倾向,几乎所有学生都有可能被考虑。

采样策略:如何从概率中选出最终答案?

在 softmax 得出一组概率分布后,模型需要据此选取一个 token 作为输出。这一选择过程并非唯一固定,不同的策略会对生成的风格与稳定性产生显著影响:

argmax:最确定的选择

  • 直接选取概率最高的那个 token;

  • 结果确定性强,但容易陷入重复或“机械化”语言风格;

  • 常用于问答、摘要等追求稳定输出的场景。

随机采样(sampling):多样性的来源

  • 按照概率分布进行抽样,每次输出可能不同;

  • 搭配合适温度,可以生成风格各异、富有创意的文本;

  • 适用于小说、诗歌、对话等生成任务。

top-k & top-p:控制多样性的边界

  • top-k:从概率排名前 K 的 token 中采样,忽略尾部不可能的词;

  • top-p(nucleus sampling):从概率排序后的 token 列表中,选取累计概率总和刚好达到或略高于 P 的最小子集,然后在该子集中进行采样,从而自适应地控制采样范围;

两者都在减少模型“胡说”的概率同时,保留一定自由度,这些策略决定了模型在既定偏好基础上,进行探索的自由度边界。

策略

输出稳定性

多样性

适用场景

argmax

问答、摘要

sampling

中等

创意生成

top-k

中等可控

泛用

top-p

中高

高但边界可控

对话/剧情

如果 softmax 是评分系统,那这些采样策略就是录取规则:只录最高分(argmax)、按概率抽签(sampling)、只抽前几名中运气好的(top-k)、只在总概率占比足够的前段区域内选人(top-p)。

最后一跳:从 token id 到自然语言

无论使用哪种采样方式,最终模型都会选定一个 token id。接下来,就只剩下最后一步——将这个 id 转换为对应的文字

这一步称为 解码(decode),其实就是查表操作:将 token id 映射回其对应的字符串。

例如:

  • id 0 → ``(特殊终止符)

  • id 1437 → "开"

  • id 28190 → "ing"

多个 token 拼接在一起,就构成了最终输出的文本片段。模型将不断重复这一生成过程,直到满足终止条件,例如:

  • 生成了特定的 终止符(EOS token)

  • 达到了最大生成长度(如 512 个 token);

  • 由外部控制逻辑中止生成。

从这个角度看,生成文本其实就是:一个 token 一个 token 地拼出一个句子的雏形。

小结:输出不是一步完成,而是逐步生成的旅程

从 logits 到 softmax、再到采样策略与解码,语言模型的每一次输出都不是一次性的“直接翻译”,而是一次多轮决策、逐步生成的过程。

我们不仅要理解模型如何计算每一步的偏好,还需要理解它在生成时如何作出选择、如何控制风格、以及最终如何停下来。

总结:从输入到输出的一条完整链路

回顾整条推理流程,从用户输入一句话开始,语言模型要经历如下关键环节:

  1. Tokenization:碎片化语言 → 将文本拆解为模型识别的最小单位(token)并编号;

  2. Embedding:映射向量空间 → 将 token id 转化为模型可处理的高维向量表示;

  3. Transformer:捕捉结构与语义 → 利用注意力机制在上下文中建构每个位置的动态表示;

  4. Logits 计算:给出偏好打分 → 对每个可能的下一个 token,生成一个打分向量;

  5. Softmax 归一化:形成概率分布 → 将打分转为概率,突显偏好集中度;

  6. 熵评估 & 温度调节:判断与调控生成开放度 → 评估当前位置的不确定性,并据此决定探索范围;

  7. 采样策略:选取输出 token → 依据策略(如 argmax、sampling、top-k/p)从概率中选择输出;

  8. 解码为文本:生成自然语言 → 将 token id 映射回字符,逐个拼接形成最终输出。

这个流程不仅体现了模型推理的每一个微观决策点,也展示了语言模型如何在结构、概率与选择中完成一次完整的语言生成。

理解这条链路,有助于我们:

  • 更好地分析模型行为背后的逻辑与“判断依据”;

  • 针对特定场景选择合适的输出策略与温度设置;

  • 为后续微调、自定义模型或自构系统打下坚实基础。

语言模型未必理解语言,但我们可以理解模型如何走向理解。只有当我们掌握它思考的路径,我们才能引导它走向我们的目标。