DS1367780968头像
关注

从零读懂 Transformer:结构、注意力、位置编码与推理优化

0. 为什么人人都在谈 Transformer

2017 年 Google 的论文 Attention Is All You Need 提出了 Transformer。它几乎不用 RNN/CNN 的串行或局部卷积,而是靠 自注意力(Self-Attention) 一次性建模序列里任意两个位置的关系。

后来:

  • BERT 等 Encoder 模型把「理解类任务」推上新高度;
  • GPT 等 Decoder-only 模型把「生成」做成大模型范式;
  • 图像(ViT)、多模态、推荐、代码生成……底层骨架多半还是 Transformer。

一句话:Transformer = 可并行的全局注意力 + 残差 + 归一化 + 前馈网络,再叠很多层。


1. 一张图看懂整体结构

原始 Transformer 是 Encoder–Decoder 结构(机器翻译最典型):

源句子 → [Embedding + 位置编码]
              ↓
        N × Encoder Block
              ↓
        编码矩阵 C(全局上下文)
              ↓
目标句子 → [Embedding + 位置编码] → N × Decoder Block → Linear + Softmax → 下一个词概率

1.1 三步直觉流程

  1. 输入表示
    每个 token 的向量 = 词嵌入(语义) + 位置信息(相加,维度相同)。

  2. Encoder
    源序列所有位置互相可见,输出矩阵:

C∈Rn×d C \in \mathbb{R}^{n \times d} CRn×d

其中 nnn 为序列长度,d=dmodeld = d_{\mathrm{model}}d=dmodel(论文默认 512)。
每一层输入输出形状一致,可叠多层。

  1. Decoder
    按目标语序生成:训练可用 Teacher Forcing + 因果掩码 并行;推理则 自回归 逐 token 生成。
    每个 Decoder 层里通常有:
    • 掩码自注意力:只看已生成的目标端上文;
    • 交叉注意力:Query 来自 Decoder,Key/Value 来自 Encoder 的 CCC
    • FFN + 残差 + 归一化

1.2 为什么每一层 Decoder 都要直接读 Encoder 的 CCC

不是「只把 CCC 给第一层,再一层层往下传」。

角度只给第一层再下传每层独立读 CCC(真实设计)
信息全局源端信息被第一层压缩,后面易稀释每层都可按当前 Query 重新取源端细节
对齐粒度高层难回看细粒度词对齐低层词对齐、高层语义对齐可同时学
梯度回传到 Encoder 路径更长多层交叉注意力提供多条直连梯度路径
分工自注意与交叉注意混在一起自注意纵向传目标上下文;交叉注意横向直连源端记忆

通俗比喻:翻译时,你要记住自己已经写出的中文(自注意),但每写一句都还应 重新对照完整英文原文(交叉注意),而不是只看上一句草稿。


2. 输入侧:词嵌入 + 位置编码

2.1 词嵌入(Token Embedding)

  • 查表:token_id → d_model 维向量
  • 可预训练(Word2Vec/GloVe)或端到端训练
  • 实现上常见缩放:乘以 dmodel\sqrt{d_{\mathrm{model}}}dmodel(Annotated Transformer 风格)

2.2 为什么必须有位置信息?

自注意力对位置置换近似对称:没有位置,就分不清「猫追狗」和「狗追猫」
RNN 靠逐步读入带顺序;Transformer 并行算全局注意力,必须显式注入位置

流程:

分词 → Token Embedding(语义) + 位置信息 → 送入 Transformer

2.3 正弦位置编码(原论文绝对位置编码)

对位置 pos\mathrm{pos}pos、维度索引 i=0,1,…,dmodel/2−1i = 0,1,\ldots,d_{\mathrm{model}}/2-1i=0,1,,dmodel/21

