想象你是一位登山向导培训师,面前是一片常年云雾缭绕的绵延山脉。山的高处错落着许多村庄——地图上“村庄密集”的区域,对应着机器学习里“数据分布的高密度区”。作为向导,你不需要背下每座山的精确海拔(那需要一张永远不存在的完整地图),你只需要掌握一个本能:无论站在山坡的哪个位置,都能感知“往哪边攀登,村庄更近”。这个“往哪边”的方向,数学上叫做分数(score)——概率密度取对数后求梯度。而“训练向导感知方向”这件事,就是分数匹配(Score Matching)。扩散模型的训练,本质上就是教一个神经网络当这样的向导:既要在雾中分辨方向(去噪分数匹配),又要用一套稳健的步伐带人登山(Langevin 采样)。本文就从这座“数据山脉”出发,一步步走到扩散模型的训练核心。

岗位关联

掌握分数匹配,等于拿到扩散模型训练的“公式说明书”,能让你在阅读 DDPM、SDE 论文时不再迷茫,并理解生成模型从理论到落地的关键一跳。

目录
  1. 可视化演示
  2. 分数核心概念:数据山脉的“坡度”
  3. Langevin采样:雾中登山者的探路杖
  4. 分数匹配目标:如何考核向导
  5. 隐式分数匹配:绕开真山神的巧计
  6. 去噪分数匹配:雾天训练法
  7. 噪声条件分数网络:多档浓雾的全面训练
  8. 与扩散模型关联:一枚硬币的两面
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示分数函数梯度场、Langevin动力学采样轨迹、以及去噪分数匹配的训练过程与损失收敛。

本节配有交互动效(进入视口后自动加载,约 3KB)。

分数函数梯度场 箭头指向数据密度增大方向 梯度强度反映局部数据密度 s(x)=∇log p(x) 分数函数引导采样向高密度区域移动

分数核心概念:数据山脉的“坡度”

老向导有一句口诀:“不用记海拔,只需辨坡度。”概率密度 p(x) 就像地图上的海拔,告诉我们哪个区域“村庄密集”;但要赶路,我们真正需要的是脚下的坡面指向——往哪个方向走,村庄更近。这个方向,就是分数 s(x)。它把“某处有多少人住”转化为“该往哪儿走”,省去了计算完整地图的麻烦。

形式化地说,设数据服从分布 p(x),分数定义为对数概率密度在点 x 处的梯度。为什么要取对数再求导?因为高维概率密度往往含有夸张的指数尺度,取对数后数值更稳定,而且对密度函数求梯度时,那个恼人的归一化常数恰好会被“求导清零”。

回到向导的视角:如果我们给向导发一张全山任何位置都标注好坡度的“风向图”,他就能在任何地方找到村庄。这张风向图就是分数向量场,而训练神经网络去复刻这张图,就是后面所有章节要做的事。

s(x)=∇xlog⁡p(x)\displaystyle s(\mathbf{x}) = \nabla_{\mathbf{x}} \log p(\mathbf{x})
分数就是“对数海拔的坡度”,它不关心你站的位置本身有多高,只关心往哪个方向走会更快到达人口密集区。
  1. 数据点的记号每个样本(图片、语音帧、分子构象)都是一个 D 维向量,在这座“山脉”上占据一个坐标。
    x=(x1,x2,…,xD)\mathbf{x} = (x_1, x_2, \dots, x_D)
  2. 概率密度函数p(x) 描述数据分布,值越大代表该位置附近样本越密集,类似地图上的“海拔高度”。
    p(x)≥0,∫p(x) dx=1p(\mathbf{x}) \ge 0, \quad \int p(\mathbf{x}) \, d\mathbf{x} = 1
  3. 对数变换对密度取对数,把复杂的乘法关系变成加法,也让后续求导更干净。
    log⁡p(x)\log p(\mathbf{x})
  4. 梯度运算符对 x 的每一个分量求偏导,得到一个向量,指向函数值增长最快的方向。
    ∇x=(∂∂x1,∂∂x2,…,∂∂xD)\nabla_{\mathbf{x}} = \left( \frac{\partial}{\partial x_1}, \frac{\partial}{\partial x_2}, \dots, \frac{\partial}{\partial x_D} \right)
  5. 分数向量场把“海拔变化”合成一个向量,每个位置都对应一个指向高密度区的箭头——这就是整个山脉的“风向图”。
    s(x)=∇xlog⁡p(x)s(\mathbf{x}) = \nabla_{\mathbf{x}} \log p(\mathbf{x})

