Diffusion Model 和 Stable Diffusion 详解

news2024/9/20 16:55:29

文章目录

  • Diffusion Model 基础
    • 生成模型
    • DDPM概述
    • 向前扩散过程
      • 前向扩散的逐步过程
      • 前向扩散的整体过程
    • 反向去噪过程
    • 网络结构
    • 训练和推理过程
      • 训练过程
      • 推理过程
      • 优化目标
  • 详细数学推导
    • 数学基础
    • 向前扩散过程
    • 反向去噪过程
  • Stable Diffusion
    • 组成结构
    • 运行流程
    • 网络结构
      • VAE 模型
      • 文本编码器
      • 噪音预测器
      • Unet 模型
    • 训练过程和损失函数
  • 参考

Diffusion Model 基础

生成模型


常见的生成模型有:

  • GAN
  • VAE
  • Flow-based
    在这里插入图片描述
    与 VAE 或Flow-based 模型不同,扩散模型是通过固定的过程学习的,latent variable 具有高维度(与原始数据相同)。

文生图模型的基本架构如下:

  • 文本编码器(Text Encoder)用于编码文本的输入
  • 生成模型 (Generation Model)输入文字和杂讯,生成一个中间产物(这个中间产物可以是人看得懂的一个压缩图片,也可以是噪音)
  • 解码器 (Decoder) 解码器,输入中间产物,得到最终的输出的图片。
    通常而言,上述的三个模型是分开训练的,最后组合到一起。
    在这里插入图片描述
  • 例如 Stable Diffusion
    在这里插入图片描述
  • DALL-E
    在这里插入图片描述
  • Imagen
    在这里插入图片描述

衡量图像生成质量的指标

  • FID
    将生成的图片和真是的图片都输入到预训练好的CNN模型中,然后计算输出高斯分布的Frechet的距离。其值越小越好。
    在这里插入图片描述
  • CLIP score
    将生成的图片和输入的文本提示,分别送入Image encoder 和text encoder ,计算二者输出的距离。如果图像文本匹配,则距离越近越好。如果不匹配,则其距离越远越好。CLIP score的得分越大越好。
    在这里插入图片描述

DDPM概述

  • 基本思想
    Denoising Diffusion Probabilistic Models (DDPM)
    受非平衡统计物理启发[1],是通过一个迭代的向前扩散过程 ,系统地、缓慢地破坏数据分布中的结构。然后,我们学习一个逆扩散过程将数据中的结构恢复,从而产生一个高度灵活且易于处理的数据生成模型

💡 原文中作者对于基本思想的描述:“The essential idea, inspired by non-equilibrium statistical physics [1], is to systematically and slowly destroy structure in a data distribution* through an iterative forward diffusion process. We then learn a reverse diffusion process that restores structure in data, yielding a highly flexible and tractable generative model of the data.”

  • 核心步骤

基于上述思想,Denoising diffusion 模型包括两个过程:

  • 向前扩散过程 (Forward Diffusion): 逐渐向输入添加噪声
  • 反向去噪过程 (Reverse Denoising): 学习通过去噪生成数据
    在这里插入图片描述

向前扩散过程

前向扩散的逐步过程

首先,我们先来介绍一下如何破坏数据分布。
在这里插入图片描述

前向扩散过程中的输入和输出

如果我们取任何一幅图像(上图a),它具有某种非随机分布。我们不知道这个分布,但我们的目标是破坏它,我们可以通过向其添加噪声来实现。在这个过程的最后,我们应该得到类似于纯噪声的噪声(上图b)。
在这里插入图片描述

T0时刻: 将噪音线性添加到图片上,得到的新图片作为T1时刻的输入

在这里插入图片描述

T1时刻: 将噪音线性添加到T0时刻的输出,得到的新图片作为T2时刻的输入

在这里插入图片描述

Tn时刻: 在最后一个step,原始的信息被完全破坏,得到一个纯噪音的图片。

前向扩散过程的每一步被定义为 q ( x t ∣ x t − 1 ) = N ( x t , 1 − β t x t − 1 , β t I ) q(x_t|x_{t-1})= \mathcal{N}\left(x_t, \sqrt{1-\beta_t} x_{t-1}, \beta_t I\right) q(xtxt1)=N(xt,1βt xt1,βtI)
其中 q q q是前向扩散过程, x t x_t xt是第 t t t步前向过程的输出(自然地, x t − 1 x_{t-1} xt1是第 t t t步的输入)。 N \mathcal{N} N是一个正态分布, 1 − β t x t − 1 \sqrt{1-\beta_t} x_{t-1} 1βt xt1是均值, β t I \beta_t I βtI定义了一个方差。


调度 (Schedule)
β t \beta_t βt被称为调度(schedule),其值范围从0到1不等。通常将值保持在较低水平,以防止方差爆炸。

  • 线性调度(Linear Schedule)

DDPM论文 [2] 使用了一个线性调度,因此输出看起来如下图:
在这里插入图片描述

使用线性调度(linear schedule)的前向扩散模型的1000个时间步

在线性调度的情况下, β t \beta_t βt从0.0001线性增加到0.02, 均值和方差也随着时间步线性变化(如下图)。
在这里插入图片描述

均值和方差随着时间步的变化过程
  • 余弦调度(Cosine Schedule)

OpenAI的研究人员在他们的2021年论文中 [3] 发现使用线性调度并不那么高效。因此提出了余弦调度(下图)。这种改进使得步骤数减少到50步。
在这里插入图片描述

使用余弦调度(cosine schedule)的前向扩散模型的50个时间步

前向扩散的整体过程

使用前向扩散过程向图像添加噪声将会很慢。训练过程不使用与前向过程一致的示例,而是使用来自任意时间步 t 的样本。这意味着在每个训练步骤中,我们需要通过 t 步来生成 1 个训练样本。
q ( x 1 : T ∣ x 0 ) : = ∏ t = 1 T q ( x t ∣ x t − 1 ) q\left(x_{1: T} \mid x_0\right):=\prod_{t=1}^T q\left(x_t \mid x_{t-1}\right) q(x1:Tx0):=t=1Tq(xtxt1)
接下来,我们对上式进行逐步分解:
q t ( q t − 1 ( q t − 2 ( q t − 3 ( ⋯ q 1 ( x 0 ) ) ) ) ) q_t\left(q_{t-1}\left(q_{t-2}\left(q_{t-3}\left(\cdots q_1\left(x_0\right)\right)\right)\right)\right) qt(qt1(qt2(qt3(q1(x0)))))
t 1 t_1 t1时刻
q ( x 1 ∣ x 0 ) = N ( x 1 , 1 − β 1 x 0 , β 1 I ) q\left(x_1 \mid x_0\right)=\mathcal{N}\left(x_1, \sqrt{1-\beta_1} x_0, \beta_1 I\right) q(x1x0)=N(x1,1β1 x0,β1I)
t 2 t_2 t2时刻
q ( x 2 ∣ x 1 ) = N ( x 2 , 1 − β 2 x 1 , β 2 I ) q\left(x_2 \mid x_1\right)=\mathcal{N}\left(x_2, \sqrt{1-\beta_2} x_1, \beta_2 I\right) q(x2x1)=N(x2,1β2 x1,β2I)
从上面的公式可以看到,只有均值是依赖于上一步的输出,方差对于任意一步都是已知的(因为 β \beta β 对于每一个时间步都是已知的)。
因此,引入下面两个记号:
α t = 1 − β t α ˉ t : = ∏ s = 1 t a s \begin{aligned} \alpha_t & =1-\beta_t \\ \bar{\alpha}_t & :=\prod_{s=1}^t a_s \end{aligned} αtαˉt=1βt:=s=1tas
代入上述记号,每一步的加噪公式变为:
q ( x 1 ∣ x 0 ) = N ( x 1 , α 1 x 0 , ( 1 − α 1 ) I ) q\left(x_1 \mid x_0\right)=\mathcal{N}\left(x_1, \sqrt{\alpha_1} x_0,\left(1-\alpha_1\right) I\right) q(x1x0)=N(x1,α1 x0,(1α1)I)
q ( x 2 ∣ x 1 ) = N ( x 2 , α 2 x 1 , ( 1 − α 2 ) I ) q\left(x_2 \mid x_1\right)=\mathcal{N}\left(x_2, \sqrt{\alpha_2} x_1,\left(1-\alpha_2\right) I\right) q(x2x1)=N(x2,α2 x1,(1α2)I)
整个过程的均值计算如下:
μ t = α t x t − 1 = α t ∗ α t − 1 x t − 2 = α t α t − 1 x t − 2 = α t α t − 1 ∗ α t − 2 x t − 3 = α t α t − 1 α t − 2 x t − 3 = α t α t − 1 α t − 2 ⋯ ∗ α 1 x 0 = α t α t − 1 α t − 2 ⋯ α 1 x 0 = α ˉ t x 0 \begin{gathered} \mu_t=\sqrt{\alpha_t} x_{t-1} \\ =\sqrt{\alpha_t} * \sqrt{\alpha_{t-1}} x_{t-2}=\sqrt{\alpha_t \alpha_{t-1}} x_{t-2} \\ =\sqrt{\alpha_t \alpha_{t-1}} * \sqrt{\alpha_{t-2}} x_{t-3}=\sqrt{\alpha_t \alpha_{t-1} \alpha_{t-2}} x_{t-3} \\ =\sqrt{\alpha_t \alpha_{t-1} \alpha_{t-2} \cdots} * \sqrt{\alpha_1} x_0=\sqrt{\alpha_t \alpha_{t-1} \alpha_{t-2} \cdots \alpha_1} x_0 \\ =\sqrt{\bar{\alpha}_t} x_0 \end{gathered} μt=αt xt1=αt αt1 xt2=αtαt1 xt2=αtαt1 αt2 xt3=αtαt1αt2 xt3=αtαt1αt2 α1 x0=αtαt1αt2α1 x0=αˉt x0
最终可以写出从 0 到 t 的整个过程的公式:
q ( x t ∣ x 0 ) = N ( x t , α ˉ t x 0 , ( 1 − α ˉ t ) I ) q\left(x_t \mid x_0\right)=\mathcal{N}\left(x_t, \sqrt{\bar{\alpha}_t} x_0,\left(1-\bar{\alpha}_t\right) I\right) q(xtx0)=N(xt,αˉt x0,(1αˉt)I)

