持续施工中

I’m still working on it.

本文是根据油管视频整理的笔记,原视频中将DDPM和DDIM都有讲到,所以我会穿插一些DDIM的东西

导入

视频:https://www.youtube.com/watch?v=ifCDXFdeaaM

基本概念

训练过程–Forward Process

逐步添加高斯噪声,直到变成纯高斯噪声

生成过程–Denoise Process

逐步去除噪声,直到变成图像

image-20240329232228525

训练过程

首先,我们来看看DDPM中的算法是怎么说的

image-20240329234016489

x0q(x0)x_0 \sim q(x_0)

这里的x0x_0是一张干净的图像(样本集中的)

tUniform(1,...,T)t\sim Uniform({1,...,T})

从均匀分布中采样一个t

ϵN(0,I)\epsilon \sim N(0,I)

再从均值是0,方差是1的标准高斯分布采样一个噪声ϵ\epsilon,这个噪声ϵ\epsilon的尺寸大小和图像一样大,但里面全是噪声

image-20240329234637266

ϵϵθ(αˉtx0+1αˉtϵ,t)2||\epsilon-\epsilon_\theta(\sqrt{\bar{\alpha}_t}x_0+\sqrt{1-\bar{\alpha}_t}\epsilon,t)||^2

  • 这里的αˉt\bar{\alpha}_t是预先人为定义好的东西,并且随着t增加,αˉt\bar{\alpha}_t会变小;即t越大,原来图占的比例越小,噪声占比越大
  • ϵθ\epsilon_\theta是模型预测出来的噪声,预测出来的噪声ϵθ\epsilon_\theta是要和原噪声ϵ\epsilon进行比较

关于这里的噪声的讨论

ϵtϵ_t之间不是相互独立的,每一步的噪声 ϵtϵ_t是基于前一状态 xt1x_{t-1}和原始图像 x0x_0的偏差计算得出的

由于每个 xtx_t都是由前一个时间步 xt1x_{t-1}加上一些噪声得到的,这意味着每个 ϵtϵ_t 实际上是包含了从 t=1t=1 到当前时间步 tt 所有噪声的累积。

尽管每一步加入的噪声是独立的,但每个时间步生成的$ ϵ_t$包含了所有之前步骤的噪声累积,因此 ϵtϵ_tϵt1ϵ_{t-1}在数学上是相关的

训练过程

image-20240328232931426

在想象中,我们的训练过程是下图这样的

image-20240328232950947

生成过程

首先,我们来看看DDPM中的算法是怎么说的

image-20240329235405739

xTN(0,I)x_T \sim N(0,I)

从标准高斯分布采样出一个噪声矩阵

然后进行T步的循环,每次循环中要采样一个噪声zz

xt1=1αt(xt1αt1αˉtϵθ(xt,t))+σtzx_{t-1}=\frac{1}{\sqrt{\alpha}_t}(x_t-\frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}}\epsilon_\theta(x_t,t))+\sigma_tz

σt=ηβt1αt11αt\sigma_t = \eta \beta_t \frac{1 - \alpha_{t-1}}{1 - \alpha_t}

  • η = 1 时,方差 σt\sigma_t 完全由 βt\beta_tαt\alpha_t 的值确定,对应原始的DDPM工作,其中噪声添加是随机的,模拟了正向扩散过程的逆过程。
  • η = 0 时,方差 σt\sigma_t 为零,这意味着在逆向生成过程中没有额外噪声被添加,此时的模型变成了确定性的,对应DDIM(去噪扩散隐式模型)方案,这是一种更加稳定和可预测的生成方式。

通过调整 η 的值,研究人员可以在随机性和确定性之间进行权衡,从而控制生成过程中噪声的影响程度

看着很复杂,不急,后面会慢慢解析

但,这儿有个问题:在生成过程中,这里为什么要再采样并加入一个噪声z???【后面有解释】

image-20240330000026098

DDPM和DDIM在生成过程中的区别

参考:https://ucladeepvision.github.io/CS188-Projects-2023Winter/2022/03/27/team27-ddim-inversion.html#implementing-ddims

image-20240504200530272

差异主要体现在状态转移和噪声处理上,我将通过对比这两种模型的去噪过程公式来说明这一点。

DDPM的去噪过程

在DDPM中,去噪过程是一个随机过程,每一步都依赖于前一步的输出和新添加的噪声。去噪公式可以表示为:
$ x_{t-1} = \frac{1}{\sqrt{\alpha_t}} \left(x_t - \frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}t}} \epsilon\theta(x_t, t)\right) + \sigma_t z $
其中:

  • xtx_t 是当前步的图像。
  • ϵθ(xt,t)\epsilon_\theta(x_t, t) 是学习得到的噪声预测。
  • αt\alpha_tαˉt\bar{\alpha}_t 是预定的方差调度参数。
  • σt\sigma_t 是根据 η\eta 调整的噪声级别,当 η=1\eta = 1 时,σt\sigma_t 最大,添加最多噪声。
  • zz 是标准正态分布的随机变量。

这个过程是一个典型的马尔可夫链过程,因为每一步的输出依赖于前一步的状态和新引入的随机噪声

DDIM的去噪过程

DDIM的设计目标是在不牺牲太多生成质量的情况下,加快生成速度并提高确定性。其去噪过程去除了额外噪声的添加,公式如下:
$ x_{t-1} = \frac{1}{\sqrt{\alpha_t}} \left(x_t - \frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}t}} \epsilon\theta(x_t, t)\right) $
注意,这里没有 σtz\sigma_t z 项,这意味着:

  • 过程是确定性的,一旦确定了开始的噪声,整个逆过程可以精确地重现,无需依赖于随机噪声。
  • 因为去除了随机噪声的引入,每一步的状态完全由前一步的状态和模型预测的噪声确定,不再是一个马尔可夫过程

