返回关卡地图
预判 0 / 2 闯关题:0 / 2 XP 0 / 200

Level 02 | 零基础导学关卡

SwiGLU Activation

每个 Mission 先猜一猜(押个假设解锁讲解)→ 看图解原理 → 做巩固题 → 回 notebook 写代码。带着问题学,比直接读记得牢。

02_SwiGLU_Activation.ipynb FFNActivationGate
先猜一猜
图解原理
巩固 + 作业
SwiGLU(x) = (x Wv) * SiLU(x Wg)
Mission 1 TODO 3 / TODO 4

门控:一路当开关,一路当内容(顺便数清楚有几块矩阵)

🎯 先猜一猜(下注解锁)

普通 MLP 升维只用 1 块矩阵就够了。SwiGLU 偏要拆成 gate + up 两块,凭空多花一倍参数——它图的到底是什么?

先押一个假设:SwiGLU 多花一块升维矩阵,最核心的目的是?

先押一个假设,下面的讲解就会解锁。猜错完全没关系——带着疑问读,记得最牢。

先补的知识

  • Linear(d_in, d_out) 就是一块权重矩阵,把最后一维从 d_in 映射到 d_out。
  • SiLU(x) = x · sigmoid(x),是一条平滑的激活曲线,输出可正可负、像“软开关”。
  • 两个 shape 完全相同的张量可以逐元素相乘(Hadamard ⊙)。

图解原理

传统 MLP 升维后只过一次激活,像一条单行道;SwiGLU 把升维这步分成并行两条:gate 支路算“开关强度”,up 支路算“内容”,两者相乘后再降维。记住它一共用了 3 块矩阵——下一关的参数推导全靠这个数字。

普通 MLP:一条单行道(2 块矩阵)

x 先升维,过一次固定激活(如 ReLU 把负数一刀切成 0),再降维。开关是写死的,不会随数据变。

xW_up → 激活W_down
SwiGLU:把“升维 + 激活”这一步拆成并行两条支路
门控 MLP:内容 × 开关(3 块矩阵)

up 支路(W_up)产出“内容”;gate 支路(W_gate)产出一个经 SiLU 的“开关强度”。两条 shape 一样,逐元素相乘,再用 W_down 降回原维度。

gate = SiLU(x · W_gate) → 开关 up = x · W_up → 内容 W_down( gate ⊙ up )

开关由数据自己学:该放行的位置接近 1,该压制的接近 0,比固定的 ReLU 灵活得多——这就是 SwiGLU 表达力更强的来源。

数一数矩阵:W_gate、W_up、W_down 共 3 块。传统 MLP 只有 2 块。多出来的那块 gate 就是门控的“代价”,下一关要把它算进账。

语法热身:用“开关 × 内容”筛选数值

knob  = torch.tensor([-1.0, 0.0, 2.0])   # 开关原始打分
value = torch.tensor([10.0, 10.0, 10.0]) # 内容

# sigmoid 把开关压到 0~1:负数→趋近 0(关),正数→趋近 1(开)
gate = torch.sigmoid(knob)               # [0.27, 0.50, 0.88]
filtered = gate * value                  # [2.7, 5.0, 8.8]
# 真正的 SwiGLU 用 F.silu 代替 sigmoid,思路完全一样

巩固一下

巩固:gate 和 up 两条支路的输出,必须满足什么条件才能执行 gate ⊙ up?

回到 notebook 的作业

这里不直接写答案。你已经拿到足够输入,最后用 notebook 的 TODO 做举一反三。

Mission 2 TODO 1 / TODO 2

为什么是 8/3 d?——给门控“多出来的那块矩阵”买单

🎯 先猜一猜(下注解锁)

传统 MLP 中间层惯例放大到 4d。换成 SwiGLU 后,LLaMA 却把它缩到了奇怪的 8/3 d ≈ 2.67d。这个分数到底从哪冒出来的?

先押一个假设:8/3 这个比例最可能是怎么定下来的?

先押一个假设,下面的讲解就会解锁。猜错完全没关系——带着疑问读,记得最牢。