然而上述的过程是无法计算的,需要对每一步前向步骤应用重参数化技巧: N ( μ , σ 2 ) = μ + σ ∗ ϵ \mathcal{N}\left(\mu, \sigma^2\right)=\mu+\sigma * \epsilon N(μ,σ2)=μ+σϵ, 其中 ϵ \epsilon ϵ来自于 N ( 0 , 1 ) \mathcal{N}(0,1) N(0,1)
q ( x t ∣ x t − 1 ) = N ( x t , 1 − β t x t − 1 , β t I ) = 1 − β t x t − 1 + β t ϵ \begin{gathered} q\left(x_t \mid x_{t-1}\right)=\mathcal{N}\left(x_t, \sqrt{1-\beta_t} x_{t-1}, \beta_t I\right) \\ =\sqrt{1-\beta_t} x_{t-1}+\sqrt{\beta_t} \epsilon \end{gathered} q(xtxt1)=N(xt,1βt xt1,βtI)=1βt xt1+βt ϵ
因为我们知道 t = 1.. T t=1..T t=1..T 的公式是什么,我们可以使用这个技巧来得到可计算的方程式。
q ( x t ∣ x t − 1 ) = N ( x t , 1 − β t x t − 1 , β t I ) = 1 − β t x t − 1 + β t ϵ \begin{gathered} q\left(x_t \mid x_{t-1}\right)=\mathcal{N}\left(x_t, \sqrt{1-\beta_t} x_{t-1}, \beta_t I\right) \\ =\sqrt{1-\beta_t} x_{t-1}+\sqrt{\beta_t} \epsilon \end{gathered} q(xtxt1)=N(xt,1βt xt1,βtI)=1βt xt1+βt ϵ

反向去噪过程


可视化步骤
在这里插入图片描述

第 t 步: 从预测的噪声中取一部分,并将其从输入中减去。减法量由调度定义。第一步只减去预测噪声的一小部分,后续步骤逐渐减去更多预测的噪声。

在这里插入图片描述

将第t步的输出变成第t-1步的输入

在这里插入图片描述

第t-1步:再次生成整个噪声,这一次取更多的噪声并从输入中减去(因为 beta 增加),输出的结果作为t-2步的输入

在这里插入图片描述

第1步:得到最终生成的图像

数学推导
论文中定义的反向去噪的公式如下:
p θ ( x 0 : T ) : = p ( x T ) ∏ t = 1 T p θ ( x t − 1 ∣ x t ) p_\theta\left(x_{0: T}\right):=p\left(x_T\right) \prod_{t=1}^T p_\theta\left(x_{t-1} \mid x_t\right) pθ(x0:T):=p(xT)t=1Tpθ(xt1xt)
其中
p θ ( x t − 1 ∣ x t ) = N ( x t − 1 , μ θ ( x t , t ) , ∑ θ ( x t , t ) ) p_\theta\left(x_{t-1} \mid x_t\right)=\mathcal{N}\left(x_{t-1}, \mu_\theta\left(x_t, t\right), \sum_\theta\left(x_t, t\right)\right) pθ(xt1xt)=N(xt1,μθ(xt,t),θ(xt,t))
扩散过程 p θ ( x 0 : T ) p_\theta\left(x_{0: T}\right) pθ(x0:T)是一个从 p ( x T ) p(x_T) p(xT)开始的高斯转换链 (chain of gaussian transitions),使用一个扩散过程步骤的方程在 𝑇 次迭代中进行,即 p θ ( x t − 1 ∣ x t ) p_\theta\left(x_{t-1} \mid x_t\right) pθ(xt1xt)

N ( x t − 1 , μ θ ( x t , t ) , ∑ θ ( x t , t ) ) \mathcal{N}\left(x_{t-1}, \mu_\theta\left(x_t, t\right), \sum_\theta\left(x_t, t\right)\right) N(xt1,μθ(xt,t),θ(xt,t)) 包含两个部分 :

  • 第一个部分是均值 μ θ ( x t , t ) \mu_\theta\left(x_t, t\right) μθ(xt,t)

