Skip to content
本文目录

Transformer 模型

← 返回AI 实践与思考

基于以下两篇笔记整理:

  • 飞天闪客《一小时从函数到Transformer》文字稿
  • 万字长文讲透LLM核心:Transformer架构原理解析

一篇讲清"零件怎么组装",一篇讲清"数据怎么流动"。下面的活动图把两者合并,按 输入 → 编码 → 自回归解码 → 输出 组织一次完整的前向流程。

text
@startuml
!theme plain
skinparam linetype ortho
title Transformer 一次输入 → 输出的完整流程

start
:原始文本\n"Transformer is powerful.";
:分词 Tokenize\n文本 → Token ID 序列;
:词嵌入 Embedding\n查嵌入矩阵,ID → 高维向量;
:注入词序信息\n 加上位置编码 Positional Encoding 形成最终的X输入矩阵;

partition "编码器 Encoder × N 层" {
  :生成 Q、K、V\n输入矩阵 X 分别乘 Wq、Wk、Wv;
  :拆分多头\nd_model 维向量切成 h 份,每头 d_k = d_model/h 维;
  fork
    :头 1\nQ₁·K₁ᵀ → ÷√d_k → Softmax → 加权求和 V₁;
  fork again
    :头 2\nQ₂·K₂ᵀ → ÷√d_k → Softmax → 加权求和 V₂;
  fork again
    :……\n每头独立计算,关注不同角度\n(如一个头学语法,一个头学语义);
  fork again
    :头 h\nQh·Khᵀ → ÷√d_k → Softmax → 加权求和 Vh;
  end fork
  :拼接 h 个头的输出\n再乘投影矩阵 Wo 还原回 d_model 维;
  :Add & Norm\n残差连接 + 层归一化;
  :前馈网络 FFN\n线性放大 → 激活(ReLU/GELU) → 线性还原;
  :Add & Norm;
}

:编码器输出:上下文表示矩阵\n(作为 K/V 供解码器查询);
:解码器初始输入 = <START>;

while (已生成结束符 <END> ?) is (否:继续自回归生成)
  partition "解码器 Decoder × N 层" {
    :掩码多头自注意力 + Add & Norm\n只能看到已生成的词,防止偷看未来;
    :交叉注意力 Cross-Attention + Add & Norm\nQ 来自解码器,K/V 来自编码器输出;
    :前馈网络 FFN + Add & Norm;
  }
  :线性层 Linear\n映射到词汇表大小的维度;
  :Softmax\n转为总和为 1 的概率分布;
  :选出下一个 Token\n(温度=0 时取概率最高者);
  :拼接到已生成序列末尾\n作为下一步的解码器输入;
endwhile (是)

:得到完整输出文本\n"Transformer很强大。";
stop
@enduml

多头是怎么分出来的

多头不是把数据复制 h 份各自跑完整注意力,而是把维度切开分摊:

  1. 输入向量是 d_model 维(如 512)。先乘三个权重矩阵 Wq、Wk、Wv 得到 Q、K、V(维度仍是 d_model)。
  2. 把 Q、K、V 在特征维度上切成 h 份,每份 d_k = d_model / h 维(如 512 / 8 = 64)。等价于每个头有自己独立的小权重矩阵 Wqᵢ、Wkᵢ、Wvᵢ(d_model × d_k),把输入投影到各自的"子空间"。
  3. 每个头在自己的 64 维子空间里独立做一遍缩放点积注意力——因为子空间不同、权重不同,每个头学到的关注角度就不同(如笔记中的例子:头 1 学"主语-系动词-表语"的语法结构,头 2 学"powerful 修饰 Transformer"的语义关系)。
  4. h 个头的输出拼接回 512 维,再乘投影矩阵 Wo 做一次融合,得到多头注意力的最终输出。

关键设计:由于每头只用 d_model/h 维,h 个头的总计算量约等于单头跑完整维度,多头是用同样的代价换取了"同时从多个角度关注"的能力。

说明

  • 核心机制浓缩:单头注意力 = Q·K 点积(衡量词与词的方向相似度)→ 缩放 → Softmax 归一化 → 对 V 加权求和;图中的 fork/end fork 表示多个头并行计算后再汇合,解码器里的掩码多头注意力展开方式与编码器相同(只是多了掩码)。
  • Decoder-only 模型(GPT、DeepSeek 等主流 LLM)可看作省略了编码器和交叉注意力,只剩"掩码自注意力 + FFN"的堆叠,流程骨架不变。

Transformer 领域概念类图

结合本次会话讨论整理的所有概念,按四个主题分包:数学基础、数据表示、模型组件、参数。关系只保留两种:

  • 泛化(继承):<|--,表示 is-a(如 张量 <|-- 向量)
  • 关联:--,表示概念之间的核心联系(如 输入矩阵 X -- 位置编码 : 词序)
text
@startuml
!theme plain
skinparam classAttributeIconSize 0
skinparam linetype ortho
hide empty members
skinparam class {
    BackgroundColor<<math>> LightYellow
    BackgroundColor<<data>> LightBlue
    BackgroundColor<<component>> LightGreen
    BackgroundColor<<param>> LightCoral
}
title Transformer 领域概念类图

package "数学基础" {
  class "张量" as Tensor <<math>>
  class "标量(0阶)" as Scalar <<math>>
  class "向量(1阶)" as Vector <<math>>
  class "矩阵(2阶)" as Matrix <<math>>
  class "点积 / 内积" as DotProduct <<math>>
  class "余弦相似度" as CosineSim <<math>>
  class "Softmax 归一化" as Softmax <<math>>
  class "加权求和" as WeightedSum <<math>>
}

package "数据表示" {
  class "原始文本" as Text <<data>>
  class "Token" as Token <<data>>
  class "特殊标记" as SpecialToken <<data>>
  class "起始符 START" as StartTok <<data>>
  class "结束符 END" as EndTok <<data>>
  class "Token ID" as TokenID <<data>>
  class "词汇表" as Vocab <<data>>
  class "词向量" as WordVec <<data>>
  class "位置编码" as PosEnc <<data>>
  class "输入矩阵 X" as InputX <<data>>
  class "上下文表示矩阵 H" as ContextH <<data>>
  class "Logits 打分向量" as Logits <<data>>
  class "概率分布" as ProbDist <<data>>
}

package "模型组件" {
  class "注意力机制" as Attention <<component>>
  class "自注意力" as SelfAttn <<component>>
  class "掩码自注意力" as MaskedAttn <<component>>
  class "交叉注意力" as CrossAttn <<component>>
  class "多头注意力" as MHA <<component>>
  class "注意力头" as Head <<component>>
  class "查询向量 Q" as Q <<component>>
  class "键向量 K" as K <<component>>
  class "值向量 V" as V <<component>>
  class "Add & Norm" as AddNorm <<component>>
  class "残差连接" as Residual <<component>>
  class "层归一化" as LayerNorm <<component>>
  class "前馈网络 FFN" as FFN <<component>>
  class "激活函数" as Activation <<component>>
  class "ReLU" as ReLU <<component>>
  class "GELU" as GELU <<component>>
  class "Linear 输出层" as Linear <<component>>
  class "编码器(x N 层)" as Encoder <<component>>
  class "解码器(x N 层)" as Decoder <<component>>
}

package "参数" {
  class "超参数" as Hyper <<param>>
  class "d_model 主维度" as DModel <<param>>
  class "h 头数" as Heads <<param>>
  class "d_k 每头维度" as DK <<param>>
  class "N 层数" as Layers <<param>>
  class "可训练参数" as Trainable <<param>>
  class "Wq / Wk / Wv" as Wqkv <<param>>
  class "Wo 输出投影" as Wo <<param>>
  class "W1 / W2(FFN)" as Wffn <<param>>
  class "W_out 输出层" as Wout <<param>>
  class "gamma / beta(归一化)" as GammaBeta <<param>>
  class "嵌入矩阵 E" as EmbMatrix <<param>>
}

' 泛化关系
Tensor <|-- Scalar
Tensor <|-- Vector
Tensor <|-- Matrix
Token <|-- SpecialToken
SpecialToken <|-- StartTok
SpecialToken <|-- EndTok
Attention <|-- SelfAttn
Attention <|-- CrossAttn
SelfAttn <|-- MaskedAttn
SelfAttn <|-- Head
Activation <|-- ReLU
Activation <|-- GELU
Hyper <|-- DModel
Hyper <|-- Heads
Hyper <|-- DK
Hyper <|-- Layers
Trainable <|-- Wqkv
Trainable <|-- Wo
Trainable <|-- Wffn
Trainable <|-- Wout
Trainable <|-- GammaBeta
Trainable <|-- EmbMatrix

' 关联关系
Text -- Token : 分词
Vocab -- TokenID : 词与 ID 映射
TokenID -- EmbMatrix : 按 ID 查表取行
EmbMatrix -- WordVec : 取出词向量
InputX -- WordVec : 词义(我是谁)
InputX -- PosEnc : 词序(我在哪)
Wqkv -- Q : 投影生成
Wqkv -- K : 投影生成
Wqkv -- V : 投影生成
SelfAttn -- DotProduct : Q 与 K 算相似度
DotProduct -- CosineSim : = |a||b|cos(θ)
SelfAttn -- Softmax : 分数 ÷√d_k 后归一化
Softmax -- WeightedSum : 输出注意力权重
WeightedSum -- V : 对 V 加权求和
MHA -- Head : 并行 h 个头
MHA -- Wo : 拼接后投影融合
Encoder -- MHA : 自注意力子层
Encoder -- FFN : 前馈子层
Encoder -- AddNorm : 每个子层之后
Decoder -- MaskedAttn : 防偷看未来
Decoder -- CrossAttn : 查询原文
CrossAttn -- ContextH : K/V 来源
Encoder -- ContextH : 输出
Decoder -- StartTok : 初始输入
Decoder -- Linear : 最终输出层
Linear -- Logits : x W_out 给每个候选词打分
Logits -- ProbDist : Softmax 转概率
ProbDist -- Token : 取概率最高者输出
Token -- Decoder : 拼接回输入(自回归)
DK -- DModel : d_k = d_model / h
EmbMatrix -- Wout : 常共享参数(互逆查表)
AddNorm -- Residual : 组合
AddNorm -- LayerNorm : 组合
FFN -- Activation : 引入非线性
@enduml