虽然这两个公式,目前看着只差了一个噪声项,但他们的推导过程不大不一样!具体推导在后面

DDIM通过使用一个确定性的采样路径,即在逆向过程中,不再随机采样噪声。这使得DDIM在恢复数据时更加高效且稳定。

DDIM的关键在于它利用了一个被称为“implicit sampling”的方法,该方法不需要在每一步明确地向数据添加噪声。相反,它直接计算从当前噪声状态到下一个较少噪声状态的最优路径。这种方式减少了随机性,使得生成的过程更加快速且具有更少的随机变化。

image-20240504200110623

如上图,假如当前是xtx_t,而当前的xtx_t它会预计最终走到x0^\hat{x_0},但如果直接到x0^\hat{x_0},得到的结果就和实际的x0x_0有一定差距,所以它并不会一大步的直接到x0^\hat{x_0},而是选择每次走一小步(去除一些噪声),然后在xt1x_{t-1}重新预测最终走到x0^\hat{x_0},也许这个新的x0^\hat{x_0}会离x0x_0​更近一些,然后它就再走一小步

就是每次去除一点然后再矫正再去一点

对比和效率

  • 随机性和效率:DDPM通过引入随机噪声保持了高度的随机性,这对于生成多样化的图像很有帮助,但这种随机性也导致了生成过程的不确定性和较慢的收敛速度。DDIM通过去除随机噪声,减少了这种不确定性,使得生成过程更快,更可控。
  • 应用场景:DDPM适用于需要图像多样性的场景,如艺术创作、样本增强等;而DDIM则更适用于需要快速、可重现结果的场景,如内容过滤、特定图像修复等。

图像生成模型的目标

https://www.youtube.com/watch?v=73qwu77ZsTM

求出“真实图像的分布

image-20240328233137012

而在如今的生成图像中,不仅仅要生成出图像,而是要添加“条件”

以前是只让生成的图像还原真实图像(生成一只狗),现在是要“一只在奔跑的狗”

image-20240328233303280

但不论怎么说,我们的目标,还是求出“真实图像的分布

也就是模拟一个分布PθP_\theta,这个PθP_\theta要和原来的分布PdataP_{data}越接近越好

image-20240328233538360

那么,怎么来衡量“接接近越好”

假设,我们现在有个分布PθP_\theta,现在任意PdataP_{data}的样本集中拿一张图,我们照样可以用模型θ\theta来还原出这张图,那这么模型就是完美还原PdataP_{data}

但实际上,不大可能;

不过,我们如果让模型θ\theta尽量还原出PdataP_{data}的样本集的图,也就是让PθP_\theta生成出PdataP_{data}的图的概率最大化

θ=argmaxθi=1mPθ(xi)\theta^*=arg\max_\theta\prod_{i=1}^mP_\theta(x^i)

不同的图像生成模型,最终目标都是让θ\theta^*最大化(似然最大化)


最终目标都是让θ\theta^*最大化(似然最大化),具体怎么操作呢?

下面是将似然最大化推导成最小化KL散度的公式KL散度用来度量两个分布的距离

image-20240328234216622


回顾VAE

为什么要先讲VAE,因为VAE很多东西和DM非常类似

VAE的全称是(Variational Autoencoders) 它定义了一个连续的、不易处理的密度函数,是通过优化似然的下界(lower bound)来逼近极大似然的方法.因此,这里要是用积分来定义公式

p(x)=p(z)p(xz)dzp(x)=\int p(z)p(x|z)dz

自编码器-Autoencoders

那么要了解VAE,首先要对自编码器(Autoencoders ,AE) 有一定的了解。自编码器是一种通过无监督的方式去学习数据内在表征(降维)的神经网络,如下图所示:

img

左侧是PCA的方法进行一个降维,右侧是通过自编码器方法对图片进行一个降维。它们的区别是:

  • PCA是将矩阵经过sigmoid激活后保留主成分达到降维的目的,然后通过和WT相乘获得新的压缩后的图片
  • 自编码器则是通过一系列神经网络(编码器)将图片变成一个向量,然后再通过一些列神经网络(解码器)将这个向量复原成一张图片

他们的效果对比如下,我们看到自编码器相对于PCA有更多的参数,但复原后的图片也更加清晰

img

自编码器进行预训练

自编码器有什么应用场景呢?

首先,训练一个能够用于重构输入的隐层向量表示:

img

然后,训练完毕后,隐层特征就可以用于其他有监督训练任务(例如有大量数据,却只有少量标签)

img

那么我们可不可以随机初始化一个隐层向量,然后通过decoder来生成图像呢?这是比较困难的。因为用固定的自编码器去生成图片的时候,虽然隐层向量空间是连续的,但是每张图片生成的向量是离散的。处于离散向量之外的其他向量,不一定能生成图片。

就如同下图,虽然自编码器可以压缩黑狗还原黑狗,压缩白狗还原白狗,但是处于黑狗和白狗之间的那部分向量,是不一定能生成斑点狗的

img

VAE的原理

由此,我们提出,在自编码器的隐层向量空间中加入一些噪音,使得自编码器也能够生成斑点狗的照片:

img

那么既然我们定义在连续空间上,因此VAE的概率密度函数也得是连续的,由此得到了公式

p(x)=p(z)p(xz)dzp(x)=\int p(z)p(x|z)dz

其中:x是图像,而z是可以是隐层向量空间里面的一个随机向量(连续变量)。所以对于每一个z可能会生成一张图片。

用VAE模型生成图像

