Consistency is All You Need


最近一周内,Consistency 突然成了文生图领域的热点词: Latent Consistency ModelLatent Consistency Model LoRA (LCM-LoRA)Consistency Decoder 接连出现。

我先画了一个简单的示意图说明这些新东西和之前算法之间的关系:

  • Stable Diffusion 是在预训练 VAE 空间训练 Diffusion Model 的结果。
  • Consistency Decoder 是用 Consistency Model 技术训练的一个 VAE Decoder,能更好地解码 VAE Latent 为 RGB 图片。
  • Stable Diffusion 经过改进后的 Consistency 蒸馏技术蒸馏后得到 Latent Consistency Model。
  • 既然 LCM 是对 SD 的一个 finetune 过程,那么就可以结合 LoRA finetune 技术,不再微调整个 SD 模型,而是微调其一个 LoRA。这样就得到了 LCM-LoRA。
  • LCM-LoRA 的作者发现,LCM-LoRA 可以和其它 Stable Diffusion 的风格微调模型组合,依然起效,可以实现免训练的加速各种 SD 微调模型。这些 SD 模型,有了 LCM-LoRA 之后,什么都不用做生成却快了十倍

在心里大概明确 SD、CM、LCM、LCM-LoRA 之间关系后,下面听我来依次讲一下我对这些带“Consistency”的新算法的理解。

Consistency Model

PF-ODE|500

Consistency Model 在 Diffusion Model 的基础上,新增了一个约束:从某个样本到某个噪声的加噪轨迹上的每一个点,都可以经过一个函数 \(f\) 映射为这条轨迹的起点。 显然,同一条轨迹上的点经过 \(f\) 映射结果都是同一个点。这也是训练 Consistency Model 时所使用的损失约束。

当微调 Diffusion Model 使其满足 Consistency 约束之后,其采样生成的过程就非常自然。从噪声中采样一个点,送入 \(f\) 中,就得到了其对应的数据样本。这就是 Consistency Model 的单步生成模式。与此同时,Consistency Model 也可以通过多步生成来实现牺牲速度提升生成质量的权衡。Consistency Model 的多步生成过程大略如下图所示:

sampling|500
CM 的采样生成过程
从一个噪声生成一个样本,然后给这个预测的样本按照 Diffusion 前向的规则加噪,到达某个中间状态 \(x_{t1}\),然后从 \(x_{t1}\) 再预测一个样本;接着再加噪,再预测… 这样循环就可以实现 Consistency Model 的多步采样生成。

形式化地讲,我们常用的 Diffusion 模型实际上是训练了一个网络 \(\textbf{s}_{\phi}(x, t)\) 拟合 \(\nabla{log(p_t(x))}\),然后 Diffusion 的采样过程可以理解为给定 \(x_{T} \sim \textbf{N}(\textbf{0}, \textbf{I})\),有

\[ \frac{\mathrm{d}x_t}{\mathrm{d}t} = -t\textbf{s}_{\phi}(x_t,t) \]

给定起始点,给定每个点的梯度后,通过迭代计算得到 \(x_{\epsilon}\),其中 \({\epsilon}\) 是一个小正数(比如 EDM 中使用的 0.002)。用 \(x_{\epsilon}\) 当作采样得到的样本。这里引入 \({\epsilon}\) 是为了避免在 \(t=0\) 处易出现的数值不稳定。

Consistency 在 Diffusion 的基础上,继续定义一个一致性函数 \(f: (x_t, t) \rightarrow x_{\epsilon}\)。一致性函数具有两个最关键的特性:

  1. \(f( x_{\epsilon}, \epsilon) = x_{\epsilon}\)
  2. 任意 \(t_1,t_2\in [\epsilon, T]\) 满足 \(f(x_{t_1}, t_1) = f(x_{t_2}, t_2)\)。

trajectory|600

