Last updated on February 21, 2025 10:22 PM
本文主要涉及无监督学习中的生成式模型,介绍了 VAE 与 DDPM。
在阅读本篇之前建议先阅读10-无监督学习。
张老师关于 VAE 的推导和讲解非常精彩,强烈建议动手跟着推一遍。
一键回城。
VAE(变分自编码器,Variational Autoencoder)
引入
在上篇笔记中的 MoG 其实已经是种生成式模型了,但其只能用于处理成簇/低维的数据(会面临维度灾难:高维下数据点之间的欧氏距离没有那么好的实际意义了)
一种高维数据的代表是图片。比如我们知道 x∼p(x),但是一般而言从 p(x) 中采样是比较困难的。但是像均匀分布 U([a,b]) 和高斯分布这样比较简单的分布还是比较容易采样的。
一种思路是,从一个简单的分布(如 [0,1] 高斯分布)中采样一个隐变量 z,然后用一个函数(可以是一个神经网络)f(z;θ) 将 z 映射到 x(可以是图片)。事实上这也是市面上大多数生成式模型的基本思路。
此时 p(x) 可以写成
p(x)=∫zp(x∣z;θ)⋅p(z)dz
为添加随机噪声可以用 N(x∣f(z;θ),σ2I) 来代替 p(x∣z;θ),p(z) 可以就是简单的 p(z)=N(z∣0,I)。和 MoG 不一样的是,此时 z 是连续的,所以要写成积分。
所以就使用 MLE 来优化 θ,最大化 θmaxi∈[n]∑logp(xi)。那么如何优化之呢?
- SGD?一个很大的问题在于,我们需要计算 z 在其全空间上的积分,而这是无法直接计算的,如果用蒙特卡洛方法来近似的话,需要进行巨量采样以较为准确地近似,而且 z 的维度过高,故也是不行的。且考虑到 xi 的数量 n 在实际中也是非常大的,所以不能使用 SGD。
- EM?优化这种带隐变量的 p(x) 确实能让人想起 EM。在 E-step 中要计算后验 p(zi∣xi;θold),在 M-step 中要最大化 θmax∫zp(zi∣xi;θold)p(xi,zi;θ)dz。但是在 E-step 这一步,回想 MoG 中,要计算的是 ∑zip(xi∣zi)⋅p(zi)p(xi∣zi)⋅p(zi),zi 的取值是有限的(k 种),但是在当前的问题里面其变为 ∫zip(xi∣zi)⋅p(zi)p(xi∣zi)⋅p(zi),这个积分也是没法算的。
SGD 和 EM 都不 work 了,核心问题在于隐变量的后验 p(z∣x;θ) 不好计算。
ELBO 推导
解决方案:引入一个变分分布(variational distribution)q(z∣x;θ′) 来近似 p(z∣x;θ)。注意这个变分分布是有自己的参数 θ′ 的,在 EM 中因为推出来其就是上一步的旧参数所以就没有单独写出来自己的参数。
接下来就是推导 ELBO 了,根据上一篇笔记的内容,我们知道
logp(x;θ)=z∑q(z∣x)⋅logq(z∣x)p(x,z;θ)−z∑q(z∣x)⋅logq(z∣x)p(z∣x;θ)
等号右边第一项就是 ELBO,第二项就是 q(z∣x) 和 p(z∣x;θ) 的 KL 散度。
不过 ELBO 事实上可以直接认为是 ELBO=logp(x)−KL(q∥p)。推导:
ELBO=logp(x;θ)−KL(q(z∣x;θ′)∥p(z∣x;θ))=logp(x;θ)−∫zq(z∣x;θ′)⋅logp(z∣x;θ)q(z∣x;θ′)dz=∫zq(z∣x;θ′)logp(x;θ)dz−∫zq(z∣x;θ′)⋅logp(z∣x;θ)q(z∣x;θ′)dz=∫zq(z∣x;θ′)logq(z∣x;θ′)p(x;θ)p(z∣x;θ)dz=∫zq(z∣x;θ′)logq(z∣x;θ′)p(x,z;θ)
发现和上一篇笔记里面得到的 ELBO 是一样的。实际中推导 ELBO 一般就使用这种方法,比较简单。注意第三行里面 ∫zq(z∣x;θ′)dz=1,凑这个项是为了和减号右边的东西更好配凑。
ELBO 和实际的对数似然之间相差的就是那个 KL 散度,所以用 ELBO 的效果好不好就取决于 q 是否足够接近 p(z∣x;θ)。
这个 ELBO 怎么优化?
其实还是通过采样 z 来近似计算这个积分,然后用梯度下降。在前面我们说过梯度下降不 work,但为什么在这里就 work 了呢?
在前面的情况,我们为了采样 z 需要在 z 的先验分布(通常是个高维高斯分布)里面“漫无目的”地进行采样,高维潜在空间中的绝大多数 z 对 p(x∣z) 的贡献几乎为零,导致蒙特卡洛估计需要极多样本才能降低方差,计算代价过高,且梯度估计的方差会很高。
但是在 ELBO 中,z 是在变分分布(近似后验) q(z∣x;θ′) 中采样的样本集中在 p(x∣z) 中有显著贡献的区域,极大提升了采样效率。
- 在 EM 中,我们是交替地优化 θ 和 q(固定一个优化另一个);
- 在 VAE 中,我们是同时优化 θ 和 q(θ′)。
关于对 ELBO 的另一种直接推导:
logp(x)=log∫zp(x∣z)q(z)dz=logEz∼q(z)[logq(z)p(x,z)]≥Ez∼q(z)[logq(z)p(x,z)]Jensen Inequality
最后得到的那个东西事实上就是 ELBO。
AE 简介
在继续推导 VAE 的具体形式之前,我们先来看一下何为 AE(autoencoder)。
如上图所示,一个 AE 由两个神经网络组成,分别称为编码器 encoder 和解码器 decoder。编码器负责将原始数据 x 压缩到一个更小的空间中,即生成隐变量 z。解码器则负责根据隐变量 z 还原出 x~。朴素 AE 的 loss 就看 decoder 重建出来的效果。
一个想法是:随机采样 z,然后直接让其过 decoder,这样其就是一个生成式模型了。但是朴素的 AE 一般不太 work,因为 encoder 生成的 z 的分布是不太好采样的,其可能散落在高维空间的各个角落,所以随机采样的 z 生成出来的 x~ 大概率是不太有道理的。
而 VAE 的想法就是将 z 集中在各向同性的标准高斯分布 N(0,I) 附近(由下式的 KL 散度实现),VAE 最终形式的损失函数为
min{reconstruction loss+KL(q(z∣x;θ′)∥p(z)∼N(0,I))}
那么我们要生成图片的时候从 N(0,I) 中采样 z,就能生成比较有道理的图片了。那么怎么推导呢?
VAE 损失函数推导
首先重写一下 ELBO:
ELBO=∫zq(z∣x;θ′)logq(z∣x;θ′)p(x,z;θ)=∫zq(z∣x;θ′)logp(x∣z;θ)dz+∫zq(z∣x;θ′)logq(z∣x;θ′)p(z)dz=∫zq(z∣x;θ′)logp(x∣z;θ)dz−KL(q(z∣x;θ′)∥p(z))
KL(q(z∣x;θ′)∥p(z)) 就是 encoder 与 z 的先验之间的 divergence(最大化 ELBO,所以要最小化这个 KL)。
∫zq(z∣x;θ′)logp(x∣z;θ)dz 可以看成 reconstruction quality。实际中建模成 p(x∣z;θ)=N(x∣f(z,θ),σ2I)。所以
logp(x∣z;θ)=log(2πσ)2d1exp(−2σ2∥f(z;θ)−x∥2)=C−2σ21∥f(z;θ)−x∥2
为了最大化 ∫zq(z∣x;θ′)logp(x∣z;θ)dz,就要最小化 ∥f(z;θ)−x∥2,我们管这个东西就叫做重建误差 reconstruction loss。
按理来说我们为了算一个 x 的 recon loss 是需要从 q(z∣x;θ′) 中采样很多个 z 来算这个积分的,但是实际操作中对每个 xi 只采样一个 zi。这样类似 SGD,可以提升随机性,缓解过拟合。
到这个时候我们就可以看一下 VAE 的大概结构了。我们将编码器 q(z∣x;θ′) 也看成高斯分布 N(z∣μ(x;θ′),Σ(x;θ′)),只不过 μ 由神经网络给出,Σ 一般为对角阵(也由神经网络计算)。对于前向传播,输入一个 x,然后从这个分布 N(z∣μ(x;θ′),Σ(x;θ′)) 里面采样一个 z,最后生成一个 x~=f(z;θ)(注意这里直接取了 p(x∣z) 的均值)。对于一个数据集 {x1,⋯,xn},损失函数就可以写为
n1i∈[n]∑[∥xi~−xi∥2+β⋅KL(q(z∣x;θ′)∥p(z))]
n1i∈[n]∑∥xi~−xi∥2 为 recon loss,前面的常数什么的就直接以 β 的形式给到 KL 散度上了。同时由于这是两个高斯分布的 KL 散度,是有闭式解的,所以也很好计算。VAE 的损失函数就这样推导出来了,非常简洁明了。
其中 β 为很重要的超参数,如果 β 过小,KL 散度不能产生贡献,其就会退化成普通 AE;如果 β 过大,recon loss 产生贡献不足,就可能导致在训练数据上都达不到好的重建效果。在实际中,调 β 是很重要的一环。
重参数化技巧(Reparameterization Trick)
不过还没完,有一个很重要的问题是,我们在做梯度回传的时候,由于有一个从 q(z∣x;θ′) 中 采样 z 的操作的存在,我们的梯度在此中断了,没法往回传到 q(θ′) 中。
解决的方法也很简单,我们不从 N(z∣μ(x;θ′),Σ(x;θ′)) 里面直接采样 z,而是从标准正态分布 N(0,I) 中采样一个 ε,然后令 z=Σ(x)21⋅ε+μ(x)。
为什么这样是可行的?
我们接下来证明 z=Σ(x)21⋅ε+μ(x)∼N(μ(x),Σ(x))。
均值是显然的,E[z]=μ(x)。
至于协方差:
Cov(z)=E[(z−E[z])(z−E[z])T]=E[Σ(x)21εεTΣT(x)21]=Σ(x)21E[εεT]Σ(x)21=Σ(x)
第三行到第四行是基于 εεT=I。
经过重参数化,梯度就可以往前流了,如下图所示:

