从数学和矩阵运算的底层逻辑来透视 仅解码器 Transformer (Decoder-only Transformer) 预填充阶段的全过程

LLaMA、Mistral 和 GPT 等生成式大模型,全部采用的是 Decoder-only Transformer 架构 。理解它,就是理解至当今所有大模型的基础。

数据在这个架构中完成一次"前向传播"(也就是生成一个词的过程),需要经过以下极其严密的流水线。我们将按顺序一步步推导:

1. 词的向量化表示 (Embedding & Positional Encoding)

计算机无法直接处理文字,必须将其转化为数字矩阵。

  • 词嵌入 (Word Embedding)
    假设你输入了一个长度为 S S S 的句子(比如 "我 爱 学习")。首先通过分词器(Tokenizer)将它们变成索引号,然后查表,映射成稠密向量。
    此时,输入数据变成了一个矩阵 X ∈ R S × d m o d e l X \in \mathbb{R}^{S \times d_{model}} X∈RS×dmodel。其中 S S S 是序列长度(Token 数量), d m o d e l d_{model} dmodel 是模型的隐藏层维度(比如 LLaMA-7B 中通常是 4096)。
  • 位置编码 (Positional Encoding)
    由于后续的矩阵乘法是"全连接"的,它本身不具备感知词语先后顺序的能力。因此,必须将位置信息 P E ∈ R S × d m o d e l PE \in \mathbb{R}^{S \times d_{model}} PE∈RS×dmodel 叠加到词向量上。
    X i n p u t = X + P E X_{input} = X + PE Xinput=X+PE

2. 线性投影生成 Q、K、V (QKV Project)

进入 Decoder 层后,输入矩阵 X X X 会与三个不同的权重矩阵相乘:

  • 权重矩阵 :模型在训练阶段学到了三个参数矩阵 W Q , W K , W V ∈ R d m o d e l × d k W_Q, W_K, W_V \in \mathbb{R}^{d_{model} \times d_k} WQ,WK,WV∈Rdmodel×dk。
  • 线性变换
    Q = X ⋅ W Q Q = X \cdot W_Q Q=X⋅WQ
    K = X ⋅ W K K = X \cdot W_K K=X⋅WK
    V = X ⋅ W V V = X \cdot W_V V=X⋅WV
    此时,我们得到了查询矩阵(Query, Q Q Q)、键矩阵(Key, K K K)和值矩阵(Value, V V V),它们的维度都是 S × d k S \times d_k S×dk。这三个矩阵包含了当前序列在这一层的所有特征信息。

3. 核心引擎:掩码自注意力机制 (Masked Self-Attention)