Consistency Model 的目标是找到一个 \(f_{\theta}\),能满足上面这两个条件,来拟合 \(f\)。在得到了一个合理的 \(f\) 的近似 \(f_{\theta}\) 后,就可以调用下面的采样算法从噪声生成样本了:

sampling|400

参考 EDM,Consistency Model 干脆设计 \(f_{\theta}(x,t)=c_{skip}(t)x+c_{out}(t)F_{\theta}(x, t)\),其中 \(c_{skip}(t)\) 和 \(c_{out}(t)\) 被定义为

\[ c_{skip}(t)=\frac{\sigma^2_{data}}{(t-\epsilon)^2+\sigma^2_{data}},c_{out}(t)=\frac{\sigma_{data}(t-\epsilon)}{\sqrt{t^2+\sigma^2_{data}}} \]

显然,当 \(t=\epsilon\) 时,这个设计下的 \(f_{\theta}\) 一定能满足一致性函数的第一条性质。

那么第二个性质怎么去拟合呢?难道是随机从轨迹中采样两个点,送入 \(f_\theta\) 约束其相同吗?

在我们已经有一个训练收敛的 Diffusion Model 时,可以通过最小化下面这个损失来去拟合第二个性质:

lcd|600

即从样本集中采样一个样本,加噪变为 \(x_{t_{n+1}}\),然后利用预训练的 Diffusion 模型去一次噪,预测到另外一个点 \(\hat{x}_{t_n}^{\phi}\)。然后计算这两个点送入 \(f_{\theta}\) 后的结果,用特定损失函数约束其一致。

这里的预测过程形式化地写就是,已知 \(\textbf{s}_{\phi}(x, t)\) 和 \(\frac{\mathrm{d}x_t}{\mathrm{d}t} = -t\textbf{s}_{\phi}(x_t,t)\),用 ODE Solver \(\Phi\) 去解这个 ODE:

\[ \hat{x}_{t_n}^\Phi = x_{t_{n+1}} + (t_n - t_{n+1})\Phi(x_{t_{n+1}}, t_{n+1};\Phi) \]

比如常用的 Euler solver 就是 \(\Phi(x,t;\phi)=-t\textbf{s}_{\theta}(x,t)\) 。DDIM、DPM++我们常听的词都是 ODE Sovler 的一种。

Consistency Model 论文附录证明了,当最小化 \(\mathcal{L}_{CD}^N\) 为 0 时,\(f_\theta\) 和 \(f\) 的误差上确界足够小。所以,通过最小化 \(\mathcal{L}_{CD}^N\) 就能让 \(f_\theta\) 和 \(f\) 足够接近。

theorem|600

这里再补充几个关键细节:

  1. \(f_{\theta}(x,t)=c_{skip}(t)x+c_{out}(t)F_{\theta}(x, t)\) 中的 \(F_\theta\) 就是给定 \(x_t\),\(t\) 去预测一个 \(\hat{x}_0\)。之前各种不同的 Diffusion 模型预测结果都可以转变为预测 \(x_0\)。由于 \(c_{skip}\) 很快收敛于 0,\(f_{\theta}\) 其实基本由 \(F_\theta\)(即 Diffusion 模型预测的 \(\hat{x}_0\)) 决定。
  2. 计算 \(\hat{x}_{t_n}^{\phi}\) 对应的轨迹起点时用的网络的参数是 \(\theta\) 的滑动平均(EMA)。作者认为这样可以稳定训练过程,提升最终训练效果。
  3. 判定两个点的 \(f_{\theta}\) 预测结果是否一致时使用的损失函数可以是 MSE、LPIPS 等等损失,实际上,针对自然图片的损失 LPIPS 在 Consistency Model 的训练过程中取得了最好的结果!

应该怎么理解这一训练过程呢?在研究数学上的证明之外,我提供一个可能不是那么严谨的直觉理解,如果有问题,欢迎指出。

