
<a id="lab02-opening-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#lab02-opening-001)


# LAB 02 · VAE：ELBO 缺口与重参数化


<a id="lab02-opening-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#lab02-opening-002)

先阅读保存结果和解释，再按本册步骤选择是否运行。[在 Deepnote 阅读与运行](https://deepnote.com/project/6f83a923-d155-47be-be58-680db701ff7f/notebook/450ef87bdfb149769de691b69da7a52d) · [下载 Notebook](https://codingai-lec04.pages.dev/notebooks/lab02.ipynb)


<a id="block-7cd6fc0d0a284ec9a3af47ae9d51f18b-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-7cd6fc0d0a284ec9a3af47ae9d51f18b-001)


# VAE：ELBO 比对数似然少在哪里？


<a id="block-7cd6fc0d0a284ec9a3af47ae9d51f18b-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-7cd6fc0d0a284ec9a3af47ae9d51f18b-002)

**先预测。** 如果近似后验 $q(z\mid x)$ 等于真实后验，ELBO 与 $\log p(x)$ 是否一样？如果只是把重构误差压低，ELBO 就一定提高吗？


<a id="block-7cd6fc0d0a284ec9a3af47ae9d51f18b-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-7cd6fc0d0a284ec9a3af47ae9d51f18b-003)

本册选择一个能手算积分的高斯模型，使每个近似步骤都可以对照精确答案。你将实际计算下界缺口、Monte Carlo 误差、路径梯度和一次小型优化。原有解析计算只用 Python 标准库；新增可视化另用 NumPy、matplotlib。


<a id="block-7cd6fc0d0a284ec9a3af47ae9d51f18b-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-7cd6fc0d0a284ec9a3af47ae9d51f18b-004)

**本轮入口：先看下面的保存图，再只改一个参数。** 原有可手算代码与推导完整保留在后面。


<a id="block-f4828e7850c14db2a2458548e10bc1da-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-f4828e7850c14db2a2458548e10bc1da-001)


## 先看问题与保存结果


<a id="block-f4828e7850c14db2a2458548e10bc1da-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-f4828e7850c14db2a2458548e10bc1da-002)

这册固定一个可解高斯生成模型，只优化一个观测的近似后验 q。它让两种 KL、重建项和 ELBO 缺口都可核对；真正共享图像编码器与解码器的学习在 LAB07。


<a id="block-f4828e7850c14db2a2458548e10bc1da-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-f4828e7850c14db2a2458548e10bc1da-003)

![这册固定一个可解高斯生成模型，只优化一个观测的近似后验 q。它让两种 KL、重建项和 ELBO 缺口都可核对；真正共享图像编码器与解码器的学习在 LAB07。](https://codingai-lec04.pages.dev/assets/labs-v13/lab02-density-and-terms.png)


<a id="block-f4828e7850c14db2a2458548e10bc1da-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-f4828e7850c14db2a2458548e10bc1da-004)

[连续概念解释](https://codingai-lec04.pages.dev/lecture.html#ch03)。读完后留下一个结果：固定量、改变项、实际观察，以及它支持的机制。


<a id="block-4180d8aa45214d14af57f1ac42a8817d-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-4180d8aa45214d14af57f1ac42a8817d-001)


## 先看保存结果：先验、真实后验与 q 怎样连到 ELBO


<a id="block-4180d8aa45214d14af57f1ac42a8817d-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-4180d8aa45214d14af57f1ac42a8817d-002)

![先验、真实后验与 q 怎样连到 ELBO：图1](https://codingai-lec04.pages.dev/assets/labs-v13/lab02-density-and-terms.png)


<a id="block-4180d8aa45214d14af57f1ac42a8817d-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-4180d8aa45214d14af57f1ac42a8817d-003)

![先验、真实后验与 q 怎样连到 ELBO：图2](https://codingai-lec04.pages.dev/assets/labs-v13/lab02-one-variable.png)


<a id="block-4180d8aa45214d14af57f1ac42a8817d-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-4180d8aa45214d14af57f1ac42a8817d-004)

灰线是采样先验，蓝线是当前观测对应的真实后验，金线是所选近似后验q。重构期望减去 KL(q||prior) 得到 ELBO；log p(x) 与 ELBO 的缺口才是 KL(q||posterior)。默认缺口约0.6195 nats。固定q方差再移动均值，只沿一条受限路径调整，不保证能让缺口到零；把均值和方差都设为真实后验才使缺口归零。


<a id="block-4180d8aa45214d14af57f1ac42a8817d-005"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-4180d8aa45214d14af57f1ac42a8817d-005)

**结果身份：** 2026-09-28由下方同源Python代码在本地CPU实际生成并核对。生成模型固定的一维可解潜变量实验，没有训练图像VAE。 图不是模型训练输出。


<a id="block-4180d8aa45214d14af57f1ac42a8817d-006"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-4180d8aa45214d14af57f1ac42a8817d-006)

保存数据、图片与代码随下载材料提供；静态图无需GPU。学生重算需要Python、NumPy、matplotlib，不发起网络请求、不打印密钥，只在当前目录写入本册输出文件夹。


<a id="block-feffe28784324b47831edd639f568679-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-feffe28784324b47831edd639f568679-001)


## 只改一个变量：Q_MU


<a id="block-feffe28784324b47831edd639f568679-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-feffe28784324b47831edd639f568679-002)

只改变 Q_MU（默认0.8），保持 Q_VAR=0.45、观测x=1.5与噪声标准差tau=0.5。三密度图和右侧五个量由同一参数重新计算。


<a id="block-feffe28784324b47831edd639f568679-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-feffe28784324b47831edd639f568679-003)

在下面参数区改值后运行本格；重算图会显示在输出中，并保存在 `lab02-visual-output`。接着用图中的具体变化解释，不从一次样本判断整个分布。


<a id="block-b64f149041004f0d8c40a722f51846e7-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b64f149041004f0d8c40a722f51846e7-001)

查看可执行代码
```
import math, json, platform
from pathlib import Path
import numpy as np
import matplotlib.pyplot as plt

# Change Q_MU only; keep Q_VAR, observed X and likelihood noise TAU fixed.
Q_MU = .8
Q_VAR = .45
VIS_X = 1.5
VIS_TAU = .5
OUT=Path('lab02-visual-output');OUT.mkdir(exist_ok=True)

def vis_normal(z,mu,var):return np.exp(-(z-mu)**2/(2*var))/np.sqrt(2*np.pi*var)
def vis_kl(mu,var,m=0.,v=1.):return .5*(math.log(v/var)+(var+(mu-m)**2)/v-1)
def vis_elbo_terms(mu,var):
    recon=-.5*(math.log(2*math.pi*VIS_TAU**2)+((VIS_X-mu)**2+var)/VIS_TAU**2)
    prior=vis_kl(mu,var);elbo=recon-prior
    evidence=-.5*(math.log(2*math.pi*(1+VIS_TAU**2))+VIS_X**2/(1+VIS_TAU**2))
    pm=VIS_X/(1+VIS_TAU**2);pv=VIS_TAU**2/(1+VIS_TAU**2)
    gap=vis_kl(mu,var,pm,pv)
    assert abs(evidence-elbo-gap)<1e-10
    return {'reconstruction':recon,'KL(q||prior)':prior,'ELBO':elbo,'log p(x)':evidence,'KL(q||posterior) = gap':gap}

pm=VIS_X/(1+VIS_TAU**2);pv=VIS_TAU**2/(1+VIS_TAU**2);grid=np.linspace(-3.5,4.5,500)
terms=vis_elbo_terms(Q_MU,Q_VAR)
fig,axes=plt.subplots(1,2,figsize=(12,4.4))
for mu,var,label,color in [(0,1,'prior p(z)','#9ca3af'),(pm,pv,'true posterior p(z|x)','#003262'),(Q_MU,Q_VAR,'chosen q(z|x)','#c28e0e')]:axes[0].plot(grid,vis_normal(grid,mu,var),label=label,color=color,lw=2.7)
axes[0].set(xlabel='latent z',ylabel='Density',title=f'Observed x={VIS_X:g}; likelihood SD={VIS_TAU:g}');axes[0].legend()
labels=['recon','KL prior','ELBO','log p(x)','gap KL posterior'];values=list(terms.values())
axes[1].barh(labels,values,color=['#6e96b1','#d6aa35','#003262','#688da7','#fdb515']);axes[1].axvline(0,color='#444',lw=.8)
for y,v in enumerate(values):axes[1].text(v,y,f' {v:.3f}',va='center',ha='left' if v>=0 else 'right')
axes[1].set(xlabel='nats',title='Different KL terms answer different questions');axes[1].set_xlim(min(values)-3,max(values)+3)
fig.tight_layout();fig.savefig(OUT/'lab02-density-and-terms.png',dpi=160);plt.show();plt.close(fig)

means=np.linspace(-.4,2.7,160);all_terms=[vis_elbo_terms(mu,Q_VAR) for mu in means]
fig,axes=plt.subplots(1,2,figsize=(12,3.7))
for key in ['reconstruction','ELBO','log p(x)']:axes[0].plot(means,[v[key] for v in all_terms],label=key)
for key in ['KL(q||prior)','KL(q||posterior) = gap']:axes[1].plot(means,[v[key] for v in all_terms],label=key)
for ax in axes:ax.axvline(Q_MU,color='#c28e0e',ls='--',label='chosen q mean');ax.set(xlabel='q mean (variance fixed)',ylabel='nats');ax.legend(fontsize=9)
fig.tight_layout();fig.savefig(OUT/'lab02-one-variable.png',dpi=160);plt.show();plt.close(fig)
payload={'kind':'analytic fixed latent-variable model; no image VAE training','X':VIS_X,'tau':VIS_TAU,'q_mu':Q_MU,'q_var':Q_VAR,'posterior':{'mu':pm,'var':pv},'terms':terms,'sweep':[{'mu':float(mu),**term} for mu,term in zip(means,all_terms)],'python':platform.python_version()}
(OUT/'lab02-results.json').write_text(json.dumps(payload,indent=2));print(json.dumps(terms,indent=2))

```

<a id="block-b64f149041004f0d8c40a722f51846e7-output-0-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b64f149041004f0d8c40a722f51846e7-output-0-001)

![LAB 02 · VAE：ELBO 缺口与重参数化的保存输出](https://codingai-lec04.pages.dev/assets/notebook-outputs/lab02-4-0.png)已保存输出；运行地点及条件见本册说明。


<a id="block-b64f149041004f0d8c40a722f51846e7-output-1-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b64f149041004f0d8c40a722f51846e7-output-1-001)

![LAB 02 · VAE：ELBO 缺口与重参数化的保存输出](https://codingai-lec04.pages.dev/assets/notebook-outputs/lab02-4-1.png)已保存输出；运行地点及条件见本册说明。


<a id="block-b64f149041004f0d8c40a722f51846e7-output-2-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b64f149041004f0d8c40a722f51846e7-output-2-001)

查看保存的计算输出
```
{
  "reconstruction": -2.105791352644727,
  "KL(q||prior)": 0.4442538481088858,
  "ELBO": -2.5500452007536127,
  "log p(x)": -1.9305103088617774,
  "KL(q||posterior) = gap": 0.6195348918918353
}

```

<a id="block-8a8670b54c2d43b48fe30a989bd29e40-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-8a8670b54c2d43b48fe30a989bd29e40-001)


## 本轮运行与后续阅读


<a id="block-8a8670b54c2d43b48fe30a989bd29e40-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-8a8670b54c2d43b48fe30a989bd29e40-002)

**本地执行与云端复核均已完成。** 2026-09-28，本册全部代码在本地CPU从空命名空间顺序执行；另通过Deepnote全本运行，状态为success，运行ID为 `4942e449-f74d-467c-bc19-c39632231ffd`，完成时间 2026-09-28T15:28:56.835Z（UTC）。运行快照检查到本册图形输出且无失败代码块。三密度与两种KL/重构项图已输出；默认ELBO缺口0.6195348919 nats，原解析等式与路径梯度检查通过。


<a id="block-8a8670b54c2d43b48fe30a989bd29e40-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-8a8670b54c2d43b48fe30a989bd29e40-003)

云端运行使用Python 3.13数据科学环境。平台总用时包含启动、Notebook执行与输出保存，不作为算法速度基准；五本均为小规模CPU计算，不调用外部模型或付费API。上方静态图仍明确保留其本地生成来源，云端输出是另一次实际复核。学生修改参数后得到的是自己的新结果。


<a id="block-8a8670b54c2d43b48fe30a989bd29e40-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-8a8670b54c2d43b48fe30a989bd29e40-004)

下面保留此前逐步计算与推导。历史本地数字保留原身份，可把图中一个关系追到对应公式。


<a id="block-01b35c3bc0c74aa8a60b5fb003fa8886-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-01b35c3bc0c74aa8a60b5fb003fa8886-001)


## 固定模型与记号


<a id="block-01b35c3bc0c74aa8a60b5fb003fa8886-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-01b35c3bc0c74aa8a60b5fb003fa8886-002)

$z\sim\mathcal N(0,1)$，$x\mid z\sim\mathcal N(z,\tau^2)$，固定观测 $x=1.5$、$\tau=0.5$。近似后验 $q(z\mid x)=\mathcal N(\mu,v)$，$v=\exp(2\rho)>0$。


<a id="block-01b35c3bc0c74aa8a60b5fb003fa8886-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-01b35c3bc0c74aa8a60b5fb003fa8886-003)

本例有 $p(x)=\mathcal N(x;0,1+\tau^2)$，以及精确后验
$$m_*={x\over 1+\tau^2},\qquad v_*={\tau^2\over 1+\tau^2}.$$


<a id="block-01b35c3bc0c74aa8a60b5fb003fa8886-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-01b35c3bc0c74aa8a60b5fb003fa8886-004)

因而可同时检查
$$\log p(x)-\mathrm{ELBO}=\mathrm{KL}(q(z\mid x)\|p(z\mid x))\ge0.$$
注意右边是到**后验**的 KL；ELBO 定义中扣掉的则是到**先验**的 KL。这两个 KL 不是一项。


<a id="block-713c9248d97747b6956d1a702fd63ba8-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-713c9248d97747b6956d1a702fd63ba8-001)

查看可执行代码
```
import math
import random
import statistics

X, TAU = 1.5, 0.5
def log_normal(value, mean, variance):
    return -0.5 * (math.log(2 * math.pi * variance)
                   + (value - mean) ** 2 / variance)

def gaussian_kl(mu, variance, target_mean=0.0, target_variance=1.0):
    return 0.5 * (math.log(target_variance / variance)
                  + (variance + (mu - target_mean) ** 2) / target_variance - 1)

def exact_elbo(mu, variance, x=X, tau=TAU):
    reconstruction = -0.5 * (math.log(2 * math.pi * tau * tau)
                            + ((x - mu) ** 2 + variance) / (tau * tau))
    kl_prior = gaussian_kl(mu, variance)
    return reconstruction - kl_prior, reconstruction, kl_prior

POST_MEAN = X / (1 + TAU ** 2)
POST_VAR = TAU ** 2 / (1 + TAU ** 2)
LOG_EVIDENCE = log_normal(X, 0, 1 + TAU ** 2)
print("exact posterior mean / variance:", POST_MEAN, POST_VAR)
print("log p(x):", round(LOG_EVIDENCE, 6))
print("q mean var | reconstruction | KL-prior | ELBO | evidence gap | KL-posterior")
for mu, variance in [(0.0, 1.0), (1.5, 0.01), (POST_MEAN, POST_VAR)]:
    bound, recon, kl_prior = exact_elbo(mu, variance)
    gap = LOG_EVIDENCE - bound
    kl_post = gaussian_kl(mu, variance, POST_MEAN, POST_VAR)
    print(f"{mu:.2f} {variance:.2f} | {recon:.6f} | {kl_prior:.6f} | {bound:.6f} | {gap:.6f} | {kl_post:.6f}")
    assert abs(gap - kl_post) < 1e-12
assert abs(LOG_EVIDENCE - exact_elbo(POST_MEAN, POST_VAR)[0]) < 1e-12

```

<a id="block-713c9248d97747b6956d1a702fd63ba8-output-0-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-713c9248d97747b6956d1a702fd63ba8-output-0-001)

查看保存的计算输出
```
exact posterior mean / variance: 1.2 0.2
log p(x): -1.93051
q mean var | reconstruction | KL-prior | ELBO | evidence gap | KL-posterior
0.00 1.00 | -6.725791 | 0.000000 | -6.725791 | 4.795281 | 4.795281
1.50 0.01 | -0.245791 | 2.932585 | -3.178376 | 1.247866 | 1.247866
1.20 0.20 | -0.805791 | 1.124719 | -1.930510 | 0.000000 | 0.000000

```

<a id="block-3e65ecce56544c249f3456c669401359-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-3e65ecce56544c249f3456c669401359-001)


### 历史本地保存输出（2026-09-26；本轮执行记录见开篇）


<a id="block-3e65ecce56544c249f3456c669401359-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-3e65ecce56544c249f3456c669401359-002)


```
exact posterior mean / variance: 1.2 0.2
log p(x): -1.93051
q mean var | reconstruction | KL-prior | ELBO | evidence gap | KL-posterior
0.00 1.00 | -6.725791 | 0.000000 | -6.725791 | 4.795281 | 4.795281
1.50 0.01 | -0.245791 | 2.932585 | -3.178376 | 1.247866 | 1.247866
1.20 0.20 | -0.805791 | 1.124719 | -1.930510 | 0.000000 | 0.000000

```

<a id="block-3e65ecce56544c249f3456c669401359-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-3e65ecce56544c249f3456c669401359-003)


## 重构更准，为什么未必是更好的下界？


<a id="block-3e65ecce56544c249f3456c669401359-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-3e65ecce56544c249f3456c669401359-004)

把 $q$ 紧缩到 $z\approx x$ 可以改善本例的期望重构对数概率，但非常小的方差有明显 KL 代价。最优近似后验是精确后验，不是无条件地把所有不确定性压成一点。


<a id="block-3e65ecce56544c249f3456c669401359-005"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-3e65ecce56544c249f3456c669401359-005)

这里对连续变量计算的是**对数密度**，因此一项重构对数密度可以是正数；不要套用离散概率不超过 1 的规则。改变 $\tau$ 还会改变重构误差的尺度，比较前必须说明观测噪声模型。


<a id="block-8c55303502374c0488e98af9db76da06-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-8c55303502374c0488e98af9db76da06-001)

查看可执行代码
```
MU, VARIANCE = 0.8, 0.45
RHO = 0.5 * math.log(VARIANCE)
def mc_elbo(mu, rho, noises, x=X, tau=TAU):
    sigma = math.exp(rho)
    terms = [log_normal(x, mu + sigma * eps, tau * tau) for eps in noises]
    estimate = statistics.mean(terms) - gaussian_kl(mu, sigma * sigma)
    se = statistics.stdev(terms) / math.sqrt(len(terms))
    return estimate, se

exact = exact_elbo(MU, VARIANCE)[0]
rng = random.Random(20260926)
NOISES = [rng.gauss(0, 1) for _ in range(40000)]
print("n      | estimate | standard error | estimate minus exact")
for n in (100, 1000, 40000):
    estimate, se = mc_elbo(MU, RHO, NOISES[:n])
    print(f"{n:6d} | {estimate:.6f} | {se:.6f} | {estimate-exact:+.6f}")
print("analytic ELBO:", round(exact, 6))
estimate, se = mc_elbo(MU, RHO, NOISES)
assert abs(estimate - exact) < 6 * se

```

<a id="block-8c55303502374c0488e98af9db76da06-output-0-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-8c55303502374c0488e98af9db76da06-output-0-001)

查看保存的计算输出
```
n      | estimate | standard error | estimate minus exact
   100 | -2.593677 | 0.253456 | -0.043632
  1000 | -2.512576 | 0.069779 | +0.037469
 40000 | -2.527719 | 0.011269 | +0.022326
analytic ELBO: -2.550045

```

<a id="block-0cf0fcd96fc64309a59a08cb3899a060-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-0cf0fcd96fc64309a59a08cb3899a060-001)


### 历史本地保存输出（2026-09-26；本轮执行记录见开篇）


<a id="block-0cf0fcd96fc64309a59a08cb3899a060-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-0cf0fcd96fc64309a59a08cb3899a060-002)


```
n      | estimate | standard error | estimate minus exact
   100 | -2.593677 | 0.253456 | -0.043632
  1000 | -2.512576 | 0.069779 | +0.037469
 40000 | -2.527719 | 0.011269 | +0.022326
analytic ELBO: -2.550045

```

<a id="block-0cf0fcd96fc64309a59a08cb3899a060-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-0cf0fcd96fc64309a59a08cb3899a060-003)


## 重参数化把随机数与参数分开


<a id="block-0cf0fcd96fc64309a59a08cb3899a060-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-0cf0fcd96fc64309a59a08cb3899a060-004)

写成 $z=\mu+\exp(\rho)\epsilon$，$\epsilon\sim\mathcal N(0,1)$，每次可先固定基础噪声，再沿 $\mu,\rho$ 对计算路径求导。


<a id="block-0cf0fcd96fc64309a59a08cb3899a060-005"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-0cf0fcd96fc64309a59a08cb3899a060-005)

本册使用解析 KL，并只对重构期望作 Monte Carlo。**单次有限样本估计不保证仍低于 $\log p(x)$**；下界性质约束的是精确期望。样本数增加一般减小估计方差，不保证误差在每次运行中单调下降。


<a id="block-0cf0fcd96fc64309a59a08cb3899a060-006"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-0cf0fcd96fc64309a59a08cb3899a060-006)

下一格把同一组噪声用于路径梯度与有限差分，避免把两组随机数的差异误当成导数。


<a id="block-2883b383d6ee448894a73c329ec06db2-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-2883b383d6ee448894a73c329ec06db2-001)

查看可执行代码
```
def path_gradients(mu, rho, noises, x=X, tau=TAU):
    sigma = math.exp(rho)
    variance = sigma * sigma
    residuals = [(x - mu - sigma * eps) / (tau * tau) for eps in noises]
    grad_mu = statistics.mean(residuals) - mu
    grad_rho = statistics.mean(r * sigma * eps for r, eps in zip(residuals, noises)) - (variance - 1)
    return grad_mu, grad_rho

eps_grad = NOISES[:2000]
grad_mu, grad_rho = path_gradients(MU, RHO, eps_grad)
delta = 1e-5
fd_mu = (mc_elbo(MU+delta, RHO, eps_grad)[0] - mc_elbo(MU-delta, RHO, eps_grad)[0])/(2*delta)
fd_rho = (mc_elbo(MU, RHO+delta, eps_grad)[0] - mc_elbo(MU, RHO-delta, eps_grad)[0])/(2*delta)
print("gradient | path | finite difference | absolute difference")
for name, path, finite in [("mu", grad_mu, fd_mu), ("rho", grad_rho, fd_rho)]:
    print(name, round(path, 8), round(finite, 8), abs(path-finite))
    assert abs(path-finite) < 1e-7

mu, rho = 0.0, 0.0
rng_train = random.Random(17)
initial_gap = LOG_EVIDENCE - exact_elbo(mu, math.exp(2*rho))[0]
for step in range(1, 301):
    noises = [rng_train.gauss(0, 1) for _ in range(256)]
    gm, gr = path_gradients(mu, rho, noises)
    lr = 0.03 / math.sqrt(1 + step / 50)
    mu += lr * gm
    rho += lr * gr
    if step in (1, 20, 100, 300):
        bound = exact_elbo(mu, math.exp(2*rho))[0]
        print(f"step={step:3d}, mu={mu:.5f}, var={math.exp(2*rho):.5f}, exact gap={LOG_EVIDENCE-bound:.7f}")
final_gap = LOG_EVIDENCE - exact_elbo(mu, math.exp(2*rho))[0]
assert final_gap < 0.01 and final_gap < initial_gap

```

<a id="block-2883b383d6ee448894a73c329ec06db2-output-0-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-2883b383d6ee448894a73c329ec06db2-output-0-001)

查看保存的计算输出
```
gradient | path | finite difference | absolute difference
mu 1.96040634 1.96040634 2.375877272697835e-11
rho -1.177317 -1.177317 1.532949323035382e-10
step=  1, mu=0.17724, var=0.78053, exact gap=3.3855988
step= 20, mu=1.13880, var=0.26814, exact gap=0.0331216
step=100, mu=1.19830, var=0.20371, exact gap=0.0000924
step=300, mu=1.20393, var=0.20108, exact gap=0.0000459

```

<a id="block-6f809380e5024972a8019d967e2f30c7-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-6f809380e5024972a8019d967e2f30c7-001)


### 历史本地保存输出（2026-09-26；本轮执行记录见开篇）


<a id="block-6f809380e5024972a8019d967e2f30c7-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-6f809380e5024972a8019d967e2f30c7-002)


```
gradient | path | finite difference | absolute difference
mu 1.96040634 1.96040634 2.375877272697835e-11
rho -1.177317 -1.177317 1.532949323035382e-10
step=  1, mu=0.17724, var=0.78053, exact gap=3.3855988
step= 20, mu=1.13880, var=0.26814, exact gap=0.0331216
step=100, mu=1.19830, var=0.20371, exact gap=0.0000924
step=300, mu=1.20393, var=0.20108, exact gap=0.0000459

```

<a id="block-6f809380e5024972a8019d967e2f30c7-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-6f809380e5024972a8019d967e2f30c7-003)


## 只改一个条件：观测噪声


<a id="block-6f809380e5024972a8019d967e2f30c7-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-6f809380e5024972a8019d967e2f30c7-004)

下一格只改变 `tau`，保留观测 $x=1.5$ 和先验 $\mathcal N(0,1)$。先预测：当解码器的观测噪声变大，后验均值会更接近观测 1.5 还是先验均值 0？后验方差会怎样变化？


<a id="block-6f809380e5024972a8019d967e2f30c7-005"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-6f809380e5024972a8019d967e2f30c7-005)

这一步比较的是不同概率模型的后验，不要说成“同一个 VAE 的 KL 权重实验”。修改噪声方差与任意乘一个 $\beta$ 并不等价。


<a id="block-ddf0c13863844496b669669b024e3f8f-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ddf0c13863844496b669669b024e3f8f-001)

查看可执行代码
```
print("tau | posterior mean | posterior variance | optimal ELBO | log evidence")
for tau in (0.2, 0.5, 1.0, 2.0):
    post_mu = X / (1 + tau*tau)
    post_var = tau*tau / (1 + tau*tau)
    optimal = exact_elbo(post_mu, post_var, x=X, tau=tau)[0]
    log_evidence = log_normal(X, 0, 1 + tau*tau)
    print(f"{tau:.1f} | {post_mu:.6f} | {post_var:.6f} | {optimal:.6f} | {log_evidence:.6f}")
    assert abs(optimal - log_evidence) < 1e-12
print("All analytic identities, finite-difference checks and seeded optimization checks passed.")

```

<a id="block-ddf0c13863844496b669669b024e3f8f-output-0-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ddf0c13863844496b669669b024e3f8f-output-0-001)

查看保存的计算输出
```
tau | posterior mean | posterior variance | optimal ELBO | log evidence
0.2 | 1.442308 | 0.038462 | -2.020280 | -2.020280
0.5 | 1.200000 | 0.200000 | -1.930510 | -1.930510
1.0 | 0.750000 | 0.500000 | -1.828012 | -1.828012
2.0 | 0.300000 | 0.800000 | -1.948657 | -1.948657
All analytic identities, finite-difference checks and seeded optimization checks passed.

```

<a id="block-b2fb5557c34f4f7b8fd6017a96bc774f-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b2fb5557c34f4f7b8fd6017a96bc774f-001)


### 历史本地保存输出（2026-09-26；本轮执行记录见开篇）


<a id="block-b2fb5557c34f4f7b8fd6017a96bc774f-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b2fb5557c34f4f7b8fd6017a96bc774f-002)


```
tau | posterior mean | posterior variance | optimal ELBO | log evidence
0.2 | 1.442308 | 0.038462 | -2.020280 | -2.020280
0.5 | 1.200000 | 0.200000 | -1.930510 | -1.930510
1.0 | 0.750000 | 0.500000 | -1.828012 | -1.828012
2.0 | 0.300000 | 0.800000 | -1.948657 | -1.948657
All analytic identities, finite-difference checks and seeded optimization checks passed.

```

<a id="block-b2fb5557c34f4f7b8fd6017a96bc774f-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b2fb5557c34f4f7b8fd6017a96bc774f-003)


## 写出你的判断


<a id="block-b2fb5557c34f4f7b8fd6017a96bc774f-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b2fb5557c34f4f7b8fd6017a96bc774f-004)

用第一张表说明两个 KL 的区别；用 Monte Carlo 表报告估计值和标准误；用一次梯度检查解释为什么要固定噪声。最后用噪声扫描回答：哪个模型更信任观测，哪个模型更接近先验？


<a id="block-b2fb5557c34f4f7b8fd6017a96bc774f-005"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-b2fb5557c34f4f7b8fd6017a96bc774f-005)

