Stable Diffusion(一)Stable Diffusion 原理

Stable Diffusion原理

此文为译文,原文见:

https://stable-diffusion-art.com/how-stable-diffusion-work/

Stable Diffusion是一个深度学习模型,我们会深入解析SD的工作原理。

 

1. Stable Diffusion能做什么

直白地说,SD是一个text-to-image模型,通过给定text prompt(文本提示词),它可以返回一个匹配文本的图片。

 

 

2. Diffusion 模型

Stable Diffusion属于深度学习模型里的一个类别,称为diffusion models(扩散模型)。这类模型时生成式模型,也就是说它们用于生成新的数据,这类新数据类似于它们训练时的数据。对于SD来说,这类新数据便是图片。

为什么叫diffusion model?因为它的数学公式看起来非常像物理上的扩散现象。下面我们具体介绍它的原理。

假设我们训练了一个diffusion model,训练时只给了2类图片:猫与狗。如下图所示,左边便是送入训练的猫与狗的图片。

 

2.1. 前向扩散

 

前向扩散将图片转为噪点(图片基于此文图片进行修改 this article

前向扩散的过程是给训练图片添加噪点的过程,并逐渐将图片转为一个反常的噪点图。也就是会将任何猫或狗的图片转为一张噪点图,并最终无法辨认噪点图对应的初始图片是猫还是狗(这点非常重要)。

这个过程就像是滴入了一滴墨水到一杯水里,墨水在水里diffuses(扩散)。在几分钟后,墨水会随机分散并融入水中。且无法判断它最初是从水杯的中心滴入,还是从边缘滴入。

下面是一张图经历前向扩散的过程。猫的图片转为了一张随机噪点图。

 

2.2. 反向扩散

然后再看反向扩散部分。我们预期的表现是:输入一张噪点图(毫无意义的图),反向扩散(reverse diffusion)可以将这张噪点图恢复为一张猫或狗的图片。这就是反向扩散的主要思想。

从技术角度来说,每个扩散过程分为2部:

  1. 漂移或定向运动(例如,针对这个案例来说,噪点图要么偏向狗的方向,要么定向于猫的方向)
  2. 随机移动

反向扩散会朝着猫或狗的图片方向进行漂移,但绝对不会停留在中间状态。这也是为什么结果智能是猫或狗的图片。

 

3. 训练过程

从反向扩散的角度来说,我们需要知道有多少“噪点”加入到了某张图片里。回答此问题的方式便是:训练一个神经网络来预测添加的噪点。这个在SD里称为噪点预测器(noise predicator)。其本质是一个U-Net模型。

训练流程为:

  1. 选择一张训练图(例如一张猫的图片)
  2. 生成随机的噪点图
  3. 给这张图继续增加多轮噪点
  4. 训练noise predictor,预测加入了多少噪点。通过神经网络训练权重,并展示其正确答案

更详细的原理可以参考:

https://www.bilibili.com/video/BV1bm4y1A7v7/

按顺序每步都增加噪点,noise predictor预测每步增加的噪点

在训练后,便可得到一个noise predictor,可以预测一张噪点图中,加入到图片的噪点信息。

 

3.1. 反向扩散

现在我们有了noise predictor(噪点预测器),应该如何使用?

我们首先生成一张完全随机的图片,并让noise predictor告诉我们噪点是什么。然后从原图中移除噪点。并重复此过程多次,最终遍得到一张猫或狗的图片。

 

可以看到在这个生成猫或狗的图片的过程中,我们没有加入任何人为控制。这个“人为控制”是我们后续会讨论到的条件“conditioning”。当前来说,图片的生成是unconditioned。

 

更多有关反向扩散采样于采样器的信息,可以参考文章:

https://stable-diffusion-art.com/samplers/

 

4. Stable Diffusion模型

现在我们需要强调的是:上面讨论的过程并非是SD工作的原理。

原因是:由于上述扩散过程是在图片空间里完成的,所以它的计算过程是非常非常慢的。上述过程基本无法在单个GPU上运行。

图片空间太广阔了。试想:一张512 x 512的图片(包含3个颜色通道:红、绿、蓝),它的空间是786,432维。也即是说我们要为一张图片指定这么多的值。

Diffusion模型如谷歌的Imagen以及Open AI的DALL-E都是在像素空间的,他们使用了一些技巧让模型运行更快,但是仍不够快。

 

4.1. Latent diffusion模型

Stable Diffusion便是用于解决速度问题的,它是一个latent diffusion model(潜扩散模型)。其方式是将图片压缩到一个“潜空间”(latent space)中,而不是在高维的图片空间里工作。

潜空间比图片空间小了48倍,所以它可以节省大量计算,继而运行速度更快。

 

4.2. Variational Autoencoder

如何将图片压缩到潜空间?使用的技术是variational autoencoder(变分自动编码器),也即为VAE文件。

VAE神经网络包含2部分:Encoder与Decoder。

Encoder将一张图片压缩到“潜空间”里的一个低维空间表示。Decoder从“潜空间”里的表示恢复为一张图片。

 

SD模型的潜空间为4 x 64 x 64 维,比图片的像素点空间要小48倍。前面提到的前向与反向扩散都是在潜空间里完成。

所以在训练时,不再是生成一张噪点图,而是在潜空间里生成一个随机张量(tensor)。并且在给图片每一步增加噪点时,也不再是给图片增加噪点,而是给图片在潜空间里的张量增加潜噪点。这么做的原因当然是由于潜空间更小,执行速度更快。

 

4.3. 图像分辨率

图像分辨率会反映在潜空间里对应图片张量的大小。对于512 x 512的图片来说,其在潜空间里的大小为4 x 64 x 64。而对于768 x 512的人像图来说,对应潜空间张量的维度即为4 x 96 x 64。这也是为什么需要更长的时间与资源生成分辨率更高的图片。

由于Stable Diffusion v1是在512 x 512的图片上进行的fine tune,所以若是生成超过512 x 512 大小的图片时,会导致有重复的对象。例如生成的人物有“双头”问题。如果一定要用v1版本,则至少先保持512像素,然后在使用AI upscaler工具生成更高的分辨率。

 

4.4. 为什么潜空间是合理的

为什么VAE可以压缩一张图片到非常小的一个潜空间而不损失信息呢?这是因为:自然图片并非是随机的,它们有很高的规律性。例如,一张脸上,鼻子、脸颊和嘴巴之间有特定的空间关系。一只狗有4只腿并且有特定的形状。

换句话说,高维的图片是人为的。自然图像可以轻松地压缩到较小的潜空间中,而不会丢失任何信息。这在机器学习中被称为流形假设。

 

4.5. 潜空间里的反向扩散

下面是SD模型里反向扩散在潜空间里的工作流程:

  1. 生成随机的潜空间矩阵
  2. Noise predictor预测潜矩阵的噪点
  3. 将预测的噪点从潜矩阵中去除
  4. 重复步骤2与3,直到特定的采样步数
  5. VAE的decoder将潜矩阵转为最终图片

 

4.6. VAE文件是什么?

在Stable Diffusion v1里,VAE files用于提升眼睛与脸的准确度。它们实际上是我们前面提到的autoencoder中的decoder。通过进一步的fine-tune decoder,模型可以生成出更多的细节。

 

5. Conditioning(条件)

到目前为止,我们还没介绍文本是如何影响图片生成的。如果没有文本prompt的影响,SD模型也不会是一个text-to-image模型。我们可以得到一张猫或狗的图片,但是没有方式来控制它。

这部分就是“条件”(conditioning)要做的事情。“条件”的目的便是引导noise predictor,让其知道:在抽取预测的噪点后,我们需要的是什么。

 

5.1. 文本条件(text-to-image)

下面展示的是:文本提示(text prompt)如何处理并输入到noise predictor:

 

首先,Tokenizer(分词器)将每个输入的单词转为一个数,称为token。每个token然后转为一个768维的向量,称为词嵌入(embedding)。词嵌入然后由Text Transformer处理,并可以被Noise predictor进行消费。

可以使用这个notebook来检查prompt的token与embedding。

 

5.2. Tokenizer

 

文本提示词首先由一个CLIP tokenizer做分词。CLIP是一个深度学习模型,由Open AI开发,用于为任何图片生成文本描述。Stable Diffusion v1使用了CLIP模型的tokenizer。

Tokenization是计算机理解单词的方式。人类可以读懂单词,但是计算机智能读懂数字。所以这也是为什么文本提示词首先要转为单词。

Tokenizer只能将其在训练过程中见到过的单词进行分词。例如,假设CLIP模型里有“dream”与“beach”单词,但是没有“dreambeach”单词。Tokenizer会将“dreambeach”分成2个单词“dream”与“beach”。所以,1个单词并非代表1个token,而是有可能进一步进行拆分。

另一个细节是:空格也是token的一部分。例如,短语 "dream beach" 产生了两个token "dream" 和 "[space]beach"。这些标记与 "dreambeach" 产生的标记不同,后者是 "dream" 和 "beach"(beach 前没有空格)。

Stable Diffusion模型限制提示词在75个单词。

 

5.3. 词嵌入(Embedding)

Stable diffusion v1使用Open AI的ViT-L/14模型,词嵌入为768维的向量。每个单词有其特定的词嵌入向量。词嵌入由CLIP模型决定,是在训练过程中得来。

为什么我们需要词嵌入?因为有些单词相互之间是非常相似的,我们希望利用到这些信息。例如,man、gentleman、guy的词嵌入是非常相近的,因此它们可以相互替换。Monet、Manet以及Degas都以印象派的风格绘画,但是方式各不相同。这些名字看起来是非常相似,但是在词嵌入里是很不一样的。

在另一片文章里,我们讨论的使用关键词来触发不同的风格,两者的embedding含义是一样的。Embedding在里面起了至关重要的作用。已经证明的是,使用合适的词嵌入可以触发任意对象与风格,一个fine-tune的技巧称为textual inversion

 

5.4. 将词嵌入输入noise predictor

 

词嵌入需要进一步由文本转换器(text transformer)进行处理,然后输入到noise predictor中。这个转换器就像是一个通用的条件(conditioning)适配器。在这个例子中,它的输入是文本嵌入向量,但是它也可以是其他的东西,例如类别标签,图片,以及depth maps。转换器不仅是进一步处理数据的组件,也提供了一种机制来加入不同的条件形式。

 

5.5. Cross-attention

文本转换器的输出,会被noise predictor在U-Net中使用到多次。U-Net以一个叫做cross-attention机制的方式来使用它。这即是prompt适配图片的地方。

这里我们使用提示词“A man with blue eyes”作为例子。SD将单词blue与eyes组合到一起(self-attention within the prompt),这样便可以生成一个蓝眼睛的男人,而不是穿蓝衬衫的男人。然后它会使用这个信息引导反向扩散,使得最终生成的图片包含蓝色眼睛(cross-attention between 提示词与图片)

一个备注:Hypernetwork是一种fine-tune Stable Diffusion模型的技术,它会操纵cross-attention网络来注入风格。LoRA模型修改cross-attention模块的权重来修改风格。可以看到,单独修改这个模块即可fine-tune一个SD模型的风格,说明了这个模块有多重要。

 

5.6. 其他条件

文本提示词并非SD模型可以参考的条件。Text prompt与depth image都可以用于depth-to-image模型的条件。

ControlNet利用监测到的轮廓、人体姿势等对noise predictor进行调节,可以实现对图像生成的出色控制。

 

6. Stable Diffusion step-by-step

现在我们了解了Stable Diffusion的机制,下面我们再通过几个例子看看底层是如何运行的。

 

6.1. 文本生成图

在文本生成图的场景下,我们给SD模型输入一组文本提示词,它可以返回一张图片。

Step 1. Stable Diffusion在潜空间里生成一个随机张量。我们通过设置随机种子seed来控制这个张量的生成。如果我们设置这个随机种子为一个特定的值,则会得到相同的随机张量。这就是我们在潜空间里的图片。但是当前还全是噪点。

 

Step 2. Noise predictor U-Net将潜噪点图已经文本提示词作为输入,并预测噪点,此噪点同样也在潜空间内(一个4 x 64 x 64的张量)

 

Step 3. 从潜图片中抽取潜噪点,并生成了新的潜图片

 

Step 2 与 Step 3 重复特定采样次数,例如20次。

Step 4. 最后,VAE的decoder将潜图片转回像素空间,这便是我们通过SD模型最终得到的图片。

 

下图是图片在每个采样步生成的结果:

 

 

6.1.2. noise schedule

可以看到,整个过程是图片是由噪点转为干净的的过程。大家可能会考虑到,是不是最开始几步noise predictor的性能不够好,所以前几步生成的图片仍包含噪点。这个实际上是因为我们希望在每个采样步中得到一个预期的噪点,而不是一次性完全抹除噪点。这个称为noise schedule。下面是一个例子:

 

Noise schedule是我们定义的一个选项。我们可以选择在每一个step中剔除等量的噪点。或者是在最开始提出更多的噪点(如上图所示)。采样器每次剔除足够的噪点,以达到下一步中预期的噪点。这便是我们在step-by-step图片中见到的样子。

 

6.2. 图生图

图生图的方法首先是在SDEdit方法中提出的。SDEdit可以应用到任何扩散模型中。所以我们也有Stable Diffusion的图生图模式。

图生图的输入是一张输入图片以及一组文本提示词。生成的图片会由输入图片以及文本提示词两者共同调节。例如,使用下面的简笔画,以及提示词“带茎、水滴和戏剧性照明的完美绿色苹果照片”作为输入,图生图可以将其转换成专业绘画。

 

下面是图生图的具体流程。

 

Step 1. 输入图片编码到潜空间

 

Step 2. 加入噪点到潜图片。Denoising strength控制加入多少噪点。如果为0,则不会加入噪点。如果为1,则会加入最多的噪点,这样潜图片则转为一张完全随机的张量。

 

Step 3. Noise predictor U-Net使用潜噪点图以及文本提示词作为输入,并预测潜空间内的噪点(一个4 x 64 x 64 的张量)

 

Step 4. 从潜图片中剔除潜噪点,并生成新的潜图片。 

 

Step 3 与 4 重复多次,直到特定采样步数,例如20次。

 

Step 5. 最后,VAE的解码器将潜图片转回像素空间,便得到了最终生成的图片。

 

现在我们知道了图生图的原理,它所要做的便是设置一个初始的、带噪点的潜图片,作为输入图片。如果denoising strength设置为1,则等同于文本生成图了,因为初始的潜图片是完全随机的噪点。

 

6.2.1. 图像修复

图像修复是图生图里的一个特殊例子。只需将噪点加入到需要被修复的图片。加入多少噪点同样也由denoising strength决定。

 

6.3. Depth-to-Image

Depth-to-image是图生图的一个增强。它生成的图片时,会使用depth map作为额外的条件。

 

Step 1. 输入图片编码到潜空间

 

Step 2. MiDaS(一个是AI深度模型)基于输入图片预测depth map

 

Step 3. 为潜图片添加噪点。同样,denoising strength控制加入多少噪点。

 

Step 4. Noise predictor预测潜空间的噪点,由文本提示词与depth map共同调控

 

Step 5. 从潜图片中剔除噪点,生成新的潜图片

 

Step 4 与 5 重复特定次数采样步数。

 

Step 6. VAE decoder解码潜图片,得到最终生成的depth-to-image图片

 

 

7. 什么是CFG值

在解释Classifier-Free Guidance(CFG)前,这篇文章仍是不够完整的。CFG是AI艺术家们每天都在调整的一个重要参数。为了明白这个参数是做什么,我们首先了解它的前身:classifier guidance(分类器指导)。

 

7.1. Classifier Guidance

分类器指导是将图片标签融入扩散模型的一种方法。我们可以使用标签来指导扩散的过程。例如,标签“猫”可以引导反向扩散过程,从而生成猫的照片。

Classifier guidance系数是一个参数,用于控制扩散过程应如何遵循标签。下面是一个从这篇论文paper中摘取的一个例子。假设有3组带标签的图片分别为:“猫”、“狗”、“人”。如果扩散过程没有被指导,则模型会从每个组的所有样本中绘制样本,但有时它可能会画出一张可以适用于两个标签的图片。例如一个男孩抚摸一只狗的图片。

 

使用更高的classifier guidance系数,由DF模型生成的图片将偏向于极端或是明显的例子。如果我们让模型生成一只猫,则它会返回明显是一只猫的图片而不是其他东西。

Classifier guidance 系数控制了遵循指导的程度。在上图中,右侧的采样比中间的采用有更高的Classifier guidance系数。在实践中,这个比值只是向带有该标签的数据漂移项的乘数。

 

7.2. Classifier-free guidance

尽管classifier guidance取得了创纪录的性能,但它仍需要一个额外的模型来提供这种指导。也就在训练过程中带来了些困难。

在作者的术语中,Classifier-free guidance是一种实现“没有分类器的分类器指导”的方法。不需要使用类别标签以及额外的模型来做指导,而是提出了使用图片说明并训练一个带条件的扩散模型来取代。这个方式与我们前面提到的“文本生成图”的原理相同。

它们将分类器部分作为noise predictor U-Net的条件,从而在图像生成中实现了称为“classifier-free”(即没有单独的图片分类器)的指导。

文本提示词在“文本生成图”中提供了这个指导。

 

7.3. CFG值

现在我们知道了通过“条件”实现classifier-free的扩散过程,那该如何控制这个“指导”被follow的程度呢?

Classifier-free guidance(CFG)系数便是控制“文本提示词”条件对扩展过程控制的程度值。在其值设置为0时,图片生成是不附加条件的(即prompt是忽略的)。更高的值会引导扩散过程朝着提示词方向前进。

 

8. Stable Diffusion v1与v2

下面对比v1与v2的区别。

 

8.1. 模型区别

SD v2使用OpenClip做文本词嵌入。SD v1使用Open AI的CLIP ViT-L/14做文本词嵌入。

做出此变更的原因:

  1. OpenClip规模提升了5倍,更大的文本嵌入模型可以提升图片质量
  2. 尽管Open AI的CLIP模型是开源的,但模型是使用专有数据进行训练的。切换到OpenClip模型可以使研究人员在研究与优化模型时获得更多的透明度,这对于长期发展是更好的

 

8.2. 训练数据区别

Stable Diffusion v1.4 使用的训练trained数据是:

l  237k steps,分辨率为256 x 256,数据集为laion2B-en

l  194k steps,分辨率为512 x 512,数据集为laion-high-resolution

l  225k steps,分辨率为512 x 512,数据集为laion-aesthetics v2 5+,使用10%的文本条件剔除

 

Stable Diffusion v2使用的训练数据为trained with

l  550k steps,分辨率为256 x 256,数据集为 LAION-5B的子集。过滤了明显色情的材料,使用LAION-NSFW classifier(punsafe=0.1参数)以及aesthetic score >= 4.5

l  850k steps,分辨率为512 x 512,在同样的数据集上(分辨率>=512 x 512)

l  150k steps,在同样的数据集上使用 v-objective

l  在 768 x 768 的图片上继续训练140k steps

 

Stable Diffusion v2.1是基于v2.0进行fine-tune的来:

l  额外55k steps训练,同样数据集(使用punsafe=0.1)

l  另外155k steps,使用punsafe=0.98

 

基本上,他们在最后的训练步骤中关闭了NSFW过滤器。

 

8.3. 结果表现的区别

用户发现使用Stable Diffusion v2控制风格以及生成名人通常会更难。虽然Stability AI并没有显式过滤艺术家以及名人的姓名,但它们在v2中的效果要弱得多。这可能是由于训练数据的不同导致的。Open AI的专有数据可能拥有更多的艺术作品和名人照片。他们的数据可能经过了高度过滤,使得每件事和每个人都看起来非常美好。

 

9. 进一步阅读

 

posted @ 2023-04-16 22:12  ZacksTang  阅读(7632)  评论(1编辑  收藏  举报