如上图所示,给定某个样本 \(x_0\),经过 Diffusion 前向加噪过程得到 \(x_{t_{n+1}}\),Diffusion Loss 是约束根据 \(x_{t_{n+1}}\) 送入网络后的输出计算得到的 \(\hat{x}_0\) 与真正的 \(x_0\) 一致。Consistency Model 则要求根据这个预测得到的 \(\hat{x}_0\) 和 \(x_{t_{n+1}}\),执行一次 Diffusion 去噪过程得到 \(\hat{x}_{t_n}\),然后继续预测 \(\hat{x}_0\),要求这两个预测 \(\hat{x}_0\) 一致。显然 Consistency Loss 是对 Diffusion Loss 的一个加强(或者可以说,更高一阶?):基于预测值再预测一个结果,要求第一次预测值与第二次预测值之间差异足够小。

我数学不太好,但感觉这种最小化两次累积预测误差的思路似乎和解 ODE 的数值计算方法(或者优化算法)里面的什么 “多走一步,计算累积误差” 之类的思路异曲同工之妙。不知道有没有人能替我懂我在说什么…

这里有个小疑问,如果 Diffusion Loss 能接近 0,那么 Consistency Loss 也能接近 0;反过来还成立吗?

当然,上面的理解是有偏差的,比如要用 \(c_{skip},c_{out},x\) 组合计算才能得到 \(f_{\theta}\)。但是我把 diffusers 中 LCM 和 CM 中的 get_scalings_for_boundary_condition 函数实现结果可视化了一下:

c_skip|500
可以发现 \(c_{skip}\) 很快收敛为接近 \(0\)(LCM 甚至直接令 \(\epsilon=0\) 了),所以我刚刚的直觉理解中直接把 \(f_\theta\) 视作预测 \(x_0\) 的函数大体上还是没问题的。

分析完从预训练 Diffusion Model 构建 Consistency Model 过程,我产生了几个疑问,不知道未来能不能回答:

  1. 用 Consistency Loss 去优化的同时,再增加 Diffusion Loss 会有什么帮助吗?毕竟 Consistency Loss 建立在得分估计网络足够准之上,只用 Consistency Loss 会降低其准确性吗?增加 Diffusion Loss 帮助维持得分估计网络的准确性有用吗?
  2. 从理论上理解,CM 的训练过程中每一步都在预测 \(x_0\),作者也指出可以用 LPIPS Loss 这样的专门针对 RGB 图片的,没有对带噪声结果特殊优化过的 Feature Match Loss 来优化 CM,那么是不是意味着可以把 GAN 领域之前常用的什么 VGG Loss 之类的一整个 loss 调参生态再加回来了?比如增加什么 ArcFace Loss 来约束生成人脸一致,做保人脸 ID 特征的下游应用…

Latent Consistency Model

Latent Consistency Model(LCM)是在 Stable Diffusion 的基础上新增 Consistency 约束蒸馏的结果。LCM 是 CM 在文生图领域的一个应用,它以 Consistency Model 作为理论基础,在 Consistency 蒸馏的过程中引入了 Classifier Free Guidance(CFG)增广,也设计了 skipping-step 这样的策略来加速蒸馏收敛。

在理解 Consistency Model 后,再看 LCM 的训练过程就没有那么难懂了,我们直接看 LCM 具体的蒸馏过程:

蓝色部分是 LCD 相对于 CD 新增的部分。LCD 多了一个 VAE 编码过程 \(E(\cdot)\)、多了一个 CFG 常用的 Guidance Scale 的范围 \([w_{min},w_{max}]\)、多了一个表示 Diffusion 去噪过程跳步大小的参数 \(k\)。