μ θ ( x t , t ) = 1 α t ( x t − 1 − α t 1 − α ˉ t ϵ θ ( x t , t ) ) \mu_\theta\left(x_t, t\right)=\frac{1}{\sqrt{\alpha_t}}\left(x_t-\frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}} \epsilon_\theta\left(x_t, t\right)\right) μθ(xt,t)=αt 1(xt1αˉt 1αtϵθ(xt,t))

  • 第二部分是方差 ∑ θ ( x t , t ) \sum_\theta\left(x_t, t\right) θ(xt,t) (等于 σ t 2 I \sigma_t^2 I σt2I
    方差是不可训练的,但是依赖于时间变化,即 β T I \beta_TI βTI (这里的 β \beta β 和前向过程中的 β \beta β一致,都表示的是调度)

这里先不涉及具体的推导,只是简单介绍下流程,具体的推导可以参考论文中的Appendix A [2] 和Lilian Weng的博文[b.5]

这样,我们可以得到 x t − 1 x_{t-1} xt1
x t − 1 = N ( x t − 1 , 1 α t ( x t − β t 1 − α ˉ t ϵ θ ( x t , t ) ) , β t ϵ ) x_{t-1}=\mathcal{N}\left(x_{t-1}, \frac{1}{\sqrt{\alpha_t}}\left(x_t-\frac{\beta_t}{\sqrt{1-\bar{\alpha}_t}} \epsilon_\theta\left(x_t, t\right)\right), \sqrt{\beta_t} \epsilon\right) xt1=N(xt1,αt 1(xt1αˉt βtϵθ(xt,t)),βt ϵ)
进一步的,我们计算给定时间步t时刻的输出:
x t − 1 = 1 a t ( x t − β t 1 − α ˉ ϵ θ ( x t , t ) ) + β t ϵ x_{t-1}=\frac{1}{\sqrt{a_t}}\left(x_t-\frac{\beta_t}{\sqrt{1-\bar{\alpha}}} \epsilon_\theta\left(x_t, t\right)\right)+\sqrt{\beta_t} \epsilon xt1=at 1(xt1αˉ βtϵθ(xt,t))+βt ϵ
其中 ϵ θ ( x t , t ) \epsilon_\theta\left(x_t, t\right) ϵθ(xt,t) 是模型的输出,即预测出的噪音。

网络结构

模型架构是修改后的 U-Net 架构 [4]。它非常简单,但随着对扩散模型的进一步改进(例如,Stabel Diffusion 增加了整个潜在层用于图像数据嵌入)。在这里,我们先只讨论Diffusion Model的最初版本

在这里插入图片描述
首先修改的Unet 架构,将基础的ResNetBlock替换成Self-Attention Block, 或者修改后的ResNet Block。
在这里插入图片描述
然后,为了防止信息丢失,添加跳跃连接(skip connection)
在这里插入图片描述
下一步是添加关于当前时间步 t 的信息。为此,我们使用正弦嵌入(sinusoidal embedding),该信息被添加到所有下采样和上采样块中。
在这里插入图片描述
为了使网络是条件化的(依赖于外部输入),我们添加了一个文本嵌入器。它将为给定的文本创建嵌入,并将输出向量添加到时间步嵌入中。
在这里插入图片描述


ResNet Block
ResNet Block的结构如下,被用于下采样和上采样块的一部分。
在这里插入图片描述


Downsample Block
在这里插入图片描述
下采样块是第一个不仅接收来自前一层的数据,还接收有关时间步长和提示的数据的块。该块具有2个输入,并且表现为 U-Net 架构中的标准下采样。它接收输入并将其下采样到下一层的大小。
它使用 MaxPool2d 层(核大小为2),将输入大小减半(64x64 -> 32x32)。之后,连接2个 ResNet 块。
嵌入经过 Sigmoid 线性单元处理,然后通过一个简单的Linear层,以达到与 ResNet 块输出相同的形状。之后,两个张量相加,并发送到下一个块。


Self-Attention Block
在这里插入图片描述

所有的注意力块的结构都相同,所以将用第一个来描述所有的注意力块(就在第一个下采样之后)。

首先,它接收一个形状为 (128, 32, 32) 的下采样张量。
然后,对输入张量进行reshape: 压缩最后两个维度,然后翻转得到的张量((128,32,32) -> (128, 1024) -> (1024, 128))并通过层归一化,并将其用作所有 3 个输入张量(Q、K、V)
接着,输入到一个多头注意力(Multi-Head Attention, MHA),嵌入维度设置为 128,有 4 个注意力头。嵌入维度在注意力块之间变化(取决于输入长度),而头的数量保持不变。

在块内部,作者添加了两个跳跃连接,与自注意力输出组合。
第一个连接将reshape 后的输入添加到注意力层的输出中,并通过前向层(Normalization -> Linear -> GELU -> Linear)传递。
第二个连接从该层获取输出,并将其添加回注意力的输出。

最后,我们需要对张量进行reshape,最终输出的大小和输入大小一致((1024, 128) -> (128, 32, 32))。


Upsample block
在这里插入图片描述
使用一个简单的上采样层,缩放因子为2。
通过上采样层传递输入张量后,我们可以将其与残差连接(来自第一个 ResNet 块)连接起来。现在,它们两者的形状都是 (64, 64, 64)。
连接的张量然后通过 2 个 ResNet 块发送(与我们在下采样块中所做的相同)
第三个输入(再次与下采样块中相同)通过 SILU 和线性层发送,然后添加到第二个 ResNet 块的结果中。
整个架构以 Conv2d 层结束,该层使用核大小为 1,将我们的张量从 (64,64,64) 缩放回 (3, 64,64)。这是我们预测的噪声。

训练和推理过程

训练过程

在这里插入图片描述

上图是训练的伪代码:

  • 数据集中采样一张图片 x 0 x_0 x0
  • 采样一个时间步 t t t
  • 从正态分布中采样一个噪音 ϵ \epsilon ϵ
  • 前面我们定义过了如何在时间步t时刻,在无需迭代的情况下前向加噪 q ( x t ∣ x 0 ) = α ˉ t x 0 + 1 − α ˉ t ϵ q\left(x_t \mid x_0\right)=\sqrt{\bar{\alpha}_t} x_0+\sqrt{1-\bar{\alpha}_t} \epsilon q(xtx0)=αˉt x0+1αˉt ϵ, 然后用梯度下降去训练网络模型 ϵ θ \epsilon_\theta ϵθ ( ϵ θ \epsilon_\theta ϵθ是用于学习生成噪音的模型Noise Predicter)。
  • 然后重复整个过程,直到模型最终收敛。

下图是训练过程的第5步的图解:
在这里插入图片描述

下图是Noise Predicter 的图解实例,它的输入有两个:一个是时间步t, 另外一个是时间步t时刻对应的添加的噪音。
在这里插入图片描述
下图是实际的训练过程。input和ground truth和时间步 来自于前向加噪的过程。在实际应用中,Noise Predicter 还会有个文本提示的输入。
在这里插入图片描述

推理过程

推理
在这里插入图片描述
上图是推理的伪代码:
1) 先从标准高斯分布中采样一个噪音
2)从时间步 T T T开始,逐步推理前一步的输出 (输入t时刻的带噪图片 x t x_t xt,生成t-1时刻的带噪音图片 x t − 1 x_{t-1} xt1)。

优化目标

对于真实的图片分布 P d a t a P_{data} Pdata中采样一些图片 x 1 , x 2 , x 3 . . . x^1,x^2,x^3... x1,x2,x3... 。然后从一个标准的高斯分布中采样一个噪音,通过生成网络(需要训练的参数集是 θ \theta θ) 得到生成图片的分布。
优化的目标是,对于给定的图片 x i x^i xi, 生成网络生成 x i x^i xi的概率越大越好。
在这里插入图片描述
最大化生成分布和真实分布的相似性 等价于 最小化二者的KL散度,推理步骤如下:
在这里插入图片描述

第一行:取log 并不印象最大化的计算
第二行:根据log的计算性质进行变换 l o g ( x 1 ) ∗ l o g ( x 2 ) = l o g ( x 1 + x 2 ) log(x_1)*log(x_2)=log(x_1+x_2) log(x1)log(x2)=log(x1+x2); 最终的求和式子近似于计算 期望值
第三行:用连续积分的形式计算期望,后面减去的部分是和 θ \theta θ 不相关的,不会影响最大化的结果。
第四行: l o g ( x 1 − x 2 ) = l o g ( x 1 ) / l o g ( x 2 ) log(x_1-x_2)=log(x_1)/ log(x_2) log(x1x2)=log(x1)/log(x2) 最终变换成KL散度的形式。

详细数学推导

数学基础


高斯分布
定义:随机变量X服从一个数学期望 μ \mu μ、方差为 σ \sigma σ的高斯分布,又名正态分布。
μ = 0 , σ = 1 \mu=0, \sigma=1 μ=0,σ=1时的正态分布是标准正态分布。
高斯分布概率密度函数(正态随机变量概率密度函数):
f ( x ) = 1 2 π σ exp ⁡ ( − ( x − μ ) 2 2 σ 2 ) f(x)=\frac{1}{\sqrt{2 \pi} \sigma} \exp \left(-\frac{(x-\mu)^2}{2 \sigma^2}\right) f(x)=2π σ1exp(2σ2(xμ)2)


两个高斯分布相加
已知两个独立的高斯分布:
N 1 ∼ ( u 1 , δ 1 2 ) , N 2 ∼ ( u 2 , δ 2 2 ) N_1 \sim\left(u_1, \delta_1^2\right), N_2 \sim\left(u_2, \delta_2^2\right) N1(u1,δ12),N2(u2,δ22)
这两个高斯分布的和,仍然是一个高斯分布
N 1 + N 2 ∼ ( u 1 + u 2 , δ 1 2 + δ 2 2 ) N_1+N_2 \sim\left(u_1+u_2, \delta_1^2+\delta_2^2\right) N1+N2(u1+u2,δ12+δ22)
同理,这两个高斯分布的差为:
N 1 − N 2 ∼ ( u 1 − u 2 , δ 1 2 + δ 2 2 ) N_1-N_2 \sim\left(u_1-u_2, \delta_1^2+\delta_2^2\right) N1N2(u1u2,δ12+δ22)


重参数化
N ( μ , σ 2 ) = μ + σ ∗ ϵ N\left(\mu, \sigma^2\right)=\mu+\sigma * \epsilon N(μ,σ2)=μ+σϵ
其中 ϵ \epsilon ϵ来自于 N ( 0 , 1 ) \mathcal{N}(0,1) N(0,1)