重参数化技巧的应用:
对于均匀分布的情况 z∼U([a,b]) 也是可以用重参数化技巧的:从 U([0,1]) 采样 ε,然后令 z=ε(b−a)+a。
KL 散度的计算
最后一个问题就是如何算 p(z)=N(z∣0,I) 和 q(z∣x;θ′)=N(z∣μ(x),Σ(x)) 之间的 KL 散度。
开推:
KL(q(z∣x;θ′)∥p(z))=∫zN(z∣μ(x),Σ(x))logN(z∣0,I)N(z∣μ(x),Σ(x))=Ez∼N(z∣μ(x),Σ(x))⎣⎢⎡log(2π)2d1exp(−21zTz)(2π)2d1∣Σ(x)∣211exp(−21(z−μ(x))TΣ(x)−1(z−μ(x)))⎦⎥⎤=Ez∼N(z∣μ(x),Σ(x))[−21logdetΣ(x)−21(z−μ(x))TΣ(x)−1(z−μ(x))+21zTz]
考虑每一项怎么求。第一项与 z 无关,所以不用管。对于第二项,需要用到一个叫做 trace trick 的方法。因为 (z−μ)TΣ−1(z−μ) 是一个标量,所以其与 tr((z−μ)TΣ−1(z−μ)) 是相等的。然后基于 tr(ABC)=tr(BCA)=tr(CAB),就可得到
===Ez[tr((z−μ)TΣ−1(z−μ))]Ez[tr((z−μ)(z−μ)TΣ−1)]tr(Ez[(z−μ)(z−μ)T]Σ−1)tr(ΣΣ−1)=tr(I)=d
其中 d 为 z 的维度。
最后还有 Ez[zTz]。我们发现凑出 Σ 是一个非常好的事情,所以这里进行一个减 μ 加 μ 的方法来配凑出 Σ:
Ez[zTz]=Ez[(z−μ+μ)T(z−μ+μ)]=Ez[(z−μ)T(z−μ)]+2Ez[(z−μ)T]⋅μ+μTμ=tr(Σ)+μTμ
第二行中的 Ez[(z−μ)T] 显然为 0,第二行到第三行同样用了 trace trick 来凑出 Σ。
所以我们最后得到
KL(q(z∣x;θ′)∥p(z))=−21logdetΣ−21d+21tr(Σ)+21μTμ
一般为了简便直接令 Σ 为对角阵,Σ(x)=σ(x)2I,其中 σ(x)2∈Rd,代表每一维的方差,同样由神经网络给出,则 KL 散度的形式可以写为
KL(q(z∣x;θ′)∥p(z))=−21j∈[d]∑logσ(x)j2−21d+21j∈[d]∑σ(x)j2+21μT(x)μ(x)
实际中神经网络输出的为 logσ(x)2,过一个 exp 就可以得到 σ(x) 了。
扩散模型(Diffusion Model)
简述
这里讲的是最基本的扩散模型 DDPM (Denoising Diffusion Probabilistic Model)。
原理:用 T(≈1000) 步去噪将一个高斯噪声逐步变成清晰图像。
对比 VAE,VAE 只有一个隐变量,而 DDPM 就可以理解为有很多层隐变量。这个去噪过程会将随机高斯噪声逐步变清晰,从完全噪声开始逐渐出现轮廓,最后变得清晰。
VAE 只有一层隐变量也导致了其性能有瓶颈,实际上 VAE 训练出来的图像都比较模糊(因为信息被压缩到 Rd 上了),但 DDPM 生成的就较为清楚。但是相应地,DDPM 对算力的消耗就相当巨大了(生成一张图需要走 T 步)。
我们的训练目标显然还是最大化对数似然 maxθlogpθ(x0),但是
pθ(x0)=∫pθ(x0,x1:T)dx1:T=∫p(xT)t∈[T]∏pθ(xt−1∣xt)dx1:T
这个积分同样是 intractable 的。
用 EM 呢?在 E-step 中需要后验 pθ(x1:T∣x0)=pθ(x0)pθ(x0:T),同样是 intractable 的。
所以类似 VAE,引入变分分布 q(x1:T∣x0) 来近似 pθ(x1:T∣x0),于是
ELBO=logpθ(x0)−KL(q(x1:T∣x0)∥pθ(x1:T∣x0))
模型示意图如下:

前向过程
问题在于用什么样的 q。
先将其 factorize:
q(x1:T∣x0)=q(xT∣xT−1)⋯q(x1∣x0)
可以将其称为前向的“扩散”过程。因为我们相当于是每一步都在给图像加噪声,直到变成完全的高斯噪声为止。
t 增大是前向,t 减小是反向。前向过程是加噪,反向过程就是去噪生成图片。
将 q(xt∣xt−1) 建模成
q(xt∣xt−1)=N(xt∣αtxt−1,(1−αt)I)
均值肯定是要与 xt−1 有关的,不过由于到了最后要变成 N(0,I),所以乘上一个 αt。这个 αt 为超参数,称为 noise scheduler,控制每一步加噪声的强度。αt 随着 t 增大而减小。
这个形式不是随便设计的,考虑利用重参数化技巧重写 xt:
xt=αtxt−1+1−αtεt−1,=αt(αt−1xt−2+1−αt−1εt−2)+1−αtεt−1=αtαt−1xt−2+αt−αtαt−1εt−2+1−αtεt−1εt−1∼N(0,I)
考虑后两项
αt−αtαt−1εt−2+1−αtεt−1∼N(0,(1−αtαt−1)I)
事实上就是将这两个高斯的 ε 合并为 1−αtαt−1⋅εt−2,这一步也是重参数化技巧。于是可以归纳证明:
xt=αtx0+1−αt⋅ε,αt=i∈[t]∏αi
就可以得到简洁的形式
q(xt∣x0)=N(xt∣αtx0,(1−αt)I)
这就使得,如果我们想要获得中间的某步隐变量 xt,就不需要一步步计算了,只需要一步到位,这就大大加速了学习的过程。
当 t=T 时,αt→0,1−αt→1,这告诉我们 q(xT∣x0)≈N(xT∣0,I)。与我们之前关于 x0 的先验是一致的,即不论什么样的 x0 最后都会变成纯的高斯噪声,这样就不用额外优化 KL 散度了。对比 VAE,我们不能保证 q 输出的分布与 z 的先验是一致的,所以 loss 里面才需要那一项 KL 散度。
去噪过程
仍然令 pθ 为高斯:
pθ(xt−1∣xt)=N(xt−1∣μθ(xt,t),Σθ(xt,t))
其中 μθ 和 Σθ 为两个神经网络。
需要往网络中额外传入 t 来表明当前是第几步(不同步之间的 xt 可能是相同的,不传入 t 的话神经网络无法进行区分)。
这个形式也不是随便取的。为了推出这个形式,考虑写出 ELBO:
ELBO=logpθ(x0)−KL=∫x1:Tq(x1:T∣x0)logpθ(x0)dx1:T−∫x1:Tq(x1:T∣x0)pθ(x1:T∣x0)q(x1:T∣x0)dx1:T=∫x1:Tq(x1:T∣x0)logq(x1:T∣x0)pθ(x0:T)dx1:T=∫x1:Tq(x1:T∣x0)log∏t∈[T]q(xt∣xt−1)p(xT)∏t∈[T]pθ(xt−1∣xt)dx1:T=Ex1:T∼q(x1:T∣x0)⎣⎢⎡logp(xT)+t∈[T]∑logq(xt∣xt−1)pθ(xt−1∣xt)⎦⎥⎤
但是问题在于,后面那项不是两个高斯分布之间的 KL 散度,如果是的话就有非常漂亮的闭式解,但这个不是:二者的变量不匹配,分子是 xt−1 而分母是 xt。如果说我们能把下面的 q 变成形如 q(xt−1∣xt) 就好了。利用贝叶斯公式
q(xt−1∣xt)=q(xt)q(xt∣xt−1)⋅q(xt−1)
我们知道 q(xt∣xt−1) 但是不知道 q(xt) 和 q(xt−1),仍然 intractable。
怎么解决呢?DDPM 中最漂亮的观察:q(xt−1∣xt) 是 intractable 的,但是 q(xt∣xt−1,x0) 是 tractable 的!
还是使用贝叶斯:
q(xt−1∣xt,x0)=q(xt∣xt−1,x0)q(xt∣x0)q(xt−1∣x0)
事实上已知 xt−1 的话 xt 与 x0 是独立的,所以 q(xt∣xt−1,x0) 就是 q(xt∣xt−1),我们已经推导过了,而 q(xt∣x0) 我们也是知道的。那么接下来开算就完了:
q(xt−1∣xt,x0)=q(xt∣xt−1,x0)q(xt∣x0)q(xt−1∣x0)=(2π)2d(1−αt)2d1⋅exp(−2(1−αt)∥xt−αtx0∥2)(2π)2d(1−αt)2d1⋅exp(−2(1−αt)∥xt−αtxt−1∥2)⋅(2π)2d(1−αt−1)2d1⋅exp(−2(1−αt−1)∥xt−1−αt−1x0∥2)⋯=(2π)2d[1−αt(1−αt)(1−αt−1)]2dexp(−21((1−αtαt+1−αt−11)∥xt−1∥2−(1−αt2αtxtT+1−αt−12αt−1x0T)xt−1+C(x0,xt)))
我们需要让他是一个高斯的形式,所以需要凑出 xt−1 减去某个均值的平方。用配方法。
先化简一下二次项系数
1−αtαt+1−αt−11=(1−αt)(1−αt−1)αt−αtαt−1+1−αt=(1−αt)(1−αt−1)1−αt
发现这个东西和分母上的形式很相似,这是好的,指导着我们其倒数应该就是所谓方差的形式。
经过复杂计算,得到
(2π)2d[1−αt(1−αt)(1−αt−1)]2d1⋅exp⎝⎜⎜⎛−2⋅1−αt(1−αt)(1−αt−1)∥∥∥∥xt−1−(1−αtαt(1−αt−1)xt+1−αtαt−1(1−αt)x0)∥∥∥∥2⎠⎟⎟⎞
于是
q(xt−1∣xt,x0)=N(1−αtαt(1−αt−1)xt+1−αtαt−1(1−αt)x0,1−αt(1−αt)(1−αt−1)I)
回顾之前的 xt 与 x0 之间关系的式子,利用重参数化技巧:
xt=αtx0+1−αt⋅εt
可以将 x0 表示为
x0=αtxt−1−αtεt
那么将其代入上面的均值最终可以化简得到
αt1(xt−1−αt1−αtεt)
此时 q(xt−1∣xt,x0) 的表达式就只包含 xt 和 εt 了:
q(xt−1∣xt,x0)=N(αt1(xt−1−αt1−αtεt),1−αt(1−αt)(1−αt−1)I)
回过头来看 ELBO 的式子,我们就需要想办法凑 q(xt−1) 了来弄出 KL 散度了:
ELBO=Ex1:T∼q(x1:T∣x0)⎣⎢⎡logp(xT)+t∈[T]∑logq(xt∣xt−1)pθ(xt−1∣xt)⎦⎥⎤=Ex1:T∼q(x1:T∣x0)[logp(xT)+logq(x1∣x0)pθ(x0∣x1)+t=2∑Tlogq(xt−1∣xt,x0)pθ(xt−1∣xt)⋅q(xt∣x0)q(xt−1∣x0)]=Ex1:T∼q(x1:T∣x0)[logq(xT∣x0)p(xT)+logpθ(x0∣x1)+t=2∑Tlogq(xt−1∣xt,x0)pθ(xt−1∣xt)]
注意到 logq(xT∣x0)p(xT)≈0,可以忽略。logpθ(x0∣x1) 稍微麻烦一些,原论文单独对其进行了建模,但实际上是不必要的,实验证明可以融入第三项,视为一个特例。所以我们只需要考虑第三项。
符号反转一下(log 里面分子分母颠倒),变为
∫x1:Tq(x1:T∣x0)⋅logpθ(xt−1∣xt)q(xt−1∣xt,x0)dx1:T
将 xt,xt−1 以外的无关项积分掉后,
∫xt∫xt−1q(xt−1,xt∣x0)logpθ(xt−1∣xt)q(xt−1∣xt,x0)dxt−1dxt
然后把 q(xt−1,xt∣x0) 拆成 q(xt−1∣xt,x0)⋅q(xt∣x0),并将对 xt 的积分拿到最外面:
∫xtq(xt∣x0)∫xt−1q(xt−1∣xt,x0)logpθ(xt−1,xt)q(xt−1∣xt,x0)dxt−1dxt
KL 散度的形式这就出来了!
Ext∼q(xt∣x0)[KL(q(xt−1∣xt,x0)∥pθ(xt−1∣xt))]
同时在这里,注意到关于 xt 求期望也可以通过重参数化的技巧等价为关于 εt∼N(0,I) 求期望。原因还是因为这个式子:xt=αtx0+1−αt⋅εt,二者是双射关系。
结论:两个高斯分布的 KL 散度
给定 N(μ1,Σ1),N(μ2,Σ2),其 KL 散度为
KL(⋅∥⋅)=−21log∣Σ1∣∣Σ2∣−2d+21tr(Σ2−1Σ1)+21(μ1−μ2)TΣ2−1(μ1−μ2)
不过先不要急。我们之前是令 pθ(xt−1∣xt)=N(xt−1∣μθ(xt,t),Σθ(xt,t)),均值和方差都由神经网络来估计。但是我们既然已经知道 q(xt−1∣xt,x0) 的均值为 αt1(xt−1−αt1−αtεt),就可以对 p 的形式进行重参数化,令为
αt1(xt−1−αt1−αtεθ(xt,t))
这样将模型预测目标从直接估计均值转化为预测噪声,可以简化优化目标并提高训练稳定性。
同时,Σ 也不由神经网络预测了,而是直接令为定值(可以简化计算,也可以减少模型复杂度,实验中证明也有效)。一般取 σt2=1−αt。即
pθ(xt−1∣xt)=N(αt1(xt−1−αt1−αtεθ(xt,t)),(1−αt)I)
这个 εθ(xt,t) 其实就是用神经网络来预测噪声。
在这样的假设下,KL 散度的式子中只有最后一项不是常数,可以推导出其为
Lt=2σt2αt(1−αt)(1−αt)2∥εt−εθ(xt,t)∥2
最终优化形式(注意求期望的对象从 xt 等价变换到了 εt)
Eεt∼N(0,I)[2σt2αt(1−αt)(1−αt)2∥εt−εθ(xt,t)∥2]
DDPM 最终形式
我们在训练的时候,肯定是会对不同的 t 求 Lt 的,相应地权重 2σt2αt(1−αt)(1−αt)2 会变化,但是实验中发现把这个权重忽略掉后效果会更好。所以其实整个 DDPM 的损失函数形式就是
Ex0,εt∼N(0,I),t∼Uniform[1,T][∥εt−εθ(xt,t)∥2]
DDPM 的魅力就在于,以非常复杂的推导最后推出了一个非常简洁的结果。
所以训练 DDPM 是可以并行的。
εθ(xt,t) 的输出与输入维度相同,本质上是对当前步添加的噪声进行预测,一般使用 U-Net 架构(本文不细讨 U-Net 的架构细节)。
但是用 DDPM 生成图片是不能并行的,只能从一个纯高斯噪声出发,然后用 εθ 计算 T 次噪声,一步步降噪输出最终结果,伪代码如下:
12345678910xT∼N(0,I)for t←T to 1 doif t=1 then z=0elsez∼N(0,I)endifxt−1=αt1(xt−1−αt1−αtεθ(xt,t))+σt⋅zend forreturn x0
其中 z 是为了添加随机噪声。
在 DDPM 的基础上有很多工作对其进行改进,在此不表。
完结撒花~