下面详细描述下 Latent Consistency Distillation 的蒸馏过程,我会着重强调与 Consistency Model 中描述蒸馏算法的不同:

  1. 采样当前一次训练所需要的数据: 从数据集中采样的样本变为了 \((z, c)\),即图片 latent 与图片 caption。SD 加噪过程共有 \(N=1000\) 步,从 \(1\) 到 \(N-k\) 中采样当前训练所针对的 timestep \(n\),即当前一个 sample \((z, c)\) 选择了 \(z_{n+k}\)、\(\hat{z}_{n}\) 这两个点去计算 Consistency 约束 loss。最后从 \([w_{min},w_{max}]\) 中选择一个 \(w\) 作为后续预测 \(\hat{z}_n\) 时使用的 Guidance Scale
  2. 加噪: 用标准的 Diffusion 加噪算法计算 \(z_{n+k}\),计算了加噪轨迹上的一个点
  3. 执行一次熟悉的 Diffusion 去噪过程: 以前 Stable Diffusion 不是在一个循环里重复去噪过程嘛?当前这步就是重复一次之前的去噪过程,可以用 DDIM、DPM Sovler++之类熟悉的 Diffusion Scheduler 完成这一步。在这一步的预测中,融合了 CFG 的 Guidance Scale,即在 Consistency Distillation 的蒸馏算法后多增加一项 \(w\) 倍的 Positive Prompt 减 Negative Prompt 这样熟悉的东西。另外,为了加速训练收敛,LCM 的作者也提出在这一步没必要只做一步 \(z_{n+1} \rightarrow z_{n}\) 这样的预测,而是可以用 DDIM 之类的算法,直接完成 \(z_{n+k} \rightarrow z_{n}\) 的预测。
  4. 计算一致性蒸馏损失:上一步得到了一个加噪轨迹上的点,以及其用 Diffusion 去噪算法预测得到的另外一个点。这一步就是分别用当前网络权重以及网络权重的 EMA 计算两个点对应的一致性函数输出,然后用一个损失函数约束输出一致。
  5. 更新网络权重
  6. 计算网络 EMA

LCM 的实验分析了一下第三步去噪算法中不同组件的选择对收敛的影响:

比如,在 \(k\) 足够合理时,只需要 2000 步迭代,LCM 4 步采样的 FID 就已经基本收敛了。观察 DDIM 那个子图,可以发现当 \(k=1\) 即没有 skipping-step 技巧时,收敛很慢;但是当 \(k=50\) 时,FID 也一直很高,说明一下子跳过太多步时,DDIM 解 ODE 的误差太大了。但是 \(k=50\) 时,DPM 和 DPM++收敛还是正常的。这个实验的结果和我们之前的积累的经验是吻合的:\(k=50\) 对应于之前 Stable Diffusion 推理时迭代 20 次,此时 DPM++和 DPM 的表现确实比 DDIM 强。

对于 Guidance Scale 的选择,LCM 作者用不同 LCM 的迭代次数与不同 Guidance Scale 做了对比。发现 \(w\) 增加有助于提升 CLIP Score,但是损失了 FID 指标(即多样性)的表现。另外,LCM 迭代次数为 2、4、8 时,CLIP Score 和 FID 相差都不大,说明了 LCM 的蒸馏性能确实非常强悍,两步前向的效果可能都足够好了,只是一步前向的结果还差些。

LCM 论文中附带的 2 步和 1 步的生成结果确实足够惊艳:
和其它 Diffusion 加速算法的对比结果也说明了 LCM 的强势:

LCM-LoRA

LCM 论文出来后,社区的关注度其实也没有那么高。但后面 LCM 作者开源了代码,很多人开始在 twitter 上惊呼这是第一篇开源了代码和模型的 Diffusion 蒸馏文章,还用了 OpenAI 的 Diffusion 祖师爷的新生成模型 Consistency Model 的思路。社区对 LCM 的关注度一下子就上去了。

但 LCM 也有问题呀,LCM 需要微调整个 SD 模型,社区里那一堆 SD finetune 模型难道每个都得再优化一下吗?这时 LCM 的作者和 Huggingface Diffusers 的作者就合作搞了 LCM-LoRA 出来。