Langevin采样:雾中登山者的探路杖

有了分数向量场,如何利用它生成新样本?想象一位经验丰富的登山者在浓雾中寻找村庄:他每走一步,用手杖探一下脚下坡度,朝最陡的方向迈一步;但他不会笔直冲刺——随身携带的“随机扰动”让他偶尔偏一偏,避免所有人永远挤在同一个山头。这就是Langevin 动力学的朴素写照。

Langevin 采样把“沿着分数方向走”和“注入随机噪声”结合成一个迭代公式。其中确定性部分保证样本向高密度区移动,随机部分让样本能够探索整个山脉(包括多个山峰),两者平衡后,迭代过程最终会收敛到目标分布的采样。

对向导来说,这根“探路杖”的意义在于:不用背地图,只要持续感知脚下坡度,就能带队抵达村庄。同样地,只要分数估计得足够准确,Langevin 采样就能生成高质量的逼真样本——这也解释了为什么分数匹配是生成任务的核心地基。

xt+1=xt+ϵ2 s(xt)+ϵ zt,zt∼N(0,I)\displaystyle \mathbf{x}_{t+1} = \mathbf{x}_t + \frac{\epsilon}{2}\, s(\mathbf{x}_t) + \sqrt{\epsilon}\, \mathbf{z}_t, \quad \mathbf{z}_t \sim \mathcal{N}(\mathbf{0}, I)
这个公式是说:向导每步走“半格坡度方向”的确定路,再加一格“随机小踉跄”,最终在整个山区均匀找到各个村庄。
  1. 当前位置登山者第 t 步所在的山坡坐标。
    xt\mathbf{x}_t
  2. 分数引导项沿着坡度方向迈出确定性一脚,步长系数为 ε/2,保证稳步走向高密度区。
    ϵ2 s(xt)\frac{\epsilon}{2}\, s(\mathbf{x}_t)
  3. 随机扰动项注入尺度为 √ε 的标准高斯噪声,让步伐带点“醉意”,从而探索不同山峰而非死守一处。
    ϵ zt,zt∼N(0,I)\sqrt{\epsilon}\, \mathbf{z}_t, \quad \mathbf{z}_t \sim \mathcal{N}(\mathbf{0}, I)
  4. 完整迭代确定性的爬坡加上随机性的探索,反复迭代后,登山者的足迹分布就等于数据分布本身。
    xt+1=xt+ϵ2 s(xt)+ϵ zt\mathbf{x}_{t+1} = \mathbf{x}_t + \frac{\epsilon}{2}\, s(\mathbf{x}_t) + \sqrt{\epsilon}\, \mathbf{z}_t

分数匹配目标:如何考核向导

既然要让神经网络当向导,就得定义“考核标准”。最自然的想法是:找一个参数为 θ 的网络 s_θ(x),让它在每个位置的预测分数都尽量接近真实分数 s(x)。用所有数据点上的平均平方偏差作为考卷,就得到了分数匹配(Score Matching)的目标函数。

这个目标非常直观:预测箭头与真实箭头方向越一致、长度越接近,误差平方越小。然而问题在于,真实分数 s(x) = ∇log p(x) 中包含未知的数据分布 p(x),我们手里只有采样出来的数据点,根本没有“标准答案”可供对照。

这就是分数匹配遇到的“先有鸡还是先有蛋”困境:要评估向导准不准,必须先知道真实分数;而真实分数又是我们试图学习的东西。解决办法是找一条不需要真实分数的“隐形考卷”——这正是接下来两节的核心内容。

J(θ)=12 Ep(x)[∥sθ(x)−s(x)∥2]\displaystyle J(\theta) = \frac{1}{2}\, \mathbb{E}_{p(\mathbf{x})}\left[ \left\| s_\theta(\mathbf{x}) - s(\mathbf{x}) \right\|^2 \right]
理想考核是“对照真山神打分”,但真山神(真实分布)从不现身,我们拿到手的只有一堆样本,因此这个目标无法直接优化。
  1. 模型的预测分数神经网络在输入 x 后输出的分数向量,即“向导报出的坡度”。
    sθ(x)∈RDs_\theta(\mathbf{x}) \in \mathbb{R}^D
  2. 真实分数数据分布的真分数,是理想答案,但包含未知的 log p(x)。
    s(x)=∇xlog⁡p(x)s(\mathbf{x}) = \nabla_{\mathbf{x}} \log p(\mathbf{x})
  3. 平方误差两个向量的欧氏距离平方,逐分量求和后衡量“报方向”的偏差。
    ∥sθ(x)−s(x)∥2=∑j=1D(sθ,j(x)−sj(x))2\left\| s_\theta(\mathbf{x}) - s(\mathbf{x}) \right\|^2 = \sum_{j=1}^{D} \left( s_{\theta,j}(\mathbf{x}) - s_j(\mathbf{x}) \right)^2
  4. 期望加权以数据分布 p(x) 为权重积分,让常见区域(高密度区)的误差被更多重视。
    Ep(x)[⋅]=∫p(x)(⋅)dx\mathbb{E}_{p(\mathbf{x})}\left[ \cdot \right] = \int p(\mathbf{x}) \left( \cdot \right) d\mathbf{x}

