Embedding 维度越大越好吗?
本课一问:Embedding 维度越大越好吗?
这一课先不碰:宽度、深度、数据量怎么一起定(C6 规模)、模型变宽之后学习率怎么跟着调(C8)。只回答 d 这一个数的取舍。
d 不只是 embedding 的长度
点任一已学环节,看这一步的输入 → 输出形状、参数量,以及它解决了什么问题(数字取自 Qwen/Qwen3.8-27B 真实 config)。
贯穿例句「小明把苹果给了小王」查表后是 [5 × 5120]:5 是 token 数,5120 就是本课要问的 d。点开流水线里的每一格看形状:Qwen3.8 从 Embedding 查表出来是 [T × 5120],之后每一层注意力、FFN 的输入输出都是 [T × 5120],一直到 lm_head。d 是贯穿整个模型的宽度(hidden size),embedding 的每一行只是它第一次出现。所以「embedding 维度」一改,整个模型都跟着变宽或变窄。
朴素的想法:维度越大,表示能力越强
对话样本(L581–L601)说得对:维度越高,能装的信息越多。那就开大一点?按我们项目模型的结构,算算每一档宽度的参数:
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
d 是超参数:在你的算力、显存和数据量之内,用实验比出来。我们项目的做法:同一份数据、同样的步数和学习率,只改 d_model 训三档,比 val loss 与参数量。
真实模型的宽度是怎么定的
本课在演进图里的位置:
- 解决了不用训练,任何文字都能编号。卡在码点从 0 排到 1,114,111,embedding 表得开 1,114,112 行,是 Qwen3.8 实际 248,320 行的 4.5 倍;而且一个字一个 ID,序列一点不缩短。
- 解决了字符集封闭,词表小。卡在序列最长:209 字的段落按字切要做 43,681 次注意力打分,是 Qwen3.8 子词切分(106 个 token)的 3.9 倍。
- 解决了一个词一块,序列短。卡在词是开放集合:我们的语料按空白和标点切出 70,310 种块,94.8% 只出现过一次;验证集里连训练集没见过的字都有 83 种——含它们的词只能记成 UNK。
- 解决了按频次反复合并相邻对:常见的整块、罕见的拆碎,词表大小由合并次数控制。卡在初始单元是字符:要覆盖全部 Unicode,基础词表就超过 13 万(GPT-2 论文 §2.2);只收见过的字,我们的验证集照样缺 83 种字。
- 解决了初始词表就是 256 个字节,任何文字都能编码,永远不出 UNK。卡在词表没学过的语言会被切碎:同义的中文段落,GPT-2 切 461 个 token,Qwen3.8 切 106 个,差 4.3 倍;同义英文段落两者一样多。
- 解决了中文常用字串整块进词表:「我喜欢机器学习」只要 2 个 token(GPT-2 要 17 个)。各家词表:DeepSeek-V3 129,280 · Qwen3 151,936 · GLM-5.3 154,880 · Kimi K3 163,840 · Qwen3.8 248,320。卡在两头各一张 V × d 的表:2 × 248,320 × 5,120 = 2,542,796,800 个参数,占 Qwen3.8 的 9.2%;同样的词表搬到我们 d = 256 的小模型上,embedding 占 95.3%。
- 解决了ID 只是行号,取出一行 5,120 维向量;one-hot 乘矩阵与查表等价,但查表只拷现成的数。卡在表里的 1,271,398,400 个数(输入端一张表)从哪来?人填不完,也不知道每一维该是什么意思。
- 解决了用「预测下一个 token」的 loss 端到端训练,用法相近的 token 被推到相近的位置。卡在只在出现时才被推:我们的项目里一个 batch 8,192 个位置,平均只出现 1,453 个不同 token;罕见 token 学得少——MiniMax 的「嘉祺」在后训练里被推偏,输出层那一行与原来的余弦只剩 0.329。
- 表示 ③ 向量该多宽(hidden size d) 各家自选:GPT-2 768 · Qwen3-8B 4,096 · Qwen3.8-2.4T 8,192 · Qwen3.8-27B 5,120 本课解决了维度越高,每个 token 能装的信息越多。卡在参数按 d² 涨:我们的模型 d 从 128 到 256,总参数 1,066,112 → 3,688,704,val loss 4.776 → 4.641(d = 256 这一档是参照 run ref_baseline,与项目基线同配置同种子;基线记录的 4.626 与它之差是重跑波动,见 C14);没有公式能给出「最优的 d」。
先读我们自己的三档:d 从 64 到 128,总参数 ×3.2,val loss 从 5.073 降到 4.776(降 0.297);从 128 到 256,总参数再 ×3.5,val loss 只再降 0.136。在这个规模上变宽仍然有用,但每一份参数换来的下降在变小——值不值,要和算力、显存、数据量一起看。
上面列出的前沿模型 hidden size——768、2,560、4,096、5,120、6,144、7,168、8,192——有两个共同点:
- 全是 256 的整数倍。 这是工程习惯:矩阵的每一维按整块对齐到硬件上算得更快(第 4 课词表补齐是同一个道理),不是从「最优维度」推出来的。
- 跟着模型总规模走。 宽度通常和层数、总参数一起按算力预算定;Kaplan 等 2020 的实验发现,在总参数固定时,loss 对「宽还是深」并不敏感——层数与宽度之比变化 40 倍,效果差得不多(例如 6 层、宽 4,288 的模型与 48 层、宽 1,600 的模型,loss 相差在 3% 以内)。真正决定性能的是总规模。
常见误解:「4,096、5,120 这些数是算出来的最优值」。 没有定理能给出最优的 d。这些数来自「在给定预算下试出来、又对齐了硬件」的工程选择;同一家公司不同规模的模型用不同的 d(Qwen3-8B 是 4,096,Qwen3.8-27B 是 5,120,Qwen3.8-2.4T-A95B 是 8,192)。
🔍 Qwen3.8 的注意力比 d 还宽
Qwen3.8 的 d = 5,120,但它的注意力有 24 个头、每头 256 维,24 × 256 = 6,144,比 d 还大——Q 投影是「升维」的。这说明 d 只是残差流的宽度,每个子层内部可以更宽或更窄(FFN 中间维是 17,408,即 3.4 × 5,120)。C3 第 1 课在 Q、K、V 的形状里标出这一点,第 7 课说明头数 × 每头维数不必等于 d。
参数为什么按 d² 涨:一层拆开数
用我们项目模型的一层来数(结构见 minillm/model.py:多头注意力、SwiGLU FFN、两个 RMSNorm,无 bias):
试三件事: ① 在朴素方案里看 d = 64 到 2,048 每翻一倍,非 embedding 参数乘了多少;② 展开改进方案,比较三档 d 的最终 val loss 差了多少、参数差了多少倍——值不值?③ 看前沿模型那一排:每个宽度除以 256 的商是不是都是整数?再想想为什么没有一个模型用 5,000 这样的整数。
维度怎么选才有依据
- 它解决什么问题:在表示容量与计算、显存、数据需求之间,为模型宽度找一个可验收的取值。
- 数学上为什么可能有效:每层参数由 d × d 量级的矩阵构成,d 翻倍参数约 ×4 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条形状计数;与项目基线实测参数量一致 出处待补 ;宽度取 256 的倍数是为了硬件对齐 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条矩阵按块计算时维度对齐更高效;收益大小依硬件而定 出处待补 。
- 实验上为什么最后选了它:我们三档宽度的 val loss 对比是项目实测 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条3 档、同一语料、同样步数、学习率不随宽度调整;小规模结论不能直接外推 出处项目实测 · 本章项目推进 ↗ ;「总规模比形状重要」来自大规模扫描 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条§1.1 与 §3.1:层数与宽度之比变化 40 倍,loss 变化很小 出处Kaplan 等 2020 ↗需联网 。
一句话、下一个缺口、你的提问
一句话: 维度 d 决定每个 token 能装多少信息,也决定每层参数按 d² 增长;它是靠实验和算力预算选出来的超参数,没有公式能算出最优值。
下一个缺口:本章结束,下一章开始
到这里,一句话已经变成了一个 [T × 5120] 的矩阵,C1 的主线走完了。但有个漏洞:第 5 课说过,每个 token 的向量只由它的 ID 决定。「小明打了小王」和「小王打了小明」切出的 3 个 token 完全相同,查表得到的是同一组向量,意思却完全相反——这些向量不知道自己在第几个位置。C2:位置——模型怎么知道顺序
你的提问
C1 还没有真实提问记录。你可能会问:
- 「为什么 Qwen3.8 的注意力比 d 还宽?」→ 上面的 Dig;C3 第 1 课标出、第 7 课说明它不必等于 d。
- 「我想亲手比一比几个分词器」→ 实验课:真 tokenizer 与我们的 tokenizer 比一比