模型内部 · 反嵌入与采样
- 图中数值
- 真实 GPT-2
- dmodel
- 768 画出 8 个
- 词表
- 50,257
- LM head
- WEᵀ,共享权重
全部步骤
最后的 LayerNorm
只有最后一个位置预测下一个词元。它的向量在经过全部 12 个块之后,再通过最后的 LayerNorm(lnf)。这些数值来自 GPT-2 small 的真实运行。
[1 × 768]Logits
这个向量与嵌入矩阵的每一行做点积:反嵌入矩阵 WU(即 LM head)在 GPT-2 中就是 WEᵀ。于是每个词元得到一个 logit。图中为最可能的 6 个词元画出了 768 维中的 8 维;每个 logit 实际上是全部 768 维之和。
[1×768]·[768×50,257] · 77M FLOPs温度
在 softmax 之前,logits 先除以温度 T。只有它们之间的差距才重要:较低的 T 拉大差距,让分布更尖锐;较高的 T 让分布更平坦。
z / TSoftmax
softmax 把缩放后的 logits 变成覆盖全部 50,257 个词元、总和为 1 的概率。T 低时前几名拿走大部分概率;提高 T 则把概率挪向长尾。
p = softmax(z / T)采样
由一种策略选出下一个词元:贪心取概率最高的;采样把概率首尾相接排开,由一个随机数 u 选中一个;top-k 或 top-p 则先砍掉长尾。生成会一直重复,直到出现 <|endoftext|> 或达到长度上限。
采样 · 贪心 · top-k · top-p
代码
x = self.transformer.ln_f(x)
logits = self.lm_head(x[:, [-1], :]) # lm_head.weight is wte.weight (tied)
logits = logits[:, -1, :] / temperature
if top_k is not None:
v, _ = torch.topk(logits, min(top_k, logits.size(-1)))
logits[logits < v[:, [-1]]] = -float("Inf")
probs = F.softmax(logits, dim=-1)
idx_next = torch.multinomial(probs, num_samples=1) # greedy: probs.argmax(-1)
idx = torch.cat((idx, idx_next), dim=1) # append, run again