贝叶斯定理
条件概率:在已知一个事件 B B B 发生的情况下,此时另一个事件A发生的概率,符号表示为 P ( A ∣ B ) P(A \mid B) P(AB) ,它等于联合概率 P ( A , B ) P(A, B) P(A,B) 除以边缘分布 P ( B ) P(B) P(B), 即:
P ( A ∣ B ) = P ( A , B ) P ( B ) P(A \mid B)=\frac{P(A, B)}{P(B)} P(AB)=P(B)P(A,B)
或可以写成:
P ( A , B ) = P ( A ∣ B ) ⋅ P ( B ) P(A, B)=P(A \mid B) \cdot P(B) P(A,B)=P(AB)P(B)
表示事件A,B联合概率等于在B发生的条件下A发生的条件概率乘以B事件发生概率。
由于P(A,B)也等于P(B|A)P(A) (P(A,B)与P(B,A)含义相同,数值相等),所以推导出贝叶斯公式:
P ( A ∣ B ) = P ( A , B ) P ( B ) = P ( B ∣ A ) ⋅ P ( A ) P ( B ) P(A \mid B)=\frac{P(A, B)}{P(B)}=\frac{P(B \mid A) \cdot P(A)}{P(B)} P(AB)=P(B)P(A,B)=P(B)P(BA)P(A)


KL散度

向前扩散过程

给定从真实数据分布中采样的数据点 x 0 ∼ q ( x ) \mathbf{x}_0 \sim q(\mathbf{x}) x0q(x),让我们定义一个前向扩散过程,在其中我们在 T T T 步中向样本添加小量的高斯噪声,产生一系列带有噪声的样本 x 1 , … , x T \mathbf{x}_1, \ldots, \mathbf{x}_T x1,,xT。步长由方差调度 { β t ∈ ( 0 , 1 ) } t = 1 T \left\{\beta_t \in(0,1)\right\}_{t=1}^T {βt(0,1)}t=1T控制。
q ( x t ∣ x t − 1 ) = N ( x t ; 1 − β t x t − 1 , β t I ) q ( x 1 : T ∣ x 0 ) = ∏ t = 1 T q ( x t ∣ x t − 1 ) q\left(\mathbf{x}_t \mid \mathbf{x}_{t-1}\right)=\mathcal{N}\left(\mathbf{x}_t ; \sqrt{1-\beta_t} \mathbf{x}_{t-1}, \beta_t \mathbf{I}\right) \quad q\left(\mathbf{x}_{1: T} \mid \mathbf{x}_0\right)=\prod_{t=1}^T q\left(\mathbf{x}_t \mid \mathbf{x}_{t-1}\right) q(xtxt1)=N(xt;1βt xt1,βtI)q(x1:Tx0)=t=1Tq(xtxt1)
随着步长 t t t的增大,数据样本 x 0 \mathbf{x_0} x0逐渐失去其可区分的特征。最终,当 T T T趋向于正无穷时, x t \mathbf{x_t} xt等效于一个各向同性的高斯分布。

在这里插入图片描述

通过逐渐添加(去除)噪声生成样本的前向(反向)扩散过程的马尔可夫链。

我们可以使用重参数化技巧在任意时间步 t t t中以封闭形式对 x t \mathbf{x_t} xt进行采样。
α t = 1 − β t \alpha_t=1-\beta_t αt=1βt α ˉ t = ∏ i = 1 t α i \bar{\alpha}_t=\prod_{i=1}^t \alpha_i αˉt=i=1tαi
x t = α t x t − 1 + 1 − α t ϵ t − 1 ;  where  ϵ t − 1 , ϵ t − 2 , ⋯ ∼ N ( 0 , I ) = α t α t − 1 x t − 2 + 1 − α t α t − 1 ϵ ˉ t − 2 ;  where  ϵ ‾ t − 2  merges two Gaussians  ( ∗ ) .  = … = α ˉ t x 0 + 1 − α ˉ t ϵ q ( x t ∣ x 0 ) = N ( x t ; α ˉ t x 0 , ( 1 − α ˉ t ) I ) \begin{aligned} & \mathbf{x}_t=\sqrt{\alpha_t} \mathbf{x}_{t-1}+\sqrt{1-\alpha_t} \boldsymbol{\epsilon}_{t-1} \quad \quad ; \text { where } \boldsymbol{\epsilon}_{t-1}, \boldsymbol{\epsilon}_{t-2}, \cdots \sim \mathcal{N}(\mathbf{0}, \mathbf{I}) \\ & =\sqrt{\alpha_t \alpha_{t-1}} \mathbf{x}_{t-2}+\sqrt{1-\alpha_t \alpha_{t-1}} \bar{\epsilon}_{t-2} \quad ; \text { where } \overline{\boldsymbol{\epsilon}}_{t-2} \text { merges two Gaussians }\left(^*\right) \text {. } \\ & =\ldots \\ & =\sqrt{\bar{\alpha}_t} \mathbf{x}_0+\sqrt{1-\bar{\alpha}_t} \boldsymbol{\epsilon} \\ & q\left(\mathbf{x}_t \mid \mathbf{x}_0\right)=\mathcal{N}\left(\mathbf{x}_t ; \sqrt{\bar{\alpha}_t} \mathbf{x}_0,\left(1-\bar{\alpha}_t\right) \mathbf{I}\right) \\ & \end{aligned} xt=αt xt1+1αt ϵt1; where ϵt1,ϵt2,N(0,I)=αtαt1 xt2+1αtαt1 ϵˉt2; where ϵt2 merges two Gaussians ()==αˉt x0+1αˉt ϵq(xtx0)=N(xt;αˉt x0,(1αˉt)I)

将两个具有不同方差的高斯分布
N ( 0 , σ 1 2 I ) \mathcal{N}\left(\mathbf{0}, \sigma_1^2 \mathbf{I}\right) N(0,σ12I) N ( 0 , σ 2 2 I ) \mathcal{N}\left(\mathbf{0}, \sigma_2^2 \mathbf{I}\right) N(0,σ22I)合并,得到的新的分布是: N ( 0 , ( σ 1 2 + σ 2 2 ) I ) \mathcal{N}\left(\mathbf{0},\left(\sigma_1^2+\sigma_2^2\right) \mathbf{I}\right) N(0,(σ12+σ22)I).
x t − 1 = α t − 1 x t − 2 + 1 − α t − 1 ϵ t − 2 \mathbf{x}_{t-1}=\sqrt{\alpha_{t-1}} \mathbf{x}_{t-2}+\sqrt{1-\alpha_{t-1}} \boldsymbol{\epsilon}_{t-2} xt1=αt1 xt2+1αt1 ϵt2 代入当上式中,得到:
x t = a t ( a t − 1 x t − 2 + 1 − α t − 1 ϵ 2 ) + 1 − α t z 1 = a t a t − 1 x t − 2 + ( a t ( 1 − α t − 1 ) ϵ 2 + 1 − α t z 1 ) x_t=\sqrt{a_t}\left(\sqrt{a_{t-1}} x_{t-2}+\sqrt{1-\alpha_{t-1}} \boldsymbol{\epsilon}_2\right)+\sqrt{1-\alpha_t} z_1 \\ =\sqrt{a_t a_{t-1}} x_{t-2}+\left(\sqrt{a_t\left(1-\alpha_{t-1}\right)}\boldsymbol{\epsilon}_2+\sqrt{1-\alpha_t} z_1\right) xt=at (at1 xt2+1αt1 ϵ2)+1αt z1=atat1 xt2+(at(1αt1) ϵ2+1αt z1)
由于每次加入的噪音 ϵ 1 \boldsymbol{\epsilon}_1 ϵ1 ϵ 2 \boldsymbol{\epsilon}_2 ϵ2都服从标准高斯分布 N ∼ ( 0 , I ) \mathcal{N} \sim (0, I) N(0,I)
a t ( 1 − α t − 1 ) z 2 ∼ N ( 0 , a t ( 1 − a t − 1 ) ) \sqrt{a_t\left(1-\alpha_{t-1}\right)} z_2 \sim N (0, a_t(1-a_{t-1})) at(1αt1) z2N(0,at(1at1)) , 1 − α t z 1 ∼ N ( 1 − a t ) \sqrt{1-\alpha_t} z_1 \sim N(1-a_t) 1αt z1N(1at)
这两个分布相加
a t ( 1 − α t − 1 ) z 2 + 1 − α t z 1 ∼ N ( 0 , ( 1 − α t ) + α t ( 1 − α t − 1 ) ) = N ( 0 , 1 − α t α t − 1 ) \sqrt{a_t\left(1-\alpha_{t-1}\right)} z_2 + \sqrt{1-\alpha_t} z_1 \sim N(0, \left(1-\alpha_t\right)+\alpha_t\left(1-\alpha_{t-1}\right) )=N(0, 1-\alpha_t \alpha_{t-1}) at(1αt1) z2+1αt z1N(0,(1αt)+αt(1αt1))=N(0,1αtαt1)