隐式分数匹配:绕开真山神的巧计

既然“对照真山神”行不通,统计学家 Hyvärinen 想出一条妙计:利用分部积分,把目标函数里对真实分数 s(x) 的依赖,转移到对模型自身导数 tr(∇s_θ) 的依赖上。相当于把“请真山神对照”改为“考察向导自身的连贯性”——一个总是在相邻两步给出连续、平滑方向的向导,大概率是靠谱的。

经过分部积分变换(要求 p(x)s_θ(x) 在无穷远处趋近于零,这对常见分布通常成立),原始目标被改写成只含模型分数及其导数的形式,真实分布 p(x) 只出现在期望算子中,而期望可以用样本均值近似。

隐式分数匹配让训练在数学上成为可能,但代价高昂:每次评估都需要计算模型对输入的雅可比矩阵并取迹,在图像等高维数据上,这个矩阵的维度可能高达数万甚至数百万,几乎无法承受。于是,我们需要一个“既绕开真实分布、又不用算大矩阵”的更好方案。

JISM(θ)=Ep(x)[12∥sθ(x)∥2+tr⁡ ⁣(∇xsθ(x))]+const\displaystyle J_{ISM}(\theta) = \mathbb{E}_{p(\mathbf{x})}\left[ \frac{1}{2} \left\| s_\theta(\mathbf{x}) \right\|^2 + \operatorname{tr}\!\left( \nabla_{\mathbf{x}} s_\theta(\mathbf{x}) \right) \right] + \text{const}
Hyvärinen 的巧计是:不再问“你离真相多远”,而是检查“你的方向感是否自洽”,从而彻底绕开未知的真实分布。
  1. 模长方项约束模型分数的长度不要失控,避免向导在无数据区域乱指方向。
    12∥sθ(x)∥2\frac{1}{2} \left\| s_\theta(\mathbf{x}) \right\|^2
  2. 导数迹项对模型分数的每个输出分量关于输入 x 求偏导,再取对角线之和,这部分吸收了真实分数的全部影响。
    tr⁡ ⁣(∇xsθ(x))=∑j=1D∂sθ,j(x)∂xj\operatorname{tr}\!\left( \nabla_{\mathbf{x}} s_\theta(\mathbf{x}) \right) = \sum_{j=1}^{D} \frac{\partial s_{\theta,j}(\mathbf{x})}{\partial x_j}
  3. 常数项由真实分数模长的期望决定,与参数 θ 无关,训练时梯度为零。
    const=12Ep(x)[∥s(x)∥2]\text{const} = \frac{1}{2} \mathbb{E}_{p(\mathbf{x})}\left[ \left\| s(\mathbf{x}) \right\|^2 \right]
  4. 分部积分桥核心等式把“真实分数与模型分数的内积”换成“模型导数的迹”,实现信息的等价迁移。
    ∫p(x) sθ(x)⊤s(x) dx=−∫p(x) tr⁡ ⁣(∇xsθ(x))dx\int p(\mathbf{x})\, s_\theta(\mathbf{x})^{\top} s(\mathbf{x}) \, d\mathbf{x} = - \int p(\mathbf{x})\, \operatorname{tr}\!\left( \nabla_{\mathbf{x}} s_\theta(\mathbf{x}) \right) d\mathbf{x}

去噪分数匹配:雾天训练法

既然真地形太陡峭、直接测量太难,训练基地想出一个绝招:先下雾,再练辨向。给每个数据点 x 叠加高斯噪声得到 x̃,相当于把锋利的山脊磨圆,让原本低密度区也有可感知的坡度。Vincent 证明了一个惊人事实:让模型在雾中(加噪数据上)学会“指向被雾掩盖的原点方向”,学到的恰好就是雾后地形的真实分数。这就是去噪分数匹配(DSM)。