若优化波动，把学习率改为原来的两倍或减半，其他条件固定。观察最终缺口和中间轨迹，不只挑一个最好的迭代。要比较方法，再使用多个种子；当前单次执行仅验证这条计算链。


<a id="block-1c869186bce447a59aecee0a4b48acfb-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-1c869186bce447a59aecee0a4b48acfb-001)


## 本册与真正 VAE 训练的距离


<a id="block-1c869186bce447a59aecee0a4b48acfb-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-1c869186bce447a59aecee0a4b48acfb-002)

本册固定生成模型，只优化**一个观测的变分后验参数**；没有学习神经解码器，没有跨样本共享的编码器，也不是 MNIST 图像 VAE。选可解模型是为了能检查 ELBO、随机估计和梯度的身份。


<a id="block-1c869186bce447a59aecee0a4b48acfb-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-1c869186bce447a59aecee0a4b48acfb-003)

真正的 amortized VAE 用编码网络为很多观测给出 $q_\phi(z\mid x)$，还可以同时更新生成参数 $\theta$。重参数化这一技术来自 [Kingma & Welling, Auto-Encoding Variational Bayes](https://arxiv.org/abs/1312.6114)；本册高斯数值实验为独立教学构造。


<a id="block-61012e5e3597429593ead7749e9fe770-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-61012e5e3597429593ead7749e9fe770-001)


## 接回主讲


<a id="block-61012e5e3597429593ead7749e9fe770-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-61012e5e3597429593ead7749e9fe770-002)

回到“潜变量怎样组织变化”“VAE 的重构与分布约束”“训练需要编码、生成可以从先验开始”。生成时从先验抽样，不能把训练时使用 $q(z\mid x)$ 的路径不加区分地照搬过去。


<a id="block-441fc1fcdac14f4cb79a114b74fdc466-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-441fc1fcdac14f4cb79a114b74fdc466-001)


## 从课堂展开：推导、反例与变量实验


<a id="block-441fc1fcdac14f4cb79a114b74fdc466-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-441fc1fcdac14f4cb79a114b74fdc466-002)

先完成上面的有限例子，再按自己尚未弄清的问题选择推导。已有代码只覆盖本册明确列出的计算；后面的研究练习是可继续提出的实验，不是已经运行的结果。


<a id="block-441fc1fcdac14f4cb79a114b74fdc466-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-441fc1fcdac14f4cb79a114b74fdc466-003)


- [三个概率对象与三种检查](https://deepnote.com/project/6f83a923-d155-47be-be58-680db701ff7f/notebook/450ef87bdfb149769de691b69da7a52d?utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_content=450ef87bdfb149769de691b69da7a52d&utm_term=get_notebook#ab42d9e69c0c49f2bb6b8c4005db7d9f)

- [二维潜空间网格，应该怎样读](https://deepnote.com/project/6f83a923-d155-47be-be58-680db701ff7f/notebook/450ef87bdfb149769de691b69da7a52d?utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_content=450ef87bdfb149769de691b69da7a52d&utm_term=get_notebook#cbadb7990fe34c07b07b1a9ad4506ec6)


<a id="block-441fc1fcdac14f4cb79a114b74fdc466-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-441fc1fcdac14f4cb79a114b74fdc466-004)

原有解释按连续主题拆到下方；本入口继续保留。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-001)


### 三个概率对象与三种检查


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-002)

本册已有可解模型分别定义先验 p(z)、真实后验 p(z|x) 与近似后验 q(z|x)。先验 KL 是 ELBO 目标的一项；后验 KL 才是 ELBO 到同一模型 log p(x) 的缺口。把 q 拉向先验未必缩小后验缺口，先用上面的解析表核对。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-003)

