跳转到内容

第 6 章 从分数到概率、损失与困惑度

6.1 分数要按什么规则,才能变成概率?

Section titled “6.1 分数要按什么规则,才能变成概率?”

第 5 章为巴黎、里昂、其他算出过 [2,1,−1] 这样的一行分数。第一项最大,但不能直接叫它概率:2 超过了 1,−1 又是负数。把三项都除以总和,也消不掉那个负值。我们需要一条规则,既保留谁大谁小的顺序,又让结果都不小于零、总和等于 1。

这种尚未转换成概率、不受概率范围限制的分数,称为 logits。一个 logit 不是观察频率,不是可靠性保证,也不是关于世界的事实;它是概率计算规则的输入。本章直接给定 logits,把转换规则与产生分数的模型分开研究。这里的教学分数是无量纲的,候选顺序始终与数值一起说明。

取指数可以得到正权重。先回想 23=2×2×2=82^3=2\times2\times2=8,而 20=12^0=1、2−1=1/22^{-1}=1/2。指数运算把这种关系扩展到非整数指数。这里通常采用底数 e≈2.71828e\approx2.71828;eze^z 也写成 exp⁡(z)\exp(z),对于任何有限实数 zz 都为正。它的逆运算是 自然对数(natural logarithm),记为 ln⁡\ln:ln⁡2\ln2 问的是“ee 的多少次方等于 2”。所以 eln⁡2=2e^{\ln2}=2,ln⁡1=0\ln1=0。

例 6.1 — 把三项给定分数变成一个分布。 仍按巴黎、里昂、其他的顺序,给定 [ln⁡2,0,0]≈[0.693147,0,0][\ln2,0,0]\approx[0.693147,0,0]。这是一组新的教学输入,并非第 5 章那张矩阵的输出。逐项取指数得到 [2,1,1],总和为 2+1+1=42+1+1=4,再逐项除以 4,得到概率 [1/2,1/4,1/4]。

分母是 4,因为我们要除以候选权重的总和。不能因为有三个候选,就把分母写成 3。这个通用操作叫作 Softmax:

pk=ezk∑j=0K−1ezj.p_k=\frac{e^{z_k}}{\sum_{j=0}^{K-1}e^{z_j}}.

zkz_k 是候选 kk 的分数,pkp_k 是转换后的概率;jj 依次遍历同一行的所有候选。这里 K=3K=3。里昂对应 k=1k=1,代入就是 p1=e0/(eln⁡2+e0+e0)=1/4p_1=e^0/(e^{\ln2}+e^0+e^0)=1/4。所有分子的总和恰好等于共同的分母,因此概率之和为 1。对于 [B,T,K] 形状的批次,要在每个样本、每个位置上,分别沿候选维归一化。如果把所有位置放在一起归一化,回答的就不再是同一个问题。

6.2 同一个概率分布,分数可以看起来差很多

Section titled “6.2 同一个概率分布,分数可以看起来差很多”

Softmax 只取决于分数之间的差。给所有候选加上同一个数,不会额外偏向其中某个候选。这个性质也让我们有办法避开不必要的巨大指数值。

例 6.2 — 每项加 1,000,预测不变。 把分数改成 [1000+ln⁡2,1000,1000][1000+\ln2,1000,1000]。在精确计算中,权重为 [2e1000,e1000,e1000][2e^{1000},e^{1000},e^{1000}],总和为 4e10004e^{1000}。约去共同因子后,仍得到 [1/2,1/4,1/4]。但普通浮点数能表示的范围有限,直接计算 e1000e^{1000} 会溢出。

可以先减去最大分数 m=max⁡jzjm=\max_j z_j。三项变成 [0,−ln 2,−ln 2],对应权重 [1,1/2,1/2],总和为 2,结果仍是 [1/2,1/4,1/4]:

pk=ezk−m∑jezj−m.p_k=\frac{e^{z_k-m}}{\sum_j e^{z_j-m}}.