通常,当sample变的noise后,我们可以采用更大的更新率。因此 β 1 < β 2 < ⋯ < β T \beta_1<\beta_2<\cdots<\beta_T β1<β2<<βT α ˉ 1 > ⋯ > α ˉ T \bar{\alpha}_1>\cdots>\bar{\alpha}_T αˉ1>>αˉT.


与随机梯度Langevin动力学的联系
Langevin 动力学是物理学中的一个概念,用于统计建模分子系统。结合随机梯度下降,随机梯度 Langevin 动力学( stochastic gradient Langevin dynamics)可以使用更新的马尔可夫链中的梯度 ∇ x log ⁡ p ( x ) \nabla_{\mathbf{x}} \log p(\mathbf{x}) xlogp(x)来从概率密度 p ( x ) p(\mathbf{x}) p(x)中产生样本:
x t = x t − 1 + δ 2 ∇ x log ⁡ p ( x t − 1 ) + δ ϵ t ,  where  ϵ t ∼ N ( 0 , I ) \mathbf{x}_t=\mathbf{x}_{t-1}+\frac{\delta}{2} \nabla_{\mathbf{x}} \log p\left(\mathbf{x}_{t-1}\right)+\sqrt{\delta} \boldsymbol{\epsilon}_t, \quad \text { where } \boldsymbol{\epsilon}_t \sim \mathcal{N}(\mathbf{0}, \mathbf{I}) xt=xt1+2δxlogp(xt1)+δ ϵt, where ϵtN(0,I)
其中 δ \delta δ 是 step size. 当 T → ∞ , ϵ → 0 , x T T \rightarrow \infty, \epsilon \rightarrow 0, \mathbf{x}_T T,ϵ0,xT 等同于true probability density p ( x ) p(\mathbf{x}) p(x).
与标准随机梯度下降相比,随机梯度 Langevin 动力学在参数更新中注入高斯噪声,以避免陷入局部最小值。

反向去噪过程

如果我们能够反转上述过程并从 q ( x t − 1 ∣ x t ) q\left(\mathbf{x}_{t-1} \mid \mathbf{x}_t\right) q(xt1xt) 中采样,我们将能够从高斯噪声输入 x T ∼ N ( 0 , I ) \mathbf{x}_T \sim \mathcal{N}(\mathbf{0}, \mathbf{I}) xTN(0,I) 中重新创建真实样本。请注意,如果 β t \beta_t βt 足够小, q ( x t − 1 ∣ x t ) q\left(\mathbf{x}_{t-1} \mid \mathbf{x}_t\right) q(xt1xt) 也将是高斯分布。不幸的是,我们无法轻松地估计 q ( x t − 1 ∣ x t ) q\left(\mathbf{x}_{t-1} \mid \mathbf{x}_t\right) q(xt1xt),因为它需要使用整个数据集,因此我们需要学习一个模型 p θ p_\theta pθ 来近似这些条件概率,以便运行反向扩散过程。
p θ ( x 0 : T ) = p ( x T ) ∏ t = 1 T p θ ( x t − 1 ∣ x t ) p θ ( x t − 1 ∣ x t ) = N ( x t − 1 ; μ θ ( x t , t ) , Σ θ ( x t , t ) ) p_\theta\left(\mathbf{x}_{0: T}\right)=p\left(\mathbf{x}_T\right) \prod_{t=1}^T p_\theta\left(\mathbf{x}_{t-1} \mid \mathbf{x}_t\right) \quad p_\theta\left(\mathbf{x}_{t-1} \mid \mathbf{x}_t\right)=\mathcal{N}\left(\mathbf{x}_{t-1} ; \boldsymbol{\mu}_\theta\left(\mathbf{x}_t, t\right), \mathbf{\Sigma}_\theta\left(\mathbf{x}_t, t\right)\right) pθ(x0:T)=p(xT)t=1Tpθ(xt1xt)pθ(xt1xt)=N(xt1;μθ(xt,t),Σθ(xt,t))
在这里插入图片描述

训练扩散模型来建模 2D swiss roll 数据的示例。

当条件是 x 0 \mathcal{x_0} x0时,反向条件概率是可处理的。
在这里插入图片描述
使用Bayes法则,可以得到
在这里插入图片描述
其中 C ( x t , x 0 ) C\left(\mathbf{x}_t, \mathbf{x}_0\right) C(xt,x0) 是某个不涉及 x t − 1 \mathbf{x}_{t-1} xt1 的常数项,不影响。

对于上式的第一行,利用贝叶斯定理展开后的三项都是已知的:
q ( x t − 1 ∣ x 0 ) a t ‾ − 1 x 0 + 1 − a t ‾ − 1 ∼ N ( a t ‾ − 1 , x 0 , 1 − a t − 1 ‾ ) q ( x t ∣ x 0 ) α ˉ t x 0 + 1 − α ˉ t z ∼ N ( α ˉ t x 0 , 1 − α ˉ t ) q ( x t ∣ x t − 1 , x 0 ) = a t x t − 1 + 1 − α t z ∼ N ( a t x t − 1 , 1 − α t ) \begin{aligned} & q\left(\mathbf{x}_{t-1} \mid \mathbf{x}_0\right) \quad \sqrt{\overline{a_t}-1} x_0+\sqrt{1-\overline{a_t}}-1 \quad \sim \mathcal{N}\left(\sqrt{\overline{a_t}}-1, x_0, 1-\overline{a_{t-1}}\right) \\ & q\left(\mathbf{x}_t \mid \mathbf{x}_0\right) \quad \sqrt{\bar{\alpha}_t} x_0+\sqrt{1-\bar{\alpha}_t} z \quad \sim \mathcal{N}\left(\sqrt{\bar{\alpha}_t} x_0, 1-\bar{\alpha}_t\right) \\ & q\left(\mathbf{x}_t \mid \mathbf{x}_{t-1}, \mathbf{x}_0\right)=\sqrt{a_t} x_{t-1}+\sqrt{1-\alpha_t} z \quad \sim \mathcal{N}\left(\sqrt{a_t} x_{t-1}, 1-\alpha_t\right) \end{aligned} q(xt1x0)at1 x0+1at 1N(at 1,x0,1at1)q(xtx0)αˉt x0+1αˉt zN(αˉt x0,1αˉt)q(xtxt1,x0)=at xt1+1αt zN(at xt1,1αt)
将标准正态分布展开之后,因为是指数运算,乘法相当于加法,除法相当于减法。因此可以得到第二行。
第三行和第四行进行展开成如下的格式:
exp ⁡ ( − ( x − μ ) 2 2 σ 2 ) = exp ⁡ ( − 1 2 ( 1 σ 2 x 2 − 2 μ σ 2 x + μ 2 σ 2 ) ) \exp \left(-\frac{(x-\mu)^2}{2 \sigma^2}\right)=\exp \left(-\frac{1}{2}\left(\frac{1}{\sigma^2} x^2-\frac{2 \mu}{\sigma^2} x+\frac{\mu^2}{\sigma^2}\right)\right) exp(2σ2(xμ)2)=exp(21(σ21x2σ22μx+σ2μ2))
这样可以进一步的进行配方,得到均值和方差。

按照标准高斯密度函数,均值和方差可以参数化如下(回想一下 α t = 1 − β t \alpha_t=1-\beta_t αt=1βt α ˉ t = ∏ i = 1 T α i ) \left.\bar{\alpha}_t=\prod_{i=1}^T \alpha_i\right) αˉt=i=1Tαi)
在这里插入图片描述

上式均值中 x 0 x_0 x0是未知的,但是我们可以通过从 x 0 x_0 x0生成 x t x_t xt的公式逆过来,得到 x 0 = 1 α ˉ t ( x t − 1 − α ˉ t ϵ t ) \mathbf{x}_0=\frac{1}{\sqrt{\bar{\alpha}_t}}\left(\mathbf{x}_t-\sqrt{1-\bar{\alpha}_t} \epsilon_t\right) x0=αˉt 1(xt1αˉt ϵt) 代入上式,得到:

在这里插入图片描述

然而 ϵ t \epsilon_t ϵt仍然是未知的,这个就是用Unet预测的每个时刻的噪音。

