← 返回题目列表

为什么语言模型会共享输入 Embedding 与输出权重?

高频 困难 第 15 / 25 题 更新于 2026/09/17
EmbeddingWeight TyingLanguage Model Head参数共享

简化版

Weight Tying 让输入 token Embedding 矩阵 E∈R^{V×H} 与输出 LM Head 使用同一组参数,输出 logits 常写成 hEᵀ。这样节省约 V×H 参数,并让“读入 token 的语义空间”与“预测 token 的分类空间”对齐。它要求词表和隐藏维兼容;在输入输出词表不同、多模态投影或量化/并行约束下未必适合,是否使用要比较困惑度、容量和真实部署收益。

详细版

未共享时,输入查表 E_in 和输出分类器 W_out∈R^{V×H} 各占一份大矩阵;共享后令 W_out=E_in。若 V=50,000、H=4096、bf16,单矩阵约 50,000×4096×2≈391 MiB,共享可少一份权重及其训练状态。

input token id -> E[token] -> Transformer -> h
logits = h @ E.T (+ output bias)

共享产生双向梯度:E 同时被输入表示与输出预测更新,属于正则化也可能限制自由度。实现要确认参数对象真正 alias,而非初始化时复制;保存、优化器参数组、分片与量化也要避免重复。扩词表时同一矩阵的新增行同时影响输入与输出。

完整版教学

一、输入与输出为何都有词表矩阵

输入 Embedding 把离散 token ID 映射为 H 维向量;输出头把 H 维隐藏状态映射回 V 个词表 logits。两者形状转置相容。

E_in:  V × H
W_out: V × H, logits = h W_out^T

既然都描述 token 与隐藏空间的关系,共享参数是自然假设,但不是数学必需。

记忆钩子:输入矩阵负责“这个词怎样读进来”,输出矩阵负责“当前状态像哪个词”;Weight Tying 让两者用同一本词典。

二、参数节省有多大

V=128K、H=4096 时矩阵含约 524M 参数。bf16 权重约 1 GiB;训练还可能有梯度与 Adam fp32 状态,未共享的额外成本远大于 1 GiB。

状态每参数典型字节额外矩阵约占用
bf16 权重21.0 GiB
bf16 梯度21.0 GiB
Adam m/v fp3284.0 GiB

实际取决于混合精度、ZeRO 分片和优化器。词表越大,共享价值越明显。

三、共享如何改变梯度

未共享时输入矩阵只从出现于上下文的位置收梯度,输出矩阵从每个预测位置的 softmax 收梯度。共享后两个来源累加到同一 E。

这使 token 表示同时适合编码与分类,常有正则化效果;也减少模型为输入和输出分别学习完全不同空间的自由度。某些任务或架构中,解除共享可能换取少量质量。

需要检查梯度不是被错误加两次,而是自动微分对同一 Parameter 正常累积。

四、为什么可能改善泛化

输出分类器要判断隐藏状态与各 token 的兼容性,共享相当于用输入语义向量作为分类原型,减少参数并施加结构先验。

低频 token 的输入与输出统计可以互相帮助,但也可能把两种不对称需求绑在一起。收益是经验性的,应通过等训练条件的困惑度和下游评测确认。

不能把参数减少后的收益简单归因于“语义更统一”,还可能来自正则化。

五、哪些场景无法直接共享

编码器—解码器可能有不同源/目标词表;多模态输入 token 与文本输出词表不同;若输出前投影维度不等于 H,也需额外变换。

场景主要障碍替代方案
不同语言独立词表V 不同部分共享或不共享
输出低维投影维度不同加适配投影
多模态输入token 语义不同各模态独立输入投影
分类任务输出非词表标签独立分类头

共享要从任务语义与张量形状同时判断。

六、实现中最容易出现“假共享”

W_out.data.copy_(E.data) 只复制初值,后续仍是两个参数;真正共享需让模块引用同一 Parameter。可比较对象 identity、存储指针和修改后是否同步。

优化器参数列表里同一参数不应重复登记,否则可能被更新两次。序列化加载时,有的格式会打破 alias,需要模型初始化后重新 tie。

lm_head.weight = embedding.weight  # alias,而不是 copy

具体框架和编译器可能有额外要求,测试比代码外观更可靠。

七、扩词表与微调的影响

新增 token 时扩展 E 的行,输入查表和输出分类器同步拥有新 token。新增行需合理初始化,并用包含新 token 的输入与目标训练。

若只想训练新增 token,冻结共享矩阵无法只冻结旧行而放开新行,通常需要梯度 mask、参数拆分或适配器。LoRA 对输入 Embedding 与输出头如何挂载也因共享而互相影响。

删除或重排 tokenizer ID 则会同时破坏读入和输出映射,必须迁移权重行。

八、量化、并行与部署

输入查表和输出 GEMM 的访问模式不同,共享一个量化权重未必满足两个 kernel 的布局。推理框架可能为性能生成两份打包副本,逻辑共享但显存未完全节省。

Tensor Parallel 常按词表维切 LM Head,Embedding 也要兼容同一分片与通信。导出后应检查文件大小、运行时显存和 logits 一致性。

理论少一个参数矩阵不保证加载后只有一份物理存储。

九、常见误区与追问

  • 误区:初始化相同就是 Weight Tying。 必须持续引用同一参数存储。
  • 误区:共享一定提高精度。 它是结构先验与正则化,效果需实验。
  • 误区:只节省推理权重。 训练还可节省梯度和优化器状态。
  • 误区:所有 Encoder-Decoder 都能完全共享。 源目标词表或维度可能不同。
  • 误区:导出后一定保持物理共享。 量化打包和序列化可能复制。
  • 追问:输出 bias 是否也共享? 输入 Embedding 没有对应 bias,通常独立或省略。
  • 追问:扩词表有什么额外影响? 同一新增行同时承担输入和输出,需要双向训练覆盖。
  • 追问:如何验证实现真的 tie? 查 Parameter identity/存储指针、优化器去重和保存加载后 alias。

十、加强记忆

Weight Tying 记住“V×H 同形、输入输出共一本词典”:令 LM Head 权重等于 Embedding,可省一整块词表矩阵及训练状态,并让编码与预测空间相互约束。它要求词表与维度兼容,实现必须是参数 alias 而非复制;扩词表、LoRA、分片、量化和导出都要重新验证逻辑与物理共享,最终用困惑度和真实显存判断收益。