VAE模型怎么去生成一张图像?

  • 首先,从高斯分布中生成一个随机变量z,使得 $z \sim N(0,I) $
  • 让每个z 去生成令一个正态分布 N(μ(z),σ(z))N(μ(z),σ(z))
  • xzx|z服从正态分布 N(μ(z),σ(z))N(μ(z),σ(z))
  • μ,σμ,σ 两个函数可以用神经网络表示
  • 因为z可以一直生成,因此理论上p(x)p(x)可以表示成无穷多个正态分布的mixture(即 p(x)=p(z)p(xz)dzp(x)=∫p(z)p(x|z)dz)。但事实上训练的图片是有限的,因此, 训练目标为最大化xp(x)∏xp(x)xlog(p(x))∑xlog(p(x))

img

但事实上z不可能随机生成的,而是要根据我们的输入图片学习而来的(巧妇难为无米之炊)。放在数学层面上解释,就是我们要去寻找后验概率p(zx)p(z|x) .这部分,就是自编码器中 decoder 的部分


在VAE中,Pθ(x)P_\theta(x)是什么?

image-20240329211444989

如上图所示

  • Pθ(x)P_\theta(x)是一个分布;
  • 网络G作用:从“高斯分布”采样出来的张量Z,经过网络G生成某个内容
  • θ\theta:泛指网络G的各种参数

所以,按理来说,如果要定义Pθ(x)P_\theta(x),其公式为

Pθ(x)=zP(z)Pθ(xz)dzP_\theta(x)=\int_zP(z)P_\theta(x|z)dz

即:每个zz被采样出的概率*由zz产生出xx的概率,再对所有的zz做积分

其中,

  • 每个zz是从高斯分布被采样出的,P(z)P(z)​是已知的

  • Pθ(xz)P_\theta(x|z)​怎么办呢?

    • 一个简单的想法是:如果G(z)生成的东西和样本中的x一样,就输入1;否则输出0;如下面公式所示

    • 但这样的结果是:Pθ(xz)P_\theta(x|z)全是零,毕竟不可能生成的东西和样本完全一样