重构、编码间插值、先验采样各自访问不同潜状态。给定固定方差 Gaussian decoder 时，平方误差解释条件均值；这不是所有 VAE 的必然外观。若想检验神经 decoder 是否使用 z，可固定其他条件分别替换、打乱或固定 z，再看任务信息是否丢失。本册解析 decoder 已被规定为依赖 z，因此它不能发现真实神经网络中的 posterior collapse；这项诊断是进一步练习，未启动新训练。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-004)

重参数化 z=μ+σε 将随机来源 ε 与可学习变换分开。代码比较路径梯度、有限差分与 Monte Carlo 误差，固定噪声是为了降低对照差异；单样本导数可精确，期望梯度仍有抽样波动。VQ 的索引/码本问题另读 DERIV 的潜表示段，本高斯实验不冒充 VQ 实验。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-005"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-005)


### MSE 从哪里来：固定方差高斯观测模型


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-006"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-006)

平方误差为什么能出现在概率模型里？


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-007"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-007)

若pθ(x|z)=N(μθ(z),σ²I)，并把σ固定，负对数似然为||x−μθ(z)||²/(2σ²)加与均值无关的常数。于是最小化该项等价于最小化平方误差。这个等价依赖高斯形式、各维协方差结构以及固定尺度；若方差也学习，或改用其他观测分布，就不能简单丢掉对应项。原课用这一例子解释重构损失，并不是宣称所有VAE都必须采用像素MSE。课程还应区分条件均值的显示效果与完整生成分布的能力。更换观测假设以后，概率归一化与对应损失也必须一并重新核对。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-008"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-008)