这是 Transformer 最具革命性的一步,也是决定生成式大模型"从左到右"逐字生成特性的根本原因 。

  • 第一步:计算注意力打分矩阵 (Attention Score)
    我们让序列中的每一个词去和所有的词(包括自己)计算相关性。在数学上,这就是矩阵的点积运算:
    S c o r e = Q ⋅ K T Score = Q \cdot K^T Score=Q⋅KT
    这里的 S c o r e Score Score 是一个 S × S S \times S S×S 的方阵。矩阵中的第 i i i 行第 j j j 列的值,代表了第 i i i 个词对第 j j j 个词的关注程度。
  • 第二步:缩放 (Scaling)
    为了防止点积结果过大导致后续的梯度消失,需要除以一个缩放因子(通常是 d k \sqrt{d_k} dk ,即 K K K 的维度的平方根):
    S c o r e ′ = S c o r e d k Score' = \frac{Score}{\sqrt{d_k}} Score′=dk Score
  • 第三步:掩码操作 (Masking) ------ 极其关键
    在文本生成时,第 i i i 个词在预测下一个词时,绝对不能 提前"看到"它后面的词(未来的词)。
    在数学上的实现方法是:引入一个下三角矩阵掩码 M M M。对于所有的 j > i j > i j>i(对角线右上方的元素),强制将 S c o r e i , j ′ Score'_{i,j} Scorei,j′ 设置为 − ∞ -\infty −∞。
  • 第四步:Softmax 归一化
    将打分矩阵转化为概率分布(权重):
    A = softmax ( S c o r e ′ + M ) A = \text{softmax}(Score' + M) A=softmax(Score′+M)
    因为掩码位置的值是 − ∞ -\infty −∞,经过 softmax 后会变成精确的 0 0 0。这确保了每个位置只能关注到它之前的位置 。
  • 第五步:加权求和得出新特征
    用计算出的权重矩阵 A A A 去乘上值矩阵 V V V:
    Z = A ⋅ V Z = A \cdot V Z=A⋅V
    最终输出的 Z ∈ R S × d k Z \in \mathbb{R}^{S \times d_k} Z∈RS×dk,就是融合了上下文语境的新向量矩阵。

4. 多头机制 (Multi-Head Attention, MHA)

为了让模型能从多个不同的维度(比如语法、情感、逻辑)去理解上下文,Transformer 不仅仅做一次上述操作,而是把隐藏维度切分成多个"头"(Heads),每个头独立进行自注意力计算,然后拼接起来。
h e a d i = Attention ( Q i , K i , V i ) head_i = \text{Attention}(Q_i, K_i, V_i) headi=Attention(Qi,Ki,Vi)
MultiHead ( Q , K , V ) = Concat ( h e a d 1 , . . . , h e a d h ) ⋅ W O \text{MultiHead}(Q, K, V) = \text{Concat}(head_1, ..., head_h) \cdot W_O MultiHead(Q,K,V)=Concat(head1,...,headh)⋅WO

这里的 W O W_O WO 是一个输出线性变换矩阵,用于将拼接后的维度重新映射回 d m o d e l d_{model} dmodel。

5. 残差连接与层归一化 (Add & Norm)

为了防止网络太深导致梯度消失或爆炸,Transformer 在每个主要模块后都加入了这两项操作。

  • 残差连接 :将 MHA 的输出加上它自己原本的输入(即最初的 X X X)。
  • 层归一化 :在特征维度上对数据进行标准化。
    X m h a = LayerNorm ( X + MHA ( X ) ) X_{mha} = \text{LayerNorm}(X + \text{MHA}(X)) Xmha=LayerNorm(X+MHA(X))

6. 前馈神经网络 (Feed-Forward Network, FFN)

经过注意力机制后,序列中的每个词都已经包含了上下文信息,但这些信息还没有经过复杂的非线性映射。

FFN 包含两个线性操作 。它只对每个词(在 S S S 维度上的每一行)独立进行操作:
FFN ( x ) = Activation ( x ⋅ W 1 + b 1 ) ⋅ W 2 + b 2 \text{FFN}(x) = \text{Activation}(x \cdot W_1 + b_1) \cdot W_2 + b_2 FFN(x)=Activation(x⋅W1+b1)⋅W2+b2

这里的关键是: W 1 W_1 W1 会把维度大幅扩张(例如从 4096 扩大到 11008),经过激活函数后, W 2 W_2 W2 再把它压缩回原来的尺寸。这极大地增强了模型存储和提取复杂知识的能力。

最后,同样需要经过一次 Add & Norm:
X o u t = LayerNorm ( X m h a + FFN ( X m h a ) ) X_{out} = \text{LayerNorm}(X_{mha} + \text{FFN}(X_{mha})) Xout=LayerNorm(Xmha+FFN(Xmha))


至此,一层 Decoder 层的完整前向计算结束。实际的大模型(如 LLaMA2-7B)就是由 32 个这样结构完全相同、但参数权重完全不同的 Decoder 层像搭积木一样串联堆叠起来的 。

我们将构建一个微型的、但结构严格符合真实大模型运作规律的沙盘推演。

假设我们要让模型处理输入序列:"我 爱 学习",并且预测下一个词。

为了方便演算,我们假设这是一个极其微小的模型:其隐藏层维度 d m o d e l = 4 d_{model} = 4 dmodel=4(真实场景如 LLaMA2-7B 中这个值是 4096 )。

以下是这三个词在模型第一层 Decoder 中的完整流转过程(即预填充阶段 Prefill Phase):

第一步:输入矩阵化 (Embedding)

系统首先通过分词器(Tokenizer)将这三个词转化为编号,并查表得到它们的初始词向量(已加上位置编码)。

此时,我们的输入矩阵 X X X 是一个 3 × 4 3 \times 4 3×4 的矩阵(3代表序列长度 S S S,4代表维度 d m o d e l d_{model} dmodel):
X = [ 1.0 0.1 0.2 0.5 0.3 1.2 0.1 0.4 0.8 0.5 1.5 0.2 ] ← "我"的初始向量 ← "爱"的初始向量 ← "学习"的初始向量 X = \begin{bmatrix} 1.0 & 0.1 & 0.2 & 0.5 \\ 0.3 & 1.2 & 0.1 & 0.4 \\ 0.8 & 0.5 & 1.5 & 0.2 \end{bmatrix} \begin{matrix} \leftarrow \text{"我"的初始向量} \\ \leftarrow \text{"爱"的初始向量} \\ \leftarrow \text{"学习"的初始向量} \end{matrix} X= 1.00.30.80.11.20.50.20.11.50.50.40.2 ←"我"的初始向量←"爱"的初始向量←"学习"的初始向量

(注:这里不懂怎么来的看这篇词嵌入和位置编码

第二步:生成 Q、K、V (线性投影)

接下来,矩阵 X X X 分别与模型已经训练好的三个权重矩阵 W Q , W K , W V W_Q, W_K, W_V WQ,WK,WV(假设维度都是 4 × 4 4 \times 4 4×4)进行完整的矩阵乘法:

  • Q = X ⋅ W Q Q = X \cdot W_Q Q=X⋅WQ
  • K = X ⋅ W K K = X \cdot W_K K=X⋅WK
  • V = X ⋅ W V V = X \cdot W_V V=X⋅WV

物理意义拆解

  • Q (Query/查询):代表这个词**"想寻找什么语境"**。例如,"爱"这个动词的 Q 向量,可能在强烈地寻找它的主语和宾语。
  • K (Key/键):代表这个词**"具有什么特征"**。例如,"我"的 K 向量会强烈地散发出"我是代词、我是主语"的信号。
  • V (Value/值):代表这个词**"本身的实际内容"**。

此时,我们得到了 Q , K , V Q, K, V Q,K,V 三个全新的 3 × 4 3 \times 4 3×4 矩阵。

第三步:掩码自注意力的计算底色 (Masked Self-Attention)

这是整个过程中最硬核的一步。模型需要计算这三个词两两之间的关联度。

1. 点积打分 (Score)

模型用查询矩阵 Q Q Q 乘以键矩阵的转置 K T K^T KT:
S c o r e = Q ⋅ K T = [ 10 2 1 4 15 3 1 8 12 ] Score = Q \cdot K^T = \begin{bmatrix} 10 & 2 & 1 \\ 4 & 15 & 3 \\ 1 & 8 & 12 \end{bmatrix} Score=Q⋅KT= 104121581312

这是一个 3 × 3 3 \times 3 3×3 的方阵。比如第三行第二列的数值是 8,这意味着"学习"( Q 3 Q_3 Q3) 对"爱"( K 2 K_2 K2) 的原始关注度是 8。

2. 强加时间箭头:掩码操作 (Masking)

在真实的生成式模型中,第 i i i 个词绝对不能看到第 i + 1 i+1 i+1 个词。模型会强制用一个下三角的掩码矩阵 M M M 加到 S c o r e Score Score 上,把对角线右上方的数值全部变成负无穷( − ∞ -\infty −∞):
S c o r e + M = [ 10 − ∞ − ∞ 4 15 − ∞ 1 8 12 ] Score + M = \begin{bmatrix} 10 & -\infty & -\infty \\ 4 & 15 & -\infty \\ 1 & 8 & 12 \end{bmatrix} Score+M= 1041−∞158−∞−∞12
解释:"我"(第一行)只能看到自己;"爱"(第二行)能看到"我"和"爱";"学习"(第三行)能看到完整的"我 爱 学习"。

3. 概率归一化 (Softmax)

对每一行进行 Softmax 计算,将这些分数转化为总和为 1 的概率权重矩阵 A A A:
A ≈ [ 1.0 0 0 0.05 0.95 0 0.01 0.29 0.70 ] A \approx \begin{bmatrix} 1.0 & 0 & 0 \\ 0.05 & 0.95 & 0 \\ 0.01 & 0.29 & 0.70 \end{bmatrix} A≈ 1.00.050.0100.950.29000.70
可以看到, − ∞ -\infty −∞ 被转换成了绝对的 0。

4. 提取新特征 (加权求和)

最后,用权重矩阵 A A A 去乘以内容矩阵 V V V:
Z = A ⋅ V Z = A \cdot V Z=A⋅V

我们知道 V V V 是一个 3 × 4 3 \times 4 3×4 的矩阵(3 个词,每个词 4 个维度)。在数学上,我们可以把 V V V 看作是由 3 个 1 × 4 1 \times 4 1×4 的**行向量(Row Vector)**上下拼起来的:

V = [ v 11 v 12 v 13 v 14 v 21 v 22 v 23 v 24 v 31 v 32 v 33 v 34 ] = [ --- V 我 --- --- V 爱 --- --- V 学习 --- ] V = \begin{bmatrix} v_{11} & v_{12} & v_{13} & v_{14} \\ v_{21} & v_{22} & v_{23} & v_{24} \\ v_{31} & v_{32} & v_{33} & v_{34} \end{bmatrix} = \begin{bmatrix} \text{--- } V_{\text{我}} \text{ ---} \\ \text{--- } V_{\text{爱}} \text{ ---} \\ \text{--- } V_{\text{学习}} \text{ ---} \end{bmatrix} V= v11v21v31v12v22v32v13v23v33v14v24v34 = --- V我 ------ V爱 ------ V学习 ---

这里的 V 我 V_{\text{我}} V我、 V 爱 V_{\text{爱}} V爱、 V 学习 V_{\text{学习}} V学习 都是长度为 4 的一维向量。最终得到了完整、严谨的 3 × 4 3 \times 4 3×4 矩阵 Z Z Z:

Z = [ --- Z 我 --- --- Z 爱 --- --- Z 学习 --- ] = [ 1.0 ⋅ V 我 0.05 ⋅ V 我 + 0.95 ⋅ V 爱 0.01 ⋅ V 我 + 0.29 ⋅ V 爱 + 0.70 ⋅ V 学习 ] Z = \begin{bmatrix} \text{--- } Z_{\text{我}} \text{ ---} \\ \text{--- } Z_{\text{爱}} \text{ ---} \\ \text{--- } Z_{\text{学习}} \text{ ---} \end{bmatrix} = \begin{bmatrix} 1.0 \cdot V_{\text{我}} \\ 0.05 \cdot V_{\text{我}} + 0.95 \cdot V_{\text{爱}} \\ 0.01 \cdot V_{\text{我}} + 0.29 \cdot V_{\text{爱}} + 0.70 \cdot V_{\text{学习}} \end{bmatrix} Z= --- Z我 ------ Z爱 ------ Z学习 --- = 1.0⋅V我0.05⋅V我+0.95⋅V爱0.01⋅V我+0.29⋅V爱+0.70⋅V学习

至此,原本孤立的词汇"学习",它的向量里已经精准地按比例融合了前文"我"和"爱"的特征信息!

上文为了演示注意力公式,我们假设整个 4 4 4 维空间只做了一次注意力计算。但在真实的 Transformer 中,模型会将这 4 4 4 个维度"劈开",分给多个不同的"头"去独立计算 。假设我们设定多头数量 h = 2 h = 2 h=2

1. 降维分发:

原本的输入 X X X 会乘上不同的投影矩阵,分别生成两组缩小版的 Q , K , V Q, K, V Q,K,V。

每一个头的维度 d k = 4 / 2 = 2 d_k = 4 / 2 = 2 dk=4/2=2。

  • 头 1 (Head 1) :关注"语法"逻辑。它计算出一个 3 × 2 3 \times 2 3×2 的结果矩阵 Z 1 Z_1 Z1。
  • 头 2 (Head 2) :关注"情感"逻辑。它计算出另一个 3 × 2 3 \times 2 3×2 的结果矩阵 Z 2 Z_2 Z2。

2. 结果拼接 (Concatenate):

将这两个头各自算出的特征横向拼起来,恢复成完整的 3 × 4 3 \times 4 3×4 矩阵:
Z c o n c a t = [ Z 1 , Z 2 ] Z_{concat} = [Z_1, Z_2] Zconcat=[Z1,Z2]

3. 输出线性映射 (Output Projection):

拼接后的矩阵还不能直接用,必须再乘上一个权重矩阵 W O W_O WO(维度 4 × 4 4 \times 4 4×4),进行最后一次特征融合。这就是论文中提到的"通过一个最终的线性层进行处理" 。
Z M H A = Z c o n c a t ⋅ W O Z_{MHA} = Z_{concat} \cdot W_O ZMHA=Zconcat⋅WO

此时得到的 Z M H A Z_{MHA} ZMHA 依然是 3 × 4 3 \times 4 3×4 的矩阵。


第四步:残差连接与层归一化 (Add & Norm)

模型绝不会直接把 Z M H A Z_{MHA} ZMHA 送进下一步。随着网络加深(比如 32 层),如果只做矩阵乘法,数值会迅速膨胀或衰减(梯度消失/爆炸)。

1. 残差连接 (Add):

将这一层的原始输入 X X X 直接加到刚刚算出的 Z M H A Z_{MHA} ZMHA 上:
X r e s = X + Z M H A X_{res} = X + Z_{MHA} Xres=X+ZMHA
物理意义 :这相当于给信息开了一条"VIP 快速通道"。即使刚才的注意力计算跑偏了,最原始的词义信息 X X X 依然保留着。

2. 层归一化 (Layer Normalization):

这一步针对 X r e s X_{res} Xres 中的每一行(每一个词的向量)独立进行 。我们以第三行("学习"的 4 4 4 维向量)为例,假设 X r e s X_{res} Xres 第三行为 [ 2.0 , 4.0 , 6.0 , 8.0 ] [2.0, 4.0, 6.0, 8.0] [2.0,4.0,6.0,8.0]。

  • 求均值 μ \mu μ : 2.0 + 4.0 + 6.0 + 8.0 4 = 5.0 \frac{2.0+4.0+6.0+8.0}{4} = 5.0 42.0+4.0+6.0+8.0=5.0
  • 求方差 σ 2 \sigma^2 σ2 : ( 2 − 5 ) 2 + ( 4 − 5 ) 2 + ( 6 − 5 ) 2 + ( 8 − 5 ) 2 4 = 5.0 \frac{(2-5)^2 + (4-5)^2 + (6-5)^2 + (8-5)^2}{4} = 5.0 4(2−5)2+(4−5)2+(6−5)2+(8−5)2=5.0
  • 标准化 :用每个元素减去均值,除以标准差 σ 2 + ϵ \sqrt{\sigma^2 + \epsilon} σ2+ϵ ( ϵ \epsilon ϵ 是极小值防除零)。这会把数据拉回均值为 0,方差为 1 的标准分布。
  • 缩放与平移 :最后乘以一个可学习的参数 γ \gamma γ,加上参数 β \beta β。
    X n o r m = LayerNorm ( X r e s ) X_{norm} = \text{LayerNorm}(X_{res}) Xnorm=LayerNorm(Xres)
    经过这套极其严密的缩放, 3 × 4 3 \times 4 3×4 的矩阵 X n o r m X_{norm} Xnorm 的数值变得极其稳定。

第五步:前馈神经网络 (FFN) 的升维打击与降维提取

FFN 包含两个线性操作,先扩大隐藏层维度,再压缩回原始大小。

1. 升维 (Up-Projection):

将 3 × 4 3 \times 4 3×4 的 X n o r m X_{norm} Xnorm 乘以一个巨大的权重矩阵 W 1 W_1 W1(例如维度 4 × 16 4 \times 16 4×16),加上偏置 b 1 b_1 b1:
H 1 = X n o r m ⋅ W 1 + b 1 H_1 = X_{norm} \cdot W_1 + b_1 H1=Xnorm⋅W1+b1

此时,数据从 3 × 4 3 \times 4 3×4 瞬间膨胀成 3 × 16 3 \times 16 3×16。
物理意义:把原本紧凑的 4 维特征投射到极其宽广的 16 维空间,让模型有足够的容量去展开和重组复杂的逻辑。

2. 非线性激活 (Activation):

对 H 1 H_1 H1 里的每一个数字使用激活函数(比如 ReLU,即将小于 0 的数全部变成 0)。
H a c t = max ⁡ ( 0 , H 1 ) H_{act} = \max(0, H_1) Hact=max(0,H1)
物理意义:这是模型产生"逻辑推理"能力的核心。没有这一步,前面算再多都只是简单的线性叠加。

3. 降维 (Down-Projection):

将 3 × 16 3 \times 16 3×16 的 H a c t H_{act} Hact 乘以第二个权重矩阵 W 2 W_2 W2(维度 16 × 4 16 \times 4 16×4),加上偏置 b 2 b_2 b2:
H 2 = H a c t ⋅ W 2 + b 2 H_2 = H_{act} \cdot W_2 + b_2 H2=Hact⋅W2+b2

数据重新被压缩回 3 × 4 3 \times 4 3×4。随后,再进行一次残差连接与层归一化
X o u t = LayerNorm ( X n o r m + H 2 ) X_{out} = \text{LayerNorm}(X_{norm} + H_2) Xout=LayerNorm(Xnorm+H2)

至此,一层 Decoder 的计算才算以极其严谨的数学形式彻底闭环。 这个 X o u t X_{out} Xout 会被送入下一层,重复上述所有计算,直到跑完 32 层。


第六步:最终的词表映射 (预测 "AI")

假设 3 × 4 3 \times 4 3×4 的矩阵终于跑出了最后一层。此时,整句话的终极信息已经完全凝结在了矩阵的最后一行 (因为我们是根据前 3 个词预测第 4 个词)。

我们提取最后一行的一维向量 v l a s t v_{last} vlast(长度为 4)。

模型自带一个极其庞大的词表嵌入矩阵 W v o c a b W_{vocab} Wvocab 。如果你的词表有 100,000 个词,这个矩阵的维度就是 4 × 100 , 000 4 \times 100,000 4×100,000。

我们将 v l a s t v_{last} vlast 与 W v o c a b W_{vocab} Wvocab 相乘:
L o g i t s = v l a s t ⋅ W v o c a b Logits = v_{last} \cdot W_{vocab} Logits=vlast⋅Wvocab

你会得到一个长度为 100,000 的一维数组(Logits)。这里面的每一个数字,代表了词表中对应词的分数。最后通过一次 Softmax 运算,把这 100,000 个分数变成总和为 1 的概率分布。

我们查看到,索引号为 9527(对应单词 "AI")的概率高达 0.82,于是模型输出了 "AI"。

这就是大模型"预填充阶段 (Prefill)" 绝对完整的底层运行轨迹。没有任何跳步,没有任何黑盒。

自回归解码阶段 (Decoding Phase) 就是把"我"、"爱"、"学习"、"AI"这 4 个词重新送进网络预测下一个词。

但真正的挑战现在才开始。按照上面的公式,我们是不是要把这 4 个词的 Q , K , V Q, K, V Q,K,V 重新计算一遍?

自回归解码阶段 (Decoding Phase) 是如何通过引入 KV Cache 机制来避免这种毁灭性的重复计算,并由此引出必须要解决的核心难题:边缘设备的内存和带宽为何会被 KV Cache 直接撑爆?

相关推荐
季远迩2 小时前
240. 搜索二维矩阵 II(中等)
人工智能·算法·矩阵
AI科技星3 小时前
从v=c螺旋时空公理出发的引力与电磁常数大统一
c语言·开发语言·人工智能·线性代数·算法·矩阵·数据挖掘
张张123y12 小时前
RAG从0到1学习:技术架构、项目实践与面试指南
人工智能·python·学习·面试·架构·langchain·transformer
renhongxia116 小时前
PostTrainBench:LLM 代理能否自动化 LLM 后培训?
运维·人工智能·深度学习·机器学习·架构·自动化·transformer
小超同学你好18 小时前
Transformer 14. DeepSeekMoE 架构解析:与 LLaMA 以及 Transformer 架构对比
语言模型·架构·transformer·llama
Tisfy20 小时前
LeetCode 1727.重新排列后的最大子矩阵:枚举矩形底边是哪一行 + 排序
算法·leetcode·矩阵
小超同学你好1 天前
Transformer 15: DeepSeek-V2 架构解析:MLA + DeepSeekMoE 与主流架构对比
语言模型·架构·transformer·llama
样例过了就是过了1 天前
LeetCode热题100 搜索二维矩阵
数据结构·c++·算法·leetcode·矩阵
Shining05961 天前
AI 编译器系列(四)《AI 编译器中的后端优化》
linux·服务器·人工智能·线性代数·算法·triton·ai编译器