现在每个指数都不大于零,所以取指数后的值都不超过 1。舍入误差仍可能存在;本例 float64 复现结果的误差在 10−1210^{-12} 以内。差值很大时,极小的正值也可能下溢,被存成零。因此,计算目标损失时,我们会使用后面推导的等价对数形式,不必先把一个极小概率存下来再取对数。

如果只给巴黎加 1,000,情况就不同了:相对分数发生变化,概率分布也会变。无论共同平移还是数值稳定处理,都没有增加“巴黎就是正确答案”的证据。

6.3 对实际出现的目标,计算预测误差

Section titled “6.3 对实际出现的目标,计算预测误差”

只有概率向量,还不能算出一次预测的损失,必须先知道目标是什么。假设记录的目标是巴黎,本例给它的概率为 1/21/2。另一个预测器若只给它 1/41/4,应受到更大的惩罚。 损失(loss) 就是给出这种惩罚值的数值规则。我们选用的规则,要能接上第 4 章逐个相乘目标概率的做法。

两次计分事件的目标概率若为 1/21/2 和 1/41/4,乘积就是 1/81/8。序列一长,连乘结果可能变得极小。对数能把乘法变成加法:ln⁡(ab)=ln⁡a+ln⁡b\ln(ab)=\ln a+\ln b。由于 0 到 1 之间概率的对数不大于零,再加一个负号,就得到非负的惩罚值。这便是单个目标的 负对数似然(negative log-likelihood):

ℓ=−ln⁡py.\ell=-\ln p_y.

下标 yy 指记录的目标,不是概率最大的候选。若 py=1/2p_y=1/2,则 ℓ=−ln⁡(1/2)=ln⁡2≈0.693147\ell=-\ln(1/2)=\ln2\approx0.693147;若 py=1/4p_y=1/4,则 ℓ=ln⁡4≈1.386294\ell=\ln4\approx1.386294。目标概率每减半,损失就增加 ln⁡2\ln2,因此它度量的是概率的相对变化。概率为 1 时损失为 0;概率趋近于零时,损失没有有限上界;目标概率恰好为零时,负对数损失为无穷大。

例 6.3 — 先给两个目标计分,再求平均。 取两个预测位置,恰好都使用上述给定分布。第一个记录目标是巴黎,第二个是里昂。这只是算术诊断,不是在说里昂是法国首都。

表 6.1 — 每次损失由自己的目标决定。

计分位置目标目标概率损失,单位为 nat
0巴黎1/21/2ln⁡2≈0.693147\ln2\approx0.693147
1里昂1/41/4ln⁡4≈1.386294\ln4\approx1.386294
总计两次事件乘积 1/81/8ln⁡8≈2.079442\ln8\approx2.079442
平均总损失除以 2—(ln⁡8)/2≈1.039721(\ln8)/2\approx1.039721

平均时要除以 参与计分的目标事件数,这里是 2,不是三个候选。如果批次含有补齐项,要数真实的计分目标,不能数包含补齐项的存储位置。一般地,若有 MM 个计分事件,

L=1M∑i=0M−1ℓi.L=\frac1M\sum_{i=0}^{M-1}\ell_i.

ii 选择一次事件,ℓi\ell_i 是这次事件的目标损失,LL 是平均值。按事件等权计分时,长句的总贡献比短句大;如果先对每句求平均,再平均这些句子,采用的就是另一种权重规则。是否计入 EOS 也要说清楚。第 4 章的序列概率包含 EOS。

同一项损失还有一个常用名称。把一个确定目标写成分布 qq:目标所在位置为 1,其余位置为 0。巴黎对应 q=[1,0,0]q=[1,0,0]。从参照分布 qq 到预测分布 pp 的 交叉熵(cross-entropy) 是

H(q,p)=−∑kqkln⁡pk.H(q,p)=-\sum_k q_k\ln p_k.

这里,参照概率给各候选的损失分配权重。当 q=[1,0,0]q=[1,0,0] 时,只留下 −ln⁡p0-\ln p_0,正是前面的目标损失。如果 qq 表示多种结果的混合,就按这些混合权重求平均。qk=0q_k=0 的项按约定贡献为零;若 qk>0q_k>0 而 pk=0p_k=0,交叉熵就是无穷大。

