上一章的熵回答了“这个分布平均有多少信息”。这一章再问一步:数据分布没变,但我们对它的预期错了,会多付多少代价?
三个概念可以沿着同一条线理解:熵是源分布自身的平均信息量,交叉熵是按另一个分布计算的信息长度的平均,KL 散度是两者的差。
用错分布,多花的是什么?
设真实分布为 p,模型分布为 q。模型把结果 x 的理想信息长度设为 −log2q(x):越认为它常见,分配的长度越短。
数据仍按 p 出现,所以平均时要用 p 加权:
H(p,q)=−x∑p(x)log2q(x)
这就是交叉熵。若模型与真实分布一致,得到 H(p,p)=H(p)。
这里的 −log2q(x) 可以是小数,表示理想信息长度。实际逐符号的二进制前缀码长度必须取整数;在适当的独立同分布长块编码中,每符号平均长度可以逼近对应的交叉熵,不能直接把两者说成任意有限编码的精确码长。编码关系可参阅 Stanford 数据压缩课程。
正在呈现知识画面
数据没变,只换一份编码预期固定 p(A)=0.75,只调整模型 q(A)。横条表示按 q 分配的理想信息长度,虚线标出按 p 分配的位置。底部把交叉熵拆成固定的真实熵与额外的 KL 代价。
{"id":"kl-coding-cost","title":"数据没变,只换一份编码预期","summary":"固定 p(A)=0.75,只调整模型 q(A)。横条表示按 q 分配的理想信息长度,虚线标出按 p 分配的位置。底部把交叉熵拆成固定的真实熵与额外的 KL 代价。","height":900,"html":"<div class=\"eyebrow\" data-i18n=\"eyebrow\"></div><h2 data-i18n=\"heading\"></h2><p class=\"hint\" data-i18n=\"intro\"></p>\n<div class=\"source\"><span data-i18n=\"source\"></span><div class=\"source-band\"><span>A · 75%</span><span>B · 25%</span></div></div>\n<div class=\"control\"><label for=\"model-q\" data-i18n=\"control\"></label><output id=\"q-value\" for=\"model-q\"></output></div><input type=\"range\" id=\"model-q\" min=\"1\" max=\"99\" step=\"1\" value=\"25\"><div class=\"scale\"><span>1%</span><span>50%</span><span>99%</span></div>\n<div class=\"legend\"><span><i class=\"target\"></i><span data-i18n=\"marker\"></span></span></div>\n<div class=\"cost-row\"><div class=\"row-label\"><strong>A <small>p = 0.75</small></strong><span id=\"cost-a\" class=\"number\"></span></div><div class=\"cost-track\"><span id=\"length-a\"></span><i id=\"ideal-a\"></i></div></div>\n<div class=\"cost-row\"><div class=\"row-label\"><strong>B <small>p = 0.25</small></strong><span id=\"cost-b\" class=\"number\"></span></div><div class=\"cost-track second\"><span id=\"length-b\"></span><i id=\"ideal-b\"></i></div></div>\n<div class=\"scale\"><span>0 bit</span><span>7 bit</span></div>\n<div class=\"summary\"><div class=\"summary-line\"><span data-i18n=\"average\"></span><strong><output id=\"cross-entropy\"></output> bit</strong></div><div class=\"average-track\"><span id=\"base-cost\"></span><span id=\"extra-cost\"></span></div><div class=\"scale\"><span>0 bit</span><span>7 bit</span></div>\n<div class=\"cost-equation\"><span>H(p) = <strong id=\"entropy\"></strong></span><span>+ KL = <strong id=\"kl\"></strong></span></div></div>\n<div class=\"copy-stack\"><p id=\"explanation\"></p><p class=\"reserve\" aria-hidden=\"true\" data-i18n=\"matched\"></p><p class=\"reserve\" aria-hidden=\"true\" data-i18n=\"mismatch\"></p></div><p class=\"note\" data-i18n=\"note\"></p>","css":".control { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-top:22px; }\n.control output { min-width:4.5em; flex-shrink:0; text-align:center; font-size:14px; font-weight:600; font-variant-numeric:tabular-nums; color:var(--accent); padding:3px 10px; background:var(--accent-soft); border-radius:6px; }\n.scale { display:flex; justify-content:space-between; font-size:10px; color:var(--muted); margin-top:5px; }\n.note { color:var(--muted); font-size:11px; line-height:1.7; margin-top:16px; }\n.copy-stack { display:grid; font-size:13px; line-height:1.75; margin-top:20px; }\n.copy-stack > * { grid-area:1/1; min-width:0; }\n.reserve { visibility:hidden; pointer-events:none; user-select:none; }\n.number { font-variant-numeric:tabular-nums; }\n.legend { display:flex; flex-wrap:wrap; gap:6px 16px; font-size:12px; color:var(--muted); margin:20px 0 12px; }\n.legend span { display:inline-flex; align-items:center; gap:6px; }\n.legend i { display:inline-block; width:16px; height:0; border-top:2px solid var(--accent); }\n.legend .target { border-color:var(--muted); border-top-style:dashed; }\n.summary { border-top:1px solid var(--rule); margin-top:22px; padding-top:16px; }\n.summary-line { display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px 16px; align-items:baseline; font-size:13px; color:var(--muted); }\n.summary-line strong { font-size:23px; font-weight:500; color:var(--ink); }\n@media(max-width:480px) { .copy-stack { font-size:12px; } }\n.source { margin-top:22px; font-size:12px; color:var(--muted); }\n.source-band { display:flex; height:30px; margin-top:8px; border-radius:4px; overflow:hidden; font-size:12px; }\n.source-band span { display:grid; place-items:center; width:75%; background:var(--surface); color:var(--ink); }\n.source-band span+span { width:25%; background:var(--rule); color:var(--ink); }\n.cost-row { margin-top:20px; }\n.row-label { display:flex; align-items:baseline; justify-content:space-between; flex-wrap:wrap; gap:6px; font-size:13px; margin-bottom:9px; }\n.row-label small { color:var(--muted); font-weight:400; margin-left:5px; font-size:11px; }\n.cost-track,.average-track { height:22px; position:relative; background:var(--surface); border-radius:3px; }\n.cost-track > span { display:block; height:100%; background:var(--ink); border-radius:3px; }\n.cost-track.second > span { background:var(--ink); }\n.cost-track i { position:absolute; top:-4px; bottom:-4px; border-left:2px dashed var(--muted); }\n.average-track { display:flex; margin-top:14px; overflow:hidden; }\n#base-cost { background:var(--muted); } #extra-cost { background:var(--accent); }\n.cost-equation { display:flex; justify-content:space-between; gap:8px; font-size:13px; margin-top:14px; font-variant-numeric:tabular-nums; }\n.cost-equation span:first-child { color:var(--muted); } .cost-equation span+span { color:var(--accent); }\n","js":"const input=document.querySelector('#model-q'), p=.75;\nconst h=viz.entropy([p,1-p]);\ndocument.querySelector('#ideal-a').style.left=(-Math.log2(p)/7*100)+'%';\ndocument.querySelector('#ideal-b').style.left=(-Math.log2(1-p)/7*100)+'%';\ndocument.querySelector('#base-cost').style.width=(h/7*100)+'%';\ndocument.querySelector('#entropy').textContent=viz.number(h);\nfunction draw(){\n const q=Number(input.value)/100, a=-Math.log2(q), b=-Math.log2(1-q), cross=p*a+(1-p)*b, kl=Math.max(0,cross-h);\n document.querySelector('#q-value').textContent=viz.number(q*100,0)+'%';\n document.querySelector('#cost-a').textContent=`−log₂ ${viz.number(q)} ≈ ${viz.number(a)} bit`;\n document.querySelector('#cost-b').textContent=`−log₂ ${viz.number(1-q)} ≈ ${viz.number(b)} bit`;\n document.querySelector('#length-a').style.width=(a/7*100)+'%';document.querySelector('#length-b').style.width=(b/7*100)+'%';\n document.querySelector('#cross-entropy').textContent=viz.number(cross);document.querySelector('#kl').textContent=viz.number(kl);\n document.querySelector('#extra-cost').style.width=(kl/7*100)+'%';\n document.querySelector('#explanation').textContent=viz.t(q===p?'matched':'mismatch');\n}\ninput.addEventListener('input',draw);draw();","audio":false,"strings":{"average":"平均理想长度 H(p,q)","control":"模型认为 A 出现的概率 q(A)","eyebrow":"01 / 看见用错分布的代价","heading":"把常见结果估得太少,会多花多少 bit?","intro":"真实频率始终不变。拖动模型的预期,观察 A、B 的长度与加权后的总成本。","marker":"虚线:按真实分布 p 分配的长度","matched":"q 与 p 一致,两条长度都对齐虚线。平均成本恰好是 H(p),额外的 KL 为 0。","mismatch":"有的结果可能变便宜,但按真实频率加权后,总成本不会低于 H(p)。灰色基础段不变,蓝色部分就是平均多付的 KL。","note":"每条长度为 −log₂q(x),可以是小数;不是一条实际整数码字。范围取 1%–99% 以使用有限标尺;若真实可能发生的结果被 q 设为 0,代价会发散。","source":"固定的真实分布 p"}}
相对熵 / KL 散度定义为:
DKL(p∥q)=x∑p(x)log2q(x)p(x)=H(p,q)−H(p)
DKL(p∥q)≥0,等号当且仅当两个分布相同。它刻画的是平均的额外代价。某个结果用 q 计算可能更便宜,对应的单项可以为负;不能把“总 KL 非负”理解成“每一项都非负”。
若 p(x)>0 而 q(x)=0,模型给真实可能发生的结果分配了无限信息长度,交叉熵和这个方向的 KL 都为 ∞。p(x)=0 的项按极限约定贡献为 0。
为什么交换方向,结果会不同?
在 DKL(p∥q) 中,我们对来自 p 的结果取平均;在 DKL(q∥p) 中,平均的权重换成了 q,对数比值也取了倒数。
以下固定 p=(0.5,0.5)、q=(0.9,0.1),只交换计算方向。零线上方是正项,下方是负项;带符号面积相加才是 KL。
正在呈现知识画面
交换方向,连平均的权重也变了同一对固定分布,切换 KL 的方向。色块宽度表示求和权重,高度表示带符号的对数比;零线上下的带符号面积之和分别约为 0.74 与 0.53 bit。
{"id":"kl-direction","title":"交换方向,连平均的权重也变了","summary":"同一对固定分布,切换 KL 的方向。色块宽度表示求和权重,高度表示带符号的对数比;零线上下的带符号面积之和分别约为 0.74 与 0.53 bit。","height":900,"html":"<div class=\"eyebrow\" data-i18n=\"eyebrow\"></div><h2 data-i18n=\"heading\"></h2><p class=\"hint\" data-i18n=\"intro\"></p>\n<div class=\"fixed-pair\"><span>p = (0.5, 0.5)</span><span>q = (0.9, 0.1)</span></div>\n<div class=\"direction-control\" role=\"group\" data-i18n-label=\"control\"><button type=\"button\" data-direction=\"forward\">KL(p ‖ q)</button><button type=\"button\" data-direction=\"reverse\">KL(q ‖ p)</button></div>\n<div class=\"direction-caption\"><span id=\"weight-label\"></span><span data-i18n=\"height\"></span></div>\n<div class=\"signed-chart\" role=\"img\" data-i18n-label=\"chart\"><div class=\"tick top\">+2.5</div><div class=\"zero\"><i>0</i></div><div class=\"tick bottom\">−2.5</div><div class=\"signed-area a\" id=\"term-a\"></div><div class=\"signed-area b\" id=\"term-b\"></div></div>\n<div class=\"weight-labels\"><span id=\"weight-a\"></span><span id=\"weight-b\"></span></div>\n<div class=\"term-equations\"><div><strong>A</strong><span id=\"expression-a\"></span></div><div><strong>B</strong><span id=\"expression-b\"></span></div></div>\n<div class=\"summary summary-line\"><span id=\"direction-formula\"></span><strong><output id=\"divergence\"></output> bit</strong></div>\n<div class=\"copy-stack\"><p id=\"explanation\"></p><p class=\"reserve\" data-i18n=\"forward\" aria-hidden=\"true\"></p><p class=\"reserve\" data-i18n=\"reverse\" aria-hidden=\"true\"></p></div><p class=\"note\" data-i18n=\"note\"></p>","css":".control { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-top:22px; }\n.control output { min-width:4.5em; flex-shrink:0; text-align:center; font-size:14px; font-weight:600; font-variant-numeric:tabular-nums; color:var(--accent); padding:3px 10px; background:var(--accent-soft); border-radius:6px; }\n.scale { display:flex; justify-content:space-between; font-size:10px; color:var(--muted); margin-top:5px; }\n.note { color:var(--muted); font-size:11px; line-height:1.7; margin-top:16px; }\n.copy-stack { display:grid; font-size:13px; line-height:1.75; margin-top:20px; }\n.copy-stack > * { grid-area:1/1; min-width:0; }\n.reserve { visibility:hidden; pointer-events:none; user-select:none; }\n.number { font-variant-numeric:tabular-nums; }\n.legend { display:flex; flex-wrap:wrap; gap:6px 16px; font-size:12px; color:var(--muted); margin:20px 0 12px; }\n.legend span { display:inline-flex; align-items:center; gap:6px; }\n.legend i { display:inline-block; width:16px; height:0; border-top:2px solid var(--accent); }\n.legend .target { border-color:var(--muted); border-top-style:dashed; }\n.summary { border-top:1px solid var(--rule); margin-top:22px; padding-top:16px; }\n.summary-line { display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px 16px; align-items:baseline; font-size:13px; color:var(--muted); }\n.summary-line strong { font-size:23px; font-weight:500; color:var(--ink); }\n@media(max-width:480px) { .copy-stack { font-size:12px; } }\n.fixed-pair { display:flex; flex-wrap:wrap; gap:8px 20px; margin-top:20px; font-size:13px; color:var(--muted); }\n.direction-control { display:flex; padding:4px; gap:4px; background:var(--surface); border:1px solid var(--rule); border-radius:8px; margin:18px 0; }\n.direction-control button { flex:1; border-color:transparent; background:transparent; }\n.direction-control button[aria-pressed='true'] { background:var(--paper); border-color:var(--rule); color:var(--accent); }\n.direction-caption { display:flex; flex-wrap:wrap; justify-content:space-between; gap:5px 12px; font-size:11px; color:var(--muted); margin-bottom:16px; }\n.signed-chart { height:220px; position:relative; margin-left:32px; border-top:1px solid var(--rule); border-bottom:1px solid var(--rule); }\n.tick { position:absolute; left:-34px; width:28px; color:var(--muted); font-size:10px; text-align:right; }\n.tick.top { top:-7px; } .tick.bottom { bottom:-7px; }\n.zero { position:absolute; top:50%; inset-inline:0; border-top:1px solid var(--muted); }\n.zero i { position:absolute; left:-30px; width:24px; top:-9px; text-align:right; color:var(--muted); font-size:11px; font-style:normal; }\n.signed-area { position:absolute; box-shadow:inset 0 0 0 1px currentColor; background:var(--accent-soft); color:var(--accent); }\n.signed-area.b { background:var(--second-soft); color:var(--second); }\n.weight-labels { display:flex; justify-content:space-between; margin:12px 0 0 32px; font-size:12px; font-variant-numeric:tabular-nums; }\n.weight-labels span:first-child { color:var(--accent); } .weight-labels span+span { color:var(--second); }\n.term-equations { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; margin-top:20px; font-size:12px; font-variant-numeric:tabular-nums; }\n.term-equations > div { border-left:2px solid currentColor; padding-left:10px; color:var(--accent); }\n.term-equations > div+div { color:var(--second); }\n.term-equations span { display:block; min-height:3.4em; line-height:1.7; }\n","js":"function draw(direction){\n const forward=direction==='forward', weights=forward?[.5,.5]:[.9,.1], reference=forward?[.9,.1]:[.5,.5];let sum=0;\n for(let i=0;i<2;i++){\n const key=i?'b':'a', log=Math.log2(weights[i]/reference[i]), value=weights[i]*log;sum+=value;\n const rect=document.querySelector('#term-'+key);rect.style.width=weights[i]*100+'%';rect.style.left=(i?weights[0]*100:0)+'%';rect.style.height=Math.abs(log)/5*100+'%';rect.style.top=(log>0?50-log/5*100:50)+'%';\n document.querySelector('#weight-'+key).textContent=`${key.toUpperCase()}: ${viz.number(weights[i])}`;\n document.querySelector('#expression-'+key).textContent=`${viz.number(weights[i])} × (${log>0?'+':''}${viz.number(log)}) ≈ ${value>0?'+':''}${viz.number(value)}`;\n }\n document.querySelector('#weight-label').textContent=viz.t(forward?'weightP':'weightQ');\n document.querySelector('#direction-formula').textContent=forward?'KL(p ‖ q)':'KL(q ‖ p)';\n document.querySelector('#divergence').textContent=viz.number(sum);\n document.querySelector('#explanation').textContent=viz.t(direction);\n document.querySelectorAll('[data-direction]').forEach(b=>b.setAttribute('aria-pressed',String(b.dataset.direction===direction)));\n}\ndocument.querySelectorAll('[data-direction]').forEach(b=>b.addEventListener('click',()=>draw(b.dataset.direction)));draw('forward');","audio":false,"strings":{"chart":"带符号面积图:宽是平均的权重,高是对数比值;上方正、下方负。","control":"KL 计算方向","eyebrow":"02 / 非对称性来自不同的期望","forward":"在 p 下平均,A、B 各占一半。A 的负项与 B 的正项相加,得到约 0.74 bit。","heading":"同样的 p、q,为什么两个方向算不一样?","height":"高度:带符号的 log₂ 比值","intro":"只交换方向。蓝色始终是 A,金色始终是 B;观察谁变宽,以及哪一块移到零线上方。","note":"零线上方加、下方减。KL 的总和非负,但单项可以为负。两幅状态使用同一标尺;图中展示的是固定分布之间的精确计算,数字作了舍入。","reverse":"在 q 下平均,A 占九成、B 占一成;对数比也倒过来。正负项的面积重新分配,总和约为 0.53 bit。","weightP":"宽度:来自 p 的权重","weightQ":"宽度:来自 q 的权重"}}
两个结果分别约为 0.737 bit 和 0.531 bit。这不是舍入差异,而是两个不同的期望。因此 KL 不满足一般距离要求的对称性,也不满足一般的三角不等式。
支撑集条件也有方向:p 在某处有质量而 q 为零,会使 DKL(p∥q) 发散;交换方向后,检查的则是 q 有质量而 p 为零的区域。连续分布要把求和换成积分,并按具有非零概率质量的区域理解这个条件,而非仅看一个孤立点。
交叉熵为什么成为分类损失?
当目标分布 p 固定、只调整模型 qθ 时:
H(p,qθ)=H(p)+DKL(p∥qθ)
H(p) 不随模型参数变化,所以最小化交叉熵与最小化这个方向的 KL 等价。
在单个有标签样本 (xi,yi) 上,通常用 one-hot 的经验目标表示观测到的标签。它不意味着真实的条件分布 p(y∣xi) 必然确定。对这个经验目标计算交叉熵,得到:
ℓi=−logqθ(yi∣xi)
对给定样本,采用条件似然乘积时:
i∑−logqθ(yi∣xi)=−logi∏qθ(yi∣xi)
因此,最小化经验交叉熵就是最大化相应的条件似然。总体交叉熵则是在真实数据分布下取期望,训练集平均是对它的经验估计。
实践中常用自然对数,损失单位是 nat;本文用以 2 为底的对数,单位是 bit。两者只差一个正的常数因子,最优解相同。自回归语言模型的 token 级负对数似然也采用这条链式分解,见 LLM 中的信息论。
Forward / reverse KL:同一个模型族,两种拟合目标
令 p 固定,优化近似 q。称 DKL(p∥q) 为 forward KL,DKL(q∥p) 为 reverse KL。如果 q 能表示 p,两个方向都可以在 q=p 处达到零。 行为差异在模型表达能力受限时尤其明显。
先用静态示意图并列看两种典型形状:当目标的两峰充分分离、近似限制为单个高斯时,forward 可以铺开覆盖两侧,reverse 可以集中在一侧。曲线用于说明形状,不表示精确的数值拟合。
灰色虚线是目标 p,彩色实线是近似 q;两幅图共用坐标尺度。这里展示的是充分分离时的典型形状,不是所有受限模型都必然出现的结果。
下面用一个具体、可计算的限制:目标是两个单位方差高斯的等权混合,近似只能是一个高斯。
p(x)=21N(x;−d/2,1)+21N(x;d/2,1),q(x)=N(x;μ,σ2)
唯一改变的是两个分量的中心间距 d;混合分布在它们靠近时可以只有一个峰。两列分别针对自己的目标重新拟合 μ,σ,并使用相同的坐标尺度。
正在呈现知识画面
拉开两峰,看受限模型如何取舍目标 p 是两个单位方差高斯的等权混合,q 只能是单个高斯。改变两峰间距,两列分别按 forward 与 reverse KL 重新拟合;它们使用同一坐标尺度。
{"id":"kl-mode-fitting","title":"拉开两峰,看受限模型如何取舍","summary":"目标 p 是两个单位方差高斯的等权混合,q 只能是单个高斯。改变两峰间距,两列分别按 forward 与 reverse KL 重新拟合;它们使用同一坐标尺度。","height":900,"html":"<div class=\"eyebrow\" data-i18n=\"eyebrow\"></div><h2 data-i18n=\"heading\"></h2><p class=\"hint\" data-i18n=\"intro\"></p>\n<div class=\"control\"><label for=\"separation\" data-i18n=\"control\"></label><output id=\"separation-value\" for=\"separation\"></output></div><input type=\"range\" id=\"separation\" min=\"0\" max=\"80\" step=\"1\" value=\"60\"><div class=\"scale\"><span>0</span><span>4</span><span>8</span></div>\n<div class=\"legend\"><span><i class=\"target\"></i><span data-i18n=\"target\"></span></span><span><i></i><span data-i18n=\"approximation\"></span></span></div>\n<div class=\"fit-panels\">\n <section class=\"fit-panel\"><h3>Forward · KL(p ‖ q)</h3><svg viewBox=\"0 0 480 200\" preserveAspectRatio=\"none\" role=\"img\" data-i18n-label=\"forwardChart\"><path class=\"fit-fill\" id=\"forward-fill\"/><path class=\"target-curve\" id=\"target-forward\"/><path class=\"fit-curve\" id=\"forward-curve\"/></svg><div class=\"scale\"><span>−12</span><span>0</span><span>12</span></div><div class=\"fit-parameters\" id=\"forward-parameters\"></div><div class=\"fit-result\">KL ≈ <strong id=\"forward-kl\"></strong> bit</div></section>\n <section class=\"fit-panel reverse\"><h3>Reverse · KL(q ‖ p)</h3><svg viewBox=\"0 0 480 200\" preserveAspectRatio=\"none\" role=\"img\" data-i18n-label=\"reverseChart\"><path class=\"fit-fill\" id=\"reverse-fill\"/><path class=\"target-curve\" id=\"target-reverse\"/><path class=\"fit-curve\" id=\"reverse-curve\"/></svg><div class=\"scale\"><span>−12</span><span>0</span><span>12</span></div><div class=\"fit-parameters\" id=\"reverse-parameters\"></div><div class=\"fit-result\">KL ≈ <strong id=\"reverse-kl\"></strong> bit</div></section>\n</div>\n<div class=\"copy-stack\"><p id=\"explanation\"></p><p class=\"reserve\" data-i18n=\"overlap\" aria-hidden=\"true\"></p><p class=\"reserve\" data-i18n=\"separated\" aria-hidden=\"true\"></p></div><details class=\"audit-details\"><summary data-i18n=\"detailLabel\"></summary><p class=\"note\" data-i18n=\"note\"></p></details>","css":".control { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-top:22px; }\n.control output { min-width:4.5em; flex-shrink:0; text-align:center; font-size:14px; font-weight:600; font-variant-numeric:tabular-nums; color:var(--accent); padding:3px 10px; background:var(--accent-soft); border-radius:6px; }\n.scale { display:flex; justify-content:space-between; font-size:10px; color:var(--muted); margin-top:5px; }\n.note { color:var(--muted); font-size:11px; line-height:1.7; margin-top:16px; }\n.copy-stack { display:grid; font-size:13px; line-height:1.75; margin-top:20px; }\n.copy-stack > * { grid-area:1/1; min-width:0; }\n.reserve { visibility:hidden; pointer-events:none; user-select:none; }\n.number { font-variant-numeric:tabular-nums; }\n.legend { display:flex; flex-wrap:wrap; gap:6px 16px; font-size:12px; color:var(--muted); margin:20px 0 12px; }\n.legend span { display:inline-flex; align-items:center; gap:6px; }\n.legend i { display:inline-block; width:16px; height:0; border-top:2px solid var(--accent); }\n.legend .target { border-color:var(--muted); border-top-style:dashed; }\n.summary { border-top:1px solid var(--rule); margin-top:22px; padding-top:16px; }\n.summary-line { display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px 16px; align-items:baseline; font-size:13px; color:var(--muted); }\n.summary-line strong { font-size:23px; font-weight:500; color:var(--ink); }\n@media(max-width:480px) { .copy-stack { font-size:12px; } }\n.fit-panels { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; }\n.fit-panel { padding:14px; border:1px solid var(--rule); border-radius:8px; min-width:0; color:var(--accent); }\n.fit-panel.reverse { color:var(--second); }\n.fit-panel h3 { font-size:13px; margin-bottom:14px; }\n.fit-panel svg { height:180px; border-bottom:1px solid var(--rule); overflow:visible; }\n.target-curve { fill:none; stroke:var(--muted); stroke-width:1.5px; stroke-dasharray:5 4; vector-effect:non-scaling-stroke; }\n.fit-curve { fill:none; stroke:currentColor; stroke-width:2px; vector-effect:non-scaling-stroke; }\n.fit-fill { fill:currentColor; opacity:.09; stroke:none; }\n.fit-parameters { margin-top:14px; font-size:12px; font-variant-numeric:tabular-nums; color:var(--muted); }\n.fit-result { font-size:13px; margin-top:6px; font-variant-numeric:tabular-nums; }\n.fit-result strong { font-size:19px; font-weight:500; }\n@media(max-width:540px) { .fit-panels { grid-template-columns:1fr; gap:14px; } .fit-panel svg { height:154px; } }\n\n@media(max-width:540px){.fit-panel{padding:10px}.fit-panel h3{margin-bottom:6px}.fit-panel svg{height:112px}.fit-parameters{margin-top:8px}.fit-panels{gap:10px}.legend{margin:12px 0 8px}.copy-stack{margin-top:12px}.fit-result strong{font-size:17px}}\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":"// Reproduce with scripts/build-kl-mode-fits.py: [separation, reverse mu, sigma, forward KL, reverse KL].\nconst fits=[[0.0,0.0,1.0,0.0,0],[0.1,0.0,1.0012492,0.0,0.0],[0.2,0.0,1.0049876,0.0,0.0],[0.3,0.0,1.0111873,0.0,0.0],[0.4,0.0,1.0198032,3e-07,3e-07],[0.5,0.0,1.0307727,1.5e-06,1.5e-06],[0.6,0.0,1.0440164,5.7e-06,5.8e-06],[0.7,0.0,1.059438,1.77e-05,1.8e-05],[0.8,0.0,1.0769242,4.63e-05,4.73e-05],[0.9,0.0,1.0963454,0.0001056,0.0001087],[1.0,0.0,1.1175572,0.0002168,0.0002252],[1.1,0.0,1.1404032,0.000409,0.0004285],[1.2,0.0,1.1647197,0.0007193,0.0007602],[1.3,0.0,1.1903399,0.0011929,0.0012714],[1.4,0.0,1.2170998,0.0018823,0.0020226],[1.5,0.0,1.2448426,0.002846,0.0030818],[1.6,0.0,1.2734227,0.0041473,0.0045233],[1.7,0.0,1.302709,0.0058523,0.0064257],[1.8,0.0,1.3325862,0.0080282,0.0088699],[1.9,0.0,1.362955,0.0107413,0.0119372],[2.0,0.0,1.3937323,0.0140558,0.0157079],[2.1,0.0,1.4248491,0.0180318,0.0202596],[2.2,0.0,1.45625,0.022724,0.0256666],[2.3,0.0,1.4878907,0.0281808,0.0319989],[2.4,0.0,1.5197363,0.0344436,0.0393218],[2.5,0.0,1.5517602,0.0415456,0.0476957],[2.6,0.0,1.583942,0.0495122,0.0571758],[2.7,0.0,1.6162665,0.0583602,0.0678126],[2.8,0.0,1.6487225,0.0680986,0.0796516],[2.9,0.0,1.681302,0.0787277,0.0927341],[3.0,0.0,1.7139994,0.0902409,0.1070967],[3.1,0.0,1.7468106,0.1026237,0.1227723],[3.2,0.0,1.7797332,0.1158555,0.1397901],[3.3,0.0,1.8127654,0.1299096,0.158176],[3.4,0.0,1.8459063,0.1447539,0.1779527],[3.5,0.0,1.8791551,0.1603519,0.1991403],[3.6,0.0,1.9125117,0.1766633,0.2217564],[3.7,0.0,1.9459756,0.1936446,0.2458162],[3.8,0.0,1.9795469,0.21125,0.2713331],[3.9,0.0,2.0132252,0.2294319,0.2983183],[4.0,0.0,2.0470104,0.2481418,0.3267819],[4.1,0.0,2.0809022,0.2673303,0.3567322],[4.2,0.0,2.1149001,0.2869485,0.3881762],[4.3,0.0,2.1490037,0.3069477,0.4211199],[4.4,0.0,2.1832125,0.3272804,0.4555682],[4.5,0.0,2.2175256,0.3479002,0.4915251],[4.6,0.0,2.2519424,0.3687623,0.5289937],[4.7,0.0,2.2864621,0.3898241,0.5679765],[4.8,0.0,2.3210837,0.4110448,0.6084753],[4.9,0.0,2.3558064,0.4323859,0.6504913],[5.0,0.0,2.3906291,0.4538115,0.6940253],[5.1,0.0,2.4255508,0.4752878,0.7390775],[5.2,0.0,2.4605704,0.4967838,0.7856479],[5.3,0.0,2.4956867,0.5182707,0.8337359],[5.4,0.0,2.5308987,0.5397224,0.8833408],[5.5,0.0,2.5662052,0.561115,0.9344615],[5.6,0.0,2.6016049,0.5824272,0.9870969],[5.7,2.8232538,1.0376737,0.6036395,0.9892609],[5.8,2.8776473,1.0320905,0.6247351,0.9910001],[5.9,2.9312827,1.0273731,0.6456988,0.9924587],[6.0,2.984306,1.0233686,0.6665173,0.9936836],[6.1,3.0368302,1.0199572,0.6871795,0.9947129],[6.2,3.0889439,1.0170438,0.7076754,0.9955781],[6.3,3.1407178,1.0145509,0.7279969,0.9963054],[6.4,3.192209,1.0124153,0.7481373,0.9969165],[6.5,3.2434638,1.0105845,0.7680908,0.9974298],[6.6,3.2945204,1.0090144,0.7878531,0.9978606],[6.7,3.3454103,1.0076681,0.8074209,0.9982218],[6.8,3.3961598,1.0065139,0.8267918,0.9985243],[6.9,3.4467909,1.0055253,0.8459641,0.9987774],[7.0,3.4973219,1.0046791,0.8649369,0.9989888],[7.1,3.5477684,1.0039557,0.88371,0.9991652],[7.2,3.5981434,1.003338,0.9022837,0.9993121],[7.3,3.648458,1.0028114,0.9206589,0.9994342],[7.4,3.6987216,1.0023631,0.9388367,0.9995356],[7.5,3.7489421,1.0019822,0.9568188,0.9996196],[7.6,3.7991262,1.0016592,0.974607,0.999689],[7.7,3.8492798,1.0013857,0.9922035,0.9997463],[7.8,3.8994076,1.0011547,1.0096105,0.9997935],[7.9,3.9495137,1.00096,1.0268306,0.9998322],[8.0,3.9996017,1.0007963,1.0438664,0.999864]];\nconst input=document.querySelector('#separation');\nconst normal=(x,mu,sigma)=>Math.exp(-.5*((x-mu)/sigma)**2)/(sigma*Math.sqrt(2*Math.PI));\nfunction curve(fn){return Array.from({length:481},(_,i)=>`${i?'L':'M'}${i},${200-200*fn(-12+i/20)/.45}`).join(' ');}\nfunction draw(){\n const [d,mu,sigma,fkl,rkl]=fits[Number(input.value)], a=d/2, forwardSigma=Math.sqrt(1+a*a);\n const target=curve(x=>(normal(x,-a,1)+normal(x,a,1))/2), f=curve(x=>normal(x,0,forwardSigma)), r=curve(x=>normal(x,mu,sigma));\n document.querySelector('#target-forward').setAttribute('d',target);document.querySelector('#target-reverse').setAttribute('d',target);\n document.querySelector('#forward-curve').setAttribute('d',f);document.querySelector('#reverse-curve').setAttribute('d',r);\n document.querySelector('#forward-fill').setAttribute('d',f+'L480 200H0Z');document.querySelector('#reverse-fill').setAttribute('d',r+'L480 200H0Z');\n document.querySelector('#separation-value').textContent=viz.number(d,1);\n document.querySelector('#forward-parameters').textContent=`μ = 0.00 · σ = ${viz.number(forwardSigma)}`;\n document.querySelector('#reverse-parameters').textContent=`μ = ${viz.number(mu)} · σ = ${viz.number(sigma)}`;\n document.querySelector('#forward-kl').textContent=viz.number(fkl);document.querySelector('#reverse-kl').textContent=viz.number(rkl);\n document.querySelector('#explanation').textContent=viz.t(mu>.5?'separated':'overlap');\n}\ninput.addEventListener('input',draw);draw();","audio":false,"strings":{"approximation":"实线:近似 q","control":"分量中心间距 d","detailLabel":"拟合方法与适用条件","eyebrow":"03 / 模型受限时,方向影响拟合","forwardChart":"Forward KL 下的单高斯近似与双峰目标,随峰距改变。","heading":"只能画一个高斯,怎样接近两个峰?","intro":"只改变两峰的间距。目标 p 用灰虚线表示,实线是各自优化后的单高斯 q。","note":"横轴 x 为 −12~12,纵轴为密度 0~0.45,两图尺度相同。Forward 解由矩匹配得到;reverse 使用多起点数值优化并展示对称解的一侧。两列优化的目标不同,KL 数值不是统一评分。","overlap":"两个分量靠近时,目标可以只有一个峰,两种方向都可以居中拟合。Reverse KL 并不总是选中一侧;差异依赖峰距和模型限制。","reverseChart":"Reverse KL 下的单高斯近似与双峰目标,随峰距改变。","separated":"两峰足够分离后,forward 的单高斯变宽来照顾两侧;reverse 的一个数值最优解靠近一侧,以减少中间低密度区的质量。","target":"虚线:目标 p"}}
Forward KL 的高斯最优解匹配 p 的均值与方差:μ=0、σ2=1+d2/4。两峰分离时,拟合会随之变宽。Reverse KL 在 q 下取期望;当两峰足够分离时,它可能通过靠近一侧来减少落在中间低密度区的质量。
这是一种有条件的拟合倾向,不是“forward 一定覆盖、reverse 一定寻峰”的普遍定理。峰距、权重、允许的模型族与优化结果都会影响行为。图中的 reverse 解来自多起点数值优化;对称的左侧解同样好,展示其中一侧不表示另一侧更差。Bishop 的 PRML 第 10.1 节 讨论了这类差异。
变分推断常最小化近似后验到真实后验的 KL。RLHF 中常见的 DKL(πθ∥πref) 则是限制策略偏离参考模型的正则项,还与奖励等目标共同作用,不能直接等同于这里的双峰拟合。
Jensen–Shannon 散度:先找一个共同参照
令 m=(p+q)/2,定义:
JS(p,q)=21DKL(p∥m)+21DKL(q∥m)
由于 m 在 p 或 q 有质量的地方都不会为零,JS 避免了两者支撑集不重叠时直接互算 KL 的无穷大。以 2 为底时,0≤JS≤1 bit。它对称,但应注意:构成度量的是 JS,不是直接把 JS 当作一般距离。
例如 p=(1,0)、q=(0,1) 时,两个方向的 KL 都为无穷大;m=(0.5,0.5),两侧到 m 的 KL 各为 1 bit,因此 JS 为 1 bit。
原始 GAN 的联系也有条件:在判别器对固定生成器达到最优时,将它代回原始 minimax 目标,生成器的目标值成为 −ln4+2JSln(pdata,pg)。这是使用自然对数的 JS;并非“判别器在最小化 JS”。常用的非饱和生成器损失也不等于这个表达式。见 Goodfellow 等人的原始论文,第 3、4.1 节。
对照与参考
| 量 | 平均依据 | 解释 |
| H(p) | p | 源分布的平均自信息 |
| H(p,q) | p | 按模型 q 计算的平均理想信息长度 |
| DKL(p∥q) | p | 相对 H(p) 的平均额外代价 |
| DKL(q∥p) | q | 交换来源和参照后得到的另一个期望 |
| JS(p,q) | 两侧各一半 | 到共同混合分布的平均 KL |