Stable Diffusion原理
Stable Diffusion能做什么
直白地说,SD
是一个text-to-image
模型,通过给定text prompt
(文本提示词),它可以返回一个匹配文本的图片。
Diffusion 模型
Stable Diffusion
属于深度学习模型里的一个类别,称为diffusion models
(扩散模型)。这类模型是生成式模型,也就是说它们用于生成新的数据,这类新数据类似于它们训练时的数据。对于SD来说,这类新数据便是图片。
为什么叫diffusion model
?因为它的数学公式看起来非常像物理上的扩散现象。下面我们具体介绍它的原理。
假设我们训练了一个diffusion model
,训练时只给了2类图片:猫与狗。如下图所示,左边便是送入训练的猫与狗的图片。
2.1. 前向扩散
前向扩散的过程是给训练图片添加噪点的过程,并逐渐将图片转为一个反常的噪点图。也就是会将任何猫或狗的图片转为一张噪点图,并最终无法辨认噪点图对应的初始图片是猫还是狗(这点非常重要)。
这个过程就像是滴入了一滴墨水到一杯水里,墨水在水里diffuses
(扩散)。在几分钟后,墨水会随机分散并融入水中。且无法判断它最初是从水杯的中心滴入,还是从边缘滴入。
下面是一张图经历前向扩散的过程。猫的图片转为了一张随机噪点图。
2.2. 反向扩散
然后再看反向扩散部分。我们预期的表现是:输入一张噪点图(毫无意义的图),反向扩散(reverse diffusion
)可以将这张噪点图恢复为一张猫或狗的图片。这就是反向扩散的主要思想。
从技术角度来说,每个扩散过程分为2部:
- 漂移或定向运动(例如,针对这个案例来说,噪点图要么偏向狗的方向,要么定向于猫的方向)
- 随机移动
反向扩散会朝着猫或狗的图片方向进行漂移,但绝对不会停留在中间状态。这也是为什么结果只能是猫或狗的图片。
3. 训练过程
从反向扩散的角度来说,我们需要知道有多少“噪点”加入到了某张图片里。回答此问题的方式便是:训练一个神经网络来预测添加的噪点。这个在SD
里称为噪点预测器(noise predicator
)。其本质是一个U-Net
模型。
训练流程为:
- 选择一张训练图(例如一张猫的图片)
- 生成随机的噪点图
- 给这张图继续增加多轮噪点
- 训练
noise predictor
,预测加入了多少噪点。通过神经网络训练权重,并展示其正确答案
在训练后,便可得到一个noise predictor
,可以预测一张噪点图中,加入到图片的噪点信息。
3.1. 反向扩散
现在我们有了noise predictor
(噪点预测器),应该如何使用?
我们首先生成一张完全随机的图片,并让noise predictor
告诉我们噪点是什么。然后从原图中移除噪点。并重复此过程多次,最终遍得到一张猫或狗的图片。
可以看到在这个生成猫或狗的图片的过程中,我们没有加入任何人为控制。这个“人为控制”是我们后续会讨论到的条件“conditioning
”。当前来说,图片的生成是unconditioned
。
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模型里反向扩散在潜空间里的工作流程:
- 生成随机的潜空间矩阵
Noise predictor
预测潜矩阵的噪点- 将预测的噪点从潜矩阵中去除
- 重复步骤2与3,直到特定的采样步数
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做文本词嵌入。
做出此变更的原因:
OpenClip
规模提升了5倍,更大的文本嵌入模型可以提升图片质量- 尽管
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
的专有数据可能拥有更多的艺术作品和名人照片。他们的数据可能经过了高度过滤,使得每件事和每个人都看起来非常美好。
其他
此文为译文,原文见:
stable-diffusion-art.com/how-stable-…
Stable Diffusion
是一个深度学习模型,我们会深入解析SD
的工作原理。