PyTorch 的 CrossEntropyLoss 接收原始 logits,在内部完成 Softmax 与对数计算。目标若采用整数类别编号,每个编号只说明该给哪个候选计分,并不是一个概率向量。如果误把已经归一化的概率当作 logits 传入,就会再次进行归一化,改变损失。PyTorch 2.7:CrossEntropyLoss

单个目标的稳定计算形式为

ℓ=m−zy+ln⁡∑jezj−m.\ell=m-z_y+\ln\sum_j e^{z_j-m}.

把 Softmax 代入 −ln⁡py-\ln p_y,再拆开商的对数,就能得到它。例 6.1 中,m=ln⁡2m=\ln2。对巴黎,m−zy=0m-z_y=0,剩余求和为 2,损失就是 ln⁡2\ln2。若 logits 是 [0,−1000]、目标为 1,即使直接算出的第二项概率下溢,这个公式仍能给出约 1,000 的损失。因存储限制而出现的零,与数学模型本身赋予精确零概率,是两件事。

一次预测;候选顺序为巴黎、里昂、其他
  1. 一组数字分数:[ln 2, 0, 0]
  2. 处理步骤取指数:[2,1,1];总和为 4
  3. 一组数字概率:[1/2,1/4,1/4]

每项权重都除以三个候选权重的总和。

两个有目标标注的预测,使用相同分布
  1. 处理步骤目标为巴黎:−ln(1/2) = ln 2
  2. 处理步骤目标为里昂:−ln(1/4) = ln 4
  3. 一组数字平均:(ln 2 + ln 4)/2;困惑度:√8

总损失除以两个计分目标,不是除以三个候选,也不是除以含补齐项的槽位数。

图 6.1 — 候选概率的归一化与目标损失的平均,使用不同的分母。 本书原创图示与教学推导,CC BY-SA 4.0。

图 6.1 把两个分母放在不同计算中:上面是在一次事件的候选之间分配权重,下面是在两次已知目标之间平均惩罚。先看清正在数什么,再决定分母。

自然对数的信息单位叫作 nat。以 2 为底的对数则使用 比特(bit):log⁡2(1/2)=−1\log_2(1/2)=-1,log⁡2(1/4)=−2\log_2(1/4)=-2。换底改变的是单位,不会改变哪个预测给目标分配了更大概率。换算关系是 log⁡2p=ln⁡p/ln⁡2\log_2 p=\ln p/\ln2。因此,例 6.3 的平均损失也可以写成 1.5 bit,而不是约 1.039721 nat。

困惑度(perplexity,PPL) 先对损失求平均,再用指数还原:

PPL⁡=eL=(∏i=0M−1pyi)−1/M.\operatorname{PPL}=e^L =\left(\prod_{i=0}^{M-1}p_{y_i}\right)^{-1/M}.

这个公式中的 LL 必须以 nat 为单位;若以 bit 为单位,则使用 2Lbits2^{L_{\rm bits}}。乘积里放的是分配给每个实际目标的概率,指数 1/M1/M 求出几何平均,负号再取其倒数。对 1/21/2 和 1/41/4,困惑度为 (1/8)−1/2=8≈2.828427(1/8)^{-1/2}=\sqrt8\approx2.828427。它不是两个倒数的算术平均;后者为 (2+4)/2=3(2+4)/2=3。

如果预测器总给实际目标分配概率 1/k1/k,困惑度就等于 kk。因此,可以借一个均匀分布来理解它所对应的预测难度。但这不意味着模型真的考虑了 2.828427 个候选,也不意味着它错了这么多次。一个很差的预测器如果反复给实际目标极低概率,困惑度甚至可以大于词表大小。

比较困惑度时,必须使用相同的计分事件、文本切分、EOS 与补齐规则,以及平均方式。按词计分与按字节计分,事件单位不同,困惑度不能直接对比。在固定的留出文本集上,困惑度下降,说明记录目标的概率几何平均提高了。它不会自动说明回答更好、系统更快或产品更有用。

6.5 比较两个分布,也不能代替判断事实

Section titled “6.5 比较两个分布,也不能代替判断事实”

