什么是 Stable diffusion


Stable diffusion 是一中潜在扩散模型(latent diffusion model),这里面除了模型这两个字,潜在和扩散听上去就不太像人话了,这里我们先弄明白什么是扩散模型,它是在训练图像上逐渐添加噪声,最后变成完全随机噪声图。这个过程就像是一滴墨水滴在一杯清水里,会慢慢扩散最终均匀分布在清水里一样,扩散这个名字就是那么来的,参考下图

这是一个前向扩散的过程,因为让一张图片越来越模糊没什么技术含量。

而扩散模型就是通过训练让上述过程获得逆向从随机噪声图生成清晰图像的过程。实现下图的过程,而训练的重点就是下图中的噪声预测器(noise predictor),它可以通过训练得出每次需要减掉的噪声,每次需要减多少噪声是预测出来的,这就是一个叫 U-net 的模型(先请记住它,下面还会反复提它),从而实现还原清晰图片的目的。

但是,这个过程无论是模型训练,还是推理(你生成图片的过程)都是非常贵的,需要海量的算力支持和内存需求,而 stable diffusion 就是让它不那么贵的解决方案,核心思想也很简单:压缩图像,它通过一个叫变分自编码器(VAE)的模型,把图像压缩到它亲妈都不认识到的程度,甚至把此类压缩方式称作降维,这种降维级别的压缩且不丢失重要信息与一套理论相关,即流形假说(Manifold hypothesis),认为高维空间的数据集可以对应到低维的潜在流形(latent manifolds )上,训练需要找到就是一些共同的高维特征。所以经过此压缩后,这个时候图像被称作低维潜在(latent)的 "图像",作为 U-net 的输入,去了潜空间(latent space),请参考下图标注 latent space 的绿色区域,也就是 U-net 现在工作的地方。在低维的潜空间里一步一步降噪后,完成反向扩散的低维 “图片” 还得通过 VAE 的解码器,把图像从潜空间转换回像素空间(pixel space)。

