扩散模型之DDPM公式推导

163 阅读3分钟

diffusion模型是当下最热门的图像生成模型,但公式比较复杂。虽然网上有很多公式推导的教程,但看完这些教程我只是知道公式是怎么推导的,但不知道公式的来源,总有种知其然不知其所以然的感觉。直到看了苏剑林老师的博客,才明白diffusion model背后的思想,在此记录。

1. 核心理念

我理解的DDPM的核心在于两点

  1. 将未知问题转化为已知问题
  2. 将一步实现改为多步迭代实现

1.1 将未知问题转化为已知问题。

VAE理论推导里有提过,生成模型的目标是利用大量目标分布的样本推断出目标分布整体,进而采样出任意多个目标分布的样本。但目标分布是未知的,很难直接表示出来,一种常见的方法是采用一个已知分布来表示目标分布,这个已知分布就是隐变量。这就是将未知问题(目标分布)转化为已知问题(隐变量)。

1.2 将一步实现改为多步迭代实现

跟其他生成模型比如VAE或者GAN不一样的是,diffusion不止有一个隐变量空间。DDPM将已知分布到目标分布的变换分为许多步(通常为1000)进行,这是diffusion模型跟其他生成模型之间的重要差异。

上面是DDPM的两个核心理念,数学公式只不过是保证两个理念能正确执行的工具而已。

2. 公式推导

DDPM定义了两个过程,分别为从目标分布转化为已知分布的过程,叫前向扩散过程从已知分布转化为目标分布样本的过程叫反向生成过程,下面详细介绍这两个过程。

2.1 前向扩散过程

前向扩散过程可以写为条件概率p(xtxt1,xt2,...x0)p(x_t|x_{t-1},x_{t-2},...x_0),但这个条件概率涉及的变量太多了,为了简化问题,采用马尔科夫链,即当前状态只跟上一步的状态有关,因此扩散过程简化为p(xtxt1)p(x_t|x_{t-1})

因为qq是已知分布,即由我们选择的分布,这里采用高斯分布,那么我们定义

p(xtxt1)N(1βtxt1),βI)(1)p(x_t|x_{t-1}) \sim N(\sqrt{1-\beta_t}x_{t-1}),\beta I) \tag{1}

上面公式就代表了xtx_txt1x_{t-1}决定,期望为1βtxt1\sqrt{1-\beta_t}x_{t-1} 方差为 β\beta

但上边的形式不利于后面的公式推导,因此换一种形式,同时为了后面化简方便我们定义αt=1βt{\alpha_t=1-\beta_t},上面公式变为

xt=αtxt1+βtϵt(2)x_t = \sqrt{\alpha_t}x_{t-1}+\sqrt{\beta_t}\epsilon_t \tag{2}

其中 ϵtN(0,I)\epsilon_t \sim N(0,I)

回想一下前向扩散的目的是什么?是为了将目标分布转化为已知分布(高斯分布)。公式(2)直观上理解其实就是对上一步的变量xtx_t添加高斯分布的噪声,αt\alpha_tβt\beta_t是权重,通过非常多次(比如1000次)的添加噪声,目标分布的信息被高斯噪声淹没,目标分布就转化为了高斯分布。

tt比较小的时候,我们只要添加少量噪声,目标分布就会有比较大的变化,而当tt比较大的时候,我们就需要添加更多的噪声,才能让xtx_t有比较大的变化,因此βt\beta_t是逐渐增大的。

每一步的变化过程已经定义好了,只要将x0x_0代入,一步步计算,就可以得到xtx_t

但这么计算太慢了,通过公式化简,可以一步将x0x_0变为xtx_t

xt1=αt1xt2+βt1ϵtx_{t-1}=\sqrt{\alpha_{t-1}}x_{t-2}+\sqrt{\beta_{t-1}}\epsilon_t 代入到(2)的等式右边并化简后可以得到