有时,参照对象不是单个已观察标签,而是一整个分布。我们想知道:如果原本按参照分布 qq 自己的概率计分,现在改用 pp,平均对数损失会多多少?这个量叫作 Kullback–Leibler 散度(KL divergence,简称 KL):

DKL(q∥p)=∑kqkln⁡qkpk=H(q,p)−H(q),H(q)=−∑kqkln⁡qk.D_{\rm KL}(q\|p)=\sum_k q_k\ln\frac{q_k}{p_k} =H(q,p)-H(q),\qquad H(q)=-\sum_k q_k\ln q_k.

H(q)H(q) 是参照分布用自身概率计算的平均负对数值,称为它的熵。把它减去,留下的就是使用 pp 多付出的平均损失。权重来自左边的 qq,所以交换两边,答案通常会改变。对于合法的有限离散分布,KL 不小于零;两分布相同时为零。它不是对称的距离。信息论教材给出了参照分布固定时,交叉熵的这一分解关系。《动手学深度学习》英文版,第 22.11 节

例 6.4 — 方向变了,权重也变了。 另设一个只有两种结果的实验,q=[3/4,1/4]q=[3/4,1/4],p=[1/2,1/2]p=[1/2,1/2]。于是

DKL(q∥p)=34ln⁡(3/2)+14ln⁡(1/2)≈0.130812,D_{\rm KL}(q\|p)=\tfrac34\ln(3/2)+\tfrac14\ln(1/2)\approx0.130812,

反过来则是

DKL(p∥q)=12ln⁡(2/3)+12ln⁡2≈0.143841.D_{\rm KL}(p\|q)=\tfrac12\ln(2/3)+\tfrac12\ln2\approx0.143841.

第一式用 3/4 和 1/4 给两个对数比值加权,第二式改用 1/2 和 1/2。单项可以为负,总和却不小于零。这里 H(q)≈0.562335H(q)\approx0.562335,H(q,p)=ln⁡2≈0.693147H(q,p)=\ln2\approx0.693147,相减也能复核第一个 KL。

分布的 支撑集(support) 是其中概率为正的结果集合。要让 DKL(q∥p)D_{\rm KL}(q\|p) 有限,所有在 qq 中概率为正的结果,在 pp 中也必须有正概率。若 q=[1,0]q=[1,0]、p=[0,1]p=[0,1],仅第一个结果就会让 KL 变成无穷大。qq 为零的项贡献为零,两边都为零时也采用这个约定。把零偷偷改成一个小常数,会改变分布和比较结果;如果确实要这样建模,就必须明确声明,不能当成不影响含义的修补。

6.6 损失很低,也可能是在奖励旧文档

Section titled “6.6 损失很低,也可能是在奖励旧文档”

回到 Part I 的虚构差旅制度。北京住宿的旧限额是每晚 600 元,适用的新限额是 750 元。假设评测文件仍把 600 标作目标,而预测器给 600 的概率是 0.99,那么损失只有 −ln⁡0.99≈0.010050-\ln0.99\approx0.010050。它很符合这个文件,却答错了当前制度问题。这些条件由作者给定,不是某次真实准确率测量。

即使标签正确,概率也不是事实证明。 概率校准(calibration) 问的是:在明确的一组预测中,被赋予 0.9 概率的事件,是否大约有 90% 发生?某个概率为 0.9 的预测仍然可能错。一个系统在某组数据上校准良好,换了任务或数据后也未必保持。事实正确性问的则是:眼前这一项主张,是否得到适用证据支持?两种问题需要不同的检查。

02-shapes-and-loss.ipynb 的固定分数练习会复现表 6.1 和 KL 数值,检查共同加 1,000 后的结果,并分别测试精确零概率与数值下溢。输入和符号化预期值保存在 data/part-ii/arithmetic.json;code/part-ii/probability_practice.py 与 PyTorch 提供两条计算路径。正文显示到小数点后六位,比较使用未舍入值。算术复现成功,并不能验证差旅制度的日期。

