Stable Diffusion工作原理
cn碳水
2024年08月14日 15:56
stable-diffusion

SD来源

2022年,Stability AI和Runway两家公司合作发表了一篇论文,提出了一个新的文生图模型Latent Diffusion Model,中文翻译为“潜空间扩散模型”。这个模型的特性是把图片进行压缩后再处理,使得生成速度更快,硬件要求更低。

为了验证论文的实际效果,Stability AI用代码实现了它,并用LAION公司的图片数据训练得到了一个可运行的模型,即Stable Diffusion 1.0。

Latent Diffusion Model论文

https://ommer-lab.com/research/latent-diffusion-models/

Stable Diffusion 1.0代码仓库

https://github.com/CompVis/stable-diffusion?tab=readme-ov-file

SD生成图片原理

SD生成图片的过程,是从一张铺满噪点的图片中,减去一些噪点,让得到的新图片更加符合SD训练时所学的物体特征,然后不断重复这个过程。

第一张铺满噪点的图片,是一张随机生成的噪点图。

每一步如何减去噪点,由SD核心组件UNet神经网络来控制。

每一步降噪都是在前一步的基础上进行。

那么,UNet神经网络是如何知道每一步要减去的噪点图呢?这就要了解模型训练。

SD模型训练原理

AI模型本质上是一堆数学公式,包括了很多参数,这些参数会影响模型输出的结果。

训练模型,就是让模型运算海量的数据,然后根据结果去调整参数,不断重复这一过程,直到模型给出满意的结果。

UNet神经网络也是一堆数学公式,SD模型训练主要是为了获得一组UNet神经网络的参数,步骤如下。

首先,我们准备一张图片,叠加一张已知的“噪音图”,可以得到一张被“污染”了的图片。

之后,我们把被“污染”的图片输入给UNet神经网络,让它输出一张“噪音预测图”。(理想情况下,被“污染”的图片 减去 噪音预测图 应该得到符合原图片特征的结果。)

然后,比较噪音预测图和原噪音图,并把比较结果反馈给UNet神经网络,用来调整UNet参数。

这就是一次训练的基本步骤,我们会重复这个过程,让UNet神经网络预测的“噪音图”越来越接近原噪音图。

事实上,我们可以给一张图片增加不同“音量”的噪音,获得多张被“污染”的图片用作训练。然后,把“污染”的图片,和对应的噪音的“音量”,在训练时一起输入给UNet。对于训练集里的海量图片,每一张都可以做类似的操作。

所以,

UNet神经网络输入:加噪音的图片、噪音量

UNet神经网络输出:噪音预测图

回顾一下,

训练SD,是在训练集图片上加噪音,最终让UNet预测的噪音图越来越准确。

SD生成图片,是从一张随机噪音图上减噪音,只有UNet预测的噪音准确,最终生成的图片质量才会好。

无论是生成图片还是训练,UNet都是根据输入的图片输出一个噪音预测图。

通常,加噪音的过程称为“正向(forward process)”,也就是扩散diffusion,去噪音的过程称为“逆向(reverse process)”。

加速UNet

为了加快图像生成速度、缩短训练时间,SD的方法是把像素图片压缩后,再交给UNet处理。因为需要处理的图片变小了,小规模的UNet神经网络也能有不错的结果,因此对算力的要求也降低了。

SD使用图片编码器压缩图片,英文叫 Variational Autoencoder。压缩的原理是对图片进行降维处理,想象一个球形的地球仪,有效数据完全可以在一个二维的平面展开。从3维到2维,数据存储所需的空间大大降低了。压缩以后的图片所在的空间在概念上叫“潜空间”。

SD训练模型时,并不是直接使用训练集的图片,而是先用图片编码器进行编码,输出潜空间图片,再投喂给UNet。生成图片时,UNet并不直接生成像素图片,而是生成潜空间图片,用图片解码器恢复成像素图片。

UNet的训练过程,某种意义上讲,也是一种信息的压缩。它只保存了从图片中抽象出的概念、特征用于生成,图片其余的信息都丢弃了。所以,UNet的训练过程也叫“语义压缩”,图片编码叫“感知压缩”。

举例来说,一张人脸的照片,感知压缩后,仍旧是人脸的图片,能看出大致的轮廓、相貌,感知上变化不大,但脸上的纹理、斑痕等细节可能就没有了。语义压缩后,这张照片就不再是图片了,而是一些概念和特征,比如“一个人,两个眼睛,一张嘴巴”等等,原来的照片完全抽象到概念层面了。所以,从语义压缩恢复(就是生成的过程),会画出另一个人,从感知压缩恢复,会把脸部细节补充完整。

带提示词的UNet

具备了前文的知识,现在我们看看提示词是如何产生作用的。

SD对提示词的处理分为两步,

(1)翻译。把自然语言的提示词翻译成UNet能理解的代码,通常叫“文本编码”。

(2)控制。把提示词引入UNet,预测噪音受提示词控制,即“交叉注意力层”。

文本编码

文本编码,在本文是指把自然语言翻译成UNet能理解的代码的过程,用户输入自然语言的提示词,是由文本编码器翻译成代码输入给UNet。文本编码器“翻译”的好坏将直接影响出图结果。

SD借助了另外的AI语言模型来完成文本编码的工作。早期SD版本使用的文本编码器是OpenAI公司的ClipText,在SD2.0版本后,替换成了更强大的OpenCLIP。

文本编码器的工作是把高维的信息进行降维处理,降维后的数学描述仍旧能够“反映”原高维信息的一些关键特征。这种降维的过程,就是一种编码,是对信息进行压缩,抽象成数学的描述。