既然 LCM 也只是一个对 SD 的一个微调过程,只是换了一个 Loss 嘛,那自然可以借助 LoRA 的力量,给 SD 外挂一个 LoRA 组件,只用 LCM 的蒸馏损失优化 LoRA 挂件的权重。这样就得到了 LCM-LoRA。

如下图,LCM-LoRA 作者发现,LCM-LoRA 可以和现在社区里的各种 LoRA 模型组合,共同作用,得到既能加速,又有风格的自定义 LCM 模型。

LCM-LoRA 为啥能随便和之前各种提供 Style 的 SD LoRA 直接加权使用呢?

  • 从模型角度出发,LoRA 本身就是把 finetune 增量矩阵限制成了低秩矩阵,两个低秩权重增量矩阵做加权冲突的程度没那么大,这是 LoRA 本身的优良性质。
  • 从数据分布角度讲,微调过程中 Diffusion 前向的数据分布没有改变,顶多是子集的差异,LCM-LoRA 训练过程中依然用到了 Diffusion 去噪,保证模型输出也不会偏移原分布太多,从 \(z_{n+k}\) 预测的 \(\hat{z}_n\) 依然接近真实 \(z_n\) 的分布。
  • 从我这种实验算法工程师的角度讲,LCM-LoRA 就训练了那么几 M 样本,网络模型又那么多冗余权重,没有那么脆弱,还没遗忘之前的东西罢了。另外可能只是结果没那么差罢了,在 Style LoRA 的训练数据集上再微调下 Style LoRA 和 LCM-LoRA 肯定能有更好的效果。

我自己也测试了一下 LCM-LoRA 的效果在我们内部的保人脸 ID 项目上的效果,直接让一张图从 2.8s 生成变成了 0.4s 生成,结果还很惊艳:

左边是微调 SD+Adapter 的效果,右边是微调 SD+Adapter+LCM-LoRA
值得关注的一点细节是,由于在 LCM-LoRA 训练过程中已经把 Guidance Scale 集成了进去,使用 LCM-LoRA 时一般是不需要再做 CFG 的。但是如果 Negative Prompt 对结果非常重要,那么也可以指定 Guidance Scale 为 1.5 这样的小值试试。还用 7.5 肯定是不行的,我替你淌过坑了。

另外,由于 LCM-LoRA 训练不太耗资源,如果对 LCM-LoRA 训练时 Guidance Scale \(w\) 的取值范围不太满意,或者想直接把 Negative Prompt 蒸馏进 LoRA,那都推荐改下 diffusers 开源的脚本自己微调一下 LCM-LoRA。

Consistency Decoder

Consistency Decoder 是 OpenAI 训练的一个以 Stable Diffusion 中所使用的 VAE 的 Latent 作为 condition 的 Consistency Model。什么训练细节 OpenAI 全部没说,甚至模型定义都是隐藏在权重文件中,由社区重定义的。这个模型在 OpenAI 的 DALLE3 介绍论文中提到过,我之前写过那篇论文的解读: Improving Image Generation with Better Captions - wrong.wang,其中也提到了它。

Consistency Decoder 是可以和 LCM-LoRA 结合使用的,只是提供了一个 latent 解码为 RGB 的新选择。我同事测试了一下 Consistency Decoder 的效果,推理慢了很多,效果提升没有想象的那么明显。

总结

LCM-LoRA 真正做到了什么都不用做,即插即用,就能让开源社区里基于 SD 的生态的模型取得几倍的速度加成。从 CM、LCM 到 LCM-LoRA 这一系列改进让我看到了什么叫做集思广益,文生图领域一日千里。正如本篇文章头图里的红色区域,当 LCM-LoRA 和 Stable Diffusion 生态相遇,会在应用端产生怎样的化学反应呢?让我们拭目以待!

这一系列 Consistency Model 背后涉及到很多理论推导,我数学不行,如果您发现我上面的叙述中有哪些不对,请评论说明,互相交流学习。

当然,写作不易,还是请大家多多表扬我!哈哈。