但是这张图片中好像除了刚刚提到潜空间和像素空间,其余的内容是什么鬼我们目前还不知道,目前的重点是压缩,因为这是让反向扩散推理以生成图片的基石,它让 Stable Diffusion 在消费级 GPU 上运行成为了可能。下面聊 Stable diffusion 的具体工作流程。图片来源 [[1]](https://zhuanlan.zhihu.com/p/612572004#ref_1)

三大核心组成部分

VAE:包括 Encoder 编码器和 Decoder 解码器,用于图像从像素空间到潜空间的转换,或者叫降维或升维,由于用于降维的 VAE Encoder 只在训练模型的阶段使用,推理过程(图像生成)只需要 VAE Decoder 解码器就 ok 了,而网上常见的 VAE 文件,就是对这个 VAE Decoder 解码器的微调改进版本,用于解决角色面部眼睛等细节方面的问题。

U-net:输出预测的噪声残差,用于每次迭代过程的降噪,提供了交叉注意力层,并且通过交叉注意力机制来消耗 CLIP 提供的条件文本嵌入 U-net,输出预测的噪声残差,实现有条件(被文本指挥)的迭代降噪。

CLIP:将 Prompt 文本转化成能够让 U-net 使用的嵌入(embedding),达到实现文本作为条件生成图片的过程,这里反复提到嵌入这个概念是因为,可以通过微调的方式,发出带有关键词的 embedding,用于调整图片的样式。你能下载到的 textual inversion 就是通过这种方式实现调整生成图像效果的,优点是文件的体积非常小。

整体工作流程

见下图 [[2]](https://zhuanlan.zhihu.com/p/612572004#ref_2)

SD 在潜空间生成随机的张量,你也可以设置种子(seed)来控制这个初始值,特定的初始值可以起到固定的作用。然后这个在潜在种子生成 64 x 64 的潜空间图像,Prompt 通过 CLIP 转化 77 x 768 条件文本嵌入(embedding);

U-net 以这个嵌入为条件,对潜空间图像迭代降噪。U-net 输出噪声的残差,通过调度器(scheduler)进行降噪计算并返回本轮的去噪样本,(而这个调度器也叫采样器或者求解器,对应了不同的算法,有各种优缺点);

在迭代 50 次后(取决于你选择的采样方法,有些 20 次迭代就可以达到高质量的结果),最后 VAE 的解码器把最终的潜空间图像转化输入到像素空间,即我们能看到的像素图片,整个工作流到此结束,你得到了结果图片。

这就 stable diffusion 的文生图大致工作原理。

采样方法(SD-Webui)

Stable diffusion webui 是 Stable diffusion 的 GUI 是将 stable diffusion 实现可视化的图像用户操作界面,它本身还集成了很多其它有用的扩展脚本。

webui 中集成了很多不同的采样方法,(上述提到的调度算法)这块也是目前 AI 艺术家们乐忠对比的环节,这里结合设置中提供的选项,简单粗略的介绍下它们的各自区别。

这些大部分的采样器是由 Katherine Crowson 根据论文实现的功能,stable diffusion 官方的 blog 也提到过她,她在 github 中有一个名为 K-diffusion 的项目[[3]](https://zhuanlan.zhihu.com/p/612572004#ref_3),理论基础主要基于 Jiaming Song 等人的论文 [[4]](https://zhuanlan.zhihu.com/p/612572004#ref_4)Karras 等人的论文[[5]](https://zhuanlan.zhihu.com/p/612572004#ref_5) 以及前不久基于 Cheng Lu 等人的论文[[6]](https://zhuanlan.zhihu.com/p/612572004#ref_6)

按照 SD webui 的顺序

Euler

基于 Karras 论文,在 K-diffusion 实现,20-30steps 就能生成效果不错的图片,采样器设置页面中的 sigma noise,sigma tmin 和 sigma churn 这三个属性会影响到它(后面会提这三个参数的作用);

Euler a

使用了祖先采样(Ancestral sampling)的 Euler 方法,受采样器设置中的 eta 参数影响(后面详细介绍 eta);

LMS

线性多步调度器(Linear multistep scheduler)源于 K-diffusion 的项目实现;

heun

基于 Karras 论文,在 K-diffusion 实现,受采样器设置页面中的 sigma 参数影响;

DPM2

这个是 Katherine Crowson 在 K-diffusion 项目中自创的,灵感来源 Karras 论文中的 DPM-Solver-2 和算法 2,受采样器设置页面中的 sigma 参数影响;

DPM2 a

使用了祖先采样(Ancestral sampling)的 DPM2 方法,受采样器设置中的 ETA 参数影响;

DPM++ 2S a

基于 Cheng Lu 等人的论文(改进后,后面又发表了一篇),在 K-diffusion 实现的 2 阶单步并使用了祖先采样(Ancestral sampling)的方法,受采样器设置中的 eta 参数影响;Cheng Lu 的 github 中也提供已经实现的代码,并且可以自定义,1、2、3 阶,和单步多步的选择,webui 使用的是 K-diffusion 中已经固定好的版本。对细节感兴趣的小伙伴可以参考 Cheng Lu 的 github 和原论文。

DPM++ 2M

基于 Cheng Lu 等人的论文(改进后的版本),在 K-diffusion 实现的 2 阶多步采样方法,在 Hagging face 中 Diffusers 中被称作已知最强调度器,在速度和质量的平衡最好。这个代表 M 的多步比上面的 S 单步在采样时会参考更多步,而非当前步,所以能提供更好的质量。但也更复杂。

DPM++ SDE

基于 Cheng Lu 等人的论文的,DPM++ 的 SDE 版本,即随机微分方程(stochastic differential equations),而 DPM++ 原本是 ODE 的求解器即常微分方程(ordinary differential equations),在 K-diffusion 实现的版本,代码中调用了祖先采样(Ancestral sampling)方法,所以受采样器设置中的 ETA 参数影响;

DPM fast

基于 Cheng Lu 等人的论文,在 K-diffusion 实现的固定步长采样方法,用于 steps 小于 20 的情况,受采样器设置中的 ETA 参数影响;

DPM adaptive

基于 Cheng Lu 等人的论文,在 K-diffusion 实现的自适应步长采样方法,DPM-Solver-12 和 23,受采样器设置中的 ETA 参数影响;

Karras 后缀

LMS Karras 基于 Karras 论文,运用了相关 Karras 的 noise schedule 的方法,可以算作是 LMS 使用 Karras noise schedule 的版本;

DPM2 Karras,DPM2 a Karras,DPM++ 2S a Karras,DPM++ 2M Karras,DPM++ SDE Karras 这些含有 Karras 名字的采样方法和上面 LMS Karras 意思相同,都是相当于使用 Karras noise schedule 的版本;

DDIM

“官方采样器” 随 latent diffusion 的最初 repository 一起出现, 基于 Jiaming Song 等人的论文,也是目前最容易被当作对比对象的采样方法,它在采样器设置界面有自己的 ETA;

PLMS

同样是元老,随 latent diffusion 的最初 repository 一起出现;

UniPC

最新被添加到 webui 中的采样器,基于 Wenliang Zhao 等人的论文 [[7]](https://zhuanlan.zhihu.com/p/612572004#ref_7),应该是目前最快最新的采样方法,10 步就可以生成高质量结果;在采样器设置界面可以自定义的参数目前也比较多,因为只针对它,所以直接展开聊一下怎么设置,先参考下图

UniPC variant

bh1 和 bh2 和 vary_coeff 是三种变体

hugging face 的团队在 diffuser 中给出了他们的建议:bh1 适合在无条件(没指挥,无引导)且步数小于 10 情况下使用,其余情况全部使用 bh2。

至于 vary_coeff 这个,作者在论文中实验对比了在 “无条件” 的和 bh1 和 bh2 的区别,即 bh1 在 5,6 步表现最好,vary_coeff 在 7,8 或 9 表现最好,10 步以上还是 bh2。

由于我们在 webui 的使用场景使用提示词就是 “有条件” 了,所以看上去 bh2 更合适,除非你热衷于 10 步以内生成图片,但 webui 的 github 上有人反应 vary_coeff 生成的图片背景细节更加丰富 [[8]](https://zhuanlan.zhihu.com/p/612572004#ref_8)。我个人使用下来看,区别不算大,可以自己对比。

一句话总结:懒得对比的话就默认 bh2

UniPC skip type

如果你生成的图片是 512 x 512 或者更大的话,选 uniform。它更适合高分辨率图(512 目前相对算高分别率)logSNR 适合低分别率

下图为 logSNR(注意看某些步数的图片异常情况)

logSNR 在 512 x 512 下会出现一些奇怪的细节(模型 SD1.5),quadratic 稍微好一些(就不放图片了)

下图是 uniform,请注意和上面相比细节的合理度。

结论:512 x 512 细节更合理, 推荐 uniform

这个 order 最后两项都有提,作者在原论文也有对比,diffuser 也有推荐:有条件(有引导)用 2 阶,无条件(无引导)用 3 阶,并且在在推理步数小于 15 时,打开 lower order final,即在最后 step 使用低阶采样。

请看下图,在不开 lower order final 的情况下

上面在 UniPC skip type 的对比环节都是开 lower order final 的情况下生成的。

结论:开 lower order final,别犹豫,order 我个人推荐 2 阶。

eta 参数

综合所有采样器,上面提到了 eta

eta (noise multiplier) for DDIM 只作用 DDIM,不为零时,DDIM 在推理时图像会一直改变,生成的图像不会最终收敛;

eta (noise multiplier) for ancestral samplers 作用于名字后缀带 a 和 SDE 的所有采样器,不为零时,生成的图像也不会收敛;

Eta noise seed delta 也是 seed 值,在 eta 不为零时起到固定初始值,这样你就可以使用相同值还原某些其它人使用了对应 eta 值的图片。

请看下图(汇集了所有受 eta 参数影响的采样方法),在所有 eta 设定为 1 时的结果,盔甲的细节结构即使在高步数时也会改变

eta 为 0,除了 Euler a 和 DDIM 还会有少量的变化外,其余带 a 的采样方法,带 SDE 的,以及 DPM fast 和 DPM adaptive 都会收敛稳定(上面的两张图片,除 eta 值,其余设置完全一样。)

再看下带 a(祖先采样)的和原本的采样方式在不同的 eta 下的对比结果如下图:

在 eta 为 0 时,带 a 和原始的采样方法生成的图片基本上相同了。

小结:使用上述图中采样方法时记得注意相应的 eta,不然会失去所谓的的 “多样性” 和“想象力”

sigma 参数

sigma 包含:sigma churn,sigma tmin,sigma noise,仅对 euler, heun 和 dpm2 这三个采样器有效

sigma churn:决定 sigma noise 值如何被使用,如果 churn 值为 0,即使 noise 值不为 0,也没有任何效果。

sigma tmin:决定最小值范围的限制,可以为 0

sigma noise:噪声本身的数值大小(注意,churn>0 时,噪声值本身才有意义)

图片对比(图片中带 a 的采样方法不受 sigma 影响,所以作为对照组一同出现)

sigma 值也是 “多样性” 或者 “想象力” 的相关数值。

采样方法小结

  1. 建议根据自己使用的 checkpoint 使用脚本跑网格图(用自己关心的参数)然后选择自己想要的结果。
  2. 懒得对比:请使用 DPM++ 2M 或 DPM++ 2M Karras 或 UniPC,想要点惊喜和变化,Euler a、DPM++ SDE、DPM++ SDE Karras、DPM2 a Karras(注意调正对应 eta 值)

3.eta 和 sigma 都是多样性相关的,但是它们的多样性来自步数的变化,追求更大多样性的话应该关注 seed 的变化,这两项参数应该是在图片框架被选定后,再在此基础上做微调时使用的参数。

面部修复 Face restoration

下面我们看下面部修复

可以在设置界面选择:CodeFormer 和 GFPGAN 都是面部修复的 AI 模型,可以修改权重值。

CodeFormer 细节参考 [[9]](https://zhuanlan.zhihu.com/p/612572004#ref_9)

GFPGAN 细节参考 [[10]](https://zhuanlan.zhihu.com/p/612572004#ref_10)

这两个目前是风格有细微的区别,根据个人喜好选择。区别参考下图,来源:[[11]](https://zhuanlan.zhihu.com/p/612572004#ref_11)

面部修复小结:

根据个人喜好选择

超分辨率 Hires.fix 和 Upscaler

或者说图片放大器,在放大分辨率的同时根据 AI 模型添加相应的细节

在 txt2img 文生图中位于 Hires. fix 选项中的 Upscaler

Latent 系列的放大器工作在潜空间(latent space)上文介绍基础工作原理时提到的那个降维空间。在 Denoising 强度低于 0.5 时会出现图片模糊等问题,高于 0.5 会显著解决问题,但是会改变原图更多的内容,失去之前的面貌。Denoising 强度 0.5 以下请使用其它放大器。

其它非 Latent 系列的放大不工作在潜空间,所以就比较灵活了,txt2img 和 img2img 都能使用。

Lanczos,Nearest 是比较老的传统算法,不是 AI 模型,不推荐使用。(接触过计算机图形学的话肯定知道这两个算法,经典算法肯定对后人的工作有启发作用。没有不尊重的意思)参考下图 [[12]](https://zhuanlan.zhihu.com/p/612572004#ref_12)

ESRGAN 系列 [[13]](https://zhuanlan.zhihu.com/p/612572004#ref_13)

ESRGAN_4x 适用于照片写实类(可能出现细节过于锐利的效果,但有些人喜欢这样的风格),R-ESRGAN 4x+(全能型),R-ESRGAN 4x+ Anime6B(适用于二次元),R-ESRGAN-General-WDN-4xV3(适用于厚涂插画)

SwinIR_4x[[14]](https://zhuanlan.zhihu.com/p/612572004#ref_14)

SwinIR_4x 需要表现光影的厚涂插画表现优于照片和二次元的图片放大,但逊于 R-ESRGAN-General-WDN-4xV3

LDSR

LDSR 照片写实类图片表现很好,插画和二次元图片不行,而且体积很大,速度很慢(好奇的话,可以尝试)

超分模型小

上面的这些超分模型并不是固定用于某一类风格的图片放大,你可以自行尝试。(个别除外, 例如 Anime6B)

懒得尝试可以按照这个来:照片类 ESRGAN_4x,插画风 R-ESRGAN-General-WDN-4xV3,二次元 R-ESRGAN 4x+ Anime6B

更懒版本:照片类 ESRGAN_4x,其余 R-ESRGAN 4x+

不想动版本:R-ESRGAN 4x+

seed 和 CFG Scale

这两个设置使用过 stable diffuion Webui 应该都知道功能,暂时不展开。

Clip skip 参数

这个 Clip skip 设置被很多人说是玄学,记得上面聊三大组成部分的时候提到的 Clip 吗?调大 Clip skip 的数值会让 Clip 更早结束文本嵌入,让 prompt 提示的指挥力度被削弱,听上去是不是和 CFG Scale 唱反调?可能有人会问那都用 CFG Scale 不就好了吗?确实,平时你可以放着默认的设置不去管他,但是有些模型在训练时会调整这个 Clip skip 对层的影响深度,所以在使用的时候也需要相应的调整,比如设置为 2,大多数我们口中的自己训练 SD 模型,其实都是对原本模型的微调,而实现微调的原理就是微调三大组件中的 Clip 或者调整 Clip 加 U-net,说到本地模型训练,今后有时间再写吧。

参考

  1. ^High-Resolution Image Synthesis with Latent Diffusion Models https://arxiv.org/abs/2112.10752
  2. ^how-stable-diffusion-work https://huggingface.co/blog/stable_diffusion#how-does-stable-diffusion-work
  3. ^k_diffusion/sampling https://github.com/crowsonkb/k-diffusion/blob/master/k_diffusion/sampling.py
  4. ^Denoising Diffusion Implicit Models https://arxiv.org/abs/2010.02502
  5. ^Elucidating the Design Space of Diffusion-Based Generative Models https://arxiv.org/abs/2206.00364
  6. ^DPM-Solver: A Fast ODE Solver for Diffusion Probabilistic Model Sampling in Around 10 Steps https://arxiv.org/abs/2206.00927
  7. ^UniPC: A Unified Predictor-Corrector Framework for Fast Sampling of Diffusion Models https://arxiv.org/abs/2302.04867
  8. ^UniPC Sampler support https://github.com/easydiffusion/sdkit/pull/12
  9. ^CodeFormer https://github.com/sczhou/CodeFormer
  10. ^GFPGAN https://github.com/TencentARC/GFPGAN
  11. ^Face restoration in webui https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#face-restoration
  12. ^ai-upscaler https://stable-diffusion-art.com/ai-upscaler/
  13. ^ESRGAN https://github.com/xinntao/Real-ESRGAN
  14. ^SwinIR https://github.com/JingyunLiang/SwinIR
Last modification:April 9, 2023