LLM 到底在做什么

📅 2026/7/10 7:05:08 👁️ 阅读次数 📝 编程学习
LLM 到底在做什么

例如输入:

法国 的 首都 是
模型要预测:

巴黎
训练时,模型会不断看到类似样本:

输入:法国 的 首都 是
目标:巴黎
如果模型给“巴黎”的概率高,loss 就小;如果模型把“伦敦”预测得更高,loss 就大。训练过程就是不断调整参数,让正确 token 的概率越来越高。

整体流程可以画成这样:

输入文本

Tokenizer 切成 token

Token Embedding

多层 Transformer Blocks

最后位置 hidden state

输出层 W_out / LM Head

logits

softmax

下一个 token 概率分布

选择或采样 token

注意:模型内部不是直接处理汉字或单词,而是处理 token id 和高维向量。

  1. Token、Embedding 和 Hidden State
    一句话进入模型前,会先经过 tokenizer:

“法国的首都是” → [“法国”, “的”, “首都”, “是”]
每个 token 会被映射成一个向量,这一步叫 embedding:

法国 → [0.12, -0.08, 0.31, …]
的 → [0.03, 0.22, -0.11, …]
首都 → [0.44, -0.19, 0.07, …]
是 → [-0.21, 0.16, 0.28, …]
如果模型的 hidden size 是 4096,那么每个 token 就会对应一个 4096 维向量。

一开始的 embedding 只是比较基础的 token 表示。经过多层 Transformer 之后,每个 token 的向量会融合上下文,变成 hidden state。

例如最后一个 token “是”的 hidden state,经过多层加工后,可以粗略理解为:

h_last ≈ “当前上下文在问:法国的首都是哪个城市”
当然,模型里实际存的是高维数字向量,不是中文句子。中文解释只是帮助我们理解。

  1. Transformer Block 的整体结构
    LLM 通常不是只有一个 Transformer Block,而是很多层 Block 堆叠起来。

常见数量大致是:

小模型:6 - 12 层
中等模型:24 - 32 层
大模型:40 - 80 层
超大模型:80 层以上
例如:

GPT-2 small:12 层
GPT-2 medium:24 层
GPT-3 175B:96 层
LLaMA 7B:32 层
LLaMA 13B:40 层
LLaMA 65B:80 层
一个现代 Decoder-only Transformer Block 通常包含:

Norm
Self-Attention
Residual Add
Norm
MLP / FFN
Residual Add
图示如下:

输入 x

LayerNorm / RMSNorm

Self-Attention

残差相加 x + Attention(…)

LayerNorm / RMSNorm

MLP / FFN

残差相加 x’ + MLP(…)

输出 y,传给下一层

公式可以简化为:

x’ = x + SelfAttention(Norm(x))
y = x’ + MLP(Norm(x’))
其中 y 就是这一层 Block 的最终输出,会作为下一层 Block 的输入。

  1. 每一层的输出会作为下一层输入吗
    是的。

可以写成:

X0 = Embedding(tokens)
X1 = Block1(X0)
X2 = Block2(X1)
X3 = Block3(X2)

XN = BlockN(XN-1)
每一层都会拿上一层输出的 hidden states 作为输入,并重新计算自己的 Q、K、V:

第 1 层:Q1 = X0 Wq1, K1 = X0 Wk1, V1 = X0 Wv1
第 2 层:Q2 = X1 Wq2, K2 = X1 Wk2, V2 = X1 Wv2
第 3 层:Q3 = X2 Wq3, K3 = X2 Wk3, V3 = X2 Wv3
重点是:

每一层输入不同,每一层 Q/K/V 参数也不同,每一层都会重新做一次注意力计算。

低层可能更偏局部搭配、词法和位置;中层可能更偏语法和实体关系;高层可能更偏语义、任务意图和预测。这个说法只是直觉,不是人工规定。

  1. Self-Attention:让 token 理解上下文
    Self-Attention 要解决的问题是:

当前 token 应该重点关注上下文里的哪些 token?

例如:

小明 把 苹果 放进 书包 因为 它 太甜 了
“它太甜”里的“它”更可能指“苹果”,因为“甜”和“苹果”的语义关系更强。

如果句子变成:

小明 把 苹果 放进 书包 因为 它 太小 了
“它太小”更可能指“书包”,因为“太小”更像是在描述容器容量。

模型并不是写死规则,而是在大量训练中学到这些统计和语义关系。

  1. Q、K、V 到底是什么
    Q、K、V 分别是:

Q = Query,查询
K = Key,键 / 标签
V = Value,值 / 内容
一句话记:

Q:我想找什么?
K:我有什么标签,能不能被别人匹配到?
V:如果别人关注我,我能提供什么内容?
每个 token 都会同时生成 Q、K、V。

例如 token “它”:

Q(“它”) ≈ 我指代的是前面哪个东西?
前面的 token 有各自的 K:

K(“苹果”) ≈ 水果、物体、可被描述味道
K(“书包”) ≈ 容器、物体、可被描述大小和容量
如果后面出现“太甜”,那么“它”的 Q 会更匹配“苹果”的 K。模型就会更多读取“苹果”的 V。

如果后面出现“太小”,那么“它”的 Q 会更匹配“书包”的 K。模型就会更多读取“书包”的 V。

QKV 计算公式是:

Q = X Wq
K = X Wk
V = X Wv
注意力公式是:

Attention(Q, K, V) = softmax(QK^T / sqrt(d_k)) V
流程图:

输入 hidden states X

Q = X Wq

K = X Wk

V = X Wv

QK^T 计算相似度

除以 sqrt(d_k) 缩放

