来源:Ho、Jain、Abbeel,2020,arXiv 2006.11239,NeurIPS 2020。公式号与论文一致。符号约定与常用公式卡见本单元 00_导读。 这一节讲:§8 把公式 12 的权重统一设成 1 得训练用的 $L_\text{simple}$(公式 14),并解释为什么去掉「最优权重」反而更好;§9 给出训练与采样的 PyTorch 实现。 --- ## §8 最朴素的损失 $L_\text{simple}$ **这一步**:公式 12 自带一串「理论最优」的权重,论文却把它统一设成 1。这不是偷懒,是一次有意的取舍:精确压上界(密度)和出好图(画质)不是同一个目标,两者冲突时论文选了画质。 **结论**:得公式 14 的 $L_\text{simple}$,纯预测噪声的 MSE,训练更稳、样本更好;代价是它不再精确等于上界 $L$。 > [!abstract] 公式 14 · 简化训练目标 > $L_\text{simple} = \mathbb{E}_{t,x_0,\epsilon}\!\Big[\big\|\epsilon - \epsilon_\theta(\sqrt{\bar\alpha_t}\,x_0 + \sqrt{1-\bar\alpha_t}\,\epsilon,\ t)\big\|^2\Big]$ > $t$ 从 $1..T$ 均匀抽、$x_0$ 从训练集抽、$\epsilon$ 从标准正态抽。 > [!note]- 为什么去掉「最优权重」反而更好(支线) > **锚点**:公式 12 的权重 $\frac{\beta_t^2}{2\sigma_t^2\alpha_t(1-\bar\alpha_t)}$。 > > 两个目标。**目标一**:精确最小化上界 $L$(等价于提高密度 $p_\theta(x_0)$)——带权重时加权损失恰等于 $L$,对此最优。**目标二**:样本质量,这是实际目标。两者不一致:密度高 ≠ 样本好。 > > 代入 $\sigma_t^2=\beta_t$,权重化简为 $\frac{\beta_t}{2\alpha_t(1-\bar\alpha_t)}$:小 $t$ 约 $\tfrac12$、大 $t$ 约 $0.01$,相差约 50 倍。原权重把大部分分量给小 $t$(加噪少、易预测、变化微小的步),而决定整体结构的大 $t$ 高噪声步权重很小。设为 1 后撤去此偏向:小 $t$ 增约 2 倍、大 $t$ 增约 100 倍,提高大 $t$ 步的相对权重,使网络多训练高噪声步。代价是 $L_\text{simple}$ 不再精确等于 $L$;两目标冲突时论文取样本质量。 > [!note]- $L_0$:最后一步连续转离散(支线) > 论文 3.3 节。像素 0–255 整数先线性缩放到 $[-1,1]$。$L_0$ 管从连续的 $x_1$ 落回离散像素:用离散解码器(公式 13),把每个像素值对应到一小段区间,$L_0$ 为反向高斯在该区间的积分。偏工程,数学非重点;其作用是连续转离散。 --- ## §9 训练与采样算法 **这一步**:全部理论落成可跑的代码。网络 $\epsilon_\theta$ 记为 `model`,训练循环就是公式 14 的逐字翻译,采样循环就是 §7 采样一步的逐字翻译。 **结论**:四块,系数预备、损失、训练、采样;每行代码右侧标了它对应的公式。 ```python # 9.0 系数预备 betas = torch.zeros(T + 1) betas[1:] = torch.linspace(0.0001, 0.02, T) # β_t, 线性日程 alphas = 1.0 - betas # α_t = 1 - β_t alpha_bars = torch.ones(T + 1) alpha_bars[1:] = torch.cumprod(alphas[1:], dim=0) # ᾱ_t sigmas = torch.sqrt(betas) # σ_t = √β_t ``` **9.1 训练(算法 1)**:每次抽一个 $t$、构造 $x_t$、做一次梯度步;迭代足够多次后各 $t$ 均匀覆盖。对应 $L_\text{simple}$(公式 14)。 ```python def loss_simple(model, x0): B = x0.shape[0] t = torch.randint(1, T + 1, (B,), device=x0.device) eps = torch.randn_like(x0) abar_t = alpha_bars[t].view(-1, 1, 1, 1) x_t = torch.sqrt(abar_t) * x0 + torch.sqrt(1.0 - abar_t) * eps # 公式 4 eps_pred = model(x_t, t) return ((eps - eps_pred) ** 2).mean() ``` **9.2 采样(算法 2)**:从纯噪声反向至 $x_0$,每步执行 §7 采样公式。$t=1$ 时 $z=0$(最后一步取均值,不注入噪声)。 ```python @torch.no_grad() def sample(model, shape, device): x = torch.randn(shape, device=device) # x_T ~ N(0, I) for t in range(T, 0, -1): z = torch.randn_like(x) if t > 1 else torch.zeros_like(x) t_batch = torch.full((shape[0],), t, device=device) eps = model(x, t_batch) coef = (1.0 - alphas[t]) / torch.sqrt(1.0 - alpha_bars[t]) # β_t / √(1-ᾱ_t) x = (x - coef * eps) / torch.sqrt(alphas[t]) + sigmas[t] * z return x ``` --- ## 本节一条线 权重设 1 得 $L_\text{simple}$(公式 14):抽 $t$、抽 $x_0$、抽 $\epsilon$,按闭式拼 $x_t$,网络猜噪声算 MSE;这一手撤掉原权重对小 $t$(易预测步)的偏向、多训高噪声步,拿「精确等于上界」换样本质量。采样从纯噪声起步,每步按公式 11 的中心加 $\sigma_t z$ 回退($t=1$ 不注噪),$T$ 步到 $x_0$(算法 1/2)。