
最近几年生成模型的研究基本被扩散模型和 Score-based Model 这两条线霸屏了。如果你翻过一些顶会论文会发现大量工作都挂着一个叫“Score”的词从图像生成到分子构象采样再到科学计算里的反问题求解到处都能看到它的影子。很多人第一次接触这个概念时容易被“得分”这个翻译带偏以为是个打分机制其实它和“打分”没有半点关系。Score-based Model 指的是对数据分布的对数密度梯度进行建模换句话说模型不直接学习分布本身而是学习分布指向高概率区域的“方向场”。这个思路绕开了概率密度归一化难题让生成这件事变得异常优雅。这篇内容适合谁看如果你已经在用扩散模型做生成任务但对其中的数学原理还停留在“去噪”这种直观理解层面想真正搞懂 Score-based Model 为什么能工作、采样时那些参数为什么这样设置那你来对地方了。如果你是刚入门生成模型的研究生或工程师想知道除了扩散模型之外还有没有其他等价视角这篇也能帮你把两套框架打通。文章会从原理逐步拆到实操细节再到训练时踩过的坑和调参经验全程用大白话遇到数学尽量用直觉解释清楚。1. 为什么要把分布的学习转成“得分”的学习1.1 从归一化难题说起任何一个概率模型的核心任务都是刻画数据分布 p(x)。最直接的做法是把这个密度函数显式写出来比如高斯混合模型就是一堆高斯分布的加权和。但现实数据往往是高维空间里极其复杂的流形比如一张 256x256 的彩色图像其本质是 196608 维空间里的一个低维流形。直接估计这个密度函数的解析形式几乎不可能因为密度函数必须满足两个条件处处非负且在整个空间上积分等于 1。第二个条件也就是归一化约束是所有显式概率模型最头疼的事。考虑一个常见的能量模型形式p(x) exp(-E(x)) / Z其中 Z 是配分函数也就是 exp(-E(x)) 在全空间的积分。在高维空间里这个积分没有解析解数值积分也会随着维度增加指数级崩溃。于是 Score-based Model 换了一个思路我不估计 p(x)我估计 ∇x log p(x)。这个量叫得分函数Score Function。关键的一点是求导操作自动消掉了归一化常数 Z因为 Z 对 x 的导数是零。用直觉理解就是归一化常数只负责把整个分布“压”到积分面积为 1它不改变分布形状的“走向”所以求梯度时它就自动消失了。这个思路等价于你不需要知道一座山每个点的绝对海拔密度值只需要知道每个点往哪个方向走是上坡以及坡有多陡。而爬山路线完全由梯度决定海拔绝对值不影响你到达山顶。1.2 得分函数到底长什么样直观一点想如果数据点集中在一个区域的中心得分函数就是这个区域边缘指向中心的箭头场。如果数据分布有几个簇得分函数就会在每个簇周围形成一个“指向簇心”的向量场而簇与簇之间的鞍点处向量会趋于零。训练 Score-based Model就是训练一个神经网络 sθ(x)让它逼近真实的得分函数 ∇x log p(x)。有了得分函数生成新样本的过程就变成了 Langevin 动力学采样。这个采样方法本质上是带噪的梯度上升每次沿得分方向走一小步同时加入一点高斯噪声防止模型收敛到同一个点。迭代若干步之后初始的随机噪声点就会被“搬运”到数据分布的高概率区域也就是生成出逼真样本。整个生成过程没有显式密度计算没有归一化常数所有困难一步到位绕开了。1.3 与扩散模型的关系澄清经常会有人问Score-based Model 和扩散模型到底是不是一回事答案是是同一类方法的不同视角。扩散模型的前向过程是逐步加噪把数据破坏成纯噪声反向过程学习的是“去噪”从纯噪声逐步还原出数据。Score-based Model 则直接定义了一个随机微分方程SDE前向过程把数据分布逐渐变成噪声分布反向过程则依赖得分函数来逆转这个过程。DDPM、DDIM、Score SDE 这些算法都能统一在同一个 SDE 框架下。用大白话解释扩散模型是从“图像被噪声毁掉”的角度学怎么修复Score-based Model 是从“知道每个像素怎么调整更像真实数据”的角度去生成。两套视角描述的是同一个物理过程只是解释起来一个像视频倒放一个像地图导航。2. 核心技术拆解从得分匹配到 SDE 统一框架2.1 训练目标为什么不能直接用 L2 距离你可能会想既然要逼近真实的得分函数那我直接用均方误差让 sθ(x) 去拟合 ∇x log p(x) 不就行了理论上没问题但实操中会撞上一堵墙真实得分函数我们根本不知道。我们手里只有一堆样本数据p(x) 本身是未知的。这就陷入“没有参考答案怎么对答案”的困境。于是有了 Score Matching 这一系列方法。它巧妙的地方在于可以把这个未知目标转成一个只依赖样本的优化目标。核心思想是通过分部积分把目标函数里的未知项换掉最终得到的形式只包括模型输出对输入的雅可比矩阵的迹以及模型本身。这个目标不需要知道真实 p(x)只需要对训练样本做前向传播就可以计算。其中一种最常用的变体是 Denoising Score MatchingDSM。它的做法更直观给数据点加上高斯噪声得到扰动后的样本然后训练模型去预测这个噪声。等等这不就是扩散模型的噪声预测目标吗对完全一样。这也从目标函数层面印证了两个框架殊途同归。2.2 单一噪声尺度为什么搞不定早期 Score-based Model 最简单的版本就是训练一个模型去匹配某个固定噪声水平下的得分函数。但实际跑起来会发现效果很差。原因在高维空间里数据流形只占据极小的体积噪声稍微小一点采样点落在流形附近的概率极低得分函数在那里几乎没有信号噪声稍微大一点数据细节全被抹掉了生成的样本模糊不清。单一噪声尺度就像用一把固定焦距的镜头拍微距对不上焦。所以后来的方法都采用多尺度噪声策略训练一个网络同时接受噪声尺度作为条件输入。低噪声水平负责捕捉细节纹理高噪声水平负责把握整体结构。采样时从大噪声开始逐步退火到小噪声这个过程本质上和扩散模型的“从纯噪声逐步去噪”完全对应。梯度场从“粗略的轮廓指引”逐步细化到“精确的细节修正”生成质量有了质的飞跃。2.3 SDE 框架把几套方法统一了我真正觉得 Score-based Model 体系漂亮的点是它的 SDE 统一视角。论文里的核心结论可以概括成这样前向过程可以用一个随机微分方程来描述dx f(x, t)dt g(t)dw其中 f 是漂移项g 是扩散系数dw 是维纳过程的增量。这个 SDE 的作用是把复杂的数据分布 p_data(x) 随时间演化成一个简单的先验分布 p_prior(x)。而神奇的是任何 SDE 都存在一个对应的反向 SDE反向过程同样可以用 SDE 表示但里面的未知项恰好就是得分函数 ∇x log p_t(x)。这意味着什么意味着只要你学会了所有时间点上的得分函数就能从先验分布开始一步步逆向演化回到数据分布。不同论文之间的区别只是 f 和 g 的取法不同。取特定的 f 和 g退出来就是 DDPM 的离散加噪过程取另一种形式就是连续时间扩散模型再换一种就是经典的郎之万动力学采样方式。这种统一视角不仅让理论更优雅还带来一个实际好处可以借用 SDE 求解器的各种数值技巧来加速采样比如后来很火的 SDE 快速求解器本质就是高阶数值解法。2.4 概率流 ODE一条确定性的生成捷径除了反向 SDE这个框架还推出了一个确定性过程叫 Probability Flow ODE。直觉解释是SDE 的反向过程中除了一个确定性的漂移项还有一个随机噪声项把样本往不同方向推。如果你把随机噪声项去掉只保留确定性部分得到的 ODE 轨迹仍然能把先验分布映射回数据分布只是每条轨迹是确定性的。好处是采样时可以大步长跳跃不用像 SDE 那样小心翼翼小步走。这个 ODE 还带来了额外红利因为它确定了从噪声到数据的可逆映射可以在潜在空间做插值、编辑比如在两张图的隐变量之间做线性插值生成过渡帧。这为生成模型做语义编辑和控制打开了大门。3. 实操过程自己训练一个 Score-based Model3.1 环境与数据准备动手实践时不需要太夸张的硬件我自己的经验是单张 24GB 显存的显卡足够跑通 CIFAR-10 级别的实验如果你只有 12GB 显存把 batch size 调小、模型宽度减少一些也能跑只是效果差点。代码框架建议直接用 PyTorch生态成熟调试方便。数据集先用简单的MNIST 或 CIFAR-10 都是好选择。MNIST 分辨率低、结构简单能快速验证 pipeline 是否正确CIFAR-10 的彩色图像和复杂纹理能检验模型是否真的学到了分布结构。我建议首次实验用 CIFAR-10因为 MNIST 太简单指标好看但掩盖了实现细节问题容易让你误以为代码写对了。模型结构推荐 U-Net这和扩散模型社区的经验一致。U-Net 的编码器-解码器结构配合跳跃连接能在不同尺度上同时捕捉全局结构和局部纹理。关键是要把噪声尺度 t 作为条件输入到网络中常见做法是做正弦位置编码后加到每个残差块上。3.2 损失函数与训练循环的关键代码训练目标用 Denoising Score Matching 的变体。给定数据点 x随机采样一个噪声尺度 σ加噪得到 x̃ x σ·ε其中 ε 是标准高斯噪声。模型的输出用于预测 ε 或者等价地预测得分损失函数如下L(θ) E[ λ(σ) · || sθ(x̃, σ) - (-ε/σ) ||² ]这里 sθ 的监督目标是 -ε/σ也就是真实得分的蒙特卡洛近似。为什么该目标有效因为 x̃ 的条件分布是已知的高斯分布它的得分函数有闭式解就是 -ε/σ不需要知道 p(x) 就能构造监督信号。权重 λ(σ) 常见取 σ²用来平衡不同噪声尺度下损失的尺度差异。实际代码里有个容易踩的坑如果没有做损失加权高噪声尺度的损失天然就大模型会偏向优化这些大尺度而忽略细节。加上 σ² 加权后相当于给低噪声尺度更大的相对权重能明显改善生成纹理的锐利度。训练循环本身并不复杂前向传播得到预测噪声计算加权 MSE反向传播更新参数。但要注意不要把噪声采样和加噪写进 DataLoader 的预处理里而是在每次迭代时随机采样。这样每个 epoch 中同一个图像会被不同强度的噪声扰动数据增强效果等于无限倍模型泛化性会好很多。3.3 采样过程参数怎么设训练完成后采样最经典的方式是 annealed Langevin dynamics。每次迭代分两步先沿得分方向更新再加噪声随机扰动x_{i1} x_i α · sθ(x_i, σ_i) √(2α) · z_i其中 α 是步长z_i 是标准高斯噪声。步长与噪声尺度的平方成正比因为大噪声水平下得分场的尺度大步子要相应变大。整个采样过程从最大的噪声尺度出发逐步减小噪声每一轮噪声尺度下迭代若干步。关键参数有三组。第一是噪声尺度序列的长度常用等差或者几何序列长度从 10 到上百都有。第二是每个尺度下的迭代步数一般 50 到 100 步足够多了边际收益很小。第三是初始噪声尺度必须大到能把数据完全淹没否则采样链永远无法从噪声区“登陆”到数据流形上。如果你生成出来的图片全是模糊一片没有结构多半是初始噪声不够大或步数太少。如果你生成的图有形状但细节很脏通常是低噪声尺度迭代不足或者模型对低频噪声拟合还不够精细。这些都需要反复调参没有万能公式但上面的排查方向基本能覆盖 90% 的问题。3.4 采样加速的实用技巧SDE 采样器虽然稳定但速度确实慢需要的步数多。实际使用中有几个提升效率的手段。第一是换成 DDIM 式的确定性采样器步数能直接从几百降到 50 甚至更少代价是多样性略微下降。第二是使用高阶 SDE 求解器比如基于指数积分器的方法能在同样的步数下获得更小的离散化误差细节保留更好。第三种技巧和模型本身配合蒸馏。用训练好的教师模型生成一批高质量的噪声-数据对再用学生模型直接学习从大噪声到小噪声的跳跃映射一步完成原来几十步做的事情。这个方案在减少生成成本上成效显著许多生产环境部署用的就是这个思路。4. 训练中的常见问题与排查心得4.1 损失曲线看着很漂亮但生成效果差这是我见过最多的一个坑。训练损失一路下降但采样出来的图像像打了马赛克甚至完全是噪声。问题通常出在“训练和采样之间的噪声尺度分布错配”。训练时模型见过的噪声分布比较宽但采样时你给的初始噪声超出了训练覆盖范围模型对没见过的噪声水平只能瞎猜。解决办法检查你训练时采样的 σ 范围是否覆盖了采样时所有可能用到的值尤其是最大值。我习惯在训练结束时多采样几个超大噪声尺度的样本放进验证集里看模型输出是否合理。另一个常见原因是训练和采样时对 σ 的条件编码方式不一致比如训练时用了 log 尺度而采样时用了线性尺度这种细节容易被忽略但破坏力极大。4.2 模型对噪声尺度条件不敏感条件注入应该是 Score-based Model 训练里最容易被忽视的步骤。如果你把 σ 编码后和图像特征直接拼接或简单相加模型很容易忽略这个条件导致所有尺度共用一套特征。正确的做法是参考 DDPM 的 AdaGN 机制把 σ 编码后生成每个残差块的缩放和偏移参数和批归一化的做法类似。判断模型是否真正“理解”了条件有个笨办法固定一张输入图连续改变 σ 输入观察输出变化是否平滑。如果输出几乎不变说明条件注入失效如果变化是渐变而非突变说明注入方式基本正确。4.3 显存溢出与 Batch Size 的平衡固定噪声尺度的 Score-based Model 前向传播不需要通过太多中间变量反传显存压力主要来自 U-Net 本身的深度和大通道数。训练时如果 OOM我一般先降 batch size 而不是降模型尺寸因为模型尺寸直接影响生成质量上限batch size 可以通过梯度累积补偿。梯度累积每 k 步做一次参数更新效果等价于用更大的 batch size代价只是训练时间线性增加。另一个节省显存的实用手段是混合精度训练。score 本身是浮点梯度误差对精度不那么敏感用 FP16 训练损失很少出问题但注意损失缩放策略要设置对否则前期容易出现 NaN。4.4 生成样本多样性不足有时候你发现生成出来的图虽然质量不错但像是在复制训练集里的样本多样性明显不足。这个现象通常和采样温度或者噪声退火策略有关。如果最终噪声水平降得太低采样链就被“钉死”在单个数据点附近失去多样性。解决办法是让最终噪声尺度不要小到完全消失留一点点噪声作为“探索温度”同时增大中低噪声段的迭代步数。还有一种情况是模型容量太高而训练数据太少模型直接把训练集记住了。这种时候调参没用得换更正则化的训练策略或者扩充数据增强方法。Score-based Model 同样受困于过拟合只是表现形态比较隐蔽。4.5 数值不稳定的处理训练偶尔会遇到 loss 突然变成 NaN。这个问题的来源通常有两个一是学习率过高导致梯度爆炸这个最好排查直接降学习率或加梯度裁剪就能解决二是数据里存在极端离群值加噪后得到的 x̃ 过于极端前向传播经过深层网络时激活值溢出。我习惯在数据预处理时做一次 z-score 标准化让像素分布零均值单位方差同时把梯度裁剪阈值设在 1.0 左右基本能挡住 99% 的数值崩溃问题。5. 更进一步Score-based Model 的扩展应用思路5.1 从图像生成到科学计算Score-based Model 最迷人的地方可能不在图像而在任意高维分布建模场景。比如分子构象生成难点在于分子在三维空间中的分布高度多模态传统方法难以采样到所有能量低谷。用 Score-based Model 对分子构象分布建模能从随机坐标出发逐步演化出合理构象而且天然处理多模态性质。类似思路也被用在蛋白质结构预测、材料设计、逆分子设计等领域。这些场景的共同特点是数据分布极其复杂、显式密度不可得、但可以拿到大量样本。这正是 Score-based Model 最擅长的设定。5.2 与强化学习的结合最近有个比较热的方向是把 Score-based Model 和学习策略结合。传统强化学习需要策略分布输出具体动作但高维动作空间的策略分布同样存在归一化难题。Score-based Model 可以绕开显式策略密度直接在动作空间上学习得分函数然后通过郎之万采样输出最优动作。这种范式在机器人控制中被造了个词叫 “Diffusion Policy”已经在不少物理仿真任务中刷新了效果榜。这类工作的工程坑往往不在策略本身而在采样延迟。郎之万采样几十步对实时控制来说太慢所以实践里大多用蒸馏或者确定性 ODE 采样器把推理压到一步以内。把生成模型的采样效率和决策频率做匹配是落地这类系统真正要面对的难题。5.3 条件生成与可控编辑如果你想让 Score-based Model 生成特定类别的图像最简单的方式是类别条件注入也就是把类别标签作为额外的条件输入网络。复杂一点的场景是文本引导生成这时得分函数要改写为条件得分 ∇x log p(x|c)根据贝叶斯公式它等于无条件得分 ∇x log p(x) 加上条件对数似然的梯度 ∇x log p(c|x)。后者通常用另一个分类器或 CLIP 模型提供这就是所谓分类器引导Classifier Guidance的原理。这种合成梯度的方法让编辑和可控生成变得非常灵活你想让图像更偏向某个属性就在得分场上叠加一个指向属性方向的偏置场。不用重新训练生成模型只需要额外训练一个轻量级分类器这也是 Score-based Model 生态能迅速扩展的原因之一。5.4 与潜在空间方法的区别很多人喜欢拿 VAE、GAN 和 Score-based Model 做比较。VAE 的问题在于用高斯分布作为潜在空间的先验太弱学到的隐变量往往没有充分解耦语义生成质量上限受限。GAN 的问题在于训练不稳定判别器和生成器的博弈很容易坍缩。Score-based Model 绕开这些困难的方式是不做显式的潜在空间建模而是直接在数据空间上定义概率路径。代价是推理时需要迭代采样计算成本更高。这个取舍在离线生成场景下完全值得因为你换来了两个显著优势一是训练过程稳定没有对抗博弈那种极度敏感的超参数二是生成的多样性有保障不会像 GAN 那样模型崩塌后只剩几张图轮流转。如果你需要快速推理且对多样性要求不高GAN 仍然有它的位置如果你要覆盖复杂数据分布且追求训练稳定性Score-based Model 显然是更稳妥的选择。6. 实操后的经验与建议跑了一整轮 Score-based Model 的实验之后我想分享几条朴素但管用的经验。第一条是先跑通小规模实验再上大模型。我在 CIFAR-10 上先把噪声尺度序列长度设成 10模型通道数减半用一个非常小的配置把损失曲线和采样流程全部跑通确保从训练到采样整条链路没问题再逐步加到完整配置。这个习惯帮我避开了很多“训练了一天发现采样代码有 bug”的惨剧。第二条是保存模型时同时保存一份采样配置。不同模型用的最优噪声尺度序列、迭代步数可能都不同把参数和模型绑定存档能省掉大量重复调参时间。我踩过因为采样配置和训练配置不一致导致结果暴涨暴跌的坑后来就养成了每次跑实验都写配置文件的习惯。第三条是可视化得分场的分布。很多人只看生成的最终图像但中间过程的诊断信息同样重要。我习惯在每个 epoch 结束后从测试集挑几张图把真实加噪样本的得分场可视化出来看模型预测的箭头是否指向数据聚集区域。这个可视化比损失数值直观得多能提早发现梯度方向混乱、条件注入失效这类深层问题。第四条是学习率要根据模型规模动态调整。Score-based Model 对学习率没有 GAN 那么敏感但仍然有明显的适用区间。模型小时学习率大一点没事模型加深加宽后需要适当降低学习率否则后期会出现 loss 震荡不减的现象。我通常先用线性学习率扫描找出量级再配合余弦退火获得更平滑的收敛过程。最后一条可能听起来有些反直觉不要迷信论文里的超参数。论文里的配置是在特定数据集、特定计算资源下调出来的直接复制到你的场景很可能不是最优甚至会出现训练不稳定。理解每个参数的作用然后用你的数据去做小规模搜索远比照抄参数清单更有效率。Score-based Model 的理论框架很优雅但它能发挥多大效果最终还是由你在工程细节上的处理水平决定。