Attention 机制
把序列依赖变成可并行计算的显式数据流
建议阅读:约 20 分钟
学习目标
本章关键词
| 关键词 | 解释 | ESP32 工程类比 |
|---|---|---|
| Attention | 用 Query 与 Key 的匹配分数对 Value 加权聚合的信息交换机制。 | 像按当前查询同时检索多个带索引的 DMA 描述符。 |
| Multi-head | 把表示投影到多个子空间并行执行注意力,再拼接输出。 | 像并行运行多组过滤规则,各自观察不同协议特征。 |
| Causal mask | 阻止当前位置访问未来 token 的上三角可见性约束。 | 像接收状态机只能读取已经到达的字节。 |
| Positional encoding | 向无循环的注意力网络注入 token 顺序或相对距离信息。 | 像给每个环形缓冲区元素附带单调序号。 |
承上:回顾与定位
上一章先建立了完整 Transformer 架构,明确 Attention 只是 block 中负责跨位置通信的子层。本章把这个大概念单独展开,追踪 Q、K、V、mask、多头和位置如何共同决定信息聚合。
历史发展脉络
Attention 从改善 encoder–decoder 对长句的压缩瓶颈开始,随后成为 Transformer 的核心数据流,并扩展到双向预训练、跨模态与 I/O-aware kernel。结构创新与系统优化共同决定它今天能处理多长的上下文。
可学习对齐缓解固定长度编码瓶颈
Bahdanau 等人在神经机器翻译中让 decoder 每一步对 encoder 状态计算对齐权重,不再要求一个固定向量承载整句信息。
神经机器翻译 Attention 原始论文 ↗Transformer 以多头 Attention 取代循环主干
缩放点积、多头 self-attention、位置编码和 causal mask 被组织成可并行训练的 encoder–decoder 架构。
Transformer 原始论文 ↗BERT 用双向 self-attention 建立通用语言表示
Masked language modeling 让表示同时利用左右上下文,展示 Transformer encoder 预训练迁移到多类理解任务的能力。
BERT 原始论文 ↗Vision Transformer 把纯 Transformer 主干带到图像
图像被切成 patch 序列后直接进入 Transformer,说明 attention 的位置交互机制并不局限于自然语言。
Vision Transformer 原始论文 ↗FlashAttention 把瓶颈定位到 HBM 数据移动
I/O-aware 分块在不近似 attention 结果的前提下减少 HBM 读写,表明相同数学公式可因内存层级调度产生巨大实现差异。
FlashAttention 原始论文 ↗类比图解
一座并行检索、分频道汇总的交换矩阵
每个输入端口发出查询,多套匹配电路分别按语法、位置或语义线索给可见端口打分,再从对应数据通道读取内容。各频道结果拼接后进入本地处理单元。矩阵可以同时服务整批输入,但如果下一个输入本身尚未产生,就不能提前处理。
类比的边界: 权重不是人类可直接命名的“语法头”或“事实头”,attention score 也不能单独证明模型的因果解释;类比只描述数据流与并行结构。
本章讲解
论文的第一性原理:缩短串行依赖
论文先把问题拆成三项:每层要花多少计算、多少步骤必须串行、远距离 token 之间要经过多长的路径。Transformer 保留 encoder–decoder 骨架,却用 multi-head self-attention 和逐位置 FFN 替代循环结构与卷积,并用 residual connection、LayerNorm 和 positional encoding 补齐训练稳定性与顺序信息。于是整段输入可以高度并行处理,远距离依赖的路径缩短;但这不等于生成也能并行,decoder 仍按已生成前缀自回归地产生下一个 token。
从公式看懂缩放点积、多头与因果屏蔽
核心公式是 Attention(Q,K,V)=softmax(QKᵀ/√d_k)V。d_k 变大时,点积的方差也会变大,直接送入 softmax 容易饱和、梯度变小;除以 √d_k 是数值稳定措施。Multi-head attention 先用不同的线性投影进入多个表示子空间,再并行计算、拼接并投影回来;causal mask 则把未来位置的分数设为不可见。先在 4 个 token 的小矩阵上验证这三件事,再谈 kernel 或 cache。
没有循环之后,位置信息必须显式进入模型
注意力本身可以同时看见一组位置,却不会自动知道顺序;论文因此把正弦/余弦 positional encoding 加到 embedding 上,并比较了 learned positional embedding。这个选择是模型契约的一部分:tokenizer、位置编码、causal mask 和 cache 的 position 必须一致。端侧工程不能只搬运权重文件,改动其中任一项都要用金向量检查输出是否仍然一致。
从论文的并行性落到 Prefill 与 Decode
论文表中的 O(1) sequential operations 描述的是一层 self-attention 在整段序列上的计算,不是说自回归输出没有顺序。Prefill 一次处理已有 prompt,适合在 token 维并行;Decode 每轮只追加一个新 token,必须等待上一步采样结果,并读取历史 K/V。因此现代 runtime 把一次吞吐导向的 prefill 与多次低延迟 decode 分开计时,不能用论文的并行性结论掩盖 decode 的带宽瓶颈。
一个 Transformer block 不只有 Attention
Attention 负责让位置之间交换信息,逐位置 FFN 则对每个位置应用相同的非线性变换;残差连接为深层网络保留短路径,LayerNorm 稳定各层数值尺度。工程分析应把 QKV 投影、attention score、value 聚合、输出投影和 FFN 分开记账。现代 LLM 中 FFN 权重往往占据大量参数,而长上下文下 attention 的中间矩阵和 K/V 状态又成为显著内存与带宽来源。
Self-attention 的优势来自路径与并行,不是免费计算
论文用每层复杂度、必须串行的操作数和任意位置间最大路径长度比较循环、卷积与 self-attention。Self-attention 缩短远距离依赖路径并允许训练时并行处理序列,却需构造随序列长度平方增长的相关性矩阵。短到中等序列时优势明显;长上下文中则需要稀疏、分块、滑窗或 I/O-aware kernel 等优化,而且这些方法各自改变计算、可见范围或数据移动,不能混称为同一种加速。
从公式到实现要检查 mask、位置与数值稳定性
实现错误常藏在广播后的 mask 方向、padding 与 causal mask 的组合、位置编号偏移、softmax 前的 dtype 和多头 reshape 顺序。建立小矩阵金向量:固定 Q/K/V,保存缩放前后分数、mask 后分数、softmax 权重与最终输出;检查每行权重和为 1,未来位置权重为 0。这样后续优化 kernel、量化或 KV cache 时,能够定位第一个破坏语义的边界。
动态过程演示
一个 token 如何通过多头 Self-Attention 读取上下文
播放器沿张量路径展示投影、打分、屏蔽、归一化、聚合与输出,而不是把 Attention 隐藏在一个黑盒节点里。
嵌入位置 · X = token embedding + position
为每个位置建立带顺序的表示
Attention 本身不会自动产生顺序
循环 / 返回条件: 每个 Transformer block 都重复这条路径;训练时多个位置可并行,生成时新的位置仍必须等待上一 token 被选择。
查看静态全景图
token ids → embedding + position
│
Q = XWq, K = XWk, V = XWv
│
scores = QKᵀ/√dₖ + mask → softmax → weighted V
│
residual + norm → FFN → residual + norm代码或命令示例
scores = Q @ K.T / sqrt(d_k)
scores = scores + causal_mask
weights = softmax(scores, axis=-1)
context = weights @ V
output = concat(heads) @ W_o动手实验
实验记录与导出
工程陷阱
核心测试
完成 3 道单选题后提交;提交前不会显示答案。
在 GitHub 上讨论本章
登录 GitHub 后提问、补充实测或分享你的实现;评论会保存在本课程的 GitHub Discussions 中。
评论区需要 JavaScript;也可以直接打开 GitHub 讨论区: 打开 GitHub 讨论区 ↗
延伸阅读
启下:下一章如何使用本章能力
下一章只讨论 KV Cache:旧 token 的 K/V 为什么可复用、每新增 token 需要多少内存,以及 GQA、分页和量化如何改变容量与带宽。
下一天: Day 11 · KV Cache