attention 的本质:动态加权求和

项目目标

这一段路线把 token 序列变成一个真正的 decoder-only Transformer。

顺序不能乱。先有 token embedding,再加位置;先手写单头 scaled dot-product attention,再扩展到 multi-head;先拼一个 decoder block,再堆成 mini-former;最后再讨论 causal LM、masked LM、prefix LM、denoising objective 的差异。

如果直接从完整 Transformer 开始,很容易只记住一堆层名。按项目拆开之后,每个部件都能用一句话解释:它解决了哪一个缺陷。

项目 3:实现位置编码

attention 本身不认识顺序。如果没有位置,我打你你打我 的 token 集合很接近,但语义截然不同。

要实现四类位置方法:

方法思路要观察的问题
learned position embedding每个位置一行可学习向量简单,但外推到更长上下文较弱
sinusoidal用不同频率的 sin/cos 编码位置不需要训练,经典 Transformer 方案
RoPE在向量空间里按位置旋转 Q/K相对位置信息自然进入 attention
ALiBi给 attention score 加距离偏置更偏向长度外推

最小实验:训练同一个小模型,只替换位置方法,比较训练 loss、验证 loss、超过训练长度后的生成质量。

破坏实验:完全去掉位置编码。观察模型是否更容易混淆顺序关系。

项目 4:手写单个 scaled dot-product attention

注意力的最小公式是:

scores = q @ k.transpose(-2, -1) / head_size**0.5
scores = scores.masked_fill(causal_mask == 0, float("-inf"))
weights = scores.softmax(dim=-1)
out = weights @ v

它只有三件事:

  1. Q 和 K 点积,得到匹配分数。
  2. causal mask 屏蔽未来 token。
  3. 用 softmax 后的权重对 V 加权求和。

必须画一张 attention heatmap。横轴是被看的 token,纵轴是当前位置。下三角之外应该全为零。如果未来位置有权重,说明 mask 写错了。

破坏实验:

  • 去掉 head_size**0.5 缩放,看 softmax 是否过早变尖。
  • 去掉 causal mask,看训练 loss 是否异常变好、生成时是否变差。
  • 把 Q/K/V 乱换,看模型是否还能学。

项目 5:扩展到 multi-head attention

单个 head 只能在一个子空间里匹配关系。multi-head 的直觉是:让不同 head 学不同关系。

实现方式是多个 head 并行,然后 concat,再过一个 projection:

out = torch.cat([head(x) for head in self.heads], dim=-1)
out = self.proj(out)

观察指标:

  • 每个 head 的 attention heatmap 是否不同。
  • head 数增加后训练 loss 如何变化。
  • 固定 embedding 维度时,head 数过多是否导致单 head 维度太小。

破坏实验:只保留一个 head,或者把所有 head 的输出平均掉,观察表达能力变化。

项目 6:拼一个 decoder block

一个 GPT block 的最小结构:

x = x + self_attention(norm(x))
x = x + mlp(norm(x))

需要实现:

  • token embedding
  • position embedding 或 RoPE
  • masked multi-head self-attention
  • residual connection
  • LayerNorm 或 RMSNorm
  • feed-forward network
  • output projection

这里要特别关注 residual 和 norm。如果去掉 residual,深层模型更难训练。如果 norm 放置位置不同,会影响稳定性。现代 decoder 常见的是 pre-norm。

破坏实验:

  • 去掉 residual,看 loss 是否震荡或不收敛。
  • 把 pre-norm 改成 post-norm,观察小模型是否更难训。
  • 把 MLP 缩小到很小,看模型容量瓶颈。

项目 7:堆成 mini-former

堆多个 block 后,就可以训练一个真正的 tiny decoder-only language model。

建议先固定一个很小配置:

n_layer = 4
n_head = 4
n_embd = 128
block_size = 128
batch_size = 32

训练时必须记录:

  • train loss
  • val loss
  • tokens/sec
  • 显存占用
  • 每隔固定 step 的生成样例

这里的目标不是让模型有用,而是理解训练循环:数据 batch、forward、loss、backward、optimizer step、eval、generate。

项目 8:对比训练目标

GPT 走 causal LM:只看过去,预测下一个 token。

BERT 走 masked LM:遮住一部分 token,让模型根据左右上下文恢复。

T5 一类模型把任务转成 text-to-text,并使用 denoising objective。

要做一个小实验:

  1. 同一份小语料。
  2. 同等规模模型。
  3. 分别实现 causal LM、masked LM、prefix LM。
  4. 对比 loss 曲线和生成/恢复样例。

这会帮助理解:模型架构相似,不代表训练目标相同;训练目标直接决定模型擅长补全、生成、理解还是转换。

本项目交付物

  • 4 种位置编码的最小实现。
  • 单头 attention heatmap。
  • multi-head attention heatmap 对比。
  • 一个 decoder block。
  • 一个 mini-former 训练脚本。
  • train/val loss 曲线。
  • 至少 3 组破坏实验记录。

和本站已有内容的连接

  • mini-gpt/05-注意力机制让模型看见上下文
  • mini-gpt/06-拼出一个真正的GPT结构
  • mini-gpt/07-完整训练看它从胡言乱语到像模像样
  • ml-basics/注意力机制
  • ml-basics/Transformer

延伸阅读

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:项目 3-8:位置、注意力与 Transformer Block

本文链接:https://www.sshipanoo.com/blog/ai/llm-roadmap/03-PositionAttentionTransformer项目/

本文最后一次更新为 天前,文章中的某些内容可能已过时!