01 / 直觉
三个角色:提问、标签、正文
模型处理一句话时,每个词会被算成三份不同的向量。
先别管矩阵怎么乘,记住它们各司其职就行——像图书馆检索:
Q Query · 我要找什么
当前这个词的问题单。
比如读到 it,问题大致是:「刚才哪个名词在指代范围内?」
K Key · 我有什么标签
每个历史词的索引。
像书脊上的关键词:这是动物?是街道?是动作?
V Value · 真正要拿走的内容
匹配上之后被汇总的正文。
相关度高的 V 权重大,相关的词「贡献」更多。
为什么标签和正文要分开?
检索系统也是这样:标题适合被搜到,正文适合被阅读。
用同一份向量干两件事,两边都做不好。K 管匹配,V 管内容。
02 / 计算过程
六步算完一次注意力
不用一次看懂全部公式。点步骤,看中间结果怎么变。
// 用伪代码写一遍
scores = Q · Kᵀ / √d // 点积 = 相似度
scores[mask] = −∞ // 不能看未来
α = softmax(scores) // 变成权重,和为 1
out = α · V // 加权汇总
- 点积当相似度:方向越接近,分数越高。你写
dot(a, b) 时也这么用。
- 除以 √d:维数一大,点积数值会爆炸,softmax 会变成 one-hot。缩放一下更稳。
- 因果掩码:写文本时只能看前文,不能偷看还没生成的词。
03 / 动手
点一个词,看它在看谁
下面是一句英文。点任意词,右边条形图就是它对历史词的注意力权重。
重点看 it——权重会压在 animal 上。
句子:The animal didn't cross the street because it was too tired
04 / 整张表
谁在看谁:一张热力图
每一行是一个位置的提问,每一列是被看的位置。颜色越深,说明越关注。
右上角空白是因为因果掩码——后面的词还没生成。
点一个格子查看详情
05 / 多头
为什么要开多个「搜索员」?
一个头只有一套关注方式。多头(Multi-Head)就是并行开几组 Q/K/V:
有的负责看邻近词,有的抓指代,有的盯固定搭配。最后把结果拼起来。
记法:多头 = 多个小组同时做检索,最后汇总。代价是每个词要多存几份 K/V——这就是下面缓存变大的原因。
06 / 显存
KV Cache:为什么长对话这么吃显存
生成第 100 个词时,它需要「看」前面 99 个词。
如果每一步都重算全部历史的 K 和 V,会非常慢。
工程上做法很直接:把算过的 K/V 缓存起来——这就是 KV Cache。
于是显存占用大约正比于:
批大小 × 序列长度 × 层数 × 每层 KV 宽度。
序列越长、同时服务的人越多,缓存越大。
三种思路一句话:
「标准」每个头各存一份;「共享 K/V」让多个头共用(省 3/4 左右);
「压缩存储」只存一份压缩后的向量,用时再展开(DeepSeek 的 MLA 大致是这条路线)。
07 / 工程提速
模型「更快更省」通常在改什么
面试或读新闻时,常听到这些词。用程序员视角对一下:
少存:压缩 KV Cache
共享 K/V(GQA)、或压成更短的向量(MLA)。
和「把每份日志从 JSON 改成差分编码再存」是同一类思路:
信息还在,占的字节更少。
少算:投机解码
先用小模型猜好几个词,大模型一次验证。
类似 CPU 的分支预测:猜对了就白赚,猜错了回滚重来。
少搬:FlashAttention
不改数学,改的是 GPU 上「中间结果别反复写回显存」。
对写过高性能代码的人:这是访存优化,不是新算法。
更小:蒸馏 / 轻量档
产品名里的 Flash / Lite / Mini,多半是蒸馏出来的小模型档位,
面向低延迟低成本,不一定是新的注意力结构。
读新闻的方法:
问自己三句——
(1) 它是让模型更准,还是更省?
(2) 省的是显存、算力,还是延迟?
(3) 对应到缓存、访存、还是模型尺寸?
08 / 小结
五句话带走
- Q 是问题,K 是标签,V 是正文。 检索系统的直觉可以直接搬过来。
- 相关度 = 点积,权重 = softmax,输出 = 加权和。 核心就这三行。
- 多头 = 并行开几组搜索员,各看各的,最后合并。
- KV Cache 让长对话变快,也让显存随序列长度线性上涨。
- 听到 GQA / MLA / FlashAttention,分别对应:少存 / 压缩存 / 少搬数据。
想再深入一点
- Jay Alammar, The Illustrated Transformer(最友好的图解)
- Vaswani et al., Attention Is All You Need(原始论文)
- 任一主流开源模型的「model card」——看它写了 GQA 还是 MLA