DSM 的关键在于:加噪数据的条件分数 ∇_x̃ log q_σ(x̃|x) 是可以直接写出来的——它只依赖于我们注入的噪声 z 和噪声强度 σ,而不依赖未知的数据分布!所以训练信号变成:模型从加噪点 x̃ 出发,预测“回到原始点 x 的方向”,也就是预测所加噪声的负方向。

DSM 一石二鸟:既绕开了未知的真实分数,又避免了 ISM 中昂贵的 Hessian 计算。今天的扩散模型训练,几乎全部建立在这个“雾天训练”的智慧之上。

LDSM(θ;σ)=12 Eqσ(x~,x)[∥sθ(x~)−∇x~log⁡qσ(x~∣x)∥2]\displaystyle L_{DSM}(\theta; \sigma) = \frac{1}{2}\, \mathbb{E}_{q_\sigma(\tilde{\mathbf{x}}, \mathbf{x})}\left[ \left\| s_\theta(\tilde{\mathbf{x}}) - \nabla_{\tilde{\mathbf{x}}} \log q_\sigma(\tilde{\mathbf{x}} \mid \mathbf{x}) \right\|^2 \right]
雾天训练法把“必须见到真山神”变成“只要认出来时路”:模型不需要知道整个山长什么样,只需要从模糊观测中找回刚撒的那把噪声的方向。
  1. 加噪观测真实数据 x 与强度 σ 的高斯噪声 z 叠加,得到模糊版本 x̃,对应“下雾后的位置”。
    x~=x+σz,z∼N(0,I)\tilde{\mathbf{x}} = \mathbf{x} + \sigma \mathbf{z}, \quad \mathbf{z} \sim \mathcal{N}(\mathbf{0}, I)
  2. 条件扰动核给定原始数据 x,加噪观测 x̃ 服从以 x 为中心、方差 σ² 的高斯分布,这就是“雾的形状”。
    qσ(x~∣x)=N ⁣(x~;x,σ2I)q_\sigma(\tilde{\mathbf{x}} \mid \mathbf{x}) = \mathcal{N}\!\left(\tilde{\mathbf{x}}; \mathbf{x}, \sigma^2 I\right)
  3. 可解析的条件分数对高斯分布直接求梯度,得到从加噪点指向原始点的方向,结果只含 x、x̃ 和 σ。
    ∇x~log⁡qσ(x~∣x)=x−x~σ2=−zσ\nabla_{\tilde{\mathbf{x}}} \log q_\sigma(\tilde{\mathbf{x}} \mid \mathbf{x}) = \frac{\mathbf{x} - \tilde{\mathbf{x}}}{\sigma^2} = -\frac{\mathbf{z}}{\sigma}
  4. 代入改写的目标把条件分数替换为 −z/σ,DSM 损失变成“预测噪声方向”的平方误差,可以纯用样本计算。
    LDSM(θ;σ)=12 E[∥sθ(x~)+zσ∥2]L_{DSM}(\theta; \sigma) = \frac{1}{2}\, \mathbb{E}\left[ \left\| s_\theta(\tilde{\mathbf{x}}) + \frac{\mathbf{z}}{\sigma} \right\|^2 \right]
  5. Vincent 等价性该目标与原分数匹配目标只相差一个与 θ 无关的常数,因此梯度一致,最优解完全相同。
    ∇θLDSM(θ;σ)=∇θJSM(θ;σ)\nabla_\theta L_{DSM}(\theta; \sigma) = \nabla_\theta J_{SM}(\theta; \sigma)

噪声条件分数网络:多档浓雾的全面训练

只下一场固定浓度的雾,向导仍可能迷路:山脊(高密度区)附近梯度陡峭,小噪声就能感知;而低谷(低密度区)一片平坦,必须用大噪声才能“垫高”地形露出坡度。于是 Song 等人提出噪声条件分数网络(NCSN):备好从小到大的一组噪声强度 σ₁,…,σ_L,让向导在“薄雾”“中雾”“浓雾”下分别练辨向,最后把各档考核加权合并。

NCSN 的关键设计是让网络额外接收噪声级别作为输入,即 s_θ(x̃, σ),从而在不同雾浓度下都能给出对应分数。训练时,对各尺度损失加权求和;推理时,Langevin 采样从大噪声对应的粗地形开始,逐步切换到小噪声的精细地形,实现“由远及近、由粗到精”的生成。

NCSN 用“多档浓雾”解决了单一噪声无法覆盖全域的难题,这也直接启发了后续的扩散模型:前向加噪过程天然提供多尺度地形,反向去噪就是逐级拨雾认路。

