深入篇 23 / Transformer 逐步拆解 · 2026-11-08

从 logits 到 token:温度、过滤与随机性

区分 logits、概率、top-p 和随机采样,解释相同种子为什么还不足以保证批不变。

核心阅读 12–18 分钟练习另需 10–20 分钟前置:15 的 LM head;16 的 softmax

本课只拿下这一件事

区分 logits、概率、top-p 和随机采样,解释相同种子为什么还不足以保证批不变。

生成采样的概念路径。top-k/top-p 是概念扩展;当前 nano-vllm 只实现 temperature 采样。
top-k/top-p 是概念扩展;当前 nano-vllm 只实现 temperature 采样。

温度改变概率,不改变词表

对 T>0,pᵢ=softmax(logits/T)ᵢ。T 小会放大相对分数差,分布更尖;T 大更平。减去同一常数不变,除以温度却会变。greedy 是选最大 logits 的单独策略;不能把 temperature=0 直接代入除法。本地 SamplingParams 对正温度有约束,sampler 也没有实现 T=0 的分支。

top-p 截取的是累计概率

把候选按概率降序排列,保留累计概率首次达到 p 的最短前缀,然后在保留集合内重新归一化。跨过阈值的那个 token 必须保留;p=1 保留整个分布。top-k 按候选数裁剪,与 top-p 的语义不同。交互仅演示算法,不能据此假设本地 nano-vllm 的参数接口支持过滤。

为什么概率除以随机数还能采样

本地 sampler 先算 p,再生成独立 Exp(1) 随机变量 e,取 argmax(p/e)。对正概率,eᵢ/pᵢ 是 rate=pᵢ 的指数变量;最先到达者为 i 的概率为 pᵢ/Σp,所以取 argmin(e/p) 就得到类别采样。源代码用 clamp_min 防止非常小随机值带来除零风险。这个推导解释分布,不意味着同一随机种子在不同 batch 布局下会给同一请求同一组随机数。

把随机数与数值路径分开排查

复现输出至少涉及:模型权重与输入、数值 kernel 路径、随机流怎样分给请求、采样参数与投机过程。batch composition 改变可能同时改变归约误差和随机数消费顺序。DeepInfer 的确定性配置会在32课按其 README 的约束讲解;别用“固定seed即可”掩盖这些前提。

把维度变化拆到每一步

  1. 先取每条请求最后一个有效hidden行,得到[B,H]。
  2. 再投到[B,Vocab],采样输出[B]个token ID。

打开元素级图解:矩阵、轴、索引与可点击反例 →

本地 sampler 的指数竞赛。等价理解为 argmin(e/p) 的指数竞赛;不等于 argmax(p)。
等价理解为 argmin(e/p) 的指数竞赛;不等于 argmax(p)。

改变变量,验证直觉

启用 JavaScript 后可交互;上面的图和下面的手算练习始终可读。

数值练习:先算,再核对

概率已排序为 [0.55,0.30,0.10,0.05],top-p=0.8。确定保留集合,并算重归一化后第一个 token 的概率。另用源码说明 temperature=0 应该怎样处理才不会除零。

闭卷检索

不要回看正文。答错后先解释原因,再重新打开这一课。

把结论落到源码

  1. 对照 sampler.py 三行运算,分别写出中间张量的 dtype 与形状。
  2. 检查 sampling_params.py 的 temperature 验证条件,区分 API 支持与概念说明。

以下行号由本地 vendor 文件生成;上游链接固定完整 commit,离线摘录可直接打开。

优先阅读:本地 Sampler.forward;生成分布的输入来自原论文 §3.4 的 softmax 输出。

速查:形状与公式 · 三框架映射 · 术语表 · 复习与实战路线 · 4070 Ti本地实验

记录你此刻能做到什么

只在当前浏览器保存自评;不会自动写成已掌握的 learning record。

随时追问老师。把“第 23 课 + 哪个公式 / 哪个张量 / 哪一行 + 你的推导”发给我,我们可以继续拆到每一步。