**追问：**既然像素MSE可能鼓励平均，是否应该在所有生成模型里删掉它？


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-009"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-009)

不能。它在这里来自明确观测分布的负对数似然，也可能在扩散中用于预测噪声。是否合适取决于预测变量、条件信息和整体生成机制。你可以批评某个观测模型过于简单，但要指出简化在哪、带来什么可测后果。删掉损失项会改变目标，并不会自动获得更正确的概率模型。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-010"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-010)

[返回当前页说明](https://codingai-lec04.pages.dev/classroom/N17.html?view=notes)


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-011"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-011)

相关阅读：[Variational Autoencoder](https://mit-6s978.github.io/assets/pdfs/lec2_vae.pdf)


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-012"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-012)


### 高斯 KL 可以逐维算出来


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-013"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-013)

μ 和 σ 分别怎样受到先验约束？


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-014"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-014)

对q=N(μ,diag(σ²))、p=N(0,I)，KL为二分之一乘各维μⱼ²+σⱼ²−logσⱼ²−1的总和。μ为零且σ为一时该项为零；把σ压到零会让负对数尺度项变大，而不是免费获得确定编码。该式是原课高斯正则例的展开，课程可用一维滑块检查形状。要统一σ表示标准差、σ²表示方差；若代码输出log variance，应先按正确关系转换，不能把协方差直接作为重参数化乘数。可以先在一维画出曲线，再按维度求和检查高维实现；解析结果提供了独立于训练过程的数值核对标准。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-015"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-015)

**追问：**把方差设得极小，编码不是更精确吗，为什么还会被罚？


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-016"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-016)

它可能减少训练时的重构随机性，但也使q高度集中，与宽的标准正态先验偏离。KL同时考虑分布的密度比，不只比较均值。你是在两种要求之间取舍：让潜状态解释特定x，以及让从先验采样仍有意义。更精确的单样本编码并不自动等于更好的整体生成分布。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-017"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-017)

[返回当前页说明](https://codingai-lec04.pages.dev/classroom/N16.html?view=notes)


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-018"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-018)

相关阅读：[Variational Autoencoder](https://mit-6s978.github.io/assets/pdfs/lec2_vae.pdf)


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-019"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-019)


### 一次潜变量采样，怎样服务于一个期望目标


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-020"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-020)

公式写期望，代码为什么常只抽一次 ε？


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-021"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-021)

重构项包含对q(z|x)的期望，实际小批量训练常对每个x抽一个或少量ε来估计。重复训练会访问不同数据与噪声样本，因此不要求每次把整个潜空间积分算完。单样本估计可能有较大波动，更多样本通常改变成本与估计方差；在适当条件下，它们针对同一个期望目标。与此相对，重构展示只固定一个z或使用后验均值，可能隐藏采样波动。训练估计、可视化选择与评估协议应分别记录。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-022"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-022)

**追问：**我两次算同一张图的重构损失不同，是否说明模型参数偷偷变化了？


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-023"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-023)

不一定。即使参数固定，从q抽到的z不同也会改变解码结果和损失。先固定数据、参数和噪声，检查是否可复现；再单独释放随机噪声，观察期望估计的波动。只有把这些因素拆开，才能区分随机采样造成的正常差异、数值问题以及真正发生的参数更新。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-024"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-024)

[返回当前页说明](https://codingai-lec04.pages.dev/classroom/N16.html?view=notes)


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-025"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-025)

相关阅读：[Variational Autoencoder](https://mit-6s978.github.io/assets/pdfs/lec2_vae.pdf)


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-026"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-026)


### 一个样本的下界，怎样变成训练集目标


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-027"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-027)

重构和 KL 应该先对哪些维度求和、再对哪些样本平均？


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-028"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-028)

单样本ELBO还需要对数据分布或训练集求期望。代码常先把一个样本的像素负对数似然求和，再把潜变量KL各维求和，最后在batch维平均。如果重构按所有像素平均而KL只按batch平均，两项相对尺度会随分辨率和潜维度变化。这样的实现可以作为另一个加权目标，但不能在未说明时声称与原公式等价。本页把原课“总体目标为数据期望”展开成实现检查，避免学生只凭两个标量看起来量级接近就随意调整。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-029"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-029)

**追问：**我只是把 sum 改成 mean，让训练更稳定，为什么还要在报告里说明？


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-030"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-030)

如果只给整项乘同一正常数，可能主要影响梯度尺度；但对重构和KL采用不同归一化，会改变两项相对权重，因而改变优化问题。分辨率变化时这个差别更明显。你可以选择这种做法，但需要明确新的目标与权重，不能把观察到的变化全部归因给模型架构或数据。


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-031"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-031)

[返回当前页说明](https://codingai-lec04.pages.dev/classroom/N16.html?view=notes)


<a id="block-ab42d9e69c0c49f2bb6b8c4005db7d9f-032"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-ab42d9e69c0c49f2bb6b8c4005db7d9f-032)

相关阅读：[Variational Autoencoder](https://mit-6s978.github.io/assets/pdfs/lec2_vae.pdf)


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-001"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-001)


### 二维潜空间网格，应该怎样读


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-002"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-002)

一张整齐的数字网格能证明哪件事？


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-003"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-003)

二维潜空间允许在规则网格上固定z并解码，直观看到数字形状随坐标变化。原课用MNIST示例展示这种方法。网格图的解释依赖坐标范围、采样分布和显示的是均值还是样本：均匀网格并不等于从高斯先验采样，边角可能落在低密度区域。它能够帮助定位局部失效、连续变化与表示组织，但不能从二维课堂模型直接推出大规模高维模型同样表现。实验应同时保留先验随机样本作为另一组证据。


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-004"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-004)

**追问：**为什么网格边缘生成得差，却不一定说明模型总体采样很差？


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-005"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-005)

如果边缘区域在先验下概率极低，普通随机生成很少访问它们，所以网格会放大某些低频失效。但这也不是忽略它们的理由，尤其在插值或控制任务需要访问这些区域时。应分别报告按先验加权的生成表现和指定坐标扫描的行为，两者回答不同使用场景的问题。


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-006"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-006)

[返回当前页说明](https://codingai-lec04.pages.dev/classroom/N18.html?view=notes)


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-007"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-007)

相关阅读：[Variational Autoencoder](https://mit-6s978.github.io/assets/pdfs/lec2_vae.pdf)


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-008"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-008)


### KL 接近零：匹配好了，还是潜变量被忽略


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-009"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-009)

如何检查 decoder 是否真的使用了 z？


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-010"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-010)

本页是围绕原课两项目标构造的诊断任务。若许多样本的q接近同一先验，KL可能很小；与此同时，能力较强的decoder可能主要依赖自身统计而很少利用z。不能仅凭小KL宣布训练成功，也不能不看其他证据就断言发生了某种失效。可以固定其他条件，交换或打乱z，检查重构与输出分布怎样变化；同时比较真实编码、先验编码与固定编码。干预应限定在合理输入范围，防止把越界扰动造成的变化误当作语义使用证据。


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-011"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-011)

**追问：**只要打乱 z 后图像发生变化，就能证明潜变量学到了有用信息吗？


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-012"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-012)

还不够。变化说明输出对z敏感，却不证明这种敏感与解释输入或生成合理样本有关。需要检查任务相关指标、变化方向和输入是否仍在模型通常访问的区域。把敏感性、信息携带、可解释性和生成质量分开，可以避免把任何可见变化都误当成成功利用潜变量。


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-013"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-013)

[返回当前页说明](https://codingai-lec04.pages.dev/classroom/N18.html?view=notes)


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-014"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-014)

相关阅读：[Variational Autoencoder](https://mit-6s978.github.io/assets/pdfs/lec2_vae.pdf)


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-015"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-015)


### 调节重构与约束的权重，会改变什么目标


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-016"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-016)

把 KL 系数乘十，还是同一个原始 ELBO 吗？


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-017"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-017)

本页课程实验将负ELBO写成重构损失加β倍先验KL，比较不同β。β为一且其他系数与似然一致时对应基础目标；任意改β一般不再等于同一观测模型的原始负ELBO。较强约束可能减少潜变量携带的信息，也可能改变先验采样表现，效果依赖模型与数据，不能预先承诺语义解耦或质量提升。实验应固定随机初始化协议、训练预算和评价方式，分别观察重构、KL、先验样本和潜变量干预，而非只比较总损失。


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-018"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-018)

**追问：**β变大后总损失也变大，能否直接说模型更差？


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-019"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-019)

不能，因为你改变了计分规则。同样的模型在更大β下就可能得到更大总损失，与能力是否退化无关。应在共同协议下比较重构、生成质量、覆盖和潜变量使用，再说明哪个用途获益或受损。调参实验有价值，但只有把目标变化与行为变化分开，结论才可解释。


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-020"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-020)

[返回当前页说明](https://codingai-lec04.pages.dev/classroom/N18.html?view=notes)


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-021"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-021)

相关阅读：[Variational Autoencoder](https://mit-6s978.github.io/assets/pdfs/lec2_vae.pdf)


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-022"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-022)


### VQ 的三条训练责任：重构、码本、编码器


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-023"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-023)

为什么需要分别控制哪些参数接受梯度？


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-024"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-024)

VQ类训练通常要让decoder重构输入、让码本靠近编码器输出，并让编码器不要任意远离被选码。原课p77提醒原始VQ-VAE采用不同的梯度权重；课程可用codebook项与commitment项的分工解释这种设计。停止梯度会使看似对称的平方距离产生不同参数更新，因此只抄标量公式不足以复现算法。不同实现也可能使用码本的移动平均更新，不能混合多个配方后仍称为同一标准实现。此页重在读懂更新对象，不要求课堂推完训练细节。


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-025"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-025)

**追问：**两个平方距离数值一样，为什么还要写成两项？


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-026"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-026)

因为停止梯度和系数可能不同，它们把更新发送给不同参数。一个项可以主要移动码本，另一个约束编码器，虽然当前标量看起来相同，优化后的变化却不一样。理解算法必须同时检查前向损失与反向路径。仅凭损失数值的代数对称，不能推断训练动力学也对称。


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-027"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-027)

[返回当前页说明](https://codingai-lec04.pages.dev/classroom/N19.html?view=notes)


<a id="block-cbadb7990fe34c07b07b1a9ad4506ec6-028"></a>
[区块原文](https://codingai-lec04.pages.dev/course/notebooks/450ef87bdfb149769de691b69da7a52d.html#block-cbadb7990fe34c07b07b1a9ad4506ec6-028)

相关阅读：[Variational Autoencoder](https://mit-6s978.github.io/assets/pdfs/lec2_vae.pdf)