θ∗=arg⁡min⁡θ∑i=1Lλ(σi) LDSM(θ;σi),λ(σi)=σi2\displaystyle \theta^* = \arg\min_{\theta} \sum_{i=1}^{L} \lambda(\sigma_i)\, L_{DSM}(\theta; \sigma_i), \quad \lambda(\sigma_i) = \sigma_i^2
多档浓雾让向导既能在晴天看清山脊,也能在浓雾中感知山谷,最终在任何地形上都不会迷失方向。
  1. 噪声级别序列从小到大排列的 L 个噪声强度,覆盖从精细到粗糙的多种“雾浓度”。
    σ1<σ2<⋯<σL\sigma_1 < \sigma_2 < \dots < \sigma_L
  2. 各尺度 DSM 损失在每个噪声级别下独立计算去噪分数匹配损失,网络同时接收级别信息作为条件。
    LDSM(θ;σi)=12 E[∥sθ(x~,σi)+zσi∥2]L_{DSM}(\theta; \sigma_i) = \frac{1}{2}\, \mathbb{E}\left[ \left\| s_\theta(\tilde{\mathbf{x}}, \sigma_i) + \frac{\mathbf{z}}{\sigma_i} \right\|^2 \right]
  3. 权重因子取 λ(σ) = σ²,平衡不同噪声级别的梯度量纲,让每个尺度都能被有效学习。
    λ(σi)=σi2\lambda(\sigma_i) = \sigma_i^2
  4. 加权联合优化把各尺度损失加权求和,让模型在所有“雾浓度”下同时达到最优。
    θ∗=arg⁡min⁡θ∑i=1Lσi2 LDSM(θ;σi)\theta^* = \arg\min_{\theta} \sum_{i=1}^{L} \sigma_i^2\, L_{DSM}(\theta; \sigma_i)

与扩散模型关联:一枚硬币的两面

细心的读者会发现,扩散模型的前向过程不就是在“下雾”吗?每一步给数据叠加高斯噪声,直到整片山脉完全隐入白雾;而逆向过程就是向导“拨雾寻路”,逐步把模糊的噪声还原成清晰样本。因此,扩散模型与分数匹配不是两套并列理论,而是同一枚硬币的两面。

以 DDPM 为例,它训练网络预测前向过程注入的噪声 ε_θ(x_t, t)。由 DSM 的推导可知,加噪数据的条件分数恰好等于噪声的负方向除以尺度因子,因此“预测噪声”与“估计分数”在数学上完全等价。DDPM 的 MSE 损失,本质上就是去噪分数匹配损失在扩散多尺度设定下的重参数化形式。

回到向导的故事:DDPM 的 U-Net 就是那位身经百战的向导,他不在晴天死记地图(那需要知道真实分布),而是在每一档雾里反复练习“认出来时路”(预测噪声)。分数匹配给扩散模型提供了坚实的理论地基,而扩散模型则把分数匹配的智慧推向图像、音频与分子生成的广阔天地。

∇xtlog⁡p(xt∣x0)=−ϵ1−αˉt⟺sθ(xt,t)=−ϵθ(xt,t)1−αˉt\displaystyle \nabla_{\mathbf{x}_t} \log p(\mathbf{x}_t \mid \mathbf{x}_0) = -\frac{\boldsymbol{\epsilon}}{\sqrt{1 - \bar{\alpha}_t}} \quad \Longleftrightarrow \quad s_\theta(\mathbf{x}_t, t) = -\frac{\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)}{\sqrt{1 - \bar{\alpha}_t}}
扩散模型把“雾”设计成随时间变化的梯级,而 DDPM 的噪声预测网络就是一个训练有素的“多档雾天向导”。
  1. 前向加噪过程数据 x₀ 经过 t 步扩散后变成 x_t,其中 ε 是注入的标准正态噪声,ᾱ_t 是累积信号强度。
    xt=αˉt x0+1−αˉt ϵ\mathbf{x}_t = \sqrt{\bar{\alpha}_t}\, \mathbf{x}_0 + \sqrt{1 - \bar{\alpha}_t}\, \boldsymbol{\epsilon}
  2. 加噪条件分数对扩散过程中加噪数据的条件分布求梯度,得到与噪声直接相关的闭式结果。
    ∇xtlog⁡p(xt∣x0)=−ϵ1−αˉt\nabla_{\mathbf{x}_t} \log p(\mathbf{x}_t \mid \mathbf{x}_0) = -\frac{\boldsymbol{\epsilon}}{\sqrt{1 - \bar{\alpha}_t}}
  3. 噪声预测转分数训练好的网络输出 ε_θ 后,除以负的尺度因子即可还原分数估计,从而实现“拨雾寻路”。
    sθ(xt,t)=−ϵθ(xt,t)1−αˉts_\theta(\mathbf{x}_t, t) = -\frac{\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)}{\sqrt{1 - \bar{\alpha}_t}}
  4. 目标一致性把这个关系代入 DSM 损失,得到的恰好是 DDPM 的噪声预测 MSE 目标。
    LDDPM∝E[∥ϵ−ϵθ(xt,t)∥2]\mathcal{L}_{DDPM} \propto \mathbb{E}\left[ \left\| \boldsymbol{\epsilon} - \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t) \right\|^2 \right]