P_\theta(x|z)= \left\{ \begin{array}\\ 1, G(z)=x & \\ 0, G(z)\neq x \end{array} \right.

而实际上呢,Pθ(xz)P_\theta(x|z)用的是下面的公式

image-20240329213958194

这里输出的G(z)是一个高斯分布的均值,所以Pθ(xz)P_\theta(x|z)就正比于exp(G(z)x2)exp(-||G(z)-x||_2)

并且很直观的,如果G(z)G(z)xx越接近,则说明Pθ(xz)P_\theta(x|z)应该越大


在实际优化过程中,我们要优化:logP(x)logP(x)​的下界

这里取loglog是为了方便计算,让累乘过程变成累加

image-20240329215025833

logP(x)=zq(zx)logP(x)dzlogP(x)=\int_zq(z|x)logP(x)dz

这里的q(zx)q(z|x)可以是任意的分布,先不管它,而P(x)又可以表示为P(x)=P(z,x)P(zx)P(x)=\frac{P(z,x)}{P(z|x)}

所以,logP(x)logP(x)可以表示为

logP(x)=zq(zx)log(P(z,x)P(zx))dzlogP(x)=\int_zq(z|x)log(\frac{P(z,x)}{P(z|x)})dz

随后在log(P(z,x)P(zx))log(\frac{P(z,x)}{P(z|x)})中,分子分母同时乘以q(zx)q(z|x)

logP(x)=zq(zx)log(P(z,x)q(zx)P(zx)q(zx))dzlogP(x)=\int_zq(z|x)log(\frac{P(z,x)q(z|x)}{P(z|x)q(z|x)})dz

这目的是为了使用log的特性,将乘法变成加法,从而得到下面公式

logP(x)=zq(zx)log(P(z,x)q(zx))dz+zq(zx)log(q(zx)P(zx))dzlogP(x)=\int_zq(z|x)log(\frac{P(z,x)}{q(z|x)})dz+\int_zq(z|x)log(\frac{q(z|x)}{P(z|x)})dz

其中, zq(zx)log(q(zx)P(zx))dz\int_zq(z|x)log(\frac{q(z|x)}{P(z|x)})dz这玩意是啥?它是q(zx)q(z|x)P(zx)P(z|x)的KL散度

KL(q(zx)P(zx))KL(q(z|x)||P(z|x))

KL散度必为正值,所以可以推导出一个不等式

logP(x)>=zq(zx)log(P(z,x)q(zx))dz=Eq(zx)[log(P(z,x)q(zx))]logP(x)>= \int_zq(z|x)log(\frac{P(z,x)}{q(z|x)})dz \\ =E_{q(z|x)}[log(\frac{P(z,x)}{q(z|x)})]

这里的Eq(zx)=zq(zx)dzE_{q(z|x)}=\int_zq(z|x)dz中,EE指期望

从而得到了P(x)P(x)​的lower bound

后续的目标是优化这个lower bound,这里的优化指的是“最大化”这个lower bound,从而让P(x)P(x)能得到较大的值

VAE完整推导


VAE过渡到DDPM

说了这么多VAE,那这和DDPM有什么关系???

我们想象中,DDPM在生成图像过程中,是不断去除噪声的----从纯高斯噪声XTX_T逐步到X0X_0

我们可以将这里去噪声网络的结果,想象成“一个高斯分布的均值

而由一个噪声XTX_T,生成到图像X0X_0的概率是

Pθ(x0)=x1:xTP(xT)Pθ(xT1xT)...Pθ(xt1xt)...Pθ(x0x1)dx1:dxTP_\theta(x_0)=\int_{x_1:x_T}P(x_T)P_\theta(x_{T-1}|x_T)...P_\theta(x_{t-1}|x_{t})...P_\theta(x_0|x_1)d_{x_1}:d_{x_T}

这里是对所有的x1:xTx_1:x_T积分,而积分的内容是xTx_T产生xT1x_{T-1}的概率,乘以xT1x_{T-1}产生xT2x_{T-2}的概率,一直乘到x1x_{1}产生x0x_{0}​的概率

注意:这里的P(xT)P(x_T)是直接从高斯分布采样的,不是模型产生的,所以没有θ\theta的角标;Pθ(xT1xT)P_\theta(x_{T-1}|x_T)是模型产生的

image-20240329220632996

从DDPM的Pθ(x0)P_\theta(x_0)​我们可以看出,DDPM其实是进行了多步的VAE,如下图

image-20240329232526756

所以呢,适用于VAE的优化目标,即**“最大化”lower bound**的方式,也适合DDPM,即下图

image-20240329221741161

这里引出了一个新的问题,我们之前在VAE说“这里的q(zx)q(z|x)可以是任意的分布

那在DDPM中,q(zx)q(z|x)就被替换成了q(x1:xTx0)q(x_1:x_T|x_0)

问题来了,这个q(x1:xTx0)q(x_1:x_T|x_0)是什么呢?怎么求呢?


求q()分布

https://www.youtube.com/watch?v=m6QchXTx6wA

首先,来看看q(xtxt1)q(x_t|x_{t-1})​是什么?

q()是个分布,它是由xt1x_{t-1}加噪声得到xtx_t

这里的q(xtxt1)q(x_t|x_{t-1})是加噪声过程的公式

下面,我们来看看怎么xtx_t

一步加噪声到xtx_t

xt=1βtxt1+βtϵx_{t}=\sqrt{1-\beta_t}*x_{t-1}+\sqrt{\beta_t}\epsilon

其中,

  • xt1x_{t-1}是上一张噪声
  • β\beta是人为设定的超参数,是用来控制不同步数添加噪声多少的
  • ϵ\epsilon一次是从高斯分布采样的噪声

它的直观演示图如下(图中的xtx_{t}xt1x_{t-1}反了

image-20240329222320835

这里的超参数β\beta是否可以自学习?可以,但DDPM作者们尝试过后,发现效果不好

即,在加噪声的过程中,每一步都要

  1. 设定步数t的超参数βt\beta_t
  2. 从高斯分布采一次噪声ϵ\epsilon
  3. 加乘法和加法

一步,一步,一步,一步……………………最终得到纯高斯噪声图像

image-20240329222827458

那,有没有简单的方法,可以直接从x0x_0加噪声到xTx_T???

比如,在从x0x_0x1x_1时,需要采样一次高斯分布的噪声

在从x1x_1x2x_2​时,需要采样一次高斯分布的噪声

这两次的噪声,是完全独立的,互不相干的

image-20240329223145789

接下来,将从x0x_0x1x_1的公式,代入到从x1x_1x2x_2的公式,那不就可以套娃了嘛,如下图

image-20240329223356098

那么问题又来了

上图中,两个采样高斯分布的噪声,能否用一次采样来代替?

没错,可以!但是公式又要稍微变化下

image-20240329223457730

原来关于加噪声的公式就要变了

1β2β1ϵ1+β2ϵ2\sqrt{1-\beta_2}*\sqrt{\beta_1}*\epsilon_1+\sqrt{\beta_2}\epsilon_2

变成了

1(1β2)(1β1)ϵ\sqrt{1-(1-\beta_2)(1-\beta_1)}*\epsilon

这里的ϵ\epsilon​只要采一次高斯分布即可!!!

为什么,这里可以用一次加噪声来平替多次加噪声?

如果真的完全相等,那么“这里的ϵ\epsilon只要采一次高斯分布”的ϵ\epsilon就一定与ϵ1\epsilon_1ϵ2\epsilon_2​是相关的!

但是,由于我们不要求完全相等,因为也没必要完全相等,毕竟都是随机加噪声出来的结果,不用那么纠结

从结果上来说,这样平替的方法效果没啥损失,反而提高了效率

解释下上面“公式的变化”,本质上是做了个正则化的技巧,当我们把两个拥有不同方差的两个高斯融合在一起时,融合后的方差就单纯的把两个方差相加(如下图)

image-20240506204028320


那么,按照这种套路,将x0x_0直接加噪声到xtx_t的公式就变成了

image-20240329223826315

xt=1β1...1βtx0+1(1β1)...(1βt)ϵx_t=\sqrt{1-\beta_1}...\sqrt{1-\beta_t}*x_0+\sqrt{1-(1-\beta_1)...(1-\beta_t)}*\epsilon

同样的,这里的ϵ\epsilon只用采样一次高斯分布

为了简化公式,这里做两个约定

  • αt=1β1\alpha_t=1-\beta_1
  • αˉt=α1α2...αt\bar{\alpha}_t=\alpha_1\alpha_2...\alpha_t

于是!

我们得到了!

常见的!

我们在前向加噪声过程中,没有训练过程,可以直接跳步!一步加噪声到任意的xtx_t

xt=αˉtx0+1αˉtϵx_t=\sqrt{\bar{\alpha}_t}*x_0+\sqrt{1-\bar{\alpha}_t}*\epsilon

找到优化的目标

为什么要求xtx_t啊,求xtx_t的目的是为了求q(x1:xT)q(x1:x_T),而求q(x1:xTx0)q(x_1:x_T|x_0)是为了求

Eq(x1:xTx0)[log(P(x0:xT)q(x1:xTx0))]E_{q(x_1:x_T|x_0)}[log(\frac{P(x_0:x_T)}{q(x_1:x_T|x_0)})]

而它,是我们要优化的目标!它叫"lower bound"!我们的目标是为了让"lower bound"最大化

我们现在已经知道了"lower bound"中每个符合的表达形式,现在我们可以开始求"lower bound"了!

lower bound推导结果

上图的推导结果来源:Understanding diffusion models a unified perspective

过程太复杂了,直接看结果

Eq(x1:xTx0)[log(P(x0:xT)q(x1:xTx0))]=Eq(x1x0)[logP(x0x1)]KL(q(xTx0)P(xT))t=2TEq(xtx0)[KL(q(xt1xt,x0)P(xt1xt))]E_{q(x_1:x_T|x_0)}[log(\frac{P(x_0:x_T)}{q(x_1:x_T|x_0)})] \\ = \mathbb{E}_{q(x_1|x_0)}[logP(x_0|x_1)]-KL(q(x_T|x_0)||P(x_T)) \\ -\sum_{t=2}^T\operatorname{E}_{q(x_t|x_0)}[KL(q(x_{t-1}|x_t,x_0)||P(x_{t-1}|x_t))]

结果一共有三项

  • Eq(x1x0)[logP(x0x1)]\mathbb{E}_{q(x_1|x_0)}[logP(x_0|x_1)]:与要训练的模型无关!
  • KL(q(xTx0)P(xT))KL(q(x_T|x_0)||P(x_T))这一项,与要训练的模型无关!
    • P(xT)P(x_T)是从高斯分布采样的初始噪声;
    • q(xTx0)q(x_T|x_0)​是已经设定好的,是在Forwarding Process中(加噪声过程中),也与模型无关;注意:加噪声过程是固定的行为,不涉及模型学习
  • t=2TEq(xtx0)[KL(q(xt1xt,x0)P(xt1xt))]\sum_{t=2}^T\operatorname{E}_{q(x_t|x_0)}[KL(q(x_{t-1}|x_t,x_0)||P(x_{t-1}|x_t))]:这里又用了KL散度,来计算两个分布的距离
    • q(xt1xt,x0)q(x_{t-1}|x_t,x_0):是与模型无关的,我们得想办法算出来
    • P(xt1xt)P(x_{t-1}|x_t)真正与模型相关的!有关的!

从结果中看,最重要的是最后一项,我们要将"lower bound"最大化,也就是要将第三项最小化(前面有个负号)

也就是说!要将两个分布的KL散度最小化!!!

没错,还是很直观的!

我们的最终大目标是生成模型要生成逼真的图像,也就是说,我们要模拟出真实图像的分布

所以,我们的模型的分布真实图像的分布,它们的KL散度(分布之间的距离)越小越好


所以,我们先不看前两个式子,我们只关注第三个,与模型相关的式子

image-20240328221304863

我们要求:图中蓝色框内的q(xt1xt,x0)q(x_{t-1}|x_t,x_0)是未知的

这里的q(xtx0)q(x_t|x_0)表示由x0x_0一个高斯噪声产生出xtx_t,这里的xtx_t从肉眼看是个图像,但它其实是个某种分布

我们目前已知:q(xtx0)q(x_t|x_0)q(xtxt1)q(x_t|x_{t-1})q(xt1x0)q(x_{t-1}|x_0),也就是说从x0x_0xt1x_{t-1},从xt1x_{t-1}xtx_t,以及直接从x0x_0xtx_{t},这三个过程我们都是知道的

但如果此时,不再给高斯噪声,而是从x0x_0xt1x_{t-1}直接到xtx_t,此时需要经过公式转换,也能求出来,如下图所示

image-20240328222006498

公式如下

q(xt1xt,x0)=q(xt1,xt,x0)q(xt,x0)=q(xtxt1)q(xt1x0)q(x0)q(xtx0)q(x0)=q(xtxt1)q(xt1x0)q(xtx0)q(x_{t-1}|x_t,x_0) \\ = \frac{q(x_{t-1},x_t,x_0)}{q(x_t,x_0)}=\frac{q(x_t|x_{t-1})q(x_{t-1}|x_0)q(x_0)}{q(x_t|x_0)q(x_0)} \\ =\frac{q(x_t|x_{t-1})q(x_{t-1}|x_0)}{q(x_t|x_0)}

也就是说,我们得到了转换后的q(xt1xt,x0)q(x_{t-1}|x_t,x_0),在公式推导下,最终得到下图的内容

image-20240328222404191

上图推导来源论文:Understanding diffusion models a unified perspective

那么,现在就知道了q(xt1xt,x0)q(x_{t-1}|x_t,x_0)具体的值,并且也是符合一个高斯分布的,其均值是由x0x_0xtx_t共同决定的

image-20240328222833900

知道了q(xt1xt,x0)q(x_{t-1}|x_t,x_0)后呢,就可以求出q(xt1xt,x0)q(x_{t-1}|x_t,x_0)P(xt1xt)P(x_{t-1}|x_t)​的KL散度(KL散度即:两个分布之间的距离)


求KL散度最小值

https://www.youtube.com/watch?v=67_M2qP5ssY

image-20240328224901922

可以用上面这个公式来将两个分布求他们的求KL散度,但实际呢,有个更简单的方法

要注意,我们求KL散度的目标,是为了让这个求KL散度值最小,从而让“整个式子”的结果最大(最大化“似然”

所以,我们刚刚求出了q(xt1xt,x0)q(x_{t-1}|x_t,x_0)具体的值,其均值是由x0x_0xtx_t共同决定的,它是一个固定的值,跟我们要训练的网络无关,如下图所示,方差和均值都是fixed

image-20240328225219777

而另一个分布P(xt1xt)P(x_{t-1}|x_t)呢,它的方差我们就当成固定的,因为在前面的讨论中,我们只让均值是符合高斯分布

image-20240328225305218

综上,我们的最终目标是让KL散度最小,而其中一个分布q(xt1xt,x0)q(x_{t-1}|x_t,x_0)是固定的;另一个分布P(xt1xt)P(x_{t-1}|x_t)​只有均值可以改变

所以,我们只能Pθ(xt1xt)P_{\theta}(x_{t-1}|x_t)的均值接近q(xt1xt,x0)q(x_{t-1}|x_t,x_0)的均值,这里的PθP_{\theta}()就是我们训练的模型


现在,我们来看下这两个分布的两个均值分别是什么

q(xt1xt,x0)q(x_{t-1}|x_t,x_0)的均值是下面的公式,它是一个固定的

αˉt1βtx0+αt(1αˉt1)xt1αˉt\frac{\sqrt{\bar{\alpha}_{t-1}}\beta_tx_0+\sqrt{\alpha_t}(1-\bar{\alpha}_{t-1})x_t}{1-\bar{\alpha}_t}

所以,我们只能训练DenoiseModel,让其输出的均值越接近q(xt1xt,x0)q(x_{t-1}|x_t,x_0)的均值越好

image-20240328225626895


目标:训练DenoiseModel,让其输出的均值越接近q(xt1xt,x0)q(x_{t-1}|x_t,x_0)的均值越好

下面举例说下,怎么训练

比如我们的x0x_0是已知的样本图,随后,用之前提到的方法**“一步到位”加噪声**,直接得到xtx_t,如下图所示

image-20240328230154278

我们将xtx_ttt​输入给DenoiseModel,而DenoiseModel要做的,就是将输出一个接近下面玩意

αˉt1βtx0+αt(1αˉt1)xt1αˉt\frac{\sqrt{\bar{\alpha}_{t-1}}\beta_tx_0+\sqrt{\alpha_t}(1-\bar{\alpha}_{t-1})x_t}{1-\bar{\alpha}_t}

我们实际上是用xtx_t来预测出上面的q(xt1xt,x0)q(x_{t-1}|x_t,x_0)的均值,而这个均值中,甚至没有xt1x_{t-1}的参与!!!

image-20240328230426266

如果将上述的q(xt1xt,x0)q(x_{t-1}|x_t,x_0)​的均值再化简,可以得到下面的公式

1αt(xt1αt1αˉtϵ)\frac{1}{\sqrt{\alpha_t}}(x_t-\frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}}\epsilon)

image-20240328230859232

xt=αˉtx0+1αˉtϵx_t=\sqrt{\bar{\alpha}_t}*x_0+\sqrt{1-\bar{\alpha}_t}*\epsilon

我们再搬出来这个公式,作一些移项后,得到了x0x_0的公式(加噪过程中的ϵ\epsilon我们不可能知道了,ϵθ\epsilon_\theta是模型预测的)

x0=xt1αˉtϵθαˉtx_0=\frac{x_t-\sqrt{1-\bar{\alpha}_t}*\epsilon_\theta}{\sqrt{\bar{\alpha}}_t}

我们把x0x_0替换掉,让上面这个图的公式中,只有xtx_t而没有x0x_0,并且,成功地把ϵ\epsilon引入到了公式中

这里是用加噪过程中的x0x_0的公式,即,使用x0^\hat{x_0}(指预测的x0x_0)替换掉了去噪过程中的x0x_0【因为我们在去噪过程中,是不可能知道x0x_0的,毕竟我们最终要生成的就是x0x_0

image-20240504200530272

这里就能看出来DDIM和DDPM的公式区别,简单来说,假如DDIM当前步是xtx_t,想要得到下一步xt1x_{t-1},它需要两个输入值:xtx_tx0^\hat{x_0}(指预测的x0x_0),而x0^\hat{x_0}仍可以用xtx_t来计算出来。这样一来,xt1x_{t-1}的最终公式中,还是xt1x_{t-1}仅需要xtx_t就可以计算出来。

而这里替换效果的好坏,就要看ϵθ\epsilon_\theta了(ϵθ\epsilon_\theta是模型训练出来的),如果ϵθ\epsilon_\theta非常牛,那么我们用**x0^\hat{x_0}(指预测的x0x_0)就可以100%替换掉去噪过程中的x0x_0,也就是让上图中的?完全等于q(xt1xt,x0)q(x_{t-1}|x_t,x_0)的均值**,也就是去噪声过程中,每一步都能100%把加噪过程那一步实际添加的ϵ\epsilon去掉(尽管实际上不可能)

而在这个公式中,只有ϵθ\epsilon_\theta是真正需要模型来预测的,而其它的α\alpha值都是人为设定的

image-20240328231150250

所以至此,我们就知道了,这个模型的输出值虽然是一个噪声,但模型的目标并不是简单的让某个图像把噪声减去后,让它更像原图

而是为了让KL散度更小

而是为了让似然最大化

而是为了让我们模拟的分布更接近真实图像分布

过程的一小步,模型的一大步


但是,原公式中还有添加了一个“额外的噪声σ\sigma

σt=ηβt(1αˉt1)/(1αˉt)=(1αt1)/(1αt)1αt/αt1\sigma_t = \eta \beta_t(1-\bar{\alpha}_{t-1})/(1-\bar{\alpha}_{t}) \\ = \sqrt{(1-\alpha_{t-1})/(1-\alpha_t)} \sqrt{1-\alpha_t/\alpha_{t-1} }

image-20240328231621337

这个问题的本身是**“为什么要额外添加随机性”**


为什么要额外添加随机性

下面这个图,是ChatGPT在输出文字时的一个逻辑,即输出几率最大的待选字

image-20240328232125252

文字合成领域

论文:https://arxiv.org/abs/1904.09751 对此进行了探讨

image-20240328231851105

如上图所示,左侧是让GPT每次都选择几率最大的待选字进行输出,右侧是人写出来的文章

可以看到,人写的文章,用的字并不是选择几率最大的那个词汇,而是有“随机性”的跳跃的;如果只输出几率最大的那个词汇,最终可能会反复出现同样的内容

语音合成领域

除了文字合成,在语音合成领域也有使用随机性噪声的案例,在合成的过程中,需要随机dropout

image-20240328232543577

图像合成领域

所以,在图像领域DiffusionModel中,在去噪声的过程中,也添加一些噪声

image-20240328232408081

如果不添加噪声会怎样?

下面是去噪声的过程中,完全不添加噪声的对比图

image-20240328232459199

实际采样过程中,每步都要加入新的noise,这样做是因为根据经验,这有助于稳定神经网络防止崩溃。如果不加入新的noise,那么结果将会更加接近原始训练数据集的平均值,而非结果(说白了依旧是一堆糊状的平均值),加入之后则会产生具体的图像

总结

假设,我们拿很多梵高的画作为训练集图片,这些图是符合某种分布的(符合某种分布可以理解为,你看到这个画就觉得这个画是梵高画的);或者把分布比作“类”,把每个图片比作“对象”,我们现在手里有很多很多”图片“而我们是希望反向推出这个”分布“;一旦得到这个分布,我们就可以从这个分布中,”生成“新的图片了

我们的做法,是先向所有图像X0X_0(时间步t=0)添加噪声,假设一共要加100次(T=100)噪声ϵi\epsilon_{i},加噪声的最终目的,是让图像转成高斯分布(因为高斯分布我们是已知的);而每一次添加噪声后(从宏观角度看,或从类的角度看),在t=1时所有的的图像X1X_1,也可以符合一种分布(我们还是未知的);然后继续添加噪声,在t=10时所有的图像X10X_{10}也可以符合一种分布(未知)。随着t越来越大,当t=90时的所有图像X90X_{90},已经很接近于我们知道的高斯分布(接近已知),而等t=100时,所有图像X100X_{100}都是高斯分布(已知)。

从而,我们得到了从未知分布到已知分布的过程【加噪声过程】

加噪声的过程中,每一步添加多少噪声,是由噪声控制表(人为设定的),能否让机器自己学呢?理论上可以,但实践发现效果不好

随后,我们需要从已知分布得到未知分布【去噪声过程】

我们希望的目的是,有一个非常强的模型,输入给他一个在时间步t=100的图像X100X_{100},它能输出【加噪声过程】对t=99的图像X99X_{99}添加了的噪声,一旦模型得到了这个噪声ϵ^99\hat{\epsilon}_{99},我们就可以拿t=100的图像 减去 噪声 得到 t=99的图像,后续反复如此。直到得到t=0的图像(也就是恢复出来的x0^\hat{x_0}

然而,在去噪声的过程中,模型预测的噪声ϵ^99\hat{\epsilon}_{99}和在t=99时添加的真实噪声ϵ99\epsilon_{99}可能有一定误差,我们根据这个误差,可以反向的修正网络的参数,直到可以控制误差小于某个阈值。此时就可以近似认为,模型可以99.99%的能力预测出时间步t的图像xtx_t的噪声

不同部件的功能

在使用像 Stable Diffusion 这类基于扩散的图像生成模型时,一些关键组件包括 ckpt (checkpoint) 模型文件采样器(如 DDPM 或 DDIM),以及调度器。这些组件共同协作,使得从随机噪声生成精细图像成为可能。我将逐一解释它们的作用和相互关系。

CKPT 模型文件

CKPT 模型文件是训练好的模型的保存状态,包含了模型的所有参数和权重。这些文件是机器学习中的“检查点”,允许从特定的训练阶段开始执行或继续训练过程。在图像生成的上下文中,这些模型文件被用来:

  • 预测噪声:具体来说,模型是训练来预测在给定的噪声图像中的原始图像的噪声分布。这样,当我们逐步去除预测的噪声时,就能逐渐还原出原始的、无噪声的图像。

采样器(Sampler)

采样器用于管理如何从完全噪声化的状态(通常是一个高斯分布)逆向生成目标图像的过程。它们定义了逆向步骤的具体执行方式:

  • DDPM(Denoising Diffusion Probabilistic Models):在这种方法中,采样过程包括向图像中注入随机噪声和逐步去除噪声的步骤。它依赖于概率推断来逐步还原图像,每一步都是随机的,这有助于探索多种可能的输出。
  • DDIM(Denoising Diffusion Implicit Models):DDIM 提供了一个更快和更确定的逆向扩散路径。它通过计算给定的扩散路径上的噪声状态,而不是随机地选择,从而可以更快地生成图像,同时保持较高的质量。

调度器(Schedule)

调度器则控制噪声的增加和减少的时间表,即在扩散和反向扩散过程中的“步骤计划”。它们精确地管理:

  • 噪声水平的调整:确定在每一步中噪声应该被加入或去除的量。
  • 步骤的数量和间隔:决定整个生成过程中应该有多少步骤,以及这些步骤之间的时间间隔。

调度器也有很多方案,如linear,cosine,karras等,不同的调度器也会影响生成结果,下图展示了一些调度器的计算公式

image-20240505170050251

注意在cosine中,当t越接近于T时,αˉT\sqrt{\bar{\alpha}_T}就越接近0,此时会让图像xTx_T​更接近于一个纯高斯噪声【并不是完全为高斯噪声】

https://isamu-website.medium.com/understanding-common-diffusion-noise-schedules-and-sample-steps-are-flawed-and-offset-noise-52a73ab4fded

这篇文章讨论了让xTx_T完全为高斯噪声的效果,即αˉT\sqrt{\bar{\alpha}_T}等于0

总结来说,ckpt 模型文件提供了训练好的模型参数,采样器(如 DDPM 和 DDIM)定义了噪声的去除过程的具体执行方式,而调度器则优化了这个过程的步骤和时间表。这些组件共同作用,实现了从高噪声状态到高质量图像的转变。

关于训练

训练过程是包含了”加噪声过和去噪过程“,加噪声过程,把一张图x0x_0加噪声,得到这个图的纯噪声图xTx_T​(服从高斯分布);去噪声过程,从这个高斯分布图开始去除噪声,使用DDIM或DDPM进行去除噪声,而生成过程,就是去噪声过程,所以也会使用DDIM或DDPM,训练过程中同样需要DDPM,DDIM之类的采样器,而一旦模型被训练好,哪怕训练过程中用DDIM作为采样器去除的噪声,在实际生成中,可以用DDIM或DDPM,但从效果上,也许用DDIM更好

实验

在ComfyUI中,使用Ksampler(Advanced)采样器,

  • add_noise: disable
  • noise_seed: 42
  • control_after_generate: fixed
  • steps: 20
  • cfg: 8
  • smapler_name: ddpm
  • scheduler: normal

可能是ComfyUI的bug,如果不对Ksampler进行一些修改,无法连续两次根据相同一样参数生成图像;于是,在使用scheduler=normal生成一张图后,将scheduler修改成karras再生成图,再调整回scheduler为normal,反复如此

Q1: 相同初始噪声,分别使用DDPM、DDIM,在使用相同的schedule添加噪声,能否得到相同图像;

结论

经过验证,当Ksampler中的"add_noise"设置为disable,在其它参数全部一致(噪声,scheduler等)下多次进行生成,DDPM确实生成了不同的图像;与原版论文中DDPM的行为相似(因为会在生成过程中添加随机噪声)

在其它参数全部一致(噪声,scheduler等)下多次进行生成,而DDIM确实只生成相同的图像

另外,当Ksampler中的"add_noise"变成enable后,DDPM也可以多次生成相同的图像,DDIM仍是多次生成相同的图像

猜测时add_noise=enable后,会启用

相同初始噪声,分别使用DDPM、DDIM,不添加噪声,能否得到相同图像

结论

使用v2-1_512-ema-pruned.safetensors,当Ksampler中的"add_noise"变成disable后,不论用DDPM/DDIM都无法生成图像(会出现全部是纯色图像或只有人物袖子的图片),无法完成任务

相关链接

Diffusion从理论角度入门讲解

Lilian Weng’s blog on Diffusion Models

这篇博客由Lilian Weng撰写,详细介绍了扩散模型的理论基础,包括其工作原理、生成质量的提升以及分辨率的扩展。

Diffusion从实战角度的入门讲解

Part I: Understanding Diffusion Models to Generate My Favorite Dog - Part 1

这篇文章是关于如何实战应用扩散模型生成图像的初学者指南,具体展示了生成过程和模型训练的基本步骤。

Part II: Understanding Diffusion Models to Generate My Favorite Dog - Part 2

这篇文章是第一部分的延续,深入探讨了更多高级技巧和优化方法,帮助读者更好地掌握扩散模型的应用。

Diffusion历史梳理

Bilibili视频:扩散模型的历史

这段视频详细梳理了扩散模型的发展历史,从早期的研究到最新的进展,为读者提供了全面的历史背景。

详解Classifier Guidance与Classifier Free Guidance(图非常好)

Geometry and Guidance in Diffusion Models - Sander.ai

这篇文章解释了扩散模型中的几何学和指导技术,包括classifier guidance和classifier-free guidance,并配有详细图示帮助理解。

Guidance Techniques in Diffusion Models - Sander.ai

本文具体探讨了不同的指导技术在扩散模型中的应用,帮助读者理解这些技术的实现细节和效果。

StableDiffusion3论文

StableDiffusion3 on arXiv

这是StableDiffusion3的原始论文链接,提供了该模型的详细研究和技术实现。

StableDiffusion3论文讲解

Stable Diffusion 3 Explained - YouTube

这段视频对StableDiffusion3的论文进行了详细讲解,适合希望快速了解该论文核心内容的读者。

Another explanation of Stable Diffusion 3 - YouTube

另一段视频讲解了StableDiffusion3的论文,从不同角度分析了其技术细节和创新点。

Rectified Flow

Understanding Rectified Flow - Hugging Face

这篇博客文章介绍了Rectified Flow的概念和应用,帮助读者理解其在生成模型中的作用和优势。

自己实现DDIM及DDIM inversion

Implementing DDIM and DDIM Inversion - UCLA Deep Vision

这篇文章详细介绍了如何实现DDIM及其逆过程,为读者提供了实战代码和实现步骤。

使用Cross Attention解释StableDiffusion

Explaining Stable Diffusion with Cross Attention - Colab

这篇Colab笔记本通过Cross Attention机制解释了Stable Diffusion模型的工作原理,适合希望通过代码实践理解模型的读者。

Transformers讲解

Transformers Explained - YouTube

这段视频对Transformer模型进行了深入讲解,适合对这一基础模型感兴趣的读者。

Another explanation of Transformers - YouTube

另一段关于Transformer模型的讲解视频,从不同角度分析了其工作机制和应用场景。

Towards Data Science: Transformers

这篇文章详细介绍了Transformer模型的工作原理和技术细节,适合希望从理论角度深入理解的读者。

Tokenizer计算

OpenAI Tokenizer

这个工具用于计算文本中的token数量,帮助用户理解和优化模型输入。

DIT架构

Diffusion Transformer (DiT) Models: A Beginner’s Guide