PE(pos, 2i)=sin⁡(pos100002i/dmodel) PE_{(\mathrm{pos},\,2i)} = \sin\left(\frac{\mathrm{pos}}{10000^{2i/d_{\mathrm{model}}}}\right) PE(pos,2i)=sin(100002i/dmodelpos)

PE(pos, 2i+1)=cos⁡(pos100002i/dmodel) PE_{(\mathrm{pos},\,2i+1)} = \cos\left(\frac{\mathrm{pos}}{10000^{2i/d_{\mathrm{model}}}}\right) PE(pos,2i+1)=cos(100002i/dmodelpos)

要点:

  • 偶数维 sin、奇数维 cos;
  • 无训练参数,公式生成固定表,与词向量 逐元素相加
  • 相对位置可用三角恒等式表达:PEpos+kPE_{\mathrm{pos}+k}PEpos+kPEposPE_{\mathrm{pos}}PEpos 存在固定线性关系,模型有机会学到相对距离;
  • 比「训练时最长 20、推理 21 就挂」的可学习绝对位置表,对略超长序列更友好——但长文本外推仍有限。

2.4 常见位置编码对比(科普版)

方式怎么做类型长文本外推代表
正弦 PE词向量 + 位置向量绝对一般原版 Transformer
可学习 PE位置向量当参数训绝对超出训练长度易崩BERT
RoPE对 Q/K 做旋转,把位置编进角度相对友好较好,常配合缩放/YaRN 等LLaMA、Qwen、DeepSeek
ALiBi注意力分数按距离加偏置衰减相对外推友好部分开源模型

RoPE 直觉(别吹过头):

  • 对位置 mmmQQQ、位置 nnnKKK 旋转后,点积主要依赖相对距离 m−nm-nmn
  • 角度可对任意 pos 计算,比固定长度绝对表更容易做长度外推
  • 工程上仍常用 Linear Scaling / YaRN / 动态 NTK 等增强超长上下文,不是「装上 RoPE 就无限完美外推」

常见误区:说「RoPE 自带强远程衰减」——衰减设计更典型的是 ALiBi;RoPE 的优势重点在相对位置与外推友好,不要和 ALiBi 混谈。

2.5 词嵌入 vs 位置编码

词嵌入位置编码
回答这个词是什么意思它在第几个位置 / 与其他词差多远
维度dmodeld_{\mathrm{model}}dmodel必须同维才能相加
融合语义 + 位置 → 编码器输入

3. 自注意力:Transformer 的发动机

3.1 Q、K、V 是什么

对输入矩阵 X∈Rn×dX \in \mathbb{R}^{n \times d}XRn×d(每行一个 token):

Q=XWQ,K=XWK,V=XWV Q = XW^{Q},\quad K = XW^{K},\quad V = XW^{V} Q=XWQ,K=XWK,V=XWV

名字角色(检索比喻)
Query QQQ我现在想查什么
Key KKK每条内容的索引标签
Value VVV真正取出的内容

3.2 缩放点积注意力(Scaled Dot-Product Attention)

Attention(Q,K,V)=softmax(QK⊤dk)V \mathrm{Attention}(Q,K,V) = \mathrm{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQK)V

分步:

  1. 相似度QK⊤QK^{\top}QK,得到 n×nn \times nn×n 的分数(谁关注谁);
  2. 缩放:除以 dk\sqrt{d_k}dkdkd_kdk 大时点积方差变大,softmax 易饱和 → 梯度变小;缩放稳住训练;
  3. Mask(可选):把不该看的位置设为很大的负数(如 −∞-\infty-1e9),softmax 后权重 ≈ 0;
  4. Softmax:对 每一行(每个 Query)归一化,得到注意力权重;
  5. 加权求和:权重乘 VVV,输出与输入序列等长的上下文向量。

表述修正:注意力整体 不是纯线性WQ,WK,WVW^{Q},W^{K},W^{V}WQ,WK,WV 是线性,但 softmax 是非线性,因此整模块能做复杂的内容选择与混合。

3.3 三种注意力的 QKV 来源