Softmax 在同一候选行内归一化正的指数权重。负对数损失给记录的目标计分,交叉熵则把它扩展到参照分布。平均损失需要明确事件数,困惑度再用与对数匹配的底数还原。KL 在指定方向上度量额外的平均对数损失,并要求检查支撑集条件。这些量评价的是相对于选定目标或分布的预测,不是产品质量的全部。

现在缺少的操作已经很明确:怎样改变参数,让 logits 随之改变,进而降低相关目标的损失?第 7 章会把这样一次变化跟踪到底。

  1. 候选顺序为旧版、当前版,logits 为 [0,ln 3]。算出两个概率、目标为当前版时的损失,以及两项同时加上 −50 后的损失。
  2. 三个真实目标的概率依次为 1/2,1/2,1/41/2,1/2,1/4,另有一个存储位置是补齐项。求以 nat 为单位的平均损失和困惑度。如果有人把总损失除以 4,会发生什么?
  3. 一份报告把 1.5 bit 的平均损失代入 e1.5e^{1.5} 求困惑度。修正结果,并解释单位出了什么问题。
  4. 取 q=[1,0]q=[1,0]、p=[1/2,1/2]p=[1/2,1/2],求 DKL(q∥p)D_{\rm KL}(q\|p),再算反方向,明确使用零项约定。
  5. 一个新系统换了 tokenizer 后困惑度下降,对旧制度文件也给出很好的分数。要声称它更会回答当前差旅问题,还缺哪些证据?
  6. 对 logits [0,−1000] 和目标 1,一个简单实现从 −log(0) 得到无穷损失。这与计数模型赋予精确零概率是同一种失败吗?怎样修复?
  1. 权重为 [1,3],总和 4,因此概率为 [1/4,3/4]。目标损失是 −ln⁡(3/4)=ln⁡(4/3)≈0.287682-\ln(3/4)=\ln(4/3)\approx0.287682。共同平移让两项权重乘上同一个因子,概率和损失不变;先减去最大值可以避免计算不必要的小权重。
  2. 总损失是 ln⁡2+ln⁡2+ln⁡4=ln⁡16\ln2+\ln2+\ln4=\ln16。除以三个目标,L=(ln⁡16)/3≈0.924196L=(\ln16)/3\approx0.924196,困惑度为 161/3≈2.51984216^{1/3}\approx2.519842。若除以 4,则得到 ln⁡2\ln2 和困惑度 2,相当于把补齐项当成一次零损失事件,虚假地改善了分数。
  3. 应用 21.5=8≈2.8284272^{1.5}=\sqrt8\approx2.828427。也可以先换成 nat,即 1.5ln⁡21.5\ln2,再以 ee 为底取指数。要逆转对数运算,底数必须对应。
  4. 正方向是 1ln⁡2=ln⁡21\ln2=\ln2,第二项的参照权重为零,贡献为零。反方向中,第二种结果的参照权重是 1/21/2,对方却给它零概率,因此 KL 为无穷大。候选顺序相同,不代表两个方向可以互换。
  5. 困惑度直接比较需要匹配事件与切分约定。任务结论还需要固定的当前问题集、适用的来源版本、相关性标注和可观察的回答错误。对旧目标文件的高似然,只能证明更符合那些目标。
  6. 精确的 Softmax 中第二项概率仍为正,只是太小,当前存储路径表示不了。直接用 m−zy+ln⁡∑jezj−mm-z_y+\ln\sum_j e^{z_j-m} 算损失,结果约为 1,000。未平滑的计数模型则可能按其规则真正给出零概率,那是模型支撑集的问题,不是浮点数下溢。
  • PyTorch 2.7:CrossEntropyLoss。规定实践中的 logits、目标形式、类别维和归约方式。本章使用不加权的平均;加权或忽略部分目标时,文档另有对应的分母规则。
  • Zhang 等,《动手学深度学习》英文版:信息论。第 22.11.4—5 节支持熵、交叉熵与有方向 KL 的关系。本章的有限分布、数值与旧制度反例均为原创教学构造。
  • scikit-learn:概率校准。开头的定义和第 1.16.1 节用实际发生频率解释校准,并区分校准与损失汇总。本章没有声称测得了某个模型的校准结果。