Stable Diffusion

Stable Diffusion(SD)模型,可以用于文生图,图生图,图像inpainting,ControlNet控制生成,图像超分等丰富的任务。

  • 文生图任务是指将一段文本输入到SD模型中,经过一定的迭代次数,SD模型输出一张符合输入文本描述的图片。
    在这里插入图片描述
  • 图生图任务在输入本文的基础上,再输入一张图片,SD模型将根据文本的提示,将输入图片进行重绘以更加符合文本的描述。
    在这里插入图片描述

组成结构

Stable Diffusion 是一个系统,由几个组件和模型构成,而非单独一个模型。

在这里插入图片描述


Text Encoder
功能:对输入的文本进行编码。
实现:CLIP 模型中的文本编码器
输入:文本
输出:77个表征向量,每个有768维度


Image Information Creator
功能:逐渐处理/扩散信息到潜在(信息)空间。
实现:Unet网络+Scheduler
输入:文本向量 和 起始多维数组(结构化的数字列表,也叫Tensor)由噪声组成。
输出:处理后的信息数组

输入:
1) 如果是图生图任务,我们在输入文本信息的同时,还需要将原图片通过图像编码器(VAE Encoder)生成Latent Feature(隐空间特征)作为输入。
2) 如果是文生图任务,我们只需要输入文本信息,再用random函数生成一个高斯噪声矩阵作为Latent Feature的“替代”输入

组成:
1)U-Net网络负责预测噪声,不断优化生成过程,在预测噪声的同时不断注入文本语义信息。
2)schedule算法对每次U-Net预测的噪声进行优化处理(动态调整预测的噪声,控制U-Net预测噪声的强度),从而统筹生成过程的进度。


Image Decoder
图像解码器通过前置信息生成器得到的信息来生成图像。它只在最后的运行一次来生成最终的像素图像。
输入:处理过的信息数组(维度:(4,64,64))
输出:结果图像(维度:(3,512,512)分别是红/绿/蓝,宽,高)

运行流程

在这里插入图片描述
Step 1: 将输入的文本提示通过Text Encoder进行编码, 作为Diffusion 的输入。
Step 2:将随机采样的噪音,也作为Diffusion的输出。
Step 3: 得到处理后的Image information 作为图像解码器的输入。

Diffusion 的过程是step-by-step 的,逐步生成清晰的图片。
下图通过图像解码器可视化每个步骤
在这里插入图片描述
扩散动作发生了多次,每一步都对输入潜在数组上操作以产生更相似于输入文本的新潜在数组,视觉信息来自于模型从所有图像训练语料。
在这里插入图片描述
下图可视化一系列的这些潜在数组:
在这里插入图片描述
在SD中,U-Net的迭代优化步数(Timesteps)大概是50或者100次,在这个过程中Latent Feature的质量不断的变好(纯噪声减少,图像语义信息增加,文本语义信息增加)


回顾Diffusion Model的内部工作原理
假设我们有张图片,我们生成了一些噪声,然后把噪声添加到图像上。
在这里插入图片描述
我们使用相同的方式来生成大量的训练样本。
在这里插入图片描述
使用这份数据集,我们可以训练噪声预测器
在这里插入图片描述
训练好的噪声预测器可以产生一个噪声图像,接来下的一系列降噪步骤,可以预测噪声。
在这里插入图片描述
采样噪声被预测了出来,所以如果我们从图像中减去它就能得到尽可能接近于模型训练样本的图像
在这里插入图片描述
逐步得到最终的生成图像
在这里插入图片描述


潜在空间

之前的Diffusion Model 不管是前向扩散过程还是反向扩散过程,都需要在像素级的图像上进行,当图像分辨率和Timesteps很大时,不管是训练还是前向推理,都非常的耗时。
而Stable Diffusion 将这些过程压缩在低维的Latent隐空间,这样一来大大降低了显存占用和计算复杂度

为了加速图像生成的过程,Stable Diffusion 是在图像的压缩空间上扩散操作。
压缩(和稍后的解压缩/绘制)是经由自编码器完成的。自编码器通过编码器压缩图像到潜在空间,然后只用压缩信息来解码重建。
在这里插入图片描述
在压缩空间上进行前向扩散过程。噪声数据是用在这些潜在空间上的,而非像素图片上的。所以,噪声预测器实际上是被训练在压缩表示上(潜在空间)来预测噪声的。
一旦训练完后,我们就可以通过反向处理(使用自编码器的解码器)来生成图像。
在这里插入图片描述

总结一下SD模型的前向推理过程:
在这里插入图片描述

网络结构

Stable Diffusion模型主要由VAE(变分自编码器,Variational Auto-Encoder),U-Net以及CLIP Text Encoder三个核心组件构成。
在这里插入图片描述

VAE 模型

VAE(变分自编码器,Variational Auto-Encoder)是基于Encoder-Decoder架构的生成模型。VAE的Encoder(编码器)结构能将输入图像压缩为低维Latent特征,并作为U-Net的输入。VAE的Decoder(解码器)结构能将低维Latent特征重建还原成像素级图像。


VAE的核心作用

1) 图像压缩和图像重建
如下图所示:
在这里插入图片描述
当我们输入一个尺寸为 H × W × C H\times W\times C H×W×C的数据,VAE的Encoder模块会将其编码为一个大小为 h × w × c h\times w\times c h×w×c 的低维Latent特征,其中 f = H / h = W / w f=H/h=W/w f=H/h=W/w为VAE的下采样率(Downsampling Factor)。反之,VAE的Decoder模块有一个相同的上采样率(Upsampling Factor)将低维Latent特征重建成像素级别的图像。

为什么VAE可以将图像压缩到一个非常小的Latent space(潜空间)后能再次对图像进行像素级重建呢?
因为虽然VAE对图像的压缩与重建过程是一个有损压缩与重建过程,但图像全图级特征关联并不是随机的,它们的分布具有很强的规律性:比如人脸的眼睛、鼻子、脸颊和嘴巴之间遵循特定的空间关系,又比如一只猫有四条腿,并且这是一个特定的生物结构特征。下面Rocky也使用VAE将图像重建成不同尺寸的生成图像,实验结论发现如果我们重建生成的图像尺寸在之上时,其实特征损失带来的影响非常小。

2) 切换不同微调训练版本的VAE模型,能够发现生成图片的细节与整体颜色也会随之改变


VAE的网络结构

VAE中Encoder和Decoder的结构如下:

  • SD VAE Encoder部分包含了三个DownBlock模块、一个ResNetBlock模块以及一个MidBlock模块,将输入图像压缩到Latent空间,转换成为Gaussian Distribution。
  • 而VAE Decoder部分正好相反,其输入Latent空间特征,并重建成为像素级图像作为输出。其包含了三个UpBlock模块、一个ResNetBlock模块以及一个MidBlock模块。
    在这里插入图片描述

三个基础组件:

  • GSC组件:GroupNorm+Swish+Conv
  • Downsample组件:Padding+Conv
  • Upsample组件:Interpolate+Conv
    两个核心组件:
  • ResNetBlock模块
  • SelfAttention模型
    在这里插入图片描述
    在这里插入图片描述

文本编码器

Stable Diffusion 中采用的文本编码器是CLIP模型中的文本编码器
CLIP模型的训练过程如下:
CLIP在4亿张图像及其对应字幕数据集上做训练。

  • 输入图像及其描述,然后使用对应的编码器各自做图像和文本编码。
  • 用余弦相似来对比上述两个编码向量,当我们开始训练过程之后,相似值会变小,即便文本正确地描述了图像。
  • 更新两个编码模型,以使得下次编码向量更相似。
    在这里插入图片描述
    将编码后的文本信息,也作为噪音生成器的输入。
    在这里插入图片描述
    由于我们将要在潜在空间中操作,所以输入的图像和已经预测的噪声都是在潜在空间的。
    在这里插入图片描述

噪音预测器

下图展示了不用文本的扩散Unet, 输入是在潜在空间中的噪音图片和时间步长。
在这里插入图片描述
通过在ResNet模块之间增加一个Attention层,添加对文本输入的支持。
在这里插入图片描述
ResNet模块并不能直接看到文本,但是Attention层将文本表达合并到了潜在空间。现在接下来的ResNet可以使用合并过来的文本信息到它的处理过程了。

Unet 模型


