理解 token ids 如何进入连续向量空间,以及 hidden states 如何投影回词表 logits
Decoder-only Transformer 最重的计算发生在中间的 blocks 里,但语言模型的输入输出关系其实由两端决定:
$$ \text{token ids} \xrightarrow{\text{embedding}} \text{hidden states} \xrightarrow{\text{LM Head}} \text{next-token logits} $$
如果这两端没有看清楚,后面很多问题都会混在一起:为什么输入是整数、为什么输出不是 token id、为什么 loss 需要 shift targets、为什么词表大小会显著影响参数量,甚至为什么有些模型会共享输入 embedding 和输出 LM Head 的权重。
本章主线只讲输入输出两端:Embedding 和 LM Head。
Embedding 是离散 token 进入连续向量空间的入口。下面从三个角度看清它:机制(怎么查表)、内容(训练后学到了什么)、扩展(怎么加新 token)。
Tokenizer 把文本变成 token id,模型第一步要把这些整数变成连续向量。设词表大小为 𝑉,hidden size 为 𝐷,token embedding 矩阵是:
$$ E \in \mathbb{R}^{V \times D} $$
输入 token ids 的形状是:
$$ x \in \mathbb{Z}^{B \times T} $$
embedding 的输出是:
$$ h^{(0)}{b,t} = E[x{b,t}], \quad h^{(0)} \in \mathbb{R}^{B \times T \times D} $$
也就是说,embedding 做的是按行查表。给定 token id 𝑖,输出就是 𝐸 的第 𝑖 行。

这就是选择 embedding 矩阵中的某些行。实际实现会直接做行索引(如 PyTorch 的 nn.Embedding),而不是先构造 one-hot 再矩阵乘。