softmax 得到注意力权重

权重加权求和 V

融合上下文后的表示

为什么要除以 sqrt(d_k)?

因为维度较大时,Q 和 K 点积的数值可能很大,softmax 会变得过于尖锐,训练不稳定。除以 sqrt(d_k) 可以稳定数值范围。

  1. 用一个例子看模型如何理解上下文
    输入:

法国 的 首都 是
模型要预测下一个 token:

巴黎
在最后一个 token “是”的位置,模型可能需要关注:

法国
首都
可以粗略理解为:

Q(“是”):这个句子需要补充什么事实?
K(“法国”):国家实体
K(“首都”):需要城市答案
V(“法国”):法国相关语义信息
V(“首都”):首都关系相关信息
Attention 聚合之后,最后位置的 hidden state 逐渐包含:

国家 = 法国
关系 = 首都
答案类型 = 城市
最后输出层再把这个 hidden state 映射到词表,得到:

巴黎: 高分
伦敦: 低分
苹果: 极低分
这就是“理解上下文”和“预测下一个 token”之间的桥。

  1. Multi-Head Attention:从多个角度看上下文
    一个注意力头只能从一种子空间理解关系。多个头可以同时关注不同关系。

例如:

Head 1:关注语法关系
Head 2:关注实体关系
Head 3:关注指代关系
Head 4:关注位置关系
Multi-Head Attention 的直觉是:

让模型从多个角度同时理解上下文。

每个 head 都有自己的 Q/K/V 投影,最后多个 head 的结果会拼接或合并,再经过一个输出投影矩阵 Wo。

输入 X

Head 1 Attention

Head 2 Attention

Head 3 Attention

Head 4 Attention

Concat / 合并

输出投影 Wo

Attention 输出

  1. MLP / FFN:对信息做加工
    Self-Attention 更像“信息检索”:

当前 token 应该从哪些上下文 token 里拿信息?
MLP / FFN 更像“信息加工”:

拿到信息之后,如何进一步变换、提炼、组合?
MLP 和 FFN 在 Transformer 语境下基本可以认为是同一个模块:

MLP = Multi-Layer Perceptron,多层感知机
FFN = Feed-Forward Network,前馈神经网络
它通常对每个 token 的 hidden state 单独处理,不负责 token 之间互相通信。token 之间的信息交换主要发生在 Attention 里。

传统 FFN 结构:

hidden_size → intermediate_size → hidden_size
例如:

4096 → 11008 → 4096
公式:

FFN(x) = W2 * activation(W1 * x + b1) + b2
常见激活函数有:

GELU
SiLU
ReLU
SwiGLU
现代 LLM 常用 SwiGLU 一类门控结构,可以理解为:

哪些特征应该通过,哪些特征应该被抑制。
Attention 和 MLP 的区别可以这样记:

Attention:token mixing,不同 token 之间交换信息
MLP:channel mixing,同一个 token 向量的不同维度之间加工组合
一句话:

Attention 负责“看谁”,MLP 负责“想明白”。

  1. 残差相加是什么
    残差连接不是让一层完全替换输入,而是:

输出 = 原输入 + 本层新加工的信息
在 Attention 后:

x’ = x + Attention(Norm(x))
在 MLP 后:

y = x’ + MLP(Norm(x’))
直觉是:

新表示 = 旧理解 + 本层补充的新理解
这有几个好处:

保留原始信息
让每一层学习增量修改
缓解深层网络梯度传播困难
让模型在某层没学到有用东西时,也可以近似保持原样
你可能会问:处理后的向量会不会盖过原向量?

理论上会。如果 Attention(x) 或 MLP(x) 数值特别大,确实可能主导结果。但实际模型有机制控制:

LayerNorm / RMSNorm 稳定数值范围
参数初始化控制初始输出幅度
训练过程会惩罚不合适的过大修改
有些模型还会使用残差缩放、门控或 Dropout
所以残差连接不是简单粗暴地覆盖,而是让每层在旧表示上做可学习的增量修正。

  1. 输出层 W_out:从 hidden state 到 token 概率
    经过最后一层 Transformer 后,每个位置都有一个 hidden state。

对于自回归语言模型,预测下一个 token 时,通常使用最后一个位置的 hidden state:

h_last
例如输入:

法国 的 首都 是
最后位置“是”的 hidden state 可以理解为:

h_last ≈ “这个句子在问法国的首都是哪个城市”
输出层的任务是:

把 h_last 映射成整个词表上每个 token 的分数。

公式:

logits = h_last W_out + b
如果:

hidden_size = 4096
vocab_size = 50000
那么:

h_last shape = 4096
W_out shape = 4096 × 50000
logits shape = 50000
也就是说:

一个 4096 维向量
→ 输出层
→ 50000 个 token 的原始分数
这些原始分数叫 logits:

巴黎: 15.2
伦敦: 7.1
苹果: -2.5
的: 0.8
logits 还不是概率,需要经过 softmax:

P(token_i) = exp(logit_i) / sum(exp(logit_j))
得到:

巴黎: 0.86
伦敦: 0.04
柏林: 0.03
苹果: 0.000001
图示:

最后位置 hidden state h_last

线性输出层 W_out

logits:每个 token 的原始分数

softmax

概率分布

选择或采样下一个 token

输出层可以理解为:

当前 hidden state 和词表中每个 token 的“答案向量”做匹配。

很多模型会让输入 embedding 和输出层权重共享参数,这叫 weight tying。直觉上就是:

输入层:把 token 变成向量
输出层:把向量再匹配回 token
12. Wq/Wk/Wv 和 W_out 的关系