AI 应用场景

图像生成:文生图模型的“向导驯化”

阶段:模型训练

解决的问题:Stable Diffusion 等文生图模型需要在海量图文数据上训练一个能“从模糊还原清晰”的生成网络。传统生成模型(如 GAN)训练不稳定、易模式崩溃,而分数匹配给出一个训练信号明确的目标:预测注入的噪声方向即可学出数据分布。

具体案例:训练 U-Net 时,给定一张猫的图片 x,随机抽取扩散步数 t,加噪得到 x_t,让网络预测所加的噪声 ε。这个 MSE 目标与去噪分数匹配完全等价。训练完成后,从纯噪声出发逐步去噪,就能生成崭新的猫图。

音频合成:WaveGrad 的分数生成路线

阶段:模型训练 + 推理采样

解决的问题:语音合成需要在给定文本条件下生成自然连贯的波形。波形数据维度极高且时序敏感,直接预测样本点容易产生机械感。基于分数的生成框架用多尺度噪声覆盖波形空间,让模型在不同“雾浓度”下逐渐还原语音结构。

具体案例:WaveGrad 采用分数匹配目标训练,推理时从高斯噪声出发,通过 Langevin 采样逐步生成 24kHz 的语音波形,在保持高音质的同时将采样步数压缩到个位数,实现实时语音合成。

科学计算:分子构象的生成式采样

阶段:模型训练 + 采样推理

解决的问题:药物发现中需要在能量景观上采样稳定的分子构象。传统分子动力学模拟需要大量计算步数,而分数生成模型可以在“构象山脉”上学会分数场,再用 Langevin 动力学快速采样多个低能构象。

具体案例:研究人员在 QM9 等分子数据集上训练分数网络,输入化学式与初始原子坐标加噪后的构象,模型预测去除噪声的方向,从而生成多样且能量合理的 3D 分子构象,显著加速候选药物筛选。

Python 演示

python72 行
import mathimport torchimport torch.nn as nn  def make_data(n_points=4096):    """生成两个高斯簇的二维混合数据,模拟双峰数据山脉"""    torch.manual_seed(0)    centers = torch.tensor([[3.0, 3.0], [-3.0, -3.0]])    points = torch.empty(n_points, 2)    for i in range(n_points):        points[i] = centers[i % 2] + 0.6 * torch.randn(2)    return points  class NoiseNet(nn.Module):    """输入加噪观测,输出所加噪声方向(分数匹配的预测噪声形式)"""     def __init__(self):        super(NoiseNet, self).__init__()        self.mlp = nn.Sequential(            nn.Linear(2, 64),            nn.SiLU(),            nn.Linear(64, 64),            nn.SiLU(),            nn.Linear(64, 2),        )     def forward(self, x):        return self.mlp(x)  def to_score(model, x, sigma):    """由预测噪声换算分数:s(x) = -eps_theta(x) / sigma"""    return -model(x) / sigma  def train_one_step(model, opt, x, sigma):    """执行一次去噪分数匹配的梯度更新"""    z = torch.randn_like(x)    x_tilde = x + sigma * z    loss = ((model(x_tilde) - z) ** 2).mean()    opt.zero_grad()    loss.backward()    opt.step()    return loss.item()  def langevin_sampling(model, sigma, steps=400, eps=0.05):    """用训练好的分数引导Langevin采样,从噪声点逐渐走向高密度区"""    model.eval()    with torch.no_grad():        x = torch.randn(1, 2) * 2.0        for _ in range(steps):            z = torch.randn_like(x)            x = x + (eps / 2.0) * to_score(model, x, sigma) + math.sqrt(eps) * z        return x.numpy()  if __name__ == "__main__":    data = make_data()    sigma = 0.5    model = NoiseNet()    opt = torch.optim.Adam(model.parameters(), lr=1e-3)    for epoch in range(300):        idx = torch.randperm(data.size(0))[:256]        batch = data[idx]        loss = train_one_step(model, opt, batch, sigma)        if epoch % 50 == 0:            print("epoch %3d loss %.4f" % (epoch, loss))    sample = langevin_sampling(model, sigma)    print("生成样本:", sample, "期望均值约(0,0)")
目的:在二维双峰数据集上实践去噪分数匹配的完整训练流程,并用 Langevin 采样验证学到的分数场能否生成接近原始分布的新样本。
  1. points[i] = centers[i % 2] + 0.6 * torch.randn(2)构造两个高斯簇,模拟有两个“村庄”的数据山脉。
  2. return -model(x) / sigma把预测噪声转换成分数方向,对应正文中 s = −ε/σ 的换算关系。
  3. x_tilde = x + sigma * z对数据加噪,相当于在山上“下一场强度为 σ 的雾”。
  4. loss = ((model(x_tilde) - z) ** 2).mean()去噪分数匹配核心损失:让模型猜出刚才注入的噪声方向。
  5. x = x + (eps / 2.0) * to_score(model, x, sigma) + math.sqrt(eps) * zLangevin 更新:分数引导与随机探索并存。

