StableDiffusion 结构总览
首先,sd 的 核心是 UNet,还有 encoder 和 decoder。
我们按照顺序,从 Encoder、CLIP Encoder 和它们生成的内容开始讲起,从左到右。
分别为:
1、Encoder 的生成内容 Z 是什么
2、CLIP Encoder 的生成内容是什么(是 One-Hot 编码),它是怎么被 Prompt Embedding 转化为低维密集向量的。
(我的这篇博客讲了它是怎么被 Prompt Embedding 转化为低维密集向量的:https://blog.csdn.net/qq_43768851/article/details/139640188?spm=1001.2014.3001.5502)
3、UNet 结构概览,训练过程解析
一、RandomNoise → Encoder 之后生成的 Z 是什么?
在扩散模型(例如 Stable Diffusion)中,随机噪声通过编码器转化为的 Z 是一个潜在空间中的向量或张量。这个表示用于捕捉图像生成的初始状态,随着扩散过程的进行,逐步被转化为最终的生成图像。
1.Z 的格式和性质
- 格式:
-
向量或张量:Z 通常是一个多维张量(tensor)。它可以视为一个高维空间中的点,这个点包含了生成图像的初始信息。
-
尺寸:其尺寸通常与图像编码器的输出尺寸有关。例如,如果图像编码器输出的尺寸是 (C,H,W),其中 C 代表通道数,H 和 W 分别代表高度和宽度,那么 Z 的尺寸也是 (C,H,W)。
- 性质:
-
随机性:初始的 Z 是从标准正态分布中采样得到的随机噪声。这个随机性保证了生成图像的多样性。
-
潜在空间表示:Z 表示了图像的潜在空间中的一个点。潜在空间是一个抽象的、高维的空间,捕捉了图像的高层次特征和结构。
2.生成过程中的 Z
在扩散模型的生成过程中,随机噪声(初始的 Z)逐步被转换为目标图像。这一过程可以分为以下几个阶段:
-
初始噪声生成:从标准正态分布中采样得到一个随机噪声张量,作为初始的 Z。
-
编码器:这个噪声通过编码器,被转换为一个潜在表示。这个编码器可以是一个简单的映射函数,也可以是一个复杂的神经网络。
-
扩散过程:在每个时间步,模型根据时间嵌入、文本提示的嵌入以及当前的潜在表示 Z,逐步更新这个表示,使其越来越接近目标图像的潜在表示。这个过程通过U-Net等神经网络架构完成,每一步都在潜在空间中进行小的调整。
-
解码器:经过多次迭代后,最终的潜在表示 Z′ 被输入到解码器中,解码器将其转换为最终的生成图像 X′。
3.潜在表示 Z 为什么是高维空间中的“点”?
其实,所谓的“点”,是从 572 * 572 * 1 变成了 32 * 32 * 1024,只是变小了,升维了而已
经过卷积之后,才会变成高维的小图像,而不是一开始就是高维
在图中,最开始的 Z 是一个格式为 572 * 572 * 1 的张量。这意味着 Z 是一个具有单通道(channel)的二维噪声图像。尽管它看起来是一个二维结构,但在扩散模型的上下文中,它仍然可以被理解为在一个高维空间中的点。这里有几个关键点可以解释这个问题:
- 高维空间的定义:
-
在机器学习和深度学习的上下文中,高维空间并不一定仅仅指向量的维数。它可以指的是特征的数量或描述数据结构的维数。
-
在这里,虽然 Z 是一个二维图像,但它的每个像素都可以看作是一个独立的维度。因此,572 * 572 的像素总数其实是 327,184 个channel==1的维度。
- 表示的多样性:
-
虽然 Z 初始是单通道的二维噪声图像,但在随后的扩散过程中,它会被处理和转换,逐渐演变为更高维的表示。
-
当 Z 被输入到扩散模型(例如 U-Net)时,模型的多个卷积层会逐步将低维表示转换为高维表示。例如,通过多个卷积操作,初始的单通道表示会变成多通道的特征图。
- 模型架构:
-
扩散模型的架构(如 U-Net)通过多层卷积和反卷积操作,将初始的低维噪声图像逐步转化为高维特征表示。每个卷积层的输出是更高维的特征图,这些特征图包含了更多关于图像的高层次信息。
-
在 U-Net 的跳跃连接(skip connections)中,低层次的特征会被传递到更高层次的特征,帮助模型更好地捕捉图像的细节。
4.举例说明
假设我们有一个初始的 572 * 572 * 1 的噪声图像:
-
初始状态:这是一个二维的噪声图像,每个像素值是随机的。
-
卷积操作:通过一系列的卷积操作,图像的通道数会增加。例如,第一次卷积后,图像可能变成 572 \times 572 \times 64,这意味着它被表示为 64 个不同的特征图,每个特征图都提取了不同层次的信息。
-
多层处理:随着更多的卷积层和池化层的应用,特征图的尺寸会逐渐变小,但通道数会增加。例如,经过几次卷积和池化操作后,图像可能变成 128 * 128 * 256。
-
高维表示:最终的高层次特征表示是一个更小尺寸但更多通道的张量,例如 32 * 32 * 1024。这个表示虽然在空间上是 32 * 32 的二维结构,但它有 1024 个通道,这实际上是一个高维空间中的点。
5.为什么选择这种表示方式?
-
高效的表示:在高维潜在空间中,图像的复杂结构可以通过较少的维度进行高效表示。这使得生成过程更加高效。
-
渐进式生成:通过扩散过程,模型可以在每一步中逐步逼近目标图像。这种方式能够更好地控制生成的过程,并且生成的图像质量较高。
-
灵活性:这种潜在表示可以很容易地结合其他信息(例如文本嵌入和时间嵌入),使得模型能够根据输入条件生成对应的图像。
6.总结
-
Z 是什么:Z 是一个多维的潜在表示张量,初始时是随机噪声,通过扩散过程逐步被转换为目标图像。
-
格式:Z 通常是一个张量,尺寸与图像编码器的输出尺寸相关。
-
性质:它表示在潜在空间中的一个点,捕捉了生成图像的高层次特征和结构。
二、什么是 CLIP Encoder?
1.CLIP Encoder 说明书
在看什么是 CLIP Encoder 之前,你要知道,它最主要的功能就是将 自然语言 转变为了 嵌入向量(One-Hot 编码的嵌入向量)
2.为什么 CLIP 的终止层数一般设置在 2 ?
-
匹配特定任务:某些任务可能对高层次的语义特征要求较低,而对低层次的特征要求较高。通过终止较低的层数,可以获取更多的低层次特征。
-
过拟合防止:减少层数可以在一定程度上防止过拟合,特别是在训练数据量较少或者数据多样性不足的情况下。
三、什么是 UNet?(重点!!!)
1.UNet的由来
UNet架构最初被提出是作为医学图像分割的解决方案,独特的结构使其擅长处理高分辨率的内容。
本质上,UNet 生成的东西是“噪声”,而不是 图像。图像 是“噪声”去噪之后的产物。
所以说,在 UNet 进行学习的时候,学习的就是某个内容的“噪声分布概率函数”,也就是,什么东西最有可能在什么地方,并且认出这个噪声代表了什么参数。比如说,噪声A 代表了 1girl,而噪声B 代表了 1boy。
2.UNet 的级联用法
我们可以将很多 UNet 串联在一起,每个 UNet 都负责处理 前一个 UNet 生成出来的图像,并且提高这些图像的分辨率。这就是“HI-Res”,高清修复。
3.UNet 是如何实现逐渐学习的?
下面这些过程很好地说明了它是如何学习的。
首先,最开始 UNet 是一张白纸,它什么都做不了。
我们给它喂一张图片(Input)→ UNet 处理 → UNet 尝试了一次生成 →
生成的图像与原本的图像进行对比,通过LOSS损失函数,更新 UNet 的神经网络节点权重 →
如此反复这个过程,迭代,它生成的图像就会越来越好。
4.UNet 的 结构
UNet 之所以被称为 UNet,是因为它处理数据的流程图,就好像一个 U 一样。
首先,UNet 的主要组成部分是 1 个 Encoder(编码器) 和 1 个 Decoder(解码器)
Encoder,编码器,负责从 Input 中(输入的图像中)提取特征。
Decoder,解码器,负责对中间特征进行上采样,并产生最终的输出。
这个过程,和 全卷积神经网络(FCN) 是很像的,都是一个 下采样 → 上采样 的过程
4.UNet 和 FCN 的区别在哪儿?
其实只有一个差别,就是 UNet 照比 FCN 添加了一个 copy and crop(复制并裁剪) 的过程
逐步进行解释。
== 注意,UNet 中的卷积是 二维卷积,不是 三维卷积 ==
input 第一层
(一共经过了 64 个 filter,所以 3x3 conv 之后,channel 变为了 64)
(w、h 计算公式:[ ( n + 2p - f )/ 1 ] + 1。n 代表 w、h;p 代表 padding;f 代表 filter)
1.1 input 的 w、h、c 分别为 572 * 572 * 1
1.2 经过 3x3 conv 卷积,64 filter,o1 = [ ( 572 + 2*0 - 3 )/ 1 ] + 1 == 570
1.3 经过 3x3 conv 卷积,0 filter,o2 = [ ( 570 + 2*0 - 3 )/ 1 ] + 1 == 568
MAX pooling( input-1 → input-2)
池化层 公式:
O 代表 outputSize,I 代表 inputSize,
F 代表 convolution kernel(卷积核)或 pooling window(池化窗口)的大小
P 代表 padding(default == 0),S 代表 strike(步数)
所以,池化公式:O = [ ( I + 2P - F ) / S ] + 1,
这不就是卷积公式吗???看来它们的公式是通用的!
O = [ ( 568 + 2 * 0 - 2 ) / 2 ] + 1 == 284
所以池化后的网络变为了 284 * 284 * 64
后面的步骤只是前面步骤的重复,不加赘述。