生成扩散模型漫谈(一):DDPM = 拆楼 + 建楼
By 苏剑林 | 2022-06-13 | 385514位读者 |说到生成模型,VAE、GAN可谓是“如雷贯耳”,本站也有过多次分享。此外,还有一些比较小众的选择,如flow模型、VQ-VAE等,也颇有人气,尤其是VQ-VAE及其变体VQ-GAN,近期已经逐渐发展到“图像的Tokenizer”的地位,用来直接调用NLP的各种预训练方法。除了这些之外,还有一个本来更小众的选择——扩散模型(Diffusion Models)——正在生成模型领域“异军突起”,当前最先进的两个文本生成图像——OpenAI的DALL·E 2和Google的Imagen,都是基于扩散模型来完成的。
从本文开始,我们开一个新坑,逐渐介绍一下近两年关于生成扩散模型的一些进展。据说生成扩散模型以数学复杂闻名,似乎比VAE、GAN要难理解得多,是否真的如此?扩散模型真的做不到一个“大白话”的理解?让我们拭目以待。
新的起点 #
其实我们在之前的文章《能量视角下的GAN模型(三):生成模型=能量模型》、《从去噪自编码器到生成模型》也简单介绍过扩散模型。说到扩散模型,一般的文章都会提到能量模型(Energy-based Models)、得分匹配(Score Matching)、朗之万方程(Langevin Equation)等等,简单来说,是通过得分匹配等技术来训练能量模型,然后通过郎之万方程来执行从能量模型的采样。
从理论上来讲,这是一套很成熟的方案,原则上可以实现任何连续型对象(语音、图像等)的生成和采样。但从实践角度来看,能量函数的训练是一件很艰难的事情,尤其是数据维度比较大(比如高分辨率图像)时,很难训练出完备能量函数来;另一方面,通过朗之万方程从能量模型的采样也有很大的不确定性,得到的往往是带有噪声的采样结果。所以很长时间以来,这种传统路径的扩散模型只是在比较低分辨率的图像上做实验。
如今生成扩散模型的大火,则是始于2020年所提出的DDPM(Denoising Diffusion Probabilistic Model),虽然也用了“扩散模型”这个名字,但事实上除了采样过程的形式有一定的相似之外,DDPM与传统基于朗之万方程采样的扩散模型可以说完全不一样,这完全是一个新的起点、新的篇章。
准确来说,DDPM叫“渐变模型”更为准确一些,扩散模型这一名字反而容易造成理解上的误解,传统扩散模型的能量模型、得分匹配、朗之万方程等概念,其实跟DDPM及其后续变体都没什么关系。有意思的是,DDPM的数学框架其实在ICML2015的论文《Deep Unsupervised Learning using Nonequilibrium Thermodynamics》就已经完成了,但DDPM是首次将它在高分辨率图像生成上调试出来了,从而引导出了后面的火热。由此可见,一个模型的诞生和流行,往往还需要时间和机遇,
拆楼建楼 #
很多文章在介绍DDPM时,上来就引入转移分布,接着就是变分推断,一堆数学记号下来,先吓跑了一群人(当然,从这种介绍我们可以再次看出,DDPM实际上是VAE而不是扩散模型),再加之人们对传统扩散模型的固有印象,所以就形成了“需要很高深的数学知识”的错觉。事实上,DDPM也可以有一种很“大白话”的理解,它并不比有着“造假-鉴别”通俗类比的GAN更难。
首先,我们想要做一个像GAN那样的生成模型,它实际上是将一个随机噪声$\boldsymbol{z}$变换成一个数据样本$\boldsymbol{x}$的过程:
\begin{equation}\require{AMScd}\begin{CD}
\text{随机噪声}\boldsymbol{z}\quad @>\quad\text{变换}\quad>> \quad\text{样本数据}\boldsymbol{x}\\
@V \text{类比} VV @VV \text{类比} V\\
\text{砖瓦水泥}\quad @>\quad\text{建设}\quad>> \quad\text{高楼大厦}\\
\end{CD}\end{equation}
我们可以将这个过程想象为“建设”,其中随机噪声$\boldsymbol{z}$是砖瓦水泥等原材料,样本数据$\boldsymbol{x}$是高楼大厦,所以生成模型就是一支用原材料建设高楼大厦的施工队。
这个过程肯定很难的,所以才有了那么多关于生成模型的研究。但俗话说“破坏容易建设难”,建楼你不会,拆楼你总会了吧?我们考虑将高楼大厦一步步地拆为砖瓦水泥的过程:设$\boldsymbol{x}_0$为建好的高楼大厦(数据样本),$\boldsymbol{x}_T$为拆好的砖瓦水泥(随机噪声),假设“拆楼”需要$T$步,整个过程可以表示为
\begin{equation}\boldsymbol{x} = \boldsymbol{x}_0 \to \boldsymbol{x}_1 \to \boldsymbol{x}_2 \to \cdots \to \boldsymbol{x}_{T-1} \to \boldsymbol{x}_T = \boldsymbol{z}\end{equation}
建高楼大厦的难度在于,从原材料$\boldsymbol{x}_T$到最终高楼大厦$\boldsymbol{x}_0$的跨度过大,普通人很难理解$\boldsymbol{x}_T$是怎么一下子变成$\boldsymbol{x}_0$的。但是,当我们有了“拆楼”的中间过程$\boldsymbol{x}_1,\boldsymbol{x}_2,\cdots,\boldsymbol{x}_T$后,我们知道$\boldsymbol{x}_{t-1} \to \boldsymbol{x}_t$代表着拆楼的一步,那么反过来$\boldsymbol{x}_t\to \boldsymbol{x}_{t-1}$不就是建楼的一步?如果我们能学会两者之间的变换关系$\boldsymbol{x}_{t-1}=\boldsymbol{\mu}(\boldsymbol{x}_t)$,那么从$\boldsymbol{x}_T$出发,反复地执行$\boldsymbol{x}_{T-1}=\boldsymbol{\mu}(\boldsymbol{x}_T)$、$\boldsymbol{x}_{T-2}=\boldsymbol{\mu}(\boldsymbol{x}_{T-1})$、...,最终不就能造出高楼大厦$\boldsymbol{x}_0$出来?
该怎么拆 #
正所谓“饭要一口一口地吃”,楼也要一步一步地建,DDPM做生成模型的过程,其实跟上述“拆楼-建楼”的类比是完全一致的,它也是先反过来构建一个从数据样本渐变到随机噪声的过程,然后再考虑其逆变换,通过反复执行逆变换来完成数据样本的生成,所以本文前面才说DDPM这种做法其实应该更准确地称为“渐变模型”而不是“扩散模型”。
具体来说,DDPM将“拆楼”的过程建模为
\begin{equation}\boldsymbol{x}_t = \alpha_t \boldsymbol{x}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t,\quad \boldsymbol{\varepsilon}_t\sim\mathcal{N}(\boldsymbol{0}, \boldsymbol{I})\label{eq:forward}\end{equation}
其中有$\alpha_t,\beta_t > 0$且$\alpha_t^2 + \beta_t^2=1$,$\beta_t$通常很接近于0,代表着单步“拆楼”中对原来楼体的破坏程度,噪声$\boldsymbol{\varepsilon}_t$的引入代表着对原始信号的一种破坏,我们也可以将它理解为“原材料”,即每一步“拆楼”中我们都将$\boldsymbol{x}_{t-1}$拆解为“$\alpha_t \boldsymbol{x}_{t-1}$的楼体 + $\beta_t \boldsymbol{\varepsilon}_t$的原料”。(提示:本文$\alpha_t,\beta_t$的定义跟原论文不一样。)
反复执行这个拆楼的步骤,我们可以得到:
\begin{equation}\begin{aligned}
\boldsymbol{x}_t =&\, \alpha_t \boldsymbol{x}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t \\
=&\, \alpha_t \big(\alpha_{t-1} \boldsymbol{x}_{t-2} + \beta_{t-1} \boldsymbol{\varepsilon}_{t-1}\big) + \beta_t \boldsymbol{\varepsilon}_t \\
=&\,\cdots\\
=&\,(\alpha_t\cdots\alpha_1) \boldsymbol{x}_0 + \underbrace{(\alpha_t\cdots\alpha_2)\beta_1 \boldsymbol{\varepsilon}_1 + (\alpha_t\cdots\alpha_3)\beta_2 \boldsymbol{\varepsilon}_2 + \cdots + \alpha_t\beta_{t-1} \boldsymbol{\varepsilon}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t}_{\text{多个相互独立的正态噪声之和}}
\end{aligned}\label{eq:expand}\end{equation}
可能刚才读者就想问为什么叠加的系数要满足$\alpha_t^2 + \beta_t^2 = 1$了,现在我们就可以回答这个问题。首先,式中花括号所指出的部分,正好是多个独立的正态噪声之和,其均值为0,方差则分别为$(\alpha_t\cdots\alpha_2)^2\beta_1^2$、$(\alpha_t\cdots\alpha_3)^2\beta_2^2$、...、$\alpha_t^2\beta_{t-1}^2$、$\beta_t^2$;然后,我们利用一个概率论的知识——正态分布的叠加性,即上述多个独立的正态噪声之和的分布,实际上是均值为0、方差为$(\alpha_t\cdots\alpha_2)^2\beta_1^2 + (\alpha_t\cdots\alpha_3)^2\beta_2^2 + \cdots + \alpha_t^2\beta_{t-1}^2 + \beta_t^2$的正态分布;最后,在$\alpha_t^2 + \beta_t^2 = 1$恒成立之下,我们可以得到式$\eqref{eq:expand}$的各项系数平方和依旧为1,即
\begin{equation}(\alpha_t\cdots\alpha_1)^2 + (\alpha_t\cdots\alpha_2)^2\beta_1^2 + (\alpha_t\cdots\alpha_3)^2\beta_2^2 + \cdots + \alpha_t^2\beta_{t-1}^2 + \beta_t^2 = 1\end{equation}
所以实际上相当于有
\begin{equation}\boldsymbol{x}_t = \underbrace{(\alpha_t\cdots\alpha_1)}_{\text{记为}\bar{\alpha}_t} \boldsymbol{x}_0 + \underbrace{\sqrt{1 - (\alpha_t\cdots\alpha_1)^2}}_{\text{记为}\bar{\beta}_t} \bar{\boldsymbol{\varepsilon}}_t,\quad \bar{\boldsymbol{\varepsilon}}_t\sim\mathcal{N}(\boldsymbol{0}, \boldsymbol{I})\label{eq:skip}\end{equation}
这就为计算$\boldsymbol{x}_t$提供了极大的便利。另一方面,DDPM会选择适当的$\alpha_t$形式,使得有$\bar{\alpha}_T\approx 0$,这意味着经过$T$步的拆楼后,所剩的楼体几乎可以忽略了,已经全部转化为原材料$\boldsymbol{\varepsilon}$。(提示:本文$\bar{\alpha}_t$的定义跟原论文不一样。)
又如何建 #
“拆楼”是$\boldsymbol{x}_{t-1}\to \boldsymbol{x}_t$的过程,这个过程我们得到很多的数据对$(\boldsymbol{x}_{t-1},\boldsymbol{x}_t)$,那么“建楼”自然就是从这些数据对中学习一个$\boldsymbol{x}_t\to \boldsymbol{x}_{t-1}$的模型。设该模型为$\boldsymbol{\mu}(\boldsymbol{x}_t)$,那么容易想到学习方案就是最小化两者的欧氏距离:
\begin{equation}\left\Vert\boldsymbol{x}_{t-1} - \boldsymbol{\mu}(\boldsymbol{x}_t)\right\Vert^2\label{eq:loss-0}\end{equation}
其实这已经非常接近最终的DDPM模型了,接下来让我们将这个过程做得更精细一些。首先“拆楼”的式$\eqref{eq:forward}$可以改写为$\boldsymbol{x}_{t-1} = \frac{1}{\alpha_t}\left(\boldsymbol{x}_t - \beta_t \boldsymbol{\varepsilon}_t\right)$,这启发我们或许可以将“建楼”模型$\boldsymbol{\mu}(\boldsymbol{x}_t)$设计成
\begin{equation}\boldsymbol{\mu}(\boldsymbol{x}_t) = \frac{1}{\alpha_t}\left(\boldsymbol{x}_t - \beta_t \boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t)\right)\label{eq:sample}\end{equation}
的形式,其中$\boldsymbol{\theta}$是训练参数,将其代入到损失函数,得到
\begin{equation}\left\Vert\boldsymbol{x}_{t-1} - \boldsymbol{\mu}(\boldsymbol{x}_t)\right\Vert^2 = \frac{\beta_t^2}{\alpha_t^2}\left\Vert \boldsymbol{\varepsilon}_t - \boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t)\right\Vert^2\end{equation}
前面的因子$\frac{\beta_t^2}{\alpha_t^2}$代表loss的权重,这个我们可以暂时忽略,最后代入结合式$\eqref{eq:skip}$和$\eqref{eq:forward}$所给出$\boldsymbol{x}_t$的表达式
\begin{equation}\boldsymbol{x}_t = \alpha_t\boldsymbol{x}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t = \alpha_t\left(\bar{\alpha}_{t-1}\boldsymbol{x}_0 + \bar{\beta}_{t-1}\bar{\boldsymbol{\varepsilon}}_{t-1}\right) + \beta_t \boldsymbol{\varepsilon}_t = \bar{\alpha}_t\boldsymbol{x}_0 + \alpha_t\bar{\beta}_{t-1}\bar{\boldsymbol{\varepsilon}}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t \end{equation}
得到损失函数的形式为
\begin{equation}\left\Vert \boldsymbol{\varepsilon}_t - \boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\bar{\alpha}_t\boldsymbol{x}_0 + \alpha_t\bar{\beta}_{t-1}\bar{\boldsymbol{\varepsilon}}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t, t)\right\Vert^2\label{eq:loss-1}\end{equation}
可能读者想问为什么要回退一步来给出$\boldsymbol{x}_t$,直接根据式$\eqref{eq:skip}$来给出$\boldsymbol{x}_t$可以吗?答案是不行,因为我们已经事先采样了$\boldsymbol{\varepsilon}_t$,而$\boldsymbol{\varepsilon}_t$跟$\bar{\boldsymbol{\varepsilon}}_t$不是相互独立的,所以给定$\boldsymbol{\varepsilon}_t$的情况下,我们不能完全独立地采样$\bar{\boldsymbol{\varepsilon}}_t$。
降低方差 #
原则上来说,损失函数$\eqref{eq:loss-1}$就可以完成DDPM的训练,但它在实践中可能有方差过大的风险,从而导致收敛过慢等问题。要理解这一点并不困难,只需要观察到式$\eqref{eq:loss-1}$实际上包含了4个需要采样的随机变量:
1、从所有训练样本中采样一个$\boldsymbol{x}_0$;
2、从正态分布$\mathcal{N}(\boldsymbol{0}, \boldsymbol{I})$中采样$\bar{\boldsymbol{\varepsilon}}_{t-1}, \boldsymbol{\varepsilon}_t$(两个不同的采样结果);
3、从$1\sim T$中采样一个$t$。
要采样的随机变量越多,就越难对损失函数做准确的估计,反过来说就是每次对损失函数进行估计的波动(方差)过大了。很幸运的是,我们可以通过一个积分技巧来将$\bar{\boldsymbol{\varepsilon}}_{t-1}, \boldsymbol{\varepsilon}_t$合并成单个正态随机变量,从而缓解一下方差大的问题。
这个积分确实有点技巧性,但也不算复杂。由于正态分布的叠加性,我们知道$\alpha_t\bar{\beta}_{t-1}\bar{\boldsymbol{\varepsilon}}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t$实际上相当于单个随机变量$\bar{\beta}_t\boldsymbol{\varepsilon}|\boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I})$,同理$\beta_t \bar{\boldsymbol{\varepsilon}}_{t-1} - \alpha_t\bar{\beta}_{t-1} \boldsymbol{\varepsilon}_t$实际上相当于单个随机变量$\bar{\beta}_t\boldsymbol{\omega}|\boldsymbol{\omega}\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I})$,并且可以验证$\mathbb{E}[\boldsymbol{\varepsilon}\boldsymbol{\omega}^{\top}]=\boldsymbol{0}$,所以这是两个相互独立的正态随机变量。
接下来,我们反过来将$\boldsymbol{\varepsilon}_t$用$\boldsymbol{\varepsilon},\boldsymbol{\omega}$重新表示出来
\begin{equation}\boldsymbol{\varepsilon}_t = \frac{(\beta_t \boldsymbol{\varepsilon} - \alpha_t\bar{\beta}_{t-1} \boldsymbol{\omega})\bar{\beta}_t}{\beta_t^2 + \alpha_t^2\bar{\beta}_{t-1}^2} = \frac{\beta_t \boldsymbol{\varepsilon} - \alpha_t\bar{\beta}_{t-1} \boldsymbol{\omega}}{\bar{\beta}_t}\end{equation}
代入到式$\eqref{eq:loss-1}$得到
\begin{equation}\begin{aligned}
&\,\mathbb{E}_{\bar{\boldsymbol{\varepsilon}}_{t-1}, \boldsymbol{\varepsilon}_t\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I})}\left[\left\Vert \boldsymbol{\varepsilon}_t - \boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\bar{\alpha}_t\boldsymbol{x}_0 + \alpha_t\bar{\beta}_{t-1}\bar{\boldsymbol{\varepsilon}}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t, t)\right\Vert^2\right] \\
=&\,\mathbb{E}_{\boldsymbol{\omega}, \boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I})}\left[\left\Vert \frac{\beta_t \boldsymbol{\varepsilon} - \alpha_t\bar{\beta}_{t-1} \boldsymbol{\omega}}{\bar{\beta}_t} - \boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\bar{\alpha}_t\boldsymbol{x}_0 + \bar{\beta}_t\boldsymbol{\varepsilon}, t)\right\Vert^2\right]
\end{aligned}\end{equation}
注意到,现在损失函数关于$\boldsymbol{\omega}$只是二次的,所以我们可以展开然后将它的期望直接算出来,结果是
\begin{equation}\frac{\beta_t^2}{\bar{\beta}_t^2}\mathbb{E}_{\boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I})}\left[\left\Vert\boldsymbol{\varepsilon} - \frac{\bar{\beta}_t}{\beta_t}\boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\bar{\alpha}_t\boldsymbol{x}_0 + \bar{\beta}_t\boldsymbol{\varepsilon}, t)\right\Vert^2\right]+\text{常数}\end{equation}
再次省掉常数和损失函数的权重,我们得到DDPM最终所用的损失函数:
\begin{equation}\left\Vert\boldsymbol{\varepsilon} - \frac{\bar{\beta}_t}{\beta_t}\boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\bar{\alpha}_t\boldsymbol{x}_0 + \bar{\beta}_t\boldsymbol{\varepsilon}, t)\right\Vert^2\end{equation}
(提示:原论文中的$\boldsymbol{\epsilon}_{\boldsymbol{\theta}}$实际上就是本文的$\frac{\bar{\beta}_t}{\beta_t}\boldsymbol{\epsilon}_{\boldsymbol{\theta}}$,所以大家的结果是完全一样的。)
递归生成 #
至此,我们算是把DDPM的整个训练流程捋清楚了。内容写了不少,你要说它很容易,那肯定说不上,但真要说非常困难的地方也几乎没有——没有用到传统的能量函数、得分匹配等工具,甚至连变分推断的知识都没有用到,只是借助“拆楼-建楼”的类比和一些基本的概率论知识,就能得到完全一样的结果。所以说,以DDPM为代表的新兴起的生成扩散模型,实际上没有很多读者想象的复杂,它可以说是我们从“拆解-重组”的过程中学习新知识的形象建模。
训练完之后,我们就可以从一个随机噪声$\boldsymbol{x}_T\sim\mathcal{N}(\boldsymbol{0}, \boldsymbol{I})$出发执行$T$步式$\eqref{eq:sample}$来进行生成:
\begin{equation}\boldsymbol{x}_{t-1} = \frac{1}{\alpha_t}\left(\boldsymbol{x}_t - \beta_t \boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t)\right)\end{equation}
这对应于自回归解码中的Greedy Search。如果要进行Random Sample,那么需要补上噪声项:
\begin{equation}\boldsymbol{x}_{t-1} = \frac{1}{\alpha_t}\left(\boldsymbol{x}_t - \beta_t \boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t)\right) + \sigma_t \boldsymbol{z},\quad \boldsymbol{z}\sim\mathcal{N}(\boldsymbol{0}, \boldsymbol{I})\end{equation}
一般来说,我们可以让$\sigma_t=\beta_t$,即正向和反向的方差保持同步。这个采样过程跟传统扩散模型的朗之万采样不一样的地方在于:DDPM的采样每次都从一个随机噪声出发,需要重复迭代$T$步来得到一个样本输出;朗之万采样则是从任意一个点出发,反复迭代无限步,理论上这个迭代无限步的过程中,就把所有数据样本都被生成过了。所以两者除了形式相似外,实质上是两个截然不同的模型。
从这个生成过程中,我们也可以感觉到它其实跟Seq2Seq的解码过程是一样的,都是串联式的自回归生成,所以生成速度是一个瓶颈,DDPM设了$T=1000$,意味着每生成一个图片,需要将$\boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t)$反复执行1000次,因此DDPM的一大缺点就是采样速度慢,后面有很多工作都致力于提升DDPM的采样速度。而说到“图片生成 + 自回归模型 + 很慢”,有些读者可能会联想到早期的PixelRNN、PixelCNN等模型,它们将图片生成转换成语言模型任务,所以同样也是递归地进行采样生成以及同样地慢。那么DDPM的这种自回归生成,跟PixelRNN/PixelCNN的自回归生成,又有什么实质区别呢?为什么PixelRNN/PixelCNN没大火起来,反而轮到了DDPM?
了解PixelRNN/PixelCNN的读者都知道,这类生成模型是逐个像素逐个像素地生成图片的,而自回归生成是有序的,这就意味着我们要提前给图片的每个像素排好顺序,最终的生成效果跟这个顺序紧密相关。然而,目前这个顺序只能是人为地凭着经验来设计(这类经验的设计都统称为“Inductive Bias”),暂时找不到理论最优解。换句话说,PixelRNN/PixelCNN的生成效果很受Inductive Bias的影响。但DDPM不一样,它通过“拆楼”的方式重新定义了一个自回归方向,而对于所有的像素来说则都是平权的、无偏的,所以减少了Inductive Bias的影响,从而提升了效果。此外,DDPM生成的迭代步数是固定的$T$,而PixelRNN/PixelCNN则是等于图像分辨率($\text{宽}\times\text{高}\times{通道数}$),所以DDPM生成高分辨率图像的速度要比PixelRNN/PixelCNN快得多。
超参设置 #
这一节我们讨论一下超参的设置问题。
在DDPM中,$T=1000$,可能比很多读者的想象数值要大,那为什么要设置这么大的$T$呢?另一边,对于$\alpha_t$的选择,将原论文的设置翻译到本博客的记号上,大致上是
\begin{equation}\alpha_t = \sqrt{1 - \frac{0.02t}{T}}\end{equation}
这是一个单调递减的函数,那为什么要选择单调递减的$\alpha_t$呢?
其实这两个问题有着相近的答案,跟具体的数据背景有关。简单起见,在重构的时候我们用了欧氏距离$\eqref{eq:loss-0}$作为损失函数,而一般我们用DDPM做图片生成,以往做过图片生成的读者都知道,欧氏距离并不是图片真实程度的一个好的度量,VAE用欧氏距离来重构时,往往会得到模糊的结果,除非是输入输出的两张图片非常接近,用欧氏距离才能得到比较清晰的结果,所以选择尽可能大的$T$,正是为了使得输入输出尽可能相近,减少欧氏距离带来的模糊问题。
选择单调递减的$\alpha_t$也有类似考虑。当$t$比较小时,$\boldsymbol{x}_t$还比较接近真实图片,所以我们要缩小$\boldsymbol{x}_{t-1}$与$\boldsymbol{x}_t$的差距,以便更适用欧氏距离$\eqref{eq:loss-0}$,因此要用较大的$\alpha_t$;当$t$比较大时,$\boldsymbol{x}_t$已经比较接近纯噪声了,噪声用欧式距离无妨,所以可以稍微增大$\boldsymbol{x}_{t-1}$与$\boldsymbol{x}_t$的差距,即可以用较小的$\alpha_t$。那么可不可以一直用较大的$\alpha_t$呢?可以是可以,但是要增大$T$。注意在推导$\eqref{eq:skip}$时,我们说过应该有$\bar{\alpha}_T\approx 0$,而我们可以直接估算
\begin{equation}\log \bar{\alpha}_T = \sum_{t=1}^T \log\alpha_t = \frac{1}{2} \sum_{t=1}^T \log\left(1 - \frac{0.02t}{T}\right) < \frac{1}{2} \sum_{t=1}^T \left(- \frac{0.02t}{T}\right) = -0.005(T+1)\end{equation}
代入$T=1000$大致是$\bar{\alpha}_T\approx e^{-5}$,这个其实就刚好达到$\approx 0$的标准。所以如果从头到尾都用较大的$\alpha_t$,那么必然要更大的$T$才能使得$\bar{\alpha}_T\approx 0$了。
最后我们留意到,“建楼”模型中的$\boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\bar{\alpha}_t\boldsymbol{x}_0 + \bar{\beta}_t\boldsymbol{\varepsilon}, t)$中,我们在输入中显式地写出了$t$,这是因为原则上不同的$t$处理的是不同层次的对象,所以应该用不同的重构模型,即应该有$T$个不同的重构模型才对,于是我们共享了所有重构模型的参数,将$t$作为条件传入。按照论文附录的说法,$t$是转换成《Transformer升级之路:1、Sinusoidal位置编码追根溯源》介绍的位置编码后,直接加到残差模块上去的。
文章小结 #
本文从“拆楼-建楼”的通俗类比中介绍了最新的生成扩散模型DDPM,在这个视角中,我们可以通过较为“大白话”的描述以及比较少的数学推导,来得到跟原始论文一模一样的结果。总的来说,本文说明了DDPM也可以像GAN一样找到一个形象类比,它既可以不用到VAE中的“变分”,也可以不用到GAN中的“概率散度”、“最优传输”,从这个意义上来看,DDPM甚至算得上比VAE、GAN还要简单。
转载到请包括本文地址:https://kexue.fm/archives/9119
更详细的转载事宜请参考:《科学空间FAQ》
如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!
如果您需要引用本文,请参考:
苏剑林. (Jun. 13, 2022). 《生成扩散模型漫谈(一):DDPM = 拆楼 + 建楼 》[Blog post]. Retrieved from https://kexue.fm/archives/9119
@online{kexuefm-9119,
title={生成扩散模型漫谈(一):DDPM = 拆楼 + 建楼},
author={苏剑林},
year={2022},
month={Jun},
url={\url{https://kexue.fm/archives/9119}},
}
July 19th, 2022
我想问一下,公式13到14里面不是有两个正态分布吗,为什么w可以算出来,另一个不行
将$\Vert \cdot \Vert^2$展开后,表达式关于$\boldsymbol{\omega}$只是一个二次函数,正态分布乘上一个二次函数进行积分,是可以直接算出来的;但是关于$\boldsymbol{\varepsilon}$是一个复杂函数,因为$\boldsymbol{\varepsilon}$还包含在$\boldsymbol{\epsilon}_{\boldsymbol{\theta}}$里边,该函数可能是任意非线性函数,因此我们没法提前算出这个积分。
苏神,还是关于$(13)$式的推导有点疑惑,
$(13)$的$\|·\|^2$展开,
$$
\|·\|^2=(\frac{\beta_t}{\bar{\beta_t}}\epsilon)^2-\frac{2\alpha_t\bar{\beta}_{t-1}\beta_t}{\bar{\beta_t}}\epsilon w+(\frac{\alpha_t\bar{\beta}_{t-1}}{\bar{\beta_t}}w)^2-\frac{2\beta_t\epsilon}{\bar{\beta_t}}\epsilon_{\theta}+\frac{2\alpha_t\bar{\beta}_{t-1}w}{\bar{\beta_t}}\epsilon_{\theta}+\epsilon_{\theta}^2
$$
右端项中的第2、3项取期望之后是与$\epsilon$,$w$无关的常数,其中第5项感觉消不掉啊,取期望之后是与$\epsilon_{\theta}$有关,即
$$
\frac{2\alpha_t\bar{\beta}_{t-1}}{\bar{\beta_t}}\epsilon_{\theta}
$$
不知道是哪里理解错了,还请指点一下
$\boldsymbol{\omega}\sim\mathcal{N}(\boldsymbol{0},\boldsymbol{I})$,期望为$\boldsymbol{0}$
老师好,我还是不太理解,w期望为0,但是ϵθ并不是常量,该函数可能是任意非线性函数,w*ϵθ的期望不应该为0
如果$x,y$是相互独立的,那么$\mathbb{E}[f(x)g(y)]=\mathbb{E}[f(x)]\mathbb{E}[g(y)]$。
@xuzihan|comment-19643的评论,展开式第4与第5项中,ϵ与w不都是在ϵθ中吗?
@1|comment-24368:里外都有
第三项是。E(w^2)等于卡方分布。其均值是1所以能够消掉。而第五项由于w和ϵθ是相互对立,且E(w)为0,所以可以消掉。不知道理解的是否正确
感觉很正确
July 20th, 2022
苏神,请教两个问题。
因为刚开始接触生成式模型,也暂时没看过GAN和VAE的东西,所以问题有点初级。
第一个问题是: 对于某个初始数据$X$,我们经历1000步拆楼,将其拆成原料之后,用一个训练好的模型去盖楼,盖了1000步之后得到$Y$。 这对儿$Y$和$X$通过损失函数建立起了对应关系么? 还是说这对儿数据仅作为求取均值的一员,两者的关系被融入到 数据集的均值 这样更泛泛的关系之中了,而并非有明确的对应关系呢?
@skbl5694|comment-19510
第二个问题是: 我注意到文章中你写到,我们会显式的写出t,作为参数传入模型。 那如果我把一个拆楼进行到900步的结果$X_{t=900}$作为初始材料(比如一张图片),在此基础上盖楼1000步的话,模型会输出所谓的$X_{t=-100}$,这个$X_{t=-100}$和按照正常方式产生的$X_{t=0}$有什么样的关系呢?(或许前者更加清晰?)。虽说在生成的时候我们选取的初始值是从标准高斯分布采样的随机噪声;但拆了900步的结果应该也可以近似看作随机噪声。所以我比较好奇在这种情况下会出现什么样的结果。
(另外,貌似因为字数太多,不得不分两次评论,但提交评论时候也没有提醒字数超过上限)
1、将一栋楼拆完了再建,新建的楼跟原来的楼可以说完全没有关系,所以DDPM不能用$\boldsymbol{x}_T$去做重构,重构不了的;
2、你可以理解为建楼的不同时期包含了不同的操作,比如砌砖、贴砖、窗户、木工,分别需要不同的工人,尽管他们都可以统一叫做“施工队”,但实际上含义不一样,因此$t$要显式传入,表明不同阶段的模型实际上是不一样的;
3、如果你把中途的结果当作随机噪声从零生成,效果可能会差,就好比你将一栋已经起砌好砖的楼又交给砌砖师傅重新砌砖,砌砖师傅就直接懵了,可能就乱来了;
4、评论没有字数限制,但网友反映有小概率会丢失评论,现在没法定位这个问题。
其实还有个更重要的问题:就是为什么可以预测噪声? 感觉一定是我哪里理解除了问题。比如我们一直一个标准正态分布,我们从这个分布产生噪声,之后一步步加到原始图片上。 按照扩散模型的意思,这个过程是可逆的。这个可逆难道是代表了我们能够一步步的找到之前加入的噪声,之后一层层将其减去么?如果不是这样的话,那该从什么样的角度理解这个可逆过程呢?希望苏神能解答一下。
你的理解全对啊,一点问题都没出。
噪声是没规律的,图像是有规律的,所以模糊的图片我们也可以通过脑补和PS得到清晰的图片,然后再减去原来模糊的图片,不就得到了噪声?所以人也是可以预测噪声的,模型自然也可以。
归根结底,它就是图片去噪换了个写法而已,本质上就是图片去噪。
但是从结果来看,扩散模型可以让我们从一个随机的高斯噪声中产生一张图片(扩散模型还没看完,难道说不是这个意思么), 我们可以从一张模糊的图片脑补和PS得到清晰的图片,但怎么能从一张纯高斯噪声起始得到一张图片呢?
这是构建一个映射而已啊,有什么不可以的,相当于抛一枚骰子,然后根据点数取出对应编号的图片,这不就构成了一个随机正数到图片的映射了么?正态分布也是一样的,只不过是连续型映射。
那是怎么保证每个噪声都能生成有意义的图片呢?通过极其大量的数据训练出的映射关系么?我脑海中的图片是: 训练时相当于我们用A集合(噪声)中大量的散点映射到B集合(各种图片),让这个映射可靠的办法就是让训练的散点尽可能遍布A集合的每个位置(感觉这像个无底洞); 如果数据少的话,这个方法是不是就不灵了呢? 现在的DALLE2和IMAGEN效果这么好是不是意味着他们训练数据的量已经某种程度足够了呢?
这就是连续模型的意义所在了,模型有从有限张图片中学到了这类图片的规律,所以等价于说模型有能力生成无限多同类的图片(以人脸为力,不同性别、年龄、发型、肤色等各种组合可以说无限的),所以从任意一个噪声都能映射出一张图片出来,因为有限多的图片可以通过模型泛化到无限多的图片。
August 5th, 2022
苏老师你好,问两个小问题:
(1)我自己训练了一个模型,模型训练好后,我做了这样的测试,我把一个$x_0$加1000次噪声得到$x_{1000}$,逆过程我从$x_{1000}$再逆回去,得到一个结构${x_0}'$,此时的$x_0$和逆过程得到的${x_0}'$会是一样的吗?两者有什么关系吗?
(2)我想问一下,对于一些数据集,如何去确定这个超参$T$呢?
希望得到您的解答,谢谢!
另外有个问题,就是我想通过逆过程得到和$x_0$一模一样(或者非常相似,类似重建任务)的$x_0'$该怎么做呢?
这个需求可以看DDIM篇或者ODE篇:
https://kexue.fm/archives/9181
https://kexue.fm/archives/9228
(1)基本可以说没关系
(2)目前我看到的工作一般都是固定$T=1000$。
August 17th, 2022
您好,非常感谢您的blog。关于这点,我有一点疑惑:
DDPM中 $\epsilon_{\theta}$ 相当于是对 $\epsilon$ 进行的参数化逼近。
您这里的 $\epsilon_{\theta}$的物理意义,是相对于 $\epsilon_t$的参数化逼近吗。
如果可以这么理解的话,为什么对$\epsilon_t$的参数化结果乘上一个 $\frac{\hat\beta_t}{\beta_t}$ 就等价于对$\epsilon$的参数化结果了呢?
这里的推导是没有问题的,我想知道这里有没有什么比较直接一些的解释。
谢谢。
这个问题貌似挺好的,我好像没啥直观理解(捂脸)
+1 同样对这个很疑惑
从公式(8)来看感觉是对 $\epsilon_t$ 的参数化,
但最后到公式(15)确实不理解了,是因为简化过程消去了$\omega$ 导致没法直观理解吗?
很遗憾,我至今没想到一个直观的解释,只能通过纯数学来推。
结合 生成扩散模型漫谈(三)中的公式(13)好像确实是相差一个 $\frac{\hat{\beta}_t}{\beta_t}$,不知道怎么理解
这点真的很有意思,我也很好奇,码住后面再看看
August 25th, 2022
苏老师,请教一下:
(1)“$\alpha_t \bar{\beta}_{t-1} \bar{\epsilon}_{t-1} + \beta_t\epsilon_t$相当于单个随机变量$\bar{\beta}_t\epsilon | \epsilon \mathcal \sim N(0,I)$”,其中“$\epsilon \mathcal \sim N(0,I)$”表示$\epsilon$服从正态分布,但是$\bar{\beta}_t\epsilon$这个怎么理解?
(2)您在回复中提到的“根据定义有$(\alpha_t \bar{\beta}_{t-1})^2 + \beta_t^2=\bar{\beta}_t^2$”,是定义“$\alpha_t^2 + \beta_t^2=1$”吗?是的话,这个定义里面$\alpha_t$是$\boldsymbol{x}_{t-1}$的系数,替换为$\bar{\epsilon}_{t-1}$的系数$\alpha_t \bar{\beta}_{t-1}$来理解,看上去好像把$\boldsymbol{x}_{t-1}$变脸替换为$\bar{\epsilon}_{t-1}$,这样做的目的是什么呢?
期待您的回复,感谢~~~
(1)这里的 $\epsilon$应该就是前面那个$x_t$展开成$x_0$式子中的$\epsilon_t$吧,这二者按照前面4,5,6式中的定义是想等的。
(2)不造~
1、$\bar{\beta}_t\boldsymbol{\varepsilon}$就是$\boldsymbol{\varepsilon}$的基础上再乘以$\bar{\beta}_t$呀,还能怎么理解?
2、根据的是$\alpha_t, \beta_t, \bar{\alpha}_t, \bar{\beta}_t$的定义:
$$(\alpha_t \bar{\beta}_{t-1})^2 + \beta_t^2=\alpha_t^2 \bar{\beta}_{t-1}^2 + \beta_t^2 = \alpha_t^2 (1 - \bar{\alpha}_{t-1}^2) + \beta_t^2 = 1 - \alpha_t^2 \bar{\alpha}_{t-1}^2 = 1 - \bar{\alpha}_t^2 = \bar{\beta}_t^2$$
动手算,看不出来的。
感谢两位的回复~~~
1.不好意思,我没描述清楚,是想问一下这个表达式的含义是什么:$\bar{\beta}_t\epsilon | \epsilon \mathcal \sim N(0,I)$?(捂脸,只明白这个$\epsilon \mathcal \sim N(0,I)$表示服从标准正态分布)
2.很清楚,感谢~~~
就是指式子$\hat{\beta}_t\epsilon$里的$\epsilon$符合正态分布。
August 25th, 2022
苏老师,还有一处不太清楚:
根据公式(6)后半部分:$\underbrace{\sqrt{1 - (\alpha_t\cdots\alpha_1)^2}}_{\text{记为}\bar{\beta}_t} \bar{\boldsymbol{\varepsilon}}_t$,那就是说$\bar{\beta}_t\bar{\boldsymbol{\varepsilon}}_t=\sqrt{(\alpha_t\cdots\alpha_2)^2\beta_1^2 + (\alpha_t\cdots\alpha_3)^2\beta_2^2 + \cdots + \alpha_t^2\beta_{t-1}^2 + \beta_t^2}\bar{\boldsymbol{\varepsilon}}_t$ 要等于$(\alpha_t\cdots\alpha_2)\beta_1 \boldsymbol{\varepsilon}_1 + (\alpha_t\cdots\alpha_3)\beta_2 \boldsymbol{\varepsilon}_2 + \cdots + \alpha_t\beta_{t-1} \boldsymbol{\varepsilon}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t$ ?但是没太看出来上下两个表达式是怎么相等的?(捂脸)
参考 @苏剑林|comment-19686 和 @高瑞|comment-19677 。
不是看出来的,是算出来的。
August 26th, 2022
这个应该是:首先多个独立的高斯变量线性叠加还是高斯的,那么对上式求期望和方差就可以得到叠加后的高斯分布,期望是0,然后方差应该就是上面第二个式子了(没计算)。(可能没有get到大哥的意思哈,如是,见谅)
确实如此,感谢辅助读者解惑。
August 31st, 2022
“将$x_{t-1}$拆解为$\alpha_{t}x_{t-1}$的楼体+$\beta_{t} \varepsilon_{t}$的原料”这里应该是拆$x_{t}$吧。^-^
对的这里应该是typo
对什么对,哪有什么typo。
将$\boldsymbol{x}_{t-1}$拆成$\boldsymbol{x}_t$,$\boldsymbol{x}_t$是“$\alpha_t \boldsymbol{x}_{t-1}$的楼体 + $\beta_t \boldsymbol{\varepsilon}_t$的原料”,这么显然成立的描述...
苏神,文章这里倒确实是有笔误,式(3)下面那段的最后一句,写成“拆$x_{t-1}$”啦
你们是阅读理解能力不好嘛?我说的就是【将$\boldsymbol{x}_{t-1}$拆解为“$\alpha_t \boldsymbol{x}_{t-1}$的楼体 + $\beta_t \boldsymbol{\varepsilon}_t$的原料”】这句话是对的,$\boldsymbol{x}_{t-1}$和$\boldsymbol{x}_t$没有搞错。
理解了,原本是$\boldsymbol x_{t-1}$,现在拆成$\boldsymbol x_t=\alpha_t \boldsymbol x_{t-1}+\beta_t\boldsymbol\epsilon_t$,苏神说的也是对的
完全没毛病,每个$x_t$本身也是由楼体和原料组成,前向得到$x_{t-1}$的过程就是对他进一步拆分的过程。慢慢楼体的比重越来越少,到最后就彻底成废墟了。
August 31st, 2022
您好苏神,请问公式5到底是如何推导的?看了半天不知所以
我的问题是,如果得到等于1始终成立的?应该如何推导?谢谢~
比如说前两项,$(\alpha_t\cdots\alpha_1)^2 +(\alpha_t\cdots \alpha_2)^2\beta_1^2=(\alpha_t\cdots \alpha_2)^2(\alpha_1^2 + \beta_1^2)=(\alpha_t\cdots \alpha_2)^2$,第一步就是提出来同类项,第二部就是利用$\alpha_t^2+\beta_t^2=1$。之后每步都这么递归就消完了。
是动“手”推导的,不是动“眼”推导的,所以看了半天都不懂很合理。
第一行:$\boldsymbol{x}_t = \alpha_t \boldsymbol{x}_{t-1} + \beta_t \boldsymbol{\varepsilon}_t$, $\alpha_t^2 + \beta_t^2 = 1$;
第二行:$\boldsymbol{x}_t = \alpha_t \big(\alpha_{t-1} \boldsymbol{x}_{t-2} + \beta_{t-1} \boldsymbol{\varepsilon}_{t-1}\big) + \beta_t \boldsymbol{\varepsilon}_t$,有
$$1 = \alpha_t^2 + \beta_t^2 = \alpha_t^2(\alpha_{t-1}^2 + \beta_{t-1}^2) + \beta_t^2 = \alpha_t^2\alpha_{t-1}^2 + \alpha_t^2\beta_{t-1}^2 + \beta_t^2$$
依此类推,每一行展开,各项系数的平方和都是1。
August 31st, 2022
公式(12)这里卡了一下,他这里主要是因为正态分布,本来就是关于0对称的,所以正负不影响。而$\alpha_t \bar{\beta}_{t-1}$和$\beta_t$这两个系数分别乘了两个正态分布变量,因此可以看成等价的 $\bar{\beta}_t\epsilon$. 然后 两个等式联立消去$\bar{\epsilon}_t$.得到(12)