常见误区

误区我学了 score,以为 score(x) 就是 p(x) 的近似值,甚至以为模型输出的分数可以直接当概率用。

正解分数是概率密度的“坡度”而非“海拔”。它只告诉你在当前位置往哪个方向走密度会增大、增大得多快,完全不包含密度的绝对数值。类比:向导报“往东偏北 30 度爬坡”,不等于告诉你“这里有多少户人家”。模型输出分数后,要得到密度值仍需额外做积分归一化。

为何常见:名字里带“分数”容易让人联想到“打分/概率值”,而梯度这种抽象概念对初学者不直观。

误区分数匹配不是最小化模型分数和真实分数的误差吗?那我把训练集每个点的真实分数算出来,不就能直接监督训练了?

正解真实分数由未知的数据分布决定,我们手里只有有限样本,无法计算样本之外区域的真实密度梯度。分数匹配的一切技巧(ISM、DSM)都是为了绕开这个“不可得的真山神”。DSM 用“预测注入噪声”替代“预测真实分数”,因为噪声是我们自己撒的,方向我们可以精确记录。

为何常见:把监督学习“有标签就能训”的直觉迁移过来,忽略了生成模型场景下分布本身未知这一前提。

误区既然模型学会了分数,那我从随机点算一次分数,往那个方向走一步,不就是一个新样本了吗?

正解Langevin 采样是一个渐进收敛的马尔可夫过程,需要几百到几千步迭代,且步长 ε 通常要随过程逐渐减小(退火),才能保证最终分布逼近目标分布。只走一步相当于雾中只探了一杖,远远找不到村庄。

为何常见:直觉上“梯度指向解”来自优化问题的习惯,但采样不是求唯一解,而是要遍历整个分布,随机性和多步迭代缺一不可。

误区DDPM 训练网络预测噪声,分数匹配训练网络预测分数,这俩是两种不同的生成模型方法吧?

正解两者数学上等价。由加噪条件分布直接可得:条件分数 = −噪声/σ,所以预测噪声的网络只需除以 −σ 就变成分数网络,损失函数也只差一个常系数。DDPM 本质上是多尺度去噪分数匹配在离散扩散步下的实现——同一个向导,只是换了张问路的说法。

为何常见:论文标题和公式风格差异大(DDPM 讲前向/逆向过程,Score-based 讲 SDE/分数场),容易让人误以为是两个独立流派。

面试题

Q1. 在分数匹配中,“分数”(score)的精确定义是?

单选题 · easy

  • A.概率密度函数本身的取值
  • B.对数概率密度的梯度向量← 正确答案
  • C.概率分布的归一化常数
  • D.数据分布的协方差矩阵

答案:B。分数是 ∇_x log p(x),即对数密度的梯度,指向密度上升最快的方向。A 是密度本身,C 是配分函数,D 是统计量,均与“方向”无关,故选 B。

Q2. 为什么估计分数比直接估计密度函数 p(x) 更容易?

单选题 · easy

  • A.分数是标量而密度是向量
  • B.梯度运算自动消掉了归一化常数← 正确答案
  • C.分数不需要任何训练数据
  • D.密度函数没有严密的数学定义

