同一套概率,既可以读成预测损失,也可以读成理想码长。但输出的随机性、模型的知识与回答的价值,需要分别讨论。
交叉熵:给实际出现的 token 多少概率
在位置 t,模型根据上下文 x<t 输出词表上的分布 qθ(⋅∣x<t)。用 ext 表示本次观测 token 的 one-hot 向量,这一步的损失为
H(ext,qθ)=−logqθ(xt∣x<t).
one-hot 只是一次观测的目标表示,不是说真实数据在这个上下文下只有一个可能的后续。在总体分布上,期望交叉熵可拆成数据条件熵与条件 KL 的平均;在有限训练集上,最小化逐 token 的负对数似然(NLL)就是最大似然学习。
把相同概率交给算术编码或 ANS,可以获得接近 NLL 的无损编码长度。真正的压缩系统仍需考虑编码开销、模型成本以及编解码双方共享的上下文;预测与压缩的联系 不等于“一个模型文件本身就是压缩器”。
困惑度:几何平均藏在指数里
固定评测序列,简写 qt=qθ(xt∣x<t),并只对参与评测的 n 个 token 求平均:
Lˉ2=−n1t=1∑nlog2qt,PPL=2Lˉ2=(t=1∏nqt1)1/n.
所以 PPL 是逐项 1/qt 的几何平均,而不是算术平均。用自然对数计算损失时,同一个数应写作 PPL=eLˉe;底数与单位必须配套。
图中三个位置分别给已观测 token 概率 0.5,0.25,0.125;它们来自不同上下文,不是一份词表分布。对应码长为 1,2,3 bit,虚线均值为 2 bit,因此 PPL 为 4。右侧四个等大格是相同 PPL 的均匀四选一基准,并非原模型的候选数。
若每个观测 token 都得到 1/N 的概率,PPL 恰好为 N,这才是“等效选项数”的精确例子。一般分布下,它既不是候选 token 个数,也不是四处数一数“模型在几个选项之间犹豫”。
正在呈现知识画面
困惑度的“平均”,到底平均了什么?四个已观测 token 的概率转成码长,虚线是平均码长。比较均匀与不均匀但同 PPL 的例子,再降低最后一个 token 的概率,观察几何平均。
{"id":"llm-perplexity","title":"困惑度的“平均”,到底平均了什么?","summary":"四个已观测 token 的概率转成码长,虚线是平均码长。比较均匀与不均匀但同 PPL 的例子,再降低最后一个 token 的概率,观察几何平均。","height":950,"html":"<p class=\"eyebrow\" data-i18n=\"eyebrow\"></p><h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p>\n<div class=\"presets\" role=\"group\" data-i18n-label=\"examples\"><button data-preset=\"balanced\" data-i18n=\"balanced\"></button><button data-preset=\"uneven\" data-i18n=\"uneven\"></button><button data-preset=\"rare\" data-i18n=\"rare\"></button></div>\n<label class=\"control\" for=\"probability\"><span data-i18n=\"control\"></span><output id=\"probability-value\"></output></label><input id=\"probability\" type=\"range\" min=\"1\" max=\"100\" value=\"50\">\n<div class=\"metric-pair\"><div><span data-i18n=\"loss\"></span><strong id=\"mean-loss\"></strong></div><div><span>PPL</span><strong id=\"ppl\"></strong></div></div><p class=\"note\" data-i18n=\"axis\"></p><div class=\"loss-chart\"><div id=\"loss-columns\"></div><div id=\"mean-line\"><span id=\"mean-label\"></span></div></div><div id=\"token-labels\"></div>\n<details class=\"audit-details\"><summary data-i18n=\"detailLabel\"></summary><div class=\"formula\" id=\"loss-formula\"></div><div class=\"formula\" id=\"ppl-formula\"></div></details><p class=\"note\" data-i18n=\"note\"></p>\n","css":".intro { margin:8px 0 18px; color:var(--muted); font-size:14px; }\n.control { display:flex; align-items:center; justify-content:space-between; gap:16px; margin-top:18px; }\n.control output { min-width:4em; flex-shrink:0; text-align:center; background:var(--accent-soft); color:var(--accent); padding:2px 8px; border-radius:6px; font-weight:600; }\n.formula { margin-top:18px; padding:14px 0; border-block:1px solid var(--rule); font-size:16px; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }\n.copy-stack { display:grid; margin-top:14px; color:var(--muted); font-size:14px; }\n.copy-stack > * { grid-area:1/1; }\n.copy-stack .reserve { visibility:hidden; }\n.note { margin-top:14px; color:var(--muted); font-size:12px; }\n.metric-pair { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:18px; }\n.metric-pair > div { min-width:0; }\n.metric-pair span { display:block; font-size:12px; color:var(--muted); }\n.metric-pair strong { display:block; font-size:24px; font-weight:500; font-variant-numeric:tabular-nums; }\n.scale { display:flex; justify-content:space-between; color:var(--muted); font-size:12px; font-variant-numeric:tabular-nums; }\n@media(max-width:480px) { .metric-pair strong { font-size:21px; } }\n.presets { display:flex; }\n.plot { position:relative; margin-top:18px; height:190px; border-left:1px solid var(--rule); border-bottom:1px solid var(--muted); }\n.plot svg { width:100%; height:100%; overflow:hidden; }\n.plot .curve { fill:none; stroke:var(--accent); stroke-width:2.5; vector-effect:non-scaling-stroke; }\n.plot .curve.secondary { stroke:var(--second); stroke-dasharray:5 4; }\n.scale { position:relative; }.scale .middle { position:absolute; left:50%; transform:translateX(-50%); }\n.formula { font-size:14px; }.formula div+div { margin-top:6px; }\n@media(max-width:480px) { .plot { height:170px; } }\n.plot .curve { transition:d .28s cubic-bezier(.22,1,.36,1); }\n.band { display:flex; height:28px; border-radius:5px; overflow:hidden; background:var(--surface); margin-top:10px; }\n.band > div { background:var(--accent); transition:width .28s ease; }\n.band > .gold { background:var(--second); }\n.legend { display:flex; flex-wrap:wrap; gap:6px 18px; margin-top:10px; font-size:12px; color:var(--muted); }\n.legend .blue::before,.legend .gold::before { content:''; display:inline-block; width:9px; height:9px; border-radius:2px; margin-right:6px; background:var(--accent); }\n.legend .gold::before { background:var(--second); }\n.rows { margin-top:18px; display:grid; gap:12px; }\n.row { display:grid; grid-template-columns:32px 1fr 60px; align-items:center; gap:10px; font-size:13px; }\n.row > div { min-width:0; }.row output { text-align:right; font-variant-numeric:tabular-nums; }\n.track { height:14px; background:var(--surface); border-radius:3px; overflow:hidden; }\n.fill { height:100%; width:0; background:var(--accent); transition:width .28s ease; }\n.presets { flex-wrap:wrap; gap:4px; }.presets button { min-width:0; }\n.metric-pair strong { overflow-wrap:anywhere; }\n.loss-chart { height:210px; position:relative; margin-top:34px; border-bottom:1px solid var(--muted); }#loss-columns { display:grid; grid-template-columns:repeat(4,1fr); gap:16px; height:100%; align-items:end; padding:0 12px; }.loss-bar { background:var(--accent); position:relative; border-radius:5px 5px 0 0; transition:height .28s ease; }.loss-bar:last-child { background:var(--second); }.loss-bar span { position:absolute; bottom:100%; width:100%; text-align:center; font-size:12px; color:var(--ink); font-variant-numeric:tabular-nums; }#mean-line { position:absolute; width:100%; border-top:1px dashed var(--ink); transition:bottom .28s ease; pointer-events:none; }#mean-label { position:absolute; right:0; top:1px; background:var(--paper); font-size:11px; padding:1px 4px; }#token-labels { display:grid; grid-template-columns:repeat(4,1fr); text-align:center; gap:4px; font-size:12px; margin-top:8px; }#token-labels span { display:block; color:var(--muted); }\n\n.loss-chart { background:repeating-linear-gradient(to top,transparent 0,transparent calc(100% / 7 - 1px),var(--rule) calc(100% / 7 - 1px),var(--rule) calc(100% / 7)); }\n@media(max-width:480px) { .loss-chart { height:168px; } }\n\n.metric-pair{margin-top:12px}.loss-chart{margin-top:24px}.intro{margin-bottom:12px}\n@media(max-width:480px){.loss-chart{height:140px}.intro{font-size:13px}.note{margin-top:10px}.metric-pair strong{font-size:21px}}\n\n.audit-details { border-top:1px solid var(--rule); margin-top:14px; padding-top:8px; }\n.audit-details summary { cursor:pointer; color:var(--accent); font-size:13px; min-height:36px; padding:6px 0; }\n.audit-details summary:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }\n.audit-details .formula { border:0; margin-top:8px; padding:8px 0; }\n","js":"const $=s=>document.querySelector(s),presets={balanced:[.5,.5,.5,.5],uneven:[.25,1,.5,.5],rare:[.5,.5,.5,.01]};let probabilities=[...presets.balanced];\nfor(let i=0;i<4;i++){$('#loss-columns').insertAdjacentHTML('beforeend','<div class=\"loss-bar\"><span></span></div>');$('#token-labels').insertAdjacentHTML('beforeend','<div>t'+(i+1)+'<span></span></div>');}\nfunction draw(){const losses=probabilities.map(p=>-Math.log2(p)),mean=losses.reduce((a,b)=>a+b)/4,ppl=2**mean;$('#probability-value').textContent=viz.number(probabilities[3],2);document.querySelectorAll('.loss-bar').forEach((e,i)=>{e.style.height=losses[i]/7*100+'%';e.querySelector('span').textContent=viz.number(losses[i],2);});document.querySelectorAll('#token-labels span').forEach((e,i)=>e.textContent='q = '+viz.number(probabilities[i],2));$('#mean-line').style.bottom=mean/7*100+'%';$('#mean-label').textContent='L̄ = '+viz.number(mean,3);\n $('#loss-formula').textContent='L̄ = ('+losses.map(l=>viz.number(l,3)).join(' + ')+') / 4 ≈ '+viz.number(mean,3)+' bit';$('#ppl-formula').textContent='PPL ≈ ⁴√('+probabilities.map(p=>viz.number(1/p,3)).join(' × ')+') ≈ '+viz.number(ppl,3);$('#mean-loss').textContent=viz.number(mean,3)+' bit';$('#ppl').textContent=viz.number(ppl,3);\n document.querySelectorAll('[data-preset]').forEach(e=>e.setAttribute('aria-pressed',String(presets[e.dataset.preset].every((p,i)=>Math.abs(p-probabilities[i])<1e-9))));}\n$('#probability').addEventListener('input',()=>{probabilities[3]=+$('#probability').value/100;draw();});document.querySelectorAll('[data-preset]').forEach(e=>e.addEventListener('click',()=>{probabilities=[...presets[e.dataset.preset]];$('#probability').value=probabilities[3]*100;draw();}));draw();\n","audio":false,"strings":{"axis":"柱高固定标尺:0–7 bit;虚线是四项平均。下方 q 分别属于四个不同上下文,无须相加为 1。","balanced":"均匀损失","control":"给第 4 个真实 token 的概率","detailLabel":"展开几何平均的计算","examples":"概率示例","eyebrow":"先平均对数,再指数化","heading":"困惑度的“平均”,到底平均了什么?","intro":"每根柱子是一个已观测 token 的 −log₂ q。柱高先做算术平均,再指数化;不是直接平均四个 1/q。","loss":"平均损失 L̄","note":"前两个预设的联合概率都为 1/16,所以 PPL 都是 2,尽管逐项损失不同。降低某个真实 token 的概率会增加平均码长。这里固定评测 token 与上下文,只比较概率赋值。","rare":"罕见末项","uneven":"相同 PPL"}}
例如 q=(1/2,1/2,1/2,1/2) 与 q=(1/4,1,1/2,1/2) 的联合概率都为 1/16,平均损失都是 1 bit,PPL 都是 2。后者若直接平均 1/qt,会得到 9/4,这不是 PPL。一个低概率的真实 token 会拉高 NLL;如果它的概率是零,损失和 PPL 则是无限大。
比较 PPL 需要统一语料、分词、上下文长度与计分规则。跨分词器时应先换算到每字节等共同单位,并保持相同原始文本与处理口径;仅换单位也无法修复不同评测集造成的差异。PPL 读的是模型的交叉熵率,不是直接测出的真实数据熵率。
KL 正则:为什么最优策略会“指数倾斜”
固定提示词 x,省略条件记号。KL 正则化的奖励目标是
J(π)=Ey∼π[r(y)]−βDKL(π∥πref),β>0.
这是 RLHF 中可用 PPO 等方法优化的目标形式,不是 PPO 算法的全部。方向是新策略到参考策略:把概率移到参考极少支持的回答上,会付出较大代价。它可以限制策略漂移,但不能保证奖励模型没有漏洞,也不能单独保证回答有用。
对有限回答空间、正的参考概率,直接在所有分布中求最优可得
π∗(y)=Zπref(y)exp(r(y)/β),Z=y∑πref(y)exp(r(y)/β).
公式有三步:从参考概率出发,乘上奖励的指数权重,再除以总量 Z。奖励相同的回答保持原概率比;奖励差越大、β 越小,比值改变越明显。若参考概率为零,有限 KL 的策略也必须在该处为零;不能凭此公式突破参考分布的支持集。
正在呈现知识画面
KL 约束下,高奖励回答会得到多少概率?固定三个回答的参考概率与奖励,改变 β,观察最优分布如何按 exp(r/β) 倾斜并重新归一化,同时计算奖励、KL 和目标值。
{"id":"llm-policy","title":"KL 约束下,高奖励回答会得到多少概率?","summary":"固定三个回答的参考概率与奖励,改变 β,观察最优分布如何按 exp(r/β) 倾斜并重新归一化,同时计算奖励、KL 和目标值。","height":950,"html":"<p class=\"eyebrow\" data-i18n=\"eyebrow\"></p><h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p>\n<label class=\"control\" for=\"beta\"><span data-i18n=\"control\"></span><output id=\"beta-value\"></output></label><input id=\"beta\" type=\"range\" min=\"25\" max=\"400\" value=\"100\">\n<div class=\"legend\"><span class=\"gray\" data-i18n=\"reference\"></span><span class=\"blue\" data-i18n=\"optimal\"></span></div><div id=\"policy-rows\" class=\"policy-rows\"></div>\n<div class=\"formula\" id=\"normalizer\"></div><div class=\"metric-pair\"><div><span data-i18n=\"reward\"></span><strong id=\"reward\"></strong></div><div><span>KL(π* ∥ πref)</span><strong id=\"kl\"></strong></div></div><div class=\"formula\" id=\"objective\"></div><p class=\"note\" data-i18n=\"note\"></p>\n","css":".intro { margin:8px 0 18px; color:var(--muted); font-size:14px; }\n.control { display:flex; align-items:center; justify-content:space-between; gap:16px; margin-top:18px; }\n.control output { min-width:4em; flex-shrink:0; text-align:center; background:var(--accent-soft); color:var(--accent); padding:2px 8px; border-radius:6px; font-weight:600; }\n.formula { margin-top:18px; padding:14px 0; border-block:1px solid var(--rule); font-size:16px; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }\n.copy-stack { display:grid; margin-top:14px; color:var(--muted); font-size:14px; }\n.copy-stack > * { grid-area:1/1; }\n.copy-stack .reserve { visibility:hidden; }\n.note { margin-top:14px; color:var(--muted); font-size:12px; }\n.metric-pair { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:18px; }\n.metric-pair > div { min-width:0; }\n.metric-pair span { display:block; font-size:12px; color:var(--muted); }\n.metric-pair strong { display:block; font-size:24px; font-weight:500; font-variant-numeric:tabular-nums; }\n.scale { display:flex; justify-content:space-between; color:var(--muted); font-size:12px; font-variant-numeric:tabular-nums; }\n@media(max-width:480px) { .metric-pair strong { font-size:21px; } }\n.presets { display:flex; }\n.plot { position:relative; margin-top:18px; height:190px; border-left:1px solid var(--rule); border-bottom:1px solid var(--muted); }\n.plot svg { width:100%; height:100%; overflow:hidden; }\n.plot .curve { fill:none; stroke:var(--accent); stroke-width:2.5; vector-effect:non-scaling-stroke; }\n.plot .curve.secondary { stroke:var(--second); stroke-dasharray:5 4; }\n.scale { position:relative; }.scale .middle { position:absolute; left:50%; transform:translateX(-50%); }\n.formula { font-size:14px; }.formula div+div { margin-top:6px; }\n@media(max-width:480px) { .plot { height:170px; } }\n.plot .curve { transition:d .28s cubic-bezier(.22,1,.36,1); }\n.band { display:flex; height:28px; border-radius:5px; overflow:hidden; background:var(--surface); margin-top:10px; }\n.band > div { background:var(--accent); transition:width .28s ease; }\n.band > .gold { background:var(--second); }\n.legend { display:flex; flex-wrap:wrap; gap:6px 18px; margin-top:10px; font-size:12px; color:var(--muted); }\n.legend .blue::before,.legend .gold::before { content:''; display:inline-block; width:9px; height:9px; border-radius:2px; margin-right:6px; background:var(--accent); }\n.legend .gold::before { background:var(--second); }\n.rows { margin-top:18px; display:grid; gap:12px; }\n.row { display:grid; grid-template-columns:32px 1fr 60px; align-items:center; gap:10px; font-size:13px; }\n.row > div { min-width:0; }.row output { text-align:right; font-variant-numeric:tabular-nums; }\n.track { height:14px; background:var(--surface); border-radius:3px; overflow:hidden; }\n.fill { height:100%; width:0; background:var(--accent); transition:width .28s ease; }\n.presets { flex-wrap:wrap; gap:4px; }.presets button { min-width:0; }\n.metric-pair strong { overflow-wrap:anywhere; }\n.policy-rows { display:grid; gap:18px; margin-top:18px; }.policy-row { border-bottom:1px solid var(--rule); padding-bottom:14px; }.policy-label { display:flex; gap:12px; justify-content:space-between; font-size:13px; margin-bottom:8px; }.policy-label code { color:var(--muted); font-size:12px; }.row { grid-template-columns:45px 1fr 55px; gap:8px; margin-top:5px; }.reference .fill { background:var(--muted); opacity:.45; }.legend .gray::before { content:''; display:inline-block; background:var(--muted); opacity:.45; width:9px; height:9px; margin-right:6px; border-radius:2px; }\n","js":"const $=s=>document.querySelector(s),ref=[.6,.3,.1],rewards=[0,1,2];for(let i=0;i<3;i++)$('#policy-rows').insertAdjacentHTML('beforeend','<div class=\"policy-row\"><div class=\"policy-label\"><strong>'+String.fromCharCode(65+i)+' · r = '+rewards[i]+'</strong><code class=\"weight\"></code></div><div class=\"row reference\"><span>πref</span><div class=\"track\"><div class=\"fill\" style=\"width:'+ref[i]*100+'%\"></div></div><output>'+viz.number(ref[i],3)+'</output></div><div class=\"row optimum\"><span>π*</span><div class=\"track\"><div class=\"fill\"></div></div><output></output></div></div>');\nfunction draw(){const b=+$('#beta').value/100,w=ref.map((p,i)=>p*Math.exp(rewards[i]/b)),z=w.reduce((a,b)=>a+b),q=w.map(v=>v/z),reward=q.reduce((a,p,i)=>a+p*rewards[i],0),kl=q.reduce((a,p,i)=>a+p*Math.log(p/ref[i]),0);$('#beta-value').textContent=viz.number(b,2);document.querySelectorAll('.policy-row').forEach((e,i)=>{e.querySelector('.weight').textContent=viz.number(ref[i],1)+' × e^('+rewards[i]+'/'+viz.number(b,2)+')';e.querySelector('.optimum .fill').style.width=q[i]*100+'%';e.querySelector('.optimum output').textContent=viz.number(q[i],3);});$('#normalizer').textContent='π*(y) = πref(y) e^(r(y)/β) / Z; Z ≈ '+viz.number(z,3);$('#reward').textContent=viz.number(reward,3);$('#kl').textContent=viz.number(kl,3)+' nat';$('#objective').textContent='J* = E[r] − β KL ≈ '+viz.number(reward,3)+' − '+viz.number(b,2)+' × '+viz.number(kl,3)+' ≈ '+viz.number(reward-b*kl,3)+' = β ln Z';}\n$('#beta').addEventListener('input',draw);draw();\n","audio":false,"strings":{"control":"KL 惩罚权重 β","eyebrow":"奖励怎样重分配概率","heading":"KL 约束下,高奖励回答会得到多少概率?","intro":"固定一个提示词,只考虑 A、B、C 三个回答。参考概率为 0.6、0.3、0.1,奖励为 0、1、2;条宽始终按 0–1 概率刻度绘制。","note":"β 越小,奖励差异被放大,概率更集中到 C;β 越大,分布更接近参考。这里精确求解有限回答空间的分布最优值,KL 使用自然对数。它不是 PPO 的训练过程,也不保证有限数据上的 DPO 达到这个分布。","optimal":"最优分布","reference":"参考分布","reward":"期望奖励 E[r]"}}
最优性不必凭直觉相信。代入 logπ∗=logπref+r/β−logZ,整理后得到
J(π)=βlogZ−βDKL(π∥π∗).
第一项与待选的 π 无关,第二项非正,因此 π=π∗ 达到最大值。这里 KL 使用 nat;更换对数底数时要相应调整惩罚系数。分布的闭式解并不等于神经网络参数的闭式解,更不是实际训练必然收敛到这里。
DPO 怎样用上这条关系?
将上式反解为奖励,可以写成
r(x,y)=βlogπref(y∣x)π∗(y∣x)+βlogZ(x).
Bradley–Terry 偏好模型只依赖两个回答的奖励差,因此同一提示词下的 logZ(x) 抵消。把策略换成待学习的 πθ,一对偏好数据 (yw,yl) 的 DPO 损失就是
−logσ(β[logπref(yw∣x)πθ(yw∣x)−logπref(yl∣x)πθ(yl∣x)]).
它比较的是两个回答相对参考模型的对数概率提升。标准 DPO 用偏好数据直接拟合这个目标,省去单独的显式奖励模型和 PPO 环节。推导与 KL 正则目标相连,但有限数据、模型参数化和优化误差仍会影响结果;不能据此认定 DPO 与 PPO 得到相同策略,也不能把 DPO 的 β 直接读成最终 KL 的硬预算。
Scaling law:压缩视角有用,指数仍是经验结果
Chinchilla 在其模型族、数据与拟合范围内发现,计算最优的参数量和训练 token 数应随算力大致同步增长。原文常用的近似是 N∝C0.5、D∝C0.5,不是对所有模型和训练条件都成立的常数。
固定评测设置后,交叉熵下降可解释为理想平均码长下降。这个视角把“如何分配算力”转成“怎样把测试交叉熵降得更低”,但源编码定理本身推不出 scaling law 的形状或指数。有限上下文下的条件熵、无限历史下的熵率、经验拟合中的常数项,也不是可以直接互换的量。架构、优化和数据质量仍要分别研究,见 稠密模型与 MoE。
温度:除 logits,为什么就改变了随机性?
对固定的有限 logits zi 和 T>0,
qT(i)=∑jezj/Tezi/T,qT(j)qT(i)=exp(Tzi−zj).
第二个式子解释了第一个:温度缩小的是对数概率比的差距。升温使候选概率更接近,降温放大原有差距。对固定 logits、不施加其他截断时,分布熵随温度单调不减;它说的是采样分布的不确定性,不是知识量增加。
正在呈现知识画面
温度改变的是概率比,不是知识量固定四个 logits,温度通过 exp((zA−zB)/T) 改变概率比。比较唯一最大值与并列最大值,并同时观察分布熵和观测到 B 时的损失。
{"id":"llm-temperature","title":"温度改变的是概率比,不是知识量","summary":"固定四个 logits,温度通过 exp((zA−zB)/T) 改变概率比。比较唯一最大值与并列最大值,并同时观察分布熵和观测到 B 时的损失。","height":950,"html":"<p class=\"eyebrow\" data-i18n=\"eyebrow\"></p><h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p>\n<div class=\"presets\" role=\"group\" data-i18n-label=\"examples\"><button data-mode=\"unique\" data-i18n=\"unique\"></button><button data-mode=\"tied\" data-i18n=\"tied\"></button></div>\n<label class=\"control\" for=\"temperature\"><span data-i18n=\"control\"></span><output id=\"temperature-value\"></output></label><input id=\"temperature\" type=\"range\" min=\"10\" max=\"400\" value=\"100\">\n<div class=\"rows\" id=\"temperature-rows\"></div><div class=\"formula\" id=\"odds\"></div><div class=\"metric-pair\"><div><span data-i18n=\"entropy\"></span><strong id=\"entropy\"></strong></div><div><span data-i18n=\"loss\"></span><strong id=\"token-loss\"></strong></div></div><div class=\"band\" role=\"img\" data-i18n-label=\"strip\"><div id=\"entropy-fill\"></div></div><div class=\"scale\"><span>0 bit</span><span>log₂ 4 = 2 bit</span></div><p class=\"note\" data-i18n=\"note\"></p>\n","css":".intro { margin:8px 0 18px; color:var(--muted); font-size:14px; }\n.control { display:flex; align-items:center; justify-content:space-between; gap:16px; margin-top:18px; }\n.control output { min-width:4em; flex-shrink:0; text-align:center; background:var(--accent-soft); color:var(--accent); padding:2px 8px; border-radius:6px; font-weight:600; }\n.formula { margin-top:18px; padding:14px 0; border-block:1px solid var(--rule); font-size:16px; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }\n.copy-stack { display:grid; margin-top:14px; color:var(--muted); font-size:14px; }\n.copy-stack > * { grid-area:1/1; }\n.copy-stack .reserve { visibility:hidden; }\n.note { margin-top:14px; color:var(--muted); font-size:12px; }\n.metric-pair { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:18px; }\n.metric-pair > div { min-width:0; }\n.metric-pair span { display:block; font-size:12px; color:var(--muted); }\n.metric-pair strong { display:block; font-size:24px; font-weight:500; font-variant-numeric:tabular-nums; }\n.scale { display:flex; justify-content:space-between; color:var(--muted); font-size:12px; font-variant-numeric:tabular-nums; }\n@media(max-width:480px) { .metric-pair strong { font-size:21px; } }\n.presets { display:flex; }\n.plot { position:relative; margin-top:18px; height:190px; border-left:1px solid var(--rule); border-bottom:1px solid var(--muted); }\n.plot svg { width:100%; height:100%; overflow:hidden; }\n.plot .curve { fill:none; stroke:var(--accent); stroke-width:2.5; vector-effect:non-scaling-stroke; }\n.plot .curve.secondary { stroke:var(--second); stroke-dasharray:5 4; }\n.scale { position:relative; }.scale .middle { position:absolute; left:50%; transform:translateX(-50%); }\n.formula { font-size:14px; }.formula div+div { margin-top:6px; }\n@media(max-width:480px) { .plot { height:170px; } }\n.plot .curve { transition:d .28s cubic-bezier(.22,1,.36,1); }\n.band { display:flex; height:28px; border-radius:5px; overflow:hidden; background:var(--surface); margin-top:10px; }\n.band > div { background:var(--accent); transition:width .28s ease; }\n.band > .gold { background:var(--second); }\n.legend { display:flex; flex-wrap:wrap; gap:6px 18px; margin-top:10px; font-size:12px; color:var(--muted); }\n.legend .blue::before,.legend .gold::before { content:''; display:inline-block; width:9px; height:9px; border-radius:2px; margin-right:6px; background:var(--accent); }\n.legend .gold::before { background:var(--second); }\n.rows { margin-top:18px; display:grid; gap:12px; }\n.row { display:grid; grid-template-columns:32px 1fr 60px; align-items:center; gap:10px; font-size:13px; }\n.row > div { min-width:0; }.row output { text-align:right; font-variant-numeric:tabular-nums; }\n.track { height:14px; background:var(--surface); border-radius:3px; overflow:hidden; }\n.fill { height:100%; width:0; background:var(--accent); transition:width .28s ease; }\n.presets { flex-wrap:wrap; gap:4px; }.presets button { min-width:0; }\n.metric-pair strong { overflow-wrap:anywhere; }\n.rows .row { grid-template-columns:76px 1fr 55px; }.row:nth-child(2) .fill { background:var(--second); }.row > span { font-size:12px; }.row strong { font-size:14px; margin-right:6px; }\n","js":"const $=s=>document.querySelector(s);let mode='unique';for(let i=0;i<4;i++)$('#temperature-rows').insertAdjacentHTML('beforeend','<div class=\"row\"><span><strong>'+String.fromCharCode(65+i)+'</strong><small></small></span><div class=\"track\"><div class=\"fill\"></div></div><output></output></div>');\nfunction draw(){const t=+$('#temperature').value/100,z=mode==='unique'?[3,2,0,-1]:[3,3,0,-1],w=z.map(v=>Math.exp((v-3)/t)),sum=w.reduce((a,b)=>a+b),p=w.map(v=>v/sum),h=viz.entropy(p);$('#temperature-value').textContent=viz.number(t,2);document.querySelectorAll('.row').forEach((e,i)=>{e.querySelector('small').textContent='z='+z[i];e.querySelector('.fill').style.width=p[i]*100+'%';e.querySelector('output').textContent=viz.number(p[i],3);});$('#entropy').textContent=viz.number(h,3)+' bit';$('#token-loss').textContent=viz.number(-Math.log2(p[1]),3)+' bit';$('#entropy-fill').style.width=h/2*100+'%';$('#odds').textContent='qT(A) / qT(B) = exp((zA − zB) / T) = exp('+ (z[0]-z[1])+' / '+viz.number(t,2)+') ≈ '+viz.number(p[0]/p[1],3);document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(mode===e.dataset.mode)));}\n$('#temperature').addEventListener('input',draw);document.querySelectorAll('[data-mode]').forEach(e=>e.addEventListener('click',()=>{mode=e.dataset.mode;draw();}));draw();\n","audio":false,"strings":{"control":"采样温度 T","entropy":"整个分布的熵 H(qT)","examples":"logits 示例","eyebrow":"从 logit 差到概率比","heading":"温度改变的是概率比,不是知识量","intro":"蓝/金条显示四个候选的概率,金色 B 是固定的观测 token。升温改变整个分布;分布熵与 B 的损失是两个不同的量。","loss":"若观测到 B:−log₂ qT(B)","note":"概率条固定 0–1,熵条固定 0–2 bit。只有最高值唯一时,T→0 的熵才趋于 0;A、B 并列时趋于 1 bit。T→∞ 时四项趋于均匀、熵趋于 2 bit。此处没有 top-k/top-p 截断;B 的损失仅是重赋概率的演示,不是模型整体 PPL。","strip":"分布熵占四候选最大熵 2 bit 的比例。","tied":"并列最高","unique":"唯一最高"}}
如果想看严格原因,用自然对数写 H(qT)=logZT−EqT[z]/T。求导时两项的一部分抵消,剩下
dTdHe(qT)=T3VarqT(z)≥0.
唯一最大 logit 在 T→0 时独占概率,熵趋于 0;若有 m 项并列最大,极限在它们之间均匀分布,熵为 log2m。T→∞ 时有限词表趋于均匀。实际生成再叠加 top-k、top-p 等采样操作 后,应分析最终分布,不能直接套用未截断的曲线。
把几个容易混淆的量分开
| 量 | 回答的问题 | 不能直接推出 |
| 测试 NLL / PPL | 给实际数据分配了多少概率? | 事实正确、推理可靠、回答有用 |
| 采样熵 H(qT) | 当前候选有多不确定? | 内容更有创造力、模型知识更多 |
| 策略与参考的 KL | 概率分布偏离了多少? | 奖励不会被利用、偏好全部满足 |
| 理想编码长度 | 共享模型下编码文本需要多少 bit? | 压缩率就是理解能力的完整评分 |
温度不会修改权重里的知识,低 PPL 也不会自动消除幻觉;更小的 KL 不等于更好的对齐。信息论让这些问题有了明确的测量语言,而事实性、推理和人类偏好仍需要相应的评测。
参考
关键词:困惑度、几何平均、交叉熵、NLL、RLHF、KL 正则、DPO、scaling law、温度、softmax