被编码压缩的高维信息支持多种模态,可以是文字,也可以是图片。在训练文本编辑器时,既要编码图片也要编码描述图片的文字,分别得到二者的数学描述,训练的目的就是让二者的数学描述“反映”的特征一致。比如,一张狗的照片,和“一只狗”这三个字,在分别编码后,得到的数学描述应该是相似的。需要注意,文本编码器本身是预先训练好的,并不受UNet训练的影响。

明白了什么是文本编码器,再来看SD如何使用文本编码器。

SD生成图片时,文本编码器会把用户输入的提示词进行编码,然后输入给UNet。

训练SD时,文本编码器将训练图片的文字标注进行编码,然后输入给UNet。

再补充一个知识点,深入学习SD,常常会见到embedding这个术语,比如,文字编码后得到text embedding,图片编码后得到image embedding,还有一种微调方法叫embedding。

embedding直译是“嵌入”,很不好理解。

实际上,embedding这个术语常用于高维空间和低维空间之间的变换。比如一个三维的地球仪,可以把球面地图展开到二维平面上,但不会损失数据。反过来,就是二维的地图“嵌入”到了三维空间中。

认为高维数据其实是低维数据“嵌入”到高维中的理论,就是流形假设 manifold hypothesis。为了压缩数据,我们常常会用到流形假设。

embedding在一些语境中,代指了这种把什么东西从一个空间“嵌入”到另一个空间的数学变换过程。

交叉注意力层

UNet神经网络是层状结构,有一些层专门用来处理从文本编码器翻译得到的提示词,这些层通常叫交叉注意力层(cross attention layer),翻译后的提示词叫token。token作为UNet运算的边界条件来控制结果。

因此,UNet的输入还要增加一项,

UNet输入:加噪音的图片、噪音量、token

UNet输出:噪音预测图

因为Unet训练时注意力层就引入了文本条件的控制,在生成时就好像使用了分类器的引导,可以生成指定内容。但实际上SD并没有使用分类器,所以SD的开发者把这个特性叫Classifier-free,UNet受文本条件控制的程度就由CFG scale(classifier-free guidance scale,无分类器引导规模)参数设置。

SD架构

根据上文的介绍,自然的就能得到SD的组成部件。

用户生成一张图片,依次运行下面3个组件。

文本编码器,把提示词编码成算法能理解的代码,然后输入给图片生成器。

输入:自然语言的提示词

输出:编码过的文本

图片生成器,是SD的核心组件,由UNet神经网络和调度算法scheduling组成。调度算法就是在webUI上的采样器,可以把UNet理解为牛马,调度算法是指挥UNet工作的管理人员。调度算法会让UNet重复去噪多次直到满意。

输入:编码过的文本,噪声图(随机生成的)

输出:潜空间图片

图片解码器,图片生成器输出潜空间图片,图片解码器进行一次解码,恢复成像素图片。

输入:潜空间图片

输出:像素图片

工程师训练模型时,还需要用到图片编码器。

图片编码器,先把像素图片压缩成潜空间图片,再投喂给图片生成器进行训练。因为图片编码的过程是图片解码的反向过程,SD的图片编/解码器都用了VAE。

输入:像素图片

输出:潜空间图片

Stable Diffusion其实是几个AI算法的组合,文本部分使用了CLIP,噪声预测使用了UNet,调度算法支持很多种,比如Euler、DPM等。整理一下,大致四部分,

(1)文本编码器,是OpenClip;

(2)图片编码器,是VAE;

(3)图片生成器,是UNet神经网络;

(4)图片解码器,是VAE;

SD对扩散模型有两个主要的改进,

第一个改进,是引入了潜空间,也就是把像素图片先压缩,再处理,降低了算力的消耗;

第二个改进,是在UNet引入了注意力层,让文本可以指导扩散过程。

图生图原理

图生图和文生图的步骤相似,只是多了一个输入的图片。

文生图从一张随机噪音图开始去噪,图生图是把输入的图片进行编码,生成潜空间图片,UNet从这张潜空间图片开始去噪。输入的图片进行编码时,会额外加入一定量的噪音,加入多少噪音就是webUI上的重绘幅度。

扩散模型

为什么叫扩散?

扩散模型在训练的时候,是向一张图片逐步叠加噪声。想象一下,一张清晰的图片,噪点越来越多,从清晰变得越来越模糊,有点像一滴墨水在清水中扩散开。这就是“扩散”的由来。

如何理解扩散模型的工作原理?

想象一个被围起来而且光滑的地面有两个坑,扔进去一个小球,这个小球最终一定会停到其中一个坑的坑底。

现在,假设一个扩散模型只学习到了两个特征,一个猫的特征,一个狗的特征,那么,扩散模型从一张随机噪声图去掉噪点,经过多次迭代以后,呈现的图片一定是这两个特征其一。扩散模型生成图片的过程和小球寻找坑底的思路是很相像的。在数学上,这其实是寻找最优解,有一组初始状态,一些边界条件,那么算法就会寻找区域中的最优解。对小球来说,最优解就是坑底,对扩散模型来说,最优解就是学习到的特征。

一个没有任何引导的扩散模型,也能生成图片,但是没办法知道会生成什么图片。就像有很多坑的地面,小球可能停在任一个坑中。加入了文字或图片的引导以后,这些引导作为边界条件,扩散模型就能在边界条件的控制下来生成图片,就像小球有了目标,知道要去哪个小坑。

参考

https://jalammar.github.io/illustrated-stable-diffusion/

潜空间扩散论文b站讲解​

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