类型QKV作用
Encoder 自注意力来自 Encoder同左同左源句双向全局建模
Decoder 掩码自注意力来自 Decoder同左同左目标端只能看过去,自回归
交叉注意力来自 Decoder来自 Encoder 的 CCC来自 CCC目标位置对齐源端信息

3.4 多头注意力(Multi-Head Attention)

不是只算一次注意力,而是切成 hhh 个头,各自一套投影,在子空间里学不同模式(句法、指代、短距/长距等),再拼接投影回去:

headi=Attention(QWiQ,KWiK,VWiV) \mathrm{head}_i = \mathrm{Attention}(QW_i^{Q}, KW_i^{K}, VW_i^{V}) headi=Attention(QWiQ,KWiK,VWiV)

MultiHead(Q,K,V)=Concat(head1,…,headh)WO \mathrm{MultiHead}(Q,K,V) = \mathrm{Concat}(\mathrm{head}_1,\ldots,\mathrm{head}_h)W^{O} MultiHead(Q,K,V)=Concat(head1,,headh)WO

常见设定:dmodel=512d_{\mathrm{model}}=512dmodel=512h=8h=8h=8,则 dk=dv=64d_k=d_v=64dk=dv=64
输出形状与输入 XXX 一致,方便残差相加。

实现提示(代码里易错):

  • 投影后 reshape 为 [batch, head, seq, d_k] 再算注意力;
  • mask 广播维度应对齐 head,常见是在 head 维 unsqueeze,不要搞错维;
  • 因果 mask 用 下三角为 1(可见)、上三角为 0(屏蔽) 时,应对 mask==0 填大负数。

4. Encoder 积木:Attention + Add&Norm + FFN

4.1 原论文结构:Post-LN

原版 Transformer 子层公式是:

LayerNorm(x+Sublayer(x)) \mathrm{LayerNorm}\big(x + \mathrm{Sublayer}(x)\big) LayerNorm(x+Sublayer(x))

即:先子层,再残差相加,再 LayerNorm(Post-LN)。

每个 Encoder Block 大致:

x
 → Multi-Head Self-Attention
 → 残差 + LayerNorm
 → Feed Forward
 → 残差 + LayerNorm
 → 输出(形状仍为 n × d)

4.2 现代大模型更常见:Pre-LN

x → LayerNorm → Attention → +x
  → LayerNorm → FFN      → +x

残差旁路尽量「干净」直通。
LLaMA、Qwen 等多为 Pre-LN;BERT 仍是 Post-LN 一类设计。
不要写成「BERT、LLaMA 都是 Pre-LN」。

4.3 残差连接在干什么

xout=x+F(x) x_{\mathrm{out}} = x + \mathcal{F}(x) xout=x+F(x)

  • xxx:旁路原始输入;
  • F(x)\mathcal{F}(x)F(x):Attention 或 FFN 的变换结果(工程上是前向输出;数学上可看成相对 xxx 的修正量)。

三大作用:

  1. 缓解深层梯度消失:反向时有一条近似「+1」的直通路径;
  2. 学增量更容易:必要时 F(x)≈0\mathcal{F}(x)\approx 0F(x)0,等价跳过该子层;
  3. 保留底层信息:词义、位置等不易被多层非线性冲掉。

4.4 为什么 NLP 用 LayerNorm 而不是 BatchNorm?

BatchNormLayerNorm
统计范围跨 batch 样本单样本特征维内
小 batch统计不稳batch=1 也稳定
变长 + Padding易被 PAD 污染不受其他句/PAD 牵连
训练/推理推理常用滑动均值公式一致
典型场景CNN 图像Transformer / 变长序列

补充:RMSNorm 去掉均值中心化、只做均方根缩放,更快,LLaMA/Qwen 常用。

4.5 FFN:为什么常是「先升维再降维」?

原论文 FFN(逐位置、两层全连接):