先补的知识

  • 一块权重矩阵的参数量 ≈ 输入维度 × 输出维度。
  • 传统 MLP 用 2 块矩阵;SwiGLU 因为多了 gate 支路,用 3 块(见上一关)。
  • “计算开销 / 参数量相同”是人为加的约束,目的是做公平对比,不是天然规律。

图解原理

8/3 不是魔法数字,而是一道初中解方程题的答案。先想清楚我们到底在跟谁比、为什么要比平,再把两边的矩阵数清楚,令它们相等,h 自然就解出来了。

0. 先想清楚:我们到底在比什么、为什么要比平?

SwiGLU 听起来更强,但它比传统 MLP 多了一条 gate 支路——等于凭空多塞了一整块大矩阵。如果直接加上去,模型自然变大、变慢。

那它效果好,究竟是“门控结构聪明”,还是单纯“参数更多、堆料堆出来的”?为了把这两者分开,研究者人为规定:让 SwiGLU 的参数量 = 传统 MLP 的参数量。这样一来,在“同样大小、同样算力预算”下 SwiGLU 还更好,功劳才能确凿地算到门控结构头上。这就是“让计算开销完全相同”的真正动机——它是一条公平竞赛规则,不是物理定律。

既然要比平,那就把两边的参数各数一遍
1. 传统 MLP 有多少参数?→ 8d²

设输入维度 = d,按惯例中间层放大到 4d。两块矩阵:升维一块、降维一块。一块的参数量 ≈ 行 × 列。

W_up:d × 4d = 4d² W_down:4d × d = 4d² 合计 = 8d²
SwiGLU 升维分叉成两块,于是是 3 块矩阵
2. SwiGLU 有多少参数?→ 3 · d · h

设 SwiGLU 的中间维度是未知数 h。升维分成 gate、up 两块(各 d × h),降维一块(h × d)。

W_gate:d × h W_up:d × h W_down:h × d 合计 = 3 · d · h
套用公平规则:令两边相等,解出 h
3. 解方程 → h = 8/3 d

把竞赛规则写成等式,两边都有一个 d,约掉即可:

3 · d · h = 8d²h = 8d / 3 ≈ 2.67 d

看懂这个结果:SwiGLU 的中间维度不是 4d,而是缩到约 2.67d。缩小的这部分,正好补偿掉多养一块 gate 矩阵的开销,于是总参数追平。这就是 LLaMA 源码里 int(8 * hidden_size / 3) 的全部来历。

最后一步工程修正:对齐到整齐的倍数
4. 向上对齐 multiple_of(如 256)

8/3 算出来常是零碎数(d=4096 时 ≈ 10922)。GPU 喜欢整齐维度:Tensor Core 要求对齐、张量并行时还得能被 GPU 张数整除。所以向上取整到 256 的倍数:10922 → 11008。

对齐会让参数量比理论值略大一点点,这是为了硬件效率付的小钱,不影响“追平传统 MLP”的初衷。

语法热身:把一个数向上补齐到某个倍数

TODO 2 要把 8/3 d 向上对齐到 multiple_of。先用排座位的小例子练这个“向上取整”技巧:

people = 26      # 要坐的人数(类比理论 intermediate_size)
row    = 8       # 每排 8 个座位(类比 multiple_of)

# 直接整除会向下丢人:26 // 8 = 3 排,只坐 24 人 ❌
# 先 +(row-1) 再整除,就能“向上取整”到能装下所有人的排数
aligned = ((people + row - 1) // row) * row   # = 32 ✅

读法:(n + m - 1) // m * m 是“把 n 向上对齐到 m 的倍数”的标准写法,记下来,工程里到处用。

巩固一下

巩固(动手算):hidden_size = 12 时,按 8/3 算出的理论 intermediate_size 约是多少?

回到 notebook 的作业

这里不直接写答案。你已经拿到足够输入,最后用 notebook 的 TODO 做举一反三。

完成 2 道闯关题后,本关即算完成;作业 checklist 用来辅助你回 notebook 练习。
进度只保存在当前浏览器 localStorage,分享 HTML 不会带走你的记录。
上一关:L01 下一关:L03