EDM Sampler在Stable Diffusion中的原理与调参实战
1. EDM Sampler 到底在 Stable Diffusion 里扮演什么角色
第一次在 Stable Diffusion 的采样器下拉框里看到 EDM 相关的选项,多数人的反应是"这又是什么黑话"。下拉框里已经有 Euler、DPM++ 2M、DDIM、UniPC 一大串名字,多出来一个 EDM Sampler,看起来像是某个小众分支,点进去试了两下觉得"好像也没差多少",然后就再也没碰过。我最初也是这样,直到有一段时间专门做纹理细节的对比测试,才发现这个采样器被严重低估了。
先把话说清楚:EDM Sampler 不是某个模型,也不是某个界面插件,它是一套完整的扩散采样方案,包含噪声调度、网络预条件和数值求解器三个部分。它源自 2022 年一篇把扩散模型"设计空间"重新拆解整理的论文,那篇论文做的事情很朴素也很狠:把前人各种扩散模型的做法拆成几个独立的设计维度,逐一做消融实验,然后给出一套在当时的基准上表现最好的组合。后来这套组合被移植进 Stable Diffusion 生态,就成了大家看到的 EDM Sampler。
它解决的问题很具体:在同样的步数下,让采样过程更稳、更可预测、更少出现"画面糊掉"或"细节崩掉"的情况。它适合谁?适合已经用过基础采样器、对步数和 CFG 有基本概念、想进一步控制画面质感的用户;也适合想搞明白"采样器之间到底差在哪"的人。如果你只做快速出图、对细节没要求,用默认的 DPM++ 2M 完全够用,不必折腾。但如果你想理解采样器背后的数学结构,或者在做高分辨率、精细纹理、图生图局部重绘时遇到瓶颈,那 EDM 值得认真看一遍。
我在实际使用中的感受是:它不是"万能更强",而是"另一种性格"。用对了场景,细节锐利度和结构稳定性会明显上一个台阶;用错了场景,画面会显得生硬、颗粒感重、甚至颜色发灰。所以下面不只是讲它怎么用,更要讲清楚它为什么这样设计、什么时候该用、什么时候该绕开。
2. 拆开 EDM 的三个核心设计维度
2.1 把"时间步"换成"噪声水平":sigma 参数化的意义
传统 DDPM 那套写法,采样过程是按离散的时间步 t=1000, 999, ..., 1 一步步往前走的,每一步对应一个固定的噪声强度表。这套写法直观,但有个麻烦:时间步是离散的、跟训练时的步数绑死的,你想换步数就得重新插值,插值方式不同结果就差很多。
EDM 的做法是把整个扩散过程用连续变量 sigma 描述,sigma 就是噪声的标准差,样本可以写成 x = x_0 + sigma · n,n 是标准正态噪声。这样一来,训练时的步数和采样时的步数彻底解耦,采样器可以在任意 sigma 区间上自由取点,想取 18 个点就取 18 个点,想取 64 个点就取 64 个点,不需要跟训练配置对齐。
这个改动听起来只是换了个记号,实际影响很大。它让"步数"从训练参数变成了纯粹的计算预算参数。你可以用 20 步,也可以用 40 步,中间不存在"必须跟训练步数匹配"的约束。我做过一个对照:用同一个种子、同一个提示词,分别跑 20、28、36 步,EDM 的收敛曲线比时间步参数化的采样器平滑得多,28 步和 36 步之间的差异已经很小,说明它确实在按噪声水平均匀推进,而不是在某个区间里浪费步数。
在 Stable Diffusion 的实际实现里,sigma 阶梯通常这么算:
sigma_i = (sigma_max^(1/rho) + i/(N-1) · (sigma_min^(1/rho) - sigma_max^(1/rho)))^rho
其中 rho 控制阶梯的疏密分布,取 7 的时候,低噪声区(也就是画面细节定型的阶段)会分配更多步数,高噪声区(构图阶段)步数少一些。这个偏向是刻意的——画面后段的结构细节比前段的整体布局更难收敛,把算力堆在刀刃上。
这里有个容易踩的坑:EDM 论文原设定里 sigma_max 取 80,那是针对像素域图像(取值归一化到 [-1,1])的参数。Stable Diffusion 工作在 VAE 的 latent 空间,latent 的数值分布完全不同,直接把 80 搬过来会把隐变量打到饱和,出来的图一片灰糊。实际实现里会把 sigma_max 映射到模型训练时对应的最大噪声水平,SD 1.5 系列大致在 14 到 15 这个量级。如果你在某个前端里发现 EDM 采样器出图发灰、对比度低,第一反应就该怀疑这个映射有没有做对。
2.2 预条件:让网络始终工作在"舒适区"
预条件(preconditioning)是 EDM 里最容易被忽略、但对结果影响最大的部分。它要解决的是一个很实际的问题:同一个网络,在极高噪声和极低噪声下的输入分布差异巨大,如果直接喂进去,网络在不同噪声水平下的输出量级会剧烈波动。
打个比方,你有一个音响系统,输入信号忽大忽小,小的时候听不清、大的时候爆音。预条件做的事情就是给输入端加一个自动音量归一化,给输出端加一个自动增益补偿,让系统在任意输入电平下都工作在线性区。
具体形式是这样一组系数,它们都是 sigma 的函数:
- c_skip = sigma_data² / (sigma² + sigma_data²)
- c_out = sigma · sigma_data / sqrt(sigma_data² + sigma²)
- c_in = 1 / sqrt(sigma_data² + sigma²)
- c_noise = ln(sigma) / 4
网络实际计算的是 D(x; sigma) = c_skip · x + c_out · F(c_in · x, c_noise)。这里的 F 是去噪网络,sigma_data 是数据本身的尺度估计值,在像素域图像上通常取 0.5。c_skip 那一项是"跳过连接",在噪声极大时让输出接近输入(因为此时网络本来也预测不出什么),噪声极小时让输出接近原始 x。c_noise 则把 sigma 转成网络的条件输入,用对数尺度可以让网络在跨几个数量级的噪声上都有良好分辨率。
这套设计的价值在于:它让网络的训练目标和推理目标在不同噪声水平下保持量级一致,从而可以用同一套权重覆盖从几乎纯噪声到几乎干净图像的全过程。在 EDM 原论文的语境里,这是它能在低步数下仍保持高质量的关键之一。
但对 Stable Diffusion 来说,这里有个必须讲清楚的错位:SD 的模型是用 epsilon 预测(预测噪声)训练的,不是 EDM 的 x_0 预测加预条件训练的。也就是说,Stable Diffusion 里的 EDM 实现是"借用"了 EDM 的调度和求解器,但预条件部分并不能完全对上原始假设。实际代码里会做适配,比如把网络的 epsilon 输出换算成 x_0 估计,再套用求解器。这种"半套用"是很多细节差异的来源——它解释了为什么 EDM 采样器在 SD 上表现不错,但没有论文里那么碾压式领先;也解释了为什么不同前端实现同一个采样器,结果会有肉眼可见的区别。
提示:如果你在不同界面里切换同一个 EDM 采样器发现效果不一样,别急着怀疑自己的参数,先确认两件事——sigma_max 的映射方式,以及 epsilon 到 x_0 的换算是否一致。这两处是不同实现之间最容易产生分歧的地方。
2.3 Heun 二阶求解器:贵一倍,准一截
EDM 配套的求解器里,最有代表性的是 Heun 二阶方法。它的思路是:
- 在当前 sigma 处用网络估计一次导数(去噪方向),用一阶 Euler 走一步,得到一个"试探点";
- 在试探点处再估计一次导数;
- 把两次导数的平均作为最终方向,从原点重新走一步。
这就是经典的预测-校正结构。它的好处是把局部误差从一阶降到二阶,步长可以放得更大;代价是每一步要评估两次网络。
这意味着一个很实际的问题:20 步的 Heun,实际执行的是 39 次网络前向(第一步只需一次评估)。很多人抱怨"EDM 采样器怎么这么慢",根子就在这里。它不是慢在实现,是慢在数学结构上。
我在一张 512×512 的图上做过计时,同样的 20 步设置,Euler 大约 3.4 秒,Heun 大约 6.5 秒,接近两倍,跟理论预期吻合。如果你用的是较老的显卡,这个成本会明显感知到。
所以有个很实用的换算:Heun 的 15 步约等于一阶方法 30 步的质量,但只花 29 次评估。在 15 到 25 步这个区间,Heun 的性价比是最高的。低于 12 步就不建议了——二阶方法需要一定步长密度才能发挥校正作用,步数太少时校正项本身误差也大,反而不如一阶方法干脆。
2.4 四个旋钮:S_churn、S_tmin、S_tmax、S_noise
EDM 采样器的参数面板上通常有四个可调项,很多人直接跳过,其实它们决定了画面的"随机性注入"程度。
- S_churn:控制每一步注入额外噪声的强度。它模拟的是随机微分方程里的噪声项,但在这里被当作可控参数。
- S_tmin / S_tmax:定义注入噪声的 sigma 区间,超出这个区间的步不加噪声。
- S_noise:注入噪声的缩放系数,相当于给噪声再乘一个倍数。
具体的计算逻辑是这样的:设步数为 N,则每步的 churn 系数 gamma = min(S_churn / N, sqrt(2) - 1)。注意后面那个截断值,sqrt(2)-1 约等于 0.414,也就是说无论你把 S_churn 拉多高,单步噪声放大倍数最多到 1.414 倍。然后当前 sigma 被临时放大为 sigma_hat = sigma · (1 + gamma),求解器在 sigma_hat 和下一个 sigma 之间推进。注入的噪声量为 S_noise · sqrt(sigma_hat² - sigma²) · n。
这个设计有个容易误解的点:S_churn 不是线性生效的。因为要除以步数 N,20 步时设 S_churn=20,每步 gamma=1,截断后变成 0.414;40 步时设 S_churn=20,每步 gamma=0.5,实际注入强度更小。所以换个步数就得重新调 churn,否则行为完全变了。
我的经验是:文生图阶段 S_churn 保持 0,让采样过程确定、可复现,构图更稳。想要一点随机性变化,别动 churn,去换种子更直接。图生图阶段可以给 5 到 15 之间,让采样器在原图结构基础上做一点探索,但超过 20 就容易把原图结构带偏。S_noise 一般保持 1.0,除非你在做特殊效果,比如故意要颗粒质的油画感,可以调到 1.2 左右试试。
3. 在 Stable Diffusion 里跑起来:配置与对照实验
3.1 采样器与调度器的组合怎么选
先说一个容易混淆的概念:采样器(sampler)和调度器(scheduler)是两回事。采样器决定"怎么走",调度器决定"在哪里落脚"。EDM 自带了一套 sigma 阶梯的计算方式,所以很多前端把它和调度器绑定在一起,不给你单独选;但也有前端允许你把 EDM 的求解器配上别的 sigma 分布,这时候结果差异就出来了。
判断一个选项是不是"真 EDM",我的方法是看三条:是否用连续的 sigma 而不是离散时间步、是否用了 Heun 或类似的二阶校正、是否带预条件系数。三条都满足才是完整实现;只有前两条的是"简化版",出图会偏硬。
在大多数界面里,完整的 EDM 实现对应的是名字里带 Heun 的那个选项。不同前端命名不统一,有的直接写 EDM,有的叫 Heun,有的叫 heunpp2。名字不重要,看它是不是二阶、是不是 sigma 参数化。
组合建议我整理成一张表:
| 使用场景 | 采样器选择 | 建议步数 | CFG | churn |
|---|---|---|---|---|
| 快速草稿 | 一阶方法(Euler 类) | 12-16 | 6-7 | 0 |
| 常规出图 | EDM / Heun | 18-22 | 6-8 | 0 |
| 细节精修 | EDM / Heun | 24-30 | 5-7 | 0 |
| 图生图轻改 | EDM / Heun | 20-25 | 5-7 | 5-10 |
| 图生图重构 | EDM / Heun | 25-32 | 6-8 | 10-20 |
| 高分辨率修复第二遍 | EDM / Heun | 15-20 | 5-6 | 0-5 |
注意细节精修那行的 CFG:用 EDM 时 CFG 不要往上拉,要往下压。因为二阶求解器本身就在做误差校正,CFG 带来的方向偏移会被放大,容易出现色块过饱和、边缘发亮的问题。我在 7.5 到 8.5 之间试过几组,8.5 以上就开始出现局部过曝。
3.2 参数计算:步数和 sigma 阶梯怎么落到实际
这里给一个可以直接抄的计算流程,帮你在换步数时心里有数。
假设当前设 20 步,S_churn=0,那么 sigma 阶梯从高到低取 20 个点,Heun 执行 39 次前向。想做一次"等效质量"的对比,把步数改成 28,前向次数变成 55,耗时增加约 41%。如果你的机器单张 512 图要 8 秒,那就是 11 秒多,这个成本差异在做批量测试时很明显。
再算 churn 的影响。假设 24 步、S_churn=12,每步 gamma = 12/24 = 0.5,没有触发截断。那么每一步的 sigma 会被临时放大 1.5 倍,注入噪声量约为 sqrt(1.5² - 1) ≈ 1.118 倍的原始 sigma 差值。这个量级不算小,画面上会看到轻微的随机扰动,在纹理区域表现为细节的自然变化,在平整区域(比如纯色背景)可能出现细微颗粒。
注意:churn 的截断值 sqrt(2)-1 是个硬上限,所以即使你设 S_churn=100、N=20,gamma 也只有 0.414,单步放大 1.414 倍。很多人以为把 churn 拉满能得到完全不同的一张图,实际并不会,它只是把噪点密度提高了一点。
3.3 一组可复现的对照实验设计
光讲参数很虚,我给一套自己常用的测试方案,你可以直接照着做。
固定变量:同一个种子、同一段提示词、同一个模型、同一分辨率 512×512、同一个 CFG 7.0、关闭高分辨率修复。只改采样器和步数。
提示词选一个包含明确结构、纹理和光影的:主体 + 材质描述 + 光照描述 + 背景描述 + 质量词,不用堆砌太多,控制在 40 个词以内,避免不同采样器对长提示词的处理差异干扰判断。
然后跑一组网格:
第一组,一阶方法 20 步、25 步,作为基线。 第二组,EDM 15 步、20 步、25 步。 第三组,EDM 20 步 + churn 10。
把六张图拼在一起看三件事:整体构图有没有跑偏、主体边缘的锐度、阴影和过渡区域的噪点密度。
我实际跑下来的结论大致是:EDM 15 步的构图稳定性已经追平一阶 20 步;EDM 20 步的细节明显更实,特别是材质纹理(织物、金属、木纹)的连贯性更好,不容易出现"糊成一片";EDM 25 步相比 20 步提升已经不大,但耗时涨了近三成。所以20 步是 EDM 的甜蜜点。
加 churn 那一组,能明显看到阴影区域的噪点变多,纹理反而更活了,但平整背景(比如纯色墙面)会有一点脏。这就是 churn 的双面性。
3.4 分辨率与 CFG 的联动细节
EDM 采样器在原生分辨率附近表现最好。SD 1.5 系列的原生训练分辨率是 512,在这个尺寸下 sigma 阶梯和网络的条件分布是对齐的。一旦把分辨率拉到 768 以上直接生成,问题就来了:所有采样器都会出现"多头多肢"或结构崩坏,EDM 也不例外,因为它解决的是数值积分精度问题,不是训练分布外推问题。别指望换个采样器就能治这个病。
正确的做法还是老一套:先按原生分辨率生成,再用高分辨率修复放大。这里有个小技巧——第二遍放大时换成 EDM 采样器,步数给 15 到 18,重绘幅度 0.35 到 0.45,效果通常比第一遍用一阶方法、第二遍也一阶更好。原因是放大阶段的主要任务是补细节,二阶方法在小步长下的边缘收敛更准,能少出一些噪点。
CFG 方面,EDM 对 CFG 的容忍度比一阶方法低。我在 SDXL 上测过,CFG 从 6 到 9 扫一遍,EDM 在 7 附近最均衡,8.5 时开始出现高对比度的"塑料感",色块之间过渡变硬。一阶方法同样条件下到 9 还能撑住。所以换 EDM 时,CFG 往下调 0.5 到 1.0 是常态。
4. 实操中遇到的问题与排查思路
4.1 出图发灰、对比度低是怎么回事
这是我遇到最多的问题,第一次用 EDM 时踩得很深。画面整体像蒙了一层雾,暗部提不上去,颜色也淡。
排查顺序是这样:先看 sigma_max 的映射。如果实现里直接把论文的 80 套过来,latents 在第一步就被打散,后续所有步骤都在错误的起点上推进,结果必然发灰。这个在各前端里表现不一,有的版本已经修好,有的旧版本还存在。
再看 churn。如果 S_churn 给了一个比较大的值,同时步数又少,那每步注入的噪声比例会很高,画面整体被推向"高熵"状态,视觉上就是发灰、失去对比。把 churn 归零再跑一次,如果对比度回来了,就是这个问题。
还有一种情况是 CFG 太高。前面说过,EDM 对 CFG 敏感,8.5 以上容易出现局部过曝,但整体可能反而显得平淡,因为过曝区域吃掉了动态范围。把 CFG 降到 6.5 试一次,对比一下。
4.2 细节"碎"、纹理颗粒感过重
这个现象很有辨识度:远看还行,放大一看满屏细碎的颗粒,像老照片的噪点。
根本原因是采样过程中噪声注入过量,或者 sigma 阶梯在后段不够密。前者对应 churn 和 S_noise 设置过高,后者对应步数太少。
处理方式很直接:S_churn 归零,S_noise 保持 1.0,步数提到 20 以上。这三个动作做完,颗粒感基本能压下去。
还有一个隐藏原因:VAE 解码的影响。有的 VAE 本身在细节区域就会产生颗粒,跟采样器无关。判断方法是换成另一个 VAE 跑同一组参数,如果颗粒感跟着变,那问题不在采样器上。
4.3 图生图完全不像原图
图生图场景下,最常见的原因是 churn 给大了。churn 注入的额外噪声会破坏原图的低层结构,重绘幅度再一叠加,原图特征就没了。
我的处理顺序:先把 churn 降到 0 跑一次,确认基础保真度;如果还不够像,把重绘幅度从 0.6 降到 0.45;如果还想保留更多结构,考虑用局部重绘而不是整图重绘。churn 只在"我想在原图基础上做风格化探索"时才加,常规改图不加。
还有一个容易忽略的点:图生图的初始 sigma 是从重绘幅度换算来的,而 EDM 的 sigma 阶梯是从高到低取的,如果起始 sigma 落在 churn 区间之外(比如 S_tmax 设得比起始 sigma 还小),churn 实际不生效,你会以为参数没起作用。检查一下 S_tmax 和起始 sigma 的大小关系。
4.4 常见问题速查表
| 现象 | 高频原因 | 处理手段 |
|---|---|---|
| 出图整体发灰 | sigma_max 映射错误、churn 过大 | 归零 churn,检查实现版本 |
| 纹理颗粒感重 | S_noise > 1、步数不足 | S_noise=1.0,步数提到 20+ |
| 局部色块过曝 | CFG 过高 | CFG 下调 0.5-1.0 |
| 步数增加但没提升 | 已收敛,阶梯密度足够 | 停在 20-24 步,别浪费算力 |
| 30 步反而比 20 步差 | churn 累积噪声 | churn 归零后重测 |
| 图生图不像原图 | churn 过大、重绘幅度高 | churn=0,重绘幅度降到 0.45 |
| 出图速度慢一倍 | 二阶求解器双倍评估 | 属正常,用 15-20 步平衡 |
| 高分辨率生成崩坏 | 超出训练分布 | 原生分辨率生成后再放大 |
提示:排查时每次只改一个变量。采样器类问题的变量太多,同时改三个参数,你永远不知道是哪个起了作用。我的习惯是准备一个固定的测试配方,改一处跑一次,做完记录。
4.5 几个不那么明显的坑
第一个坑是步数取奇偶数时的差异。Heun 的第一步只评估一次,后续每步评估两次,所以总评估数是 2N-1。当 N 取奇数时,最后一步的校正可能落在一个比较尴尬的位置,个别实现会因此产生轻微差异。这个影响很小,但如果你在做严格的 A/B 对比,最好把步数固定在偶数上,减少变量。
第二个坑是切换采样器后种子不通用。同一串种子在不同采样器下出来的是完全不同的图,这不算 bug,但很多人做对比时忘了这一点,以为是采样器出问题了。做对比实验必须固定种子,但也要明白同一张图在不同采样器下本来就该不同。
第三个坑是某些前端把 EDM 和一阶方法混在一个下拉框里,名字看着像但实际不是。判断方法还是那三条:sigma 参数化、二阶校正、预条件。如果拿不准,就看耗时,双倍耗时的多半是完整实现。
5. 和其他采样器的横向对比与选型思路
5.1 一张表看清差异
| 采样器类型 | 每步网络评估 | 20 步实际评估 | 低步数表现 | 细节锐度 | 随机性控制 |
|---|---|---|---|---|---|
| Euler 类一阶 | 1 次 | 20 次 | 及格 | 中等 | 弱 |
| Heun 类二阶 | 2 次(首步 1 次) | 39 次 | 良好 | 较高 | 强(可调 churn) |
| DPM 多步类 | 1 次 | 20 次 | 良好 | 高 | 中 |
| 带 SDE 的变体 | 1-2 次 | 20-39 次 | 优秀 | 高 | 强 |
看这张表能得出一个很实用的结论:如果你的算力充裕、想要可预测的收敛行为,选 EDM;如果算力紧张、追求速度,一阶或多步方法更划算。EDM 的优势不在"绝对画质更高",而在于"同样的画质下步数更少、行为更可控"。
我在一张 1024×1024 的图上做过粗略对比,一阶方法要 30 步才达到的细节完整度,EDM 大约 18 到 20 步就能达到,但总耗时还是 EDM 略高一点(因为双倍评估)。所以严格说,EDM 省的是步数,不是时间。这个认知很重要,能避免很多不切实际的期待。
5.2 什么时候该用它,什么时候别碰
适合用的场景,我总结成三类:
第一类是材质和纹理要求高的图。织物、金属、木纹、石材这几种材质,EDM 的连贯性明显更好,因为它在小 sigma 区间的步长分配更密,细节定型阶段收敛更充分。我做过一组金属表面的对比,一阶方法在 20 步时高光边缘会糊,EDM 同样 20 步边缘是清楚的。
第二类是需要严格复现的批量生产。因为 churn 可以归零、sigma 阶梯是确定的、步数和结果的关系平滑,做批量任务时不容易出现"这批图某几张莫名其妙崩掉"的情况。
第三类是图生图的中等幅度改造。配合较小的 churn,能在保留原图结构的同时做出风格变化,比一阶方法更少出现"结构被撕碎"的现象。
不适合的场景也说三个:
一是低步数快速草稿。10 步以下的 EDM 没有意义,二阶校正来不及发挥作用,还不如一阶方法干脆。
二是追求极致随机变化的场景。EDM 的确定性是优点也是限制,想要那种每步都带随机分支的"探索感",带 SDE 的变体更合适。
三是显卡性能吃紧时的批量任务。双倍评估在批量场景下成本累积很明显,这时候用多步一阶方法更实际。
5.3 一个实用的组合工作流
我现在的常规流程是这样,分享出来供参考。
第一步,用一阶方法 14 步、CFG 6.5 快速出一组 4 张草图,只判断构图和主体位置,不看细节。这个阶段耗时短,方便快速迭代提示词。
第二步,选中构图满意的图,种子记下来,换成 EDM 采样器,20 步、CFG 7.0、churn 0,重新生成。这一步的耗时大约是草图的两倍,但因为只跑一张,完全可以接受。
第三步,如果要做高分辨率,放大时继续用 EDM,步数 16、CFG 6.0、重绘幅度 0.4,让二阶方法去补细节。
这套流程的好处是在试错成本最低的环节快速迭代,在质量最关键的环节用最稳的方法。直接用 EDM 做草图会浪费时间,直接用一阶方法做最终出图细节又不够。
还有一个小技巧:如果你发现 EDM 出图整体偏"硬"、少了一点自然感,可以试着把 CFG 往下压一点点,同时把提示词里的风格描述词加强,用提示词去补风格,而不是靠拉高 CFG 硬顶。这个调整方向我踩过几次坑才摸出来,CFG 往上走总是先出问题。
最后说个我自己的体会:采样器这类东西,看得再多不如自己跑一组对照。不同模型、不同分辨率、不同显卡,最优参数都会有偏移,网上的参数表只能当起点,不能当答案。我上面这些数字都是在自己常用的配置下调出来的,你拿去用的时候,把它当成"初始猜测",然后用 3.3 节那套对照方法自己验一遍,通常一两轮就能校准到适合你的位置。真正值钱的不是某个具体数字,而是那套"一次只改一个变量、固定种子、固定提示词"的测试习惯。