FFN(x)=max⁡(0,xW1+b1)W2+b2 \mathrm{FFN}(x) = \max(0, xW_1+b_1)W_2+b_2 FFN(x)=max(0,xW1+b1)W2+b2

形状直觉(以 768 为例):768→3072→768768 \rightarrow 3072 \rightarrow 7687683072768(约 4 倍)。

怎么理解:

  1. 注意力:主要在序列维上混合不同 token 的信息;
  2. FFN:对 每个 token 自己的特征 做非线性变换,提高容量;
  3. 升维 → 激活(ReLU/GELU/SwiGLU 等)稀疏筛选 → 降维回 dmodeld_{\mathrm{model}}dmodel 以配合残差。

注意:

  • 「4 倍」是经典经验折中,不是物理定律;现代模型有 SwiGLU 等变体,中间维设定会不同;
  • 原论文中间层是 ReLU;很多 BERT 实现用 GELU;当代 LLM 常用 SwiGLU 等。

5. Decoder 重点:掩码、训练并行、推理串行

5.1 因果掩码(Causal / Look-ahead Mask)

生成第 iii 个词时,不能看见 i+1,i+2,…i+1,i+2,\ldotsi+1,i+2,

  • QK⊤QK^{\top}QK 上对「未来位置」加 −∞-\infty
  • Softmax 后未来权重 ≈ 0;
  • 因而 ZiZ_iZi 只聚合「自己 + 过去」的 VVV

命名别绕晕:

  • 「下三角可见」:保留对角线及以下;
  • 「上三角屏蔽」:把右上角未来置为不可见。
    两种说法描述同一件事,写文章时固定一种并配一张示意即可。

5.2 训练 vs 推理

训练推理生成
目标端输入完整标准答案(Teacher Forcing)上一步模型自己吐出的 token
序列维计算可并行(一次算整句各位置损失)必须串行自回归
防泄密因果掩码天然只拼已生成前缀;Prefill 仍要因果逻辑
优化KV Cache 避免重复算历史 K/V

类比:

  • 训练 = 对着标准答案整张卷子一起算分;
  • 推理 = 闭卷写作文,写完上句才能写下句。

5.3 交叉注意力再强调

  • QQQ:当前解码位置「我需要什么」;
  • K,VK,VK,V:源端编码 CCC「原文里有什么」;
  • 不需要对源端做未来掩码(源句在编码阶段已全部可见)。

最后 Decoder 顶层接线性层 + Softmax,得到词表上的下一个 token 分布。


6. 推理优化:KV Cache(只在生成时)

6.1 痛点

自回归每步都要和全部历史做注意力。若每步把历史 Q/K/V 全重算,浪费极大。

6.2 做法

  • 只缓存历史的 K、V(各层各自一份);
  • 新 token 只算自己的 Q/K/V,K/V 追加进缓存,Q 与 全部历史 K 做注意力。

为什么不缓存 Q?
Q 表示 当前步 的查询,步步不同;K/V 是历史内容的键值,可复用。

6.3 Prefill 与 Decode

用户 Prompt
  → Prefill:处理整段 prompt,写入 KV,得到首个生成 token
  → Decode:每次 1 个新 token,读缓存 + 追加,直到 EOS
PrefillDecode
输入整段 prompt单 token
KV首次写入读历史 + 追加
常见瓶颈算力显存带宽
指标语感首字时延 TTFT续写流畅度

复杂度表述(严谨一点):
相对「每步重算全部历史」,逐步 decode 的边际成本可降到与当前长度近似线性相关;生成长度为 nnn 时,总注意力代价仍常是 O(n2)O(n^2)O(n2),只是常数与工程实现好很多。科普里说「用显存换重复计算」比绝对说「从 O(n2)O(n^2)O(n2) 变成 O(n)O(n)O(n)」更稳妥。