Unet模型的作用
预测噪声残差,并结合Sampling method(调度算法:DDPM、DDIM、DPM++等)对输入的特征矩阵进行重构,逐步将其从随机高斯噪声转化成图片的Latent Feature。
在前向推理过程中,SD模型通过反复调用 U-Net,将预测出的噪声残差从原噪声矩阵中去除,得到逐步去噪后的图像Latent Feature,再通过VAE的Decoder结构将Latent Feature重建成像素级图像。


Unet 模型的结构
Stable Diffusion中的U-Net,在传统深度学习时代的Encoder-Decoder结构的基础上,增加了ResNetBlock(包含Time Embedding)模块,Spatial Transformer(SelfAttention + CrossAttention + FeedForward)模块以及CrossAttnDownBlockCrossAttnUpBlockCrossAttnMidBlock模块。

在这里插入图片描述

  • ResNetBlock模块:借鉴ResNet模型的“残差结构”,让网络能够构建的更深的同时,将Time Embedding信息嵌入模型。

  • GSC模块:Stable Diffusion U-Net中的最小组件之一,由GroupNorm+SiLU+Conv三者组成。

  • DownSample模块:Stable Diffusion U-Net中的下采样组件,使用了Conv(kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))进行采下采样。

  • UpSample模块:Stable Diffusion U-Net中的上采样组件,由插值算法(nearest)+Conv组成。

  • UpBlock_X模块:由X个ResNetBlock模块和一个UpSample模块组成。
    在这里插入图片描述

  • CrossAttnDownBlock_X模块:是Stable Diffusion U-Net中Encoder部分的主要模块,由X个(ResNetBlock模块+Spatial Transformer模块)+DownSample模块组成。

  • CrossAttnMidBlock模块:是Stable Diffusion U-Net中Encoder和ecoder连接的部分,由ResNetBlock+Spatial Transformer+ResNetBlock组成
    在这里插入图片描述

  • FeedForward模块:Attention机制中的经典模块,由GeGlU+Dropout+Linear组成。

  • CrossAttnUpBlock_X模块:是Stable Diffusion U-Net中Decoder部分的主要模块,由X个(ResNetBlock模块+Spatial Transformer模块)+UpSample模块组成。

  • Spatial Transformer模块:由GroupNorm+Conv+BasicTransformer Block+Conv构成
    在这里插入图片描述

  • BasicTransformer Block模块:由LayerNorm+SelfAttention+CrossAttention+FeedForward组成,是多重Attention机制的级联,并且也借鉴ResNet模型的“残差结构”。通过加深网络和多Attention机制,大幅增强模型的学习能力与图文的匹配能力。

  • SelfAttention模块:SelfAttention模块的整体结构与CrossAttention模块相同,这是输入全部都是图像信息,不再输入文本信息。
    在这里插入图片描述

  • CrossAttention模块:将文本的语义信息与图像的语义信息进行Attention机制,增强输入文本Prompt对生成图片的控制。
    在这里插入图片描述

训练过程和损失函数

在Stable Diffusion中,需要对VAE模型进行微调训练,主要采用了L1回归损失感知损失(perceptual loss,Learned Perceptual Image Patch Similarity,LPIPS)作为损失函数,同时使用了基于patch的对抗训练策略
为了防止在Latent空间的任意缩放导致的标准差过大,在训练VAE模型的过程中引入了正则化损失


L1回归损失
L1回归损失用在回归问题中衡量预测值与真实值之间的差异。
L 1 ( y , y ^ ) = ∑ i = 1 n ∣ y i − y ^ i ∣ L 1(y, \hat{y})=\sum_{i=1}^n\left|y_i-\hat{y}_i\right| L1(y,y^)=i=1nyiy^i

其中, y i y_i yi 是输入数据的真实值, y ^ i \hat{y}_i y^i 是模型生成数据的预测值, n n n 是数据总数。


感知损失
感知损失的核心思想是比较原始图像和生成图像在传统深度学习模型(VGG、ResNet、ViT等)不同层中特征图之间的相似度,而不直接进行像素级别的对比。传统深度学习模型能够提取图像的高维语义信息的特征,如果两个图像在高维语义信息的特征上接近,那么它们在像素级别的语意上也应该是相似的。
感知损失的公式如下所示:
L perceptual  = ∑ l λ l ⋅ ∥ ϕ l ( I pred  ) − ϕ l ( I target  ) ∥ 2 2 L_{\text {perceptual }}=\sum_l \lambda_l \cdot\left\|\phi_l\left(I_{\text {pred }}\right)-\phi_l\left(I_{\text {target }}\right)\right\|_2^2 Lperceptual =lλlϕl(Ipred )ϕl(Itarget )22

其中: ϕ l \phi_l ϕl 表示在预训练模型 (比如VGG/ResNet网络) 的第 l l l 层的激活特征。 I p r e d I_{p r e d} Ipred 是模型生成的图像。 I target  I_{\text {target }} Itarget  是真实图像。 λ l \lambda_l λl 是第 l l l 层的权重,可以根据实际情况设置合适值。


正则化损失

  • KL(Kullback-Leibler)正则化
    让Latnet特征不要偏离正态分布太远,同时设置了较小的权重(~10e-6)来保证VAE的重建效果。
  • VQ(Vector Quantization)正则化
    过在decoder模块中引入一个VQ-layer,将VAE转换成VQ-GAN,同样为了保证VAE的重建效果,设置较高的codebook采样维度(8192)。

虽然VAE模型使用了KL正则化,但是由于KL正则化的权重系数非常小,实际生成的Latent特征的标准差依旧存在比较大的情况,所以Stable Diffusion论文中提出了一种rescaling方法强化正则效果
首先我们计算第一个batch数据中Latent特征的标准差 σ \sigma σ ,然后采用 1 / σ 1 / \sigma 1/σ 的系数来rescale后续所有的Latent特征使其标准差接近于1。同时在Decoder模块进行重建时,只需要将生成的Latent 特征除以 1 / σ 1 / \sigma 1/σ ,再进行像素级重建即可。
在SD中,U-Net模型使用的是经过rescaling后的Latent 特征,并且将rescaling系数设置为 0.18215 。


基于patch的对抗训练策略
使用PatchGAN的判别器来对VAE模型进行对抗训练,通过优化判别器损失,来提升生成图像的局部真实性(纹理和细节)与清晰度。
PatchGAN是GAN系列模型的一个变体,其判别器架构不再评估整个生成图像是否真实,而是评估生成图像中的patch部分是否真实。具体来说,PatchGAN的判别器接收一张图像,并输出一个矩阵,矩阵中的每个元素代表图像中对应区域的真实性。


总损失函数
Diffusion中VAE训练的完整损失函数:
L Autoencoder  = min ⁡ E , D max ⁡ ψ ( L r e c ( x , D ( E ( x ) ) ) − L a d v ( D ( E ( x ) ) ) + log ⁡ D ψ ( x ) + L r e g ( x ; E , D ) ) \begin{gathered} \mathcal{L}_{\text {Autoencoder }}=\min _{\mathcal{E}, \mathcal{D}} \max _\psi \\ \left(\mathcal{L}_{r e c}(x, \mathcal{D}(\mathcal{E}(x)))-\mathcal{L}_{a d v}(\mathcal{D}(\mathcal{E}(x)))+\log \mathcal{D}_\psi(x)+\mathcal{L}_{r e g}(x ; \mathcal{E}, \mathcal{D})\right) \end{gathered} LAutoencoder =E,Dminψmax(Lrec(x,D(E(x)))Ladv(D(E(x)))+logDψ(x)+Lreg(x;E,D))

其中 E ( x ) \mathcal{E}(x) E(x) 表示VAE重建的图像, L r e c \mathcal{L}_{r e c} Lrec 表示L1回归损失和感知损失, L a d v + log ⁡ D ψ \mathcal{L}_{a d v}+\log \mathcal{D}_\psi Ladv+logDψ 表示 PachGAN的判别器损失, L r e g \mathcal{L}_{r e g} Lreg 表示KL正则损失。

参考


论文
【1】 DDPM的灵感来源 Deep Unsupervised Learning using Nonequilibrium Thermodynamics
【2】DDPM 开山之作 : Denoising Diffusion Probabilistic Models (DDPM)
【3】DDPM的改进,提出余弦调度策略 Improved Denoising Diffusion Probabilistic Models
【4】DDPM采用的最基础的Unet架构U-Net: Convolutional Networks for Biomedical Image Segmentation


