Transformer模型计算过程

举报
张谱继 发表于 2026/06/25 20:48:12 2026/06/25
【摘要】 自注意力的核心数学公式只有一行:Attention(Q,K,V)=softmax(QKTdk)VAttention(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)VAttention(Q,K,V)=softmax(dk​​QKT​)V● Query (Q):代表“当前这个新词”想找什么。● Key (K) 和 Val...

自注意力的核心数学公式只有一行:

Attention(Q,K,V)=softmax(QKTdk)VAttention(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V

● Query (Q):代表“当前这个新词”想找什么。
● Key (K) 和 Value (V):代表“历史所有词”提供了什么线索。
➤ Q (Query):代表当前这个词“我想找什么”。
➤ K (Key):代表当前这个词“我能提供什么特征以供对照”。
➤ V (Value):代表当前这个词“我包含的实际核心内容是什么”。

以下是大模型在实际运行中,单次计算(以生成一个新词为例)的完整标准流水线


一、 大模型单次推理的完整计算顺序

假设当前历史对话为“我想吃”N=3N=3),模型正在解码(Decoding 阶段)准备输出第四个词“苹果”

1. 线性投影与身份解耦(算新词 Q,K,VQ, K, V

  • 输入:上一步生成的最新词“吃”的向量特征 XnewR1×dmodelX_{new} \in \mathbb{R}^{1 \times d_{model}}
  • 动作:通过矩阵乘法,乘以三个可学习的权重参数矩阵:

Qnew=Xnew×WQ(1×dk)Q_{new} = X_{new} \times W^Q \quad (1 \times d_k)

Knew=Xnew×WK(1×dk)K_{new} = X_{new} \times W^K \quad (1 \times d_k)

Vnew=Xnew×WV(1×dv)V_{new} = X_{new} \times W^V \quad (1 \times d_v)

  • 结果:只算出了最新词的 Q,K,VQ, K, V,此时历史词的 QQ 随用随扔,不参与计算。

2. 缓存更新与追加(KV Cache 拼接)

  • 动作:将刚刚算出的 KnewK_{new}VnewV_{new} 追加到显存中已有的 KV Cache 矩阵末尾。
  • 结果
  • KcacheK_{cache} 变更为:[词1的K, 词2的K, 词3的K, 词4的K],形状为 4×dk4 \times d_k
  • VcacheV_{cache} 变更为:[词1的V, 词2的V, 词3的V, 词4的V],形状为 4×dv4 \times d_v

3. 全局关联计算(点积与缩放)

  • 动作:拿最新词的一行 QnewQ_{new} 乘以整个 KcacheK_{cache} 的转置,并除以缩放因子 dk\sqrt{d_k}(防止方差过大导致梯度消失)。

Z=Qnew×KcacheTdkZ = \frac{Q_{new} \times K_{cache}^T}{\sqrt{d_k}}

  • 矩阵变化(1×dk)×(dk×4)=1×4(1 \times d_k) \times (d_k \times 4) = \mathbf{1 \times 4}
  • 结果:算出了最新词对全句(包括对角线上它自己)的原始相关性得分向量。

4. 权重平滑归一化(Softmax 变换)

  • 动作:进行硬件防溢出处理(各元素减去最大值 zmaxz_{max})后,执行 Row-wise Softmax。

A=softmax(Z)Ai=ezizmaxezmzmaxA = \text{softmax}(Z) \quad \longrightarrow \quad A_i = \frac{e^{z_i - z_{max}}}{\sum e^{z_m - z_{max}}}

  • 结果:得到一行平滑、可导且相加严格等于 1 的注意力权重概率分布(例如 [0.1, 0.1, 0.1, 0.7],表示 70% 的注意力在自己身上)。

5. 特征加权聚合(打包带走)

  • 动作:用这一行权重 AA 去乘以完整的 VcacheV_{cache}

h=A×Vcache(1×4)×(4×dv)=1×dv\mathbf{h} = A \times V_{cache} \quad \longrightarrow \quad (1 \times 4) \times (4 \times d_v) = \mathbf{1 \times d_v}

  • 结果:历史词的所有核心资产被按比例抽取,融合进这个全新的上下文特征向量 h\mathbf{h} 中。

6. 词表映射(算 Logits 分数)

  • 动作:将 h\mathbf{h} 乘以上层全连接线性层权重 WvocabW_{vocab},将其从特征空间映射到整个人类词表空间。

z=h×Wvocab(1×词表大小)\mathbf{z} = \mathbf{h} \times W_{vocab} \quad \longrightarrow \quad (1 \times \text{词表大小})

  • 结果:词表里的每一个词(如“苹果”、“汽车”)都得到了一个未归一化的原始得分(Logits)。

7. 灵魂调节与概率生成(温度系数与采样)

  • 温度干预:用 Logits 除以温度系数 z/T\mathbf{z} / TTT 小则放大差距、生成严谨;TT 大则熨平差距、充满创意。
  • 最终预测:再次过一次 Softmax 得到各词语的最终被选概率。
  • 摇号采样:如果是贪婪搜索则直接取最高分;如果是 Top-p/Top-k 随机采样,则在概率转盘上“摇号”蹦出最终的新词:“苹果”

二、 工业级加速与异常处理方案

在长文本或高并发的实际业务场景中,上述原生流水线会遭遇算力与显存的极限挑战。以下是对应的工业级解决方案:

1. 运行阶段的加速方案 (Prefill 与 Decoding 分离)

由于单次推理中,用户刚输入的阶段与蹦字阶段的性能瓶颈完全不同,现代引擎(如 vLLM, TensorRT-LLM)会进行架构拆分:

  • Prefill 阶段(预填充)

  • 机制:用户 Prompt 输入后,不使用 KV Cache,而是利用因果掩码(Causal Mask)强行将 N×NN \times N 注意力矩阵的右上角抹为 0,实现整个输入序列的一次性全局并行预计算

  • 定位:计算密集型。专门交给算力强劲的流水线处理。

  • Decoding 阶段(解码)

  • 机制:完美运行上述“一字一轮”的串行计算,全面依赖 KV Cache 将每步计算量从 O(N2)O(N^2) 降维到 1×N1 \times N 的行向量。

  • 底层硬件架构优化(GQA 分组查询):在模型设计时让多个 QQ 头共享一组 K,VK, V 头,从源头上将 KV Cache 的常驻体积裁剪 4~8 倍。

2. 显存超限 (OOM) 异常处理方案

当上下文极长、显存即将被 KV Cache 撑爆时,系统会触发以下多级防御机制:

  • 防御一级:虚拟内存页式管理 (PagedAttention)

  • 做法:打碎连续显存的限制,将 KV Cache 像操作系统分页一样拆成固定大小的物理页块动态分配,彻底消除显存碎片,提升并发容纳率。

  • 防御二级:量化压缩 (KV Cache Quantization)

  • 做法:将原本 FP16(2字节)存储的 K,VK, V 矩阵动态量化为 INT8(1字节)甚至 INT4(0.5字节),在几乎不损耗模型长文本理解力的情况下,让显存直接缩减到原来的 1/2 至 1/4。

  • 防御三级:长期对话的流式驱逐 (StreamingLLM)

  • 做法:针对无限轮次的对话,在缓存中死守开头凝聚巨大注意力的“注意力汇(Attention Sinks)”,同时开启滑动窗口。随着新词进来,自动把最老、且不是开头的 KV 缓存从显存中驱逐丢弃,确保显存永远恒定,杜绝长文本崩溃。

  • 防御四级:空间换成功的内存兜底 (Offloading)

  • 做法:当 GPU 显存彻底见底,推理引擎通过 PCIe 总线将久未使用的 KV Cache 临时置换卸载到主机的 CPU 系统内存NVMe SSD 中。虽然带来了传输延迟,但保证了超长上下文任务的“绝对死不断线”。

在大模型的整个生命周期中,训练(Training)和推理(Inference)有着本质的区别。

推理是“一字一字往外蹦”的串行复仇记;而训练则是“上帝视角”的全局并行大合唱。在训练时,我们手头已经有了完整的标准答案(比如一整篇网文、一本书或一段对话),我们不需要、也绝对不用 KV Cache,而是利用因果掩码(Causal Mask)实现整句话的并行计算和梯度回传。

以下是大模型在训练时,单次迭代(One Forward & Backward Pass)的完整计算全景:


一、 前向传播阶段:完全并行的“并行计算”

假设我们的训练样本是一句话:“我想吃苹果”(一共 5 个 Token,序列长度 N=5N=5)。

1. 词嵌入与位置编码 (Embedding)

  • 动作:5 个词同时被送入模型。首先通过词表转换成 5 个一维稠密向量,再加上位置编码(Positional Encoding),组合成一个完整的输入矩阵 XX
  • 矩阵形状XR5×dmodelX \in \mathbb{R}^{5 \times d_{model}}(5 行,每行代表一个词的初始特征)。

2. 算齐所有的 Q、K、V(矩阵大合唱)

在训练时,GPU 发挥其恐怖的矩阵并行能力,拿整个 XX(5行)直接去乘以三个权重矩阵 WQ,WK,WVW^Q, W^K, W^V

Q=X×WQ(5×dk)Q = X \times W^Q \quad (5 \times d_k)

K=X×WK(5×dk)K = X \times W^K \quad (5 \times d_k)

V=X×WV(5×dv)V = X \times W^V \quad (5 \times d_v)

  • 重点:这里一步到位,算出了所有词在所有位置的 Q,K,VQ, K, V

3. 计算全员关联方阵(点积与缩放)

  • 动作:让整个 QQ 矩阵乘以 KK 的转置 KTK^T,并除以 dk\sqrt{d_k}

Z=Q×KTdkZ = \frac{Q \times K^T}{\sqrt{d_k}}

  • 矩阵形状(5×dk)×(dk×5)=5×5(5 \times d_k) \times (d_k \times 5) = \mathbf{5 \times 5} 的方阵。
  • 物理意义:这个 5×55 \times 5 的矩阵,算出了这 5 个词两两之间所有的关联分数(包含过去看现在、现在看未来、现在看现在)。

4. 引入因果掩码(Causal Mask)—— 防止作弊

因为我们在训练模型预测下一个词,绝对不能让前面的词提前看到后面的词(不能让“我”看到后面的“吃”和“苹果”)。

  • 动作:引入一个 5×55 \times 5 的上三角掩码矩阵,右上角全为 -\infty。将其加到刚刚算出的 ZZ 矩阵上。
  • 矩阵效果

Masked Z=(1.22.30.80.53.11.40.11.24.20.90.20.51.13.81.7)\text{Masked } Z = \begin{pmatrix} 1.2 & -\infty & -\infty & -\infty & -\infty \\ 2.3 & 0.8 & -\infty & -\infty & -\infty \\ 0.5 & 3.1 & 1.4 & -\infty & -\infty \\ 0.1 & 1.2 & 4.2 & 0.9 & -\infty \\ 0.2 & 0.5 & 1.1 & 3.8 & 1.7 \end{pmatrix}

5. 平滑归一化与特征聚合 (Softmax & V)

  • Softmax:对上述矩阵进行按行(Row-wise)Softmax。因为右上角是 -\infty,经过指数化后全变成了 0。这在数学上完美实现了“只有过去的词和自己能拥有注意力,未来的词权重为0”。
  • 乘以 V

O=softmax(Masked Z)×V(5×5)×(5×dv)=5×dvO = \text{softmax}(\text{Masked } Z) \times V \quad \longrightarrow \quad (5 \times 5) \times (5 \times d_v) = \mathbf{5 \times d_v}

  • 成果:我们得到了一个 5×dv5 \times d_v 的输出矩阵 OO。它的第 1 行只融合了“我”的特征;第 3 行融合了“我、想、吃”三个词的特征。整个句子的上下文特征被一次性全部并行抽完

6. 计算损失(Loss Computation)

  • 动作:将 OO 映射到词表空间得到所有位置的 Logits。接下来,模型要同时做 5 个预测任务,并与标准答案对比:

  • 拿着第 1 行(输入是“我”)去预测下一个词,看是不是“想”。

  • 拿着第 3 行(输入是“我想吃”)去预测下一个词,看是不是“苹果”。

  • 算总账:通过交叉熵损失函数(Cross-Entropy Loss),把这 5 个预测结果和真实标签计算出一个综合总损失(Loss)值


二、 反向传播阶段:误差倒推与参数洗练

有了总 Loss 之后,训练最核心的魔术——反向传播(Backpropagation) 开始启动。GPU 要沿着前向传播的逆方向,利用微积分链式法则把误差传回源头。

1. 第一步:误差传回注意力层输出 (LO\frac{\partial L}{\partial O})

优化器从最终的 Loss 出发,首先算出门户线性层和词表映射层的导数,将误差信号推回到注意力机制的输出矩阵 OO,得到梯度矩阵 LO\frac{\partial L}{\partial O}(形状为 5×dv5 \times d_v)。

2. 第二步:穿过特征聚合(对 AAVV 求导)

因为前向是 O=A×VO = A \times V,逆向时:

  • 对注意力权重 AA 的梯度:LA=LO×VT\frac{\partial L}{\partial A} = \frac{\partial L}{\partial O} \times V^T
  • 对语义资产 VV 的梯度:LV=AT×LO\frac{\partial L}{\partial V} = A^T \times \frac{\partial L}{\partial O}
  • 物理意义:模型在排查责任。如果某处的预测大错特错,说明当时分配的注意力权重 AA 或者提取的特征 VV 问题很大,这部分就会收到极高强度的修正信号。

3. 第三步:逆穿 Softmax 与掩码区

将梯度 LA\frac{\partial L}{\partial A} 传回 Softmax 的输入矩阵 ZZ

  • 神奇之处:因为前向传播时,右上角被掩码强行抹成了 0(不参与计算),所以在反向传播时,右上角那一半矩阵的梯度也全部是 0!这意味着未来的信息不仅在前向时被屏蔽,在反向时也完全无法对过去的参数产生任何污染和影响

4. 第四步:推导源头参数梯度(对 WQ,WK,WVW^Q, W^K, W^V 求导)

通过链式法则继续往前推,穿过点积,最终计算出大模型真正的核心资产——那三个可学习权重矩阵的精确梯度:

LWQ=XT×LQ\frac{\partial L}{\partial W^Q} = X^T \times \frac{\partial L}{\partial Q}

LWK=XT×LK\frac{\partial L}{\partial W^K} = X^T \times \frac{\partial L}{\partial K}

LWV=XT×LV\frac{\partial L}{\partial W^V} = X^T \times \frac{\partial L}{\partial V}

5. 第五步:参数更新(梯度下降)

这时候,优化器(如 AdamW)拿着这三个热乎的梯度矩阵,对现有的参数进行微调:

WWηOptimizer(LW)W \leftarrow W - \eta \cdot \text{Optimizer}(\frac{\partial L}{\partial W})


三、 为什么训练不需要 KV Cache?(总结对比)

学完训练的全过程后,你可以非常清晰地看出它们两者的本质区别:

  • 推理时(Decoding):我们没有未来,句子是一个字一个字动态变长的。为了不重复计算历史,我们必须搞一个 KV Cache 把过去的资产存起来,每一步只算最新的一行。
  • 训练时(Training):我们掌控未来,整句话都在手里。我们利用 Causal Mask 矩阵在数学上直接切出了一个左下三角形,实现了全句 Token 的一次性并行输入、一次性并行计算、一次性并行回传。所以,训练过程不需要、也根本用不上 KV Cache。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。