5-A2S1-attention.ipynb 逐步说明这份 notebook 你们在 2/1-class-prog.md 里已经知道它的总体目标了:建立 attention 的行为直觉。这里不再重复“它在做什么”,而是专门补上 notebook 里每个关键 cell 的具体作用。
它和后面第 3 课的 LoRA / Qwen 实验也有直接关系:
course_lora_qwen_src 里你们会改 q_proj / k_proj / v_projtorchimport torch这一格很简单,但这里已经在告诉你:后面的 attention 不是符号推导,而是要拿真实张量直接算。
torch.manual_seed(447)作用是让 key / value 等初始化结果固定下来,保证每个同学跑出来的数值环境一致。
这和你们前面在 course_lora-tinygpt2 里做最小实验时固定环境,是同一种“保证可复现”的习惯。
attention(...) 和 check_query(...)def attention(query, key, value):
return F.scaled_dot_product_attention(query, key, value, scale=1)scaled_dot_product_attentionscale=1为什么这么做?
也就是说,这份作业在简化问题,让你先看懂机制。
check_query(...)def check_query(query, target, key=key, value=value):
a_out = attention(query, key, value)
print("maximum absolute element-wise difference:", (target - a_out).abs().max())这个函数的作用不是给你答案,而是告诉你:
这和后面第 3 课里不断打印 loss、检查生成结果,是同一种“先验证行为,再谈理论”的工程思路。
题目要求你构造一个 query,让 attention 输出尽量接近第一个 value 向量。
这里真正想让你体会的是:
所以这道题不是在考“有没有唯一正确答案”,而是在考:
你是否知道 query 要朝哪个 key 的方向靠近。
这道题要求你构造 query matrix,让输出近似等于整个 value 矩阵本身。
它在考的其实是:
这正是后面 multi-head attention、batch 计算能成立的最基本直觉。
这一格最值得注意的不是答案,而是思路:
最朴素的做法就是让 query 对所有 key 的相似度差不多。
这和后面 Transformer 里“某个 token 同时关注多个上下文位置”是同一个机制。
这一格开始从“均匀平均”进阶到“部分平均”。
真正的难点是:
这已经很接近真实 attention 的感觉了:一个 token 往往会对几个相关位置同时分配权重,而不是只盯着一个位置。
这里第一次不改 query,而改 key。
这题很重要,因为它说明:
这和你们后面在第 3 课里改 q_proj / k_proj 的意义是一致的:
这是本 notebook 最“行为操控”味道的一题。
它要你体会:
如果学生能真正理解这题,后面看到第 3 课里:
target_modules=['q_proj','k_proj','v_proj', ...]就不会觉得这是魔法参数,而会知道:这些层控制的正是相似度与信息路由。
如果这三个感觉已经建立起来,A2S2 里的手写 attention 就会顺很多。