xt=αtαt1xt2+1αtαt1ϵ(3)x_t = \sqrt{\alpha_t\alpha_{t-1}}x_{t-2}+\sqrt{1-\alpha_t\alpha_{t-1}}\epsilon \tag{3}

其中 ϵN(0,I)\epsilon \sim N(0,I)。 依次代入直到等式右边只有x0x_0

xt=αtˉx0+1αtˉϵ(4)x_t = \sqrt{\bar{\alpha_t}}x_0+\sqrt{1-\bar{\alpha_t}}\epsilon \tag{4}

αˉt=i=0tαt\bar{\alpha}_t=\prod \limits_{i=0}^t\alpha_t。公式(4)就是由x0x_0变换为xtx_t的过程,即前向扩散过程p(xtx0)p(x_t|x_0)

2.2 反向生成过程

前向扩散过程定义的是从x0x_0xtx_t的过程,但我们最终需要的是从xtx_tx0x_0。根据贝叶斯公式可知

p(xt1xt)=p(xt1)p(xtxt1)p(xt)(5)p(x_{t-1}|x_t)=\frac{p(x_{t-1})p(x_{t}|x_{t-1})}{p(x_t)} \tag{5}

我们的目标是要求p(xt1xt)p(x_{t-1}|x_t),其中p(xtxt1)p(x_{t}|x_{t-1})是前向扩散过程,但p(xt1)p(x_{t-1})p(xt)p(x_t) 都是未知过程。

还记得文章开头说过的DDPM的两个核心吗?这里就需要用到其中一个:将未知问题转化为已知问题。 具体来说就是用p(xt1x0)p(x_{t-1}|x_0)p(xtx0)p(x_t|x_0)来代替p(xt1)p(x_{t-1})p(xt)p(x_t)。公式变为

p(xt1xt,x0)=p(xt1x0)p(xtxt1)p(xtx0)(6)p(x_{t-1}|x_t,x_0)=\frac{p(x_{t-1}|x_0)p(x_{t}|x_{t-1})}{p(x_t|x_0)} \tag{6}

p(xt1x0)p(x_{t-1}|x_0)p(xtx0)p(x_t|x_0)可以由公式(4)求出。

利用高斯分布的概率密度函数化简公式(6)后得到

p(xt1xt,x0)N(αt(1αˉt1)1αtˉxt+αˉt1βt1αtˉx0,1αˉt11αˉtβt)(7)p(x_{t-1}|x_t,x_0) \sim N(\frac{\sqrt{\alpha_t}(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha_t}}x_t+\frac{\sqrt{\bar{\alpha}_{t-1}}\beta_t}{1\bar{\alpha_t}}x_0,\frac{1-\bar{\alpha}_{t-1}}{1-\bar{\alpha}_t}\beta_t) \tag{7}

但问题又出现了,x0x_0是未知的,怎么办呢?DDPM给出的方案是用xtx_t估计x0x_0

由公式(4)我们知道

x0=xt1αtˉϵαˉt(8)x_0 = \frac{x_t-\sqrt{1-\bar{\alpha_t}}\epsilon}{\sqrt{\bar{\alpha}_t}} \tag{8}

我们设计一个网络ϵθ\epsilon_\theta去学习ϵ\epsilon就可以了,所以定义损失函数为

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

最后当我们训练好了ϵθ\epsilon_\theta,前向生成的过程就是由xtx_t->公式(8)->x0x_0->公式(7)->xt1x_{t-1},这么反复t次,得到最终的x0x_0

这里有一个问题,既然我们已经使用xtx_t估计出了x0x_0,我们为什么还要算xt1x_{t-1}呢?这不是多此一举吗?

这涉及到DDPM第二个核心点,即将一步实现改为多步迭代实现,多步迭代能获得更高质量的图片,这也是diffusion模型跟其他生成模型的重要差异。

Reference

Denoising Diffusion Probabilistic Models

苏剑林老师的博客

Stable Diffusion from scratch