分数模型与扩散 SDE:参考答案#
说明#
以下答案与正文10道题逐题对应。推导题给出主要步骤;编程和实验题给出参考程序和检查方法,并说明结果适用于哪些条件。
忽略与 \(\bx\) 无关的常数,\(\log p(\bx)=-\lVert\bx-\bmu\rVert_2^2/(2\sigma^2)+C\),所以 \(\nabla_{\bx}\log p(\bx)=-(\bx-\bmu)/\sigma^2\)。分数与 \(\bx\) 同形,指向均值即更高密度方向。归一化常数只进入 \(C\),关于 \(\bx\) 的梯度为 0,因此即使只知道未归一化密度也能计算分数。
条件分布是均值 \(\sqrt{\bar\alpha_t}\bx_0\)、协方差 \((1-\bar\alpha_t)\bI\) 的高斯,故分数为 \(-[\bx_t-\sqrt{\bar\alpha_t}\bx_0]/(1-\bar\alpha_t)\)。把分子写成 \(\sqrt{1-\bar\alpha_t}\tilde{\boldsymbol{\epsilon}}_t\) 后得到题中关系,其中 \(\tilde{\boldsymbol{\epsilon}}_t\) 表示直接构造 \(\bx_t\) 时使用的累计标准高斯噪声。因此 \(\bs_{\btheta}(\bx_t,t)=-\boldsymbol\epsilon_{\btheta}(\bx_t,t)/\sqrt{1-\bar\alpha_t}\);符号和标准差因子都不能省略。
这是 AR(1) 链,系数 \(a=1-\eta/2\),创新方差为 \(\eta\)。当 \(|a|<1\) 即 \(0<\eta<4\) 时,平稳方差 \(v\) 满足 \(v=a^2v+\eta\),故 \(v=\eta/[1-(1-\eta/2)^2]=1/(1-\eta/4)\)。当 \(\eta\to0\) 时 \(v\to1\);有限步长的方差略大于 1,体现 Euler 离散偏差。
反向 SDE 的确定性漂移为 \(\boldsymbol f-g^2\bs=-4(-\bx)=4\bx=(12,-4)\);概率流 ODE 漂移为 \(\boldsymbol f-g^2\bs/2=2\bx=(6,-2)\)。这些是公式右侧的向量;实际从 \(T\) 向 0 离散时 \(\Delta t<0\),更新增量的方向还要乘以负时间步。若求解器改用正向重参数化时间,漂移符号必须同步变换。
批次构造和 NFE 计数应显式化:
def dsm_batch(x0, sigma, rng): scale = np.asarray(sigma).reshape((-1,) + (1,) * (x0.ndim-1)) if scale.shape[0] != x0.shape[0] or np.any(scale <= 0): raise ValueError("每个样本需要正噪声尺度") eps = rng.normal(size=x0.shape) noisy = x0 + scale * eps return noisy, -eps / scale def dsm_loss(predicted_score, target_score, sigma, weights=None): if predicted_score.shape != target_score.shape: raise ValueError("预测分数与目标分数必须同形") sigma = np.asarray(sigma, dtype=float) if np.any(sigma <= 0) or sigma.shape != (predicted_score.shape[0],): raise ValueError("每个样本需要一个正噪声尺度") axes = tuple(range(1, predicted_score.ndim)) per_sample = np.mean( (predicted_score - target_score) ** 2, axis=axes ) weight = sigma ** 2 if weights is None else np.asarray(weights) if weight.shape != sigma.shape or not np.isfinite(weight).all(): raise ValueError("损失权重维度或数值不合法") return np.mean(weight * per_sample) def langevin(x, sigmas, steps, step_size, score, rng): nfe = 0 for sigma in sigmas: for _ in range(steps): s = score(x, sigma); nfe += 1 x = x + 0.5 * step_size * s + np.sqrt(step_size) * rng.normal(size=x.shape) return x, nfe
代码默认使用常见的 \(\lambda(\sigma)=\sigma^2\),也允许显式传入其他逐样本权重;应另外按噪声尺度记录未加权误差,避免总平均值掩盖某一尺度的失败。
一维高斯的解析分数用第 1 题公式,二维高斯混合可用各分量后验责任加权分量分数。先把解析分数代入采样器,确认均值、协方差和模态位置接近目标,再换成网络以区分求解器与训练误差。对同一 \(\bx_t,t\) 检查
score == -eps_pred / sqrt_one_minus_alpha_bar。二维结果应同时看分布图与定量距离,不能只核对均值。维度断言为
score.shape == x.shape;尺度从 \((m,)\) 重整为 \(m\times1\times\cdots\);高斯样本在均值右侧时分数为负、左侧时为正;很小 \(\sigma\) 时先检查目标与损失有限;反向网格满足np.diff(times) < 0;同种子轨迹完全一致;用包装函数每调用一次网络就加 1,最终计数必须等于记录 NFE。非法尺度和非有限输入应立即失败。更多尺度可减小相邻分布间的跳跃,更多校正步可改善局部混合,但二者都会增加 NFE 与生成时间。所有设置共享训练数据、种子、网络容量和更新次数;若尺度集合影响训练采样,也应保持每个更新的样本数相同。报告 FID/KID 或玩具分布距离、覆盖、训练秒数、固定样本生成秒数、实际 NFE、参数量和峰值内存。
两种动力学共享同一分数检查点,训练时间和参数量注明为相同共享成本。用相近 NFE 或同时画质量—NFE 曲线,固定初始样本和数值容差。反向 SDE 有随机项,可能提供不同轨迹;概率流 ODE 给定初值时确定,并可用自适应求解。报告质量、多样性、生成时间、NFE 和峰值内存;“边缘分布相同”是连续精确条件,不保证离散近似完全一致。
最大 NFE 而非名义步数决定主要网络成本;预测—校正每个时间层通常包含预测与若干校正调用,自适应 ODE 的接受/拒绝步也会增加 NFE。使用同一模型、初始集合和种子,记录实际调用而非估算值。结果表包含质量、覆盖或失败率、共享训练时间、固定样本生成时间、NFE、参数量与峰值内存,并以质量—成本曲线比较,不应只报告步数最少的方法。