博文
【b.1】通过可视化的动画,逐步讲解 Step by Step Visual Introduction to Diffusion Models
【b.2】主页里有对应的ppt和yotube链接 cvpr2022-tutorial-diffusion-models
【b.3】偏向于数学的角度介绍 How diffusion models work: the math from scratch
【b.4】Arxiv24最新的一篇关于DDPM非常详细的讲解 Tutorial on Diffusion Models for Imaging and Vision
【b.5】介绍的非常全面,包括具体的数学推导What are Diffusion Models?
【b.6】Stable Diffusion 图解 The Illustrated Stable Diffusion
【b.7】强烈推荐知乎上的一个讲解 深入浅出完整解析Stable Diffusion(SD)核心基础知识


视频
【1】李宏毅老师的系列讲解
【生成式AI】淺談圖像生成模型 Diffusion Model 原理
【生成式AI】Stable Diffusion、DALL-E、Imagen 背後共同的套路
【生成式AI】Diffusion Model 原理剖析 (1/4) (optional)
【生成式AI】Diffusion Model 原理剖析 (2/4) (optional)
【生成式AI】Diffusion Model 原理剖析 (3/4) (optional)
【生成式AI】Diffusion Model 原理剖析 (4/4) (optional)

【2】Yotube上的视频,不仅介绍了DDPM基础还有应用
Tutorial on Denoising Diffusion-based Generative Modeling: Foundations and Applications

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1704175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据恢复的救星!快速恢复手机数据的2个秘籍!

当我们的照片、视频、联系人、短信和应用程序丢失时&#xff0c;许多人可能会感到束手无策&#xff0c;无论是珍贵的照片、重要的工作文件还是个人的联系方式&#xff0c;一旦丢失&#xff0c;都可能带来极大的不便和困扰。但随着数据恢复技术的发展&#xff0c;我们有了更多的…

【pm2 - sdk 集成到程序中,典型用法】

pm2作为一款进程管理神器&#xff0c;除了命令行的启动方式外&#xff0c;其还对应有sdk&#xff0c;集成到程序中&#xff0c;我们可以连接到已有或创建pm2的守护进程&#xff0c;与其进行交互&#xff0c;动态&#xff0c;编程式地控制程序的启停等。以下为示例&#xff1a; …

数据结构——不相交集(并查集)

一、基本概念 关系&#xff1a;定义在集合S上的关系指对于a&#xff0c;b∈S&#xff0c;若aRb为真&#xff0c;则a与b相关 等价关系&#xff1a;满足以下三个特性的关系R称为等价关系 (1)对称性&#xff0c;aRb为真则bRa为真&#xff1b; (2)反身性,aRa为真; (3)传递性,aRb为真…

Android studio 连接 adb传输文件到电脑

前提是已经连接到adb window R&#xff1a; 打开控制台adb devices&#xff1a;可以查看已经连接的设备adb pull /storage/emulated/0/Download/aa.png C:\Users\Administrator\Desktop&#xff1a;拉取连接设备的文件 aa.png 到电脑桌面上 (在电脑控制台进行拉取操作) 如果…

XShell免费版的安装配置

官网下载 https://www.xshell.com/zh/free-for-home-school/ 下载地址 通过邮箱验证 新建会话 通过ssh登录树莓派 填写主机IP 点击用户身份验证 成功连接

Swagger测试接口,请求头添加token

概述Swagger 1、概述 在日常开发中&#xff0c;我们的业务需要用户登录&#xff0c;权限控制。但是在某些情况下我们使用Swagger测试接口&#xff0c;部分接口需要携带token&#xff0c;才能访问&#xff0c;就需要在swagger添加token窗口。 效果图&#xff1a; 由 右上角 A…

Autodl如何进行实例使用(同区)

一、首先找到之前保存的实例 二、点击更多然后选择克隆实例 三、选择是否要保存之前的数据盘 四、选择空余的GPU进行创建即可

等了10年,终于迎来RTX5/RTX4全家桶开源,开源,开源! 且免费商用

我们的V4, V5, V6 ,V7开发板都配套了大量的RTX4, RTX5教程和案例&#xff0c;从2015年发布首版RTX4内核教程以来&#xff0c;已经整整10年了。 1、制作这个RTX教程和案例&#xff0c;其实也承受了很大的压力&#xff0c;因为只有RTX内核是免费商用的&#xff0c;中间件并不免费…

spring-boot 3.2 + spring-boot-starter-quartz + HikariCP配置

第一步&#xff0c;添加 spring-boot-starter-quartz 的 maven 依赖。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> 第二步&#xff0c;在 ap…

【Android14 ShellTransitions】(四)Transition收集动画参与者

这一节的内容在WMCore中&#xff0c;现在Transition已经走到COLLECTING状态了&#xff0c;并且可以收集动画参与者了。 那么Transition是在什么时候去收集动画参与者&#xff1f;回到我们最初的ActivityStarter.startActivityUnchecked&#xff1a; 在调用了TransitionControl…

python爬虫学习(2)——requests模块

520那天我向心仪的女孩要微信&#xff1a;“女神&#xff0c;能给我你的微信号吗&#xff1f;” 女神&#xff1a;“给我——爬&#xff01;&#xff01;&#xff01;&#xff01;” 从那天开始&#xff0c;我就决定要学好爬虫&#xff0c;爬到女神微信号&#xff01;&#xff…

nacos(一) 安装

一 nacos 1.4.7安装 安装 nacos-server nacos官方下载 说明&#xff1a; 下载1.4.7和2.3.2版本,本专栏后续以1.4.7为例进行讲解补充&#xff1a; nacos-server服务端和nacos-client客户端附加&#xff1a; spring 版本、nacos-server、nacos-client版本要适配思考&#xf…

实战项目:飞机坦克大战 —— 面向对象编程之旅

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、项目概览与背景介绍 二、面向对象编程基本概念解析 1. 类与对象 2. 构造函数与属性封…

执法行动高压下,勒索软件攻击仍持续增加

执法行动 最近几年&#xff0c;随着网络犯罪特别是勒索软件犯罪的日益猖獗&#xff0c;勒索软件攻击已经对网络空间安全构成重大威胁。互联网不是法外之地&#xff0c;执法机构也对应加强了执法力度&#xff0c;对全球威胁重大的网络犯罪团伙进行重点打击。对勒索软件团伙所控…

面向对象编程:坦克飞机大战游戏的重构之旅

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、面向对象编程思想入门 坦克对象的定义 属性与行为方法的实现 二、面向过程与面向对象…

利用大语言模型增强网络抓取:一种现代化的方法

本文将探讨大语言模型(LLMs)与网络抓取的集成&#xff0c;以及如何利用LLMs高效地将复杂的HTML转换为结构化的JSON。 作为一名数据工程师&#xff0c;我的职业生涯可以追溯到2016年。那时&#xff0c;我的主要职责是利用自动化工具从不同网站上获取海量数据&#xff0c;这个过…

TiDB学习3:TiKV

目录 1. TiKV架构和作用 2. RocksDB 2.1 写入 2.2 查询 2.3 Column Families列簇 3. 分布式事务 3.1 事务流程 3.2 分布式事务流程 3.3 MVCC 4. Raft与Multi Raft 4.1 Raft日志复制 4.2 Raft Leader选举 5. TiKV- 读写 5.1 数据的写入 5.2 数据的读取ReadIndex …

正邦科技(day1)

1&#xff1a;充电桩工作了两个半小时&#xff0c;已用电量13度电&#xff08;一般的话是一个小时7度电&#xff09; 2&#xff1a;火线&#xff08;红色&#xff0c;棕色&#xff09;&#xff0c;零线&#xff08;蓝色&#xff09; 3&#xff1a;充电桩工作了两个半小时&#…

Vue3骨架屏(Skeleton)

效果如下图&#xff1a;在线预览 APIs 参数说明类型默认值必传animated是否展示动画效果booleantruefalsebutton是否使用按钮占位图boolean | SkeletonButtonPropsfalsefalseavatar是否显示头像占位图boolean | SkeletonAvatarPropsfalsefalseinput是否使用输入框占位图boolea…

FPGA之tcp/udp

在调试以太网的过程中&#xff0c;考虑了vivado IP配置(管脚、reset等)&#xff0c;SDK中PHY芯片的配置(芯片地址、自适应速率配置等)&#xff0c;但是&#xff0c;唯独忽略了tcp/udp协议&#xff0c;所以在ping通之后仍无法连接。 所以现在来学习一下tcp与udp的区别 ---- 为什…