答案:B。p(x) = exp(g(x))/Z,对 log p(x) 求梯度时,常数 Z 求导为 0,因此分数不依赖归一化常数。A 说反了(分数是向量);C、D 明显错误。

Q3. Langevin 采样公式中,随机噪声项 √ε·z 的主要作用是什么?

单选题 · mid

  • A.让采样过程更快地收敛
  • B.增加探索性,防止样本困在单一峰← 正确答案
  • C.完全消除梯度方向的影响
  • D.让梯度计算更加精准

答案:B。随机扰动让采样过程具有各态历经性,能够遍历多个高密度区域,避免所有样本坍缩到同一个峰。它不会消除梯度影响(否则只是纯噪声),与梯度计算精度无关,故选 B。

Q4. 直接分数匹配目标无法直接优化的原因有哪些?

多选题 · mid

  • A.真实分数 s(x) 依赖未知的数据分布← 正确答案
  • B.数据分布 p(x) 本身是未知的← 正确答案
  • C.无法构造可用的监督信号← 正确答案
  • D.梯度下降算法在此处不可用

答案:ABC。真实分数和分布都未知,因此“模型分数 vs 真实分数”的监督信号无法构造,A、B、C 正确。梯度下降本身没问题,问题在于目标不可计算,所以 D 错误。

Q5. 隐式分数匹配(ISM)中出现的 tr(∇_x s_θ(x)) 项,本质上是什么?

单选题 · hard

  • A.模型输出分数的欧氏模长
  • B.模型分数的雅可比矩阵对角线之和← 正确答案
  • C.数据分布的高阶统计矩
  • D.神经网络的可训练参数量

答案:B。该项是模型分数对输入 x 求导所得雅可比矩阵的迹(对角线元素和),它通过分部积分替代了原目标中的真实分数项。A 是另一项,C、D 与导数迹无关。

Q6. 去噪分数匹配(DSM)的核心思想包括哪些?

多选题 · mid

  • A.用加噪数据的条件分数充当监督信号← 正确答案
  • B.条件分数等于噪声负方向除以强度 σ← 正确答案
  • C.仍需直接估计原始分布的归一化常数
  • D.用高斯扰动核平滑数据分布地形← 正确答案

答案:ABD。DSM 利用可解析的条件分数作为监督(A),该条件分数为 −z/σ(B),高斯扰动让地形更平滑、低密度区也有信号(D)。它完全绕开归一化常数,因此 C 错误。

Q7. NCSN 使用多尺度噪声训练的核心原因是什么?

单选题 · hard

  • A.增加模型参数量以提升拟合能力
  • B.单一噪声级别难以覆盖低密度稀疏区域← 正确答案
  • C.让每个样本获得多个监督标签
  • D.减少训练迭代所需的步数

答案:B。低密度区域在无噪声时分数信号几乎为零,单一小噪声感知不到;大噪声能把地形“垫高”露出坡度。多尺度本质是覆盖全域方向感,与参数量、标签数、步数无关,故选 B。

Q8. 扩散模型 DDPM 中,网络预测的噪声 ε_θ 与分数估计的关系是?

单选题 · mid

  • A.分数等于噪声预测的网络输出
  • B.分数是负噪声预测除以尺度因子← 正确答案
  • C.分数是噪声预测乘以尺度因子
  • D.分数与噪声预测完全没有关系

答案:B。加噪条件分数 = −ε/√(1−ᾱ_t),因此训练好的噪声预测网络除以负的尺度因子即得分数估计。A、C、D 均不满足该换算,故选 B。

Q9. Vincent 等价性说明去噪分数匹配与原始分数匹配是什么关系?

单选题 · hard

  • A.两者损失函数在形式上完全相同
  • B.两者的梯度在期望意义上一致← 正确答案
  • C.DSM 仍需计算归一化常数项
  • D.DSM 只适用于离散型数据

答案:B。DSM 目标与 SM 目标相差一个与 θ 无关的常数,因此关于 θ 的梯度相同,共享最优解。A 错在“形式完全相同”;C、D 均与事实相反。

Q10. 去噪分数匹配在工业界的实际应用包括哪些?

多选题 · easy

  • A.训练图像扩散生成模型← 正确答案
  • B.音频波形生成的分数预测← 正确答案
  • C.数据库索引与查询优化
  • D.分子构象三维结构采样← 正确答案

答案:ABD。图像生成(如 Stable Diffusion)、音频合成(如 WaveGrad)和分子构象采样都是分数匹配的典型落地场景。数据库索引与查询优化属于传统数据工程,与分数匹配无关,故选 A、B、D。