6.4 显存压力与常见缓解

  • GQA/MQA:多组 Q 共享少量 KV 头,缓存缩小;
  • KV 量化(INT8/INT4);
  • PagedAttention(分页管理 KV,提吞吐);
  • 滑动窗口 / 只保留近期 KV 等。

7. 分词与 OOV:大模型输入的前站

7.1 OOV(Out-of-Vocabulary)

词表外的词。纯词表 + [UNK] 会让不同新词共用一个向量,语义糊掉。

7.2 粒度对比

粒度单元OOV序列长度现状
词级整词易 OOV传统 NLP
字符级字/字母几乎无很长辅助/特殊场景
子词高频片段极少适中工业标配
字节级 BBPEUTF-8 字节理论上无偏长,靠合并压GPT 系底层思路

7.3 三种子词算法

算法合并依据特点代表
WordPiece更偏语言模型似然增益常带 ## 续片标记BERT
BPE / BBPE高频字节对/字符对生成模型常用GPT、LLaMA
SentencePieceBPE 或 Unigram,可直接吃原始句中日韩、多语言友好T5 等

原则:高频整词保留,低频/新词拆成词表内片段,在语义完整与无 OOV 之间折中。


8. 和 ResNet 的关系(一句话串起来)

ResNet 用

H(x)=F(x)+x H(x)=F(x)+x H(x)=F(x)+x

解决深度 CNN 退化与梯度问题;Transformer 把同一思想搬到 NLP:每个子层都残差,再配合 LN,才能稳稳堆 12、24、甚至上百层。

  • ResNet:偏局部卷积、视觉;
  • Transformer:偏全局注意力、序列与多模态。

9. 极简公式速查

位置编码(正弦)

PEpos,2i=sin⁡ ⁣(pos100002i/d),PEpos,2i+1=cos⁡ ⁣(pos100002i/d) PE_{\mathrm{pos},2i}=\sin\!\left(\frac{\mathrm{pos}}{10000^{2i/d}}\right),\quad PE_{\mathrm{pos},2i+1}=\cos\!\left(\frac{\mathrm{pos}}{10000^{2i/d}}\right) PEpos,2i=sin(100002i/dpos),PEpos,2i+1=cos(100002i/dpos)

缩放点积注意力

Attention(Q,K,V)=softmax ⁣(QK⊤dk)V \mathrm{Attention}(Q,K,V)=\mathrm{softmax}\!\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQK)V

残差 +(Post)归一化

y=LayerNorm(x+Sublayer(x)) y=\mathrm{LayerNorm}\big(x+\mathrm{Sublayer}(x)\big) y=LayerNorm(x+Sublayer(x))

FFN(原论文)

FFN(x)=ReLU(xW1+b1)W2+b2 \mathrm{FFN}(x)=\mathrm{ReLU}(xW_1+b_1)W_2+b_2 FFN(x)=ReLU(xW1+b1)W2+b2


10. 一篇文章建议记住的 12 句话

  1. Transformer 用自注意力并行建模全局依赖,不再依赖 RNN 逐步递推。
  2. 输入 = 语义嵌入 + 位置信息。
  3. Attention 用 Q 去匹配 K,再按权重汇总 V。
  4. 除以 dk\sqrt{d_k}dk 是为了训练稳定。
  5. Multi-Head = 多组子空间注意力再拼接。
  6. Encoder 双向;Decoder 自注意因果掩码;交叉注意读源端 CCC
  7. 残差让深层可训;LN 适配变长与小 batch。
  8. FFN 做逐 token 非线性扩容,常先升维再降维。
  9. 训练可并行(Teacher Forcing + Mask);推理自回归串行。
  10. KV Cache 缓存历史 K/V,加速 decode。
  11. 子词分词基本消灭 OOV。
  12. 现代 LLM:Decoder-only + Pre-LN + RoPE + GQA + 更大上下文,是同一骨架上的工程进化

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/DS1367780968/article/details/163134166

文章来源crawl

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--