当前位置: 首页 > news >正文

扩散生成基础原理(二)——DDPM概率去噪扩散模型

系列文章:
扩散生成基础原理(一)——发展历程与前置知识

简介

加州大学伯克利分校20年在NIPS发表的文章,可以说直接奠定了图像生成技术的使用,去年很火的Sora,还有科研应用最广泛的Stable Diffusion均以扩散模型为核心,可以说是研究图像生成必看的一篇文章。

受非平衡热力学考虑启发,作者提出了一种潜在变量模型,使用扩散概率模型呈现高质量的图像合成结果。模型自然地接受了一种渐进式有损解压缩方案,可以解释为自回归解码的泛化。在无条件CIFAR10数据集上,我们获得了 9.46 的 Inception 分数和 3.17 分的最新 FID 分数。

DDPM模型

参考链接DDPM解读。

DDPM分为两个过程:
forward加噪过程,从右向左,不断加入噪声,将原始图像转化为噪声图像,该部分依赖数学原理;
reverse去噪过程,从左向右,利用神经网络学习规律,根据提示词将噪声退化成图像。
扩散生成过程

前向加噪

前向扩散过程中,向数据分布中逐步添加高斯噪声,加噪过程持续​TTT次,产生一系列带噪声图片(x0,x1,...xT)(x_0,x_1,...x_T)(x0,x1,...xT),随着TTT的不断增大,当T→∞T\to \inftyT时原有的图像就被加噪成完全的噪声图像,xT−1x_{T-1}xT1xTx_TxT的加噪过程,噪声的方差来自固定βT\beta_TβT,均值来自固定值βT\beta_TβT和当前图像xT−1x_{T-1}xT1,该步骤的概率公式为:
q(xt∣xt−1):=N(xt;1−βtxt−1,βtI)\quad 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)q(xtxt1):=N(xt;1βtxt1,βtI)

首先解释什么要用概率来表示这一过程,如果往后看我们会发现前向过程是有确定性公式可以描述的,如xt=αtxt−1+1−αtϵtx_t=\sqrt{\alpha_t}x_{t-1}+\sqrt{1-\alpha_{t}}\epsilon_{t}xt=αtxt1+1αtϵt,但仍然要使用概率公式定义前向过程,原因有两个:

  1. 虽然有确定性公式,但噪声ϵt\epsilon_{t}ϵt是不确定的,所以给定xt−1x_{t-1}xt1的情境下xtx_txt并非唯一确定,而是服从指定方差和均值的分布,所以使用概率公式q(xt∣xt−1)\quad q\left(\mathbf{x}_{t} \mid \mathbf{x}_{t-1}\right)q(xtxt1)首先是对这种不确定性的描述。
  2. 状态的转换是非确定马尔科夫链过程。每次迭代过程只根据上一步状态加上噪声即可实现,噪声的随机性也导致了无法实现确定性转换,只能由当前状态确定一个可能的分布。

该公式说明,再由xt−1x_{t-1}xt1xtx_txt的转换过程q(xt∣xt−1)q(x_t|x_{t-1})q(xtxt1)满足分布N(xt;1−βtxt−1,βtI)\mathcal{N}\left(\mathbf{x}_{t} ; \sqrt{1-\beta_{t}} \mathbf{x}_{t-1}, \beta_{t} \mathbf{I}\right)N(xt;1βtxt1,βtI),该分布指以1−βtxt−1\sqrt{1-\beta_{t}} \mathbf{x}_{t-1}1βtxt1为均值,βtI\beta_{t} \mathbf{I}βtI为方差的分布。I\mathbf{I}I是单位矩阵,用于将方差放大到相应维度上。

定义αt=1−βt,ϵt−1∼N(0,1)\alpha_t=1-\beta_t,\epsilon_{t-1}\sim N(0,1)αt=1βt,ϵt1N(0,1),则上述公式可被修改为:xt=αtxt−1+1−αtϵt−1x_t=\sqrt{\alpha_t}x_{t-1}+\sqrt{1-\alpha_{t}}\epsilon_{t-1}xt=αtxt1+1αtϵt1
迭代替换后可得xtx_txtx0x_0x0的关系如下:
xt=αtˉx0+1−αtˉϵ0∼N(xt;αˉtx0,(1−αˉt)I)x_t=\sqrt{\bar{\alpha_t}}x_{0}+\sqrt{1-\bar{\alpha_{t}}}\epsilon_{0}\sim \mathcal{N}\left(\boldsymbol{x}_{t} ; \sqrt{\bar{\alpha}_{t}} \boldsymbol{x}_{0},\left(1-\bar{\alpha}_{t}\right) \mathbf{I}\right)xt=αtˉx0+1αtˉϵ0N(xt;αˉtx0,(1αˉt)I)

迭代替换的过程为:
xt=αtxt−1+1−αtϵt−1x_t=\sqrt{\alpha_t}x_{t-1}+\sqrt{1-\alpha_{t}}\epsilon_{t-1}xt=αtxt1+1αtϵt1
xt−1=αt−1xt−2+1−αt−1ϵt−2x_{t-1}=\sqrt{\alpha_{t-1}}x_{t-2}+\sqrt{1-\alpha_{t-1}}\epsilon_{t-2}xt1=αt1xt2+1αt1ϵt2带入上式可得
xt=αt(αt−1xt−2+1−αt−2ϵt−2)+1−αtϵt−1x_t=\sqrt{\alpha_t}(\sqrt{\alpha_{t-1}}x_{t-2}+\sqrt{1-\alpha_{t-2}}\epsilon_{t-2})+\sqrt{1-\alpha_{t}}\epsilon_{t-1}xt=αt(αt1xt2+1αt2ϵt2)+1αtϵt1
xt=αtαt−1xt−2+αt−αtαt−1ϵt−2+1−αtϵt−1x_t=\sqrt{\alpha_t\alpha_{t-1}}x_{t-2}+\sqrt{\alpha_t-\alpha_t\alpha_{t-1}}\epsilon_{t-2}+\sqrt{1-\alpha_{t}}\epsilon_{t-1}xt=αtαt1xt2+αtαtαt1ϵt2+1αtϵt1
因为两个独立正态分布的和仍然符合正态分布,组成的新分布均值=均值1+均值2,方差=方差1+方差2,也就是将αt−αtαt−1ϵt−2\sqrt{\alpha_t-\alpha_t\alpha_{t-1}}\epsilon_{t-2}αtαtαt1ϵt2视为从N(0,(αt−αtαt−1)I)N(0,(\alpha_t-\alpha_t\alpha_{t-1})I)N(0,(αtαtαt1)I)正态分布中的采样,1−αtϵt−1\sqrt{1-\alpha_{t}}\epsilon_{t-1}1αtϵt1视为从N(0,(1−αt)IN(0,(1-\alpha_{t})IN(0,(1αt)I的采样,整合后噪声可视为从N(0,(αt−αtαt−1+1−αt)I)N(0,(\alpha_t-\alpha_t\alpha_{t-1}+1-\alpha_t)I)N(0,(αtαtαt1+1αt)I)的采样
该公式可进一步整合为:
xt=αtαt−1xt−2+αt−αtαt−12+1−αt2ϵt−2x_t=\sqrt{\alpha_t\alpha_{t-1}}x_{t-2}+\sqrt{\sqrt{\alpha_t-\alpha_t\alpha_{t-1}}^2+\sqrt{1-\alpha_{t}}^2}\epsilon_{t-2}xt=αtαt1xt2+αtαtαt12+1αt2ϵt2
xt=αtαt−1xt−2+1−αtαt−1ϵt−2x_t=\sqrt{\alpha_t\alpha_{t-1}}x_{t-2}+\sqrt{1-\alpha_t\alpha_{t-1}}\epsilon_{t-2}xt=αtαt1xt2+1αtαt1ϵt2
依次类推就能找到规律,直到x0x_0x0,均值系数为α\alphaα的积,即∏i=1taix0\sqrt{ {\textstyle \prod_{i=1}^{t}} a_i}x_0i=1taix0,方差系数则是1−α1-\alpha1α的积,即1−∏i=1taiϵ0\sqrt{1- {\textstyle \prod_{i=1}^{t}} a_i}\epsilon_01i=1taiϵ0
(这里我其实有个疑问?
噪声epsilonepsilonepsilon应该是每步独立的,为什么可以整合到一起,虽说整体分布可以叠加为新的正态分布,但已经添加的噪声与该过程无关吧。
不过有文章证明了,说用了重参数方法,就暂且接受吧。)
Understanding Diffusion Models: A Unified Perspective从统一视角了解扩散模型文章解读

其中αtˉ=∏i=1tai\bar{\alpha_t}= {\textstyle \prod_{i=1}^{t}} a_iαtˉ=i=1tai,也就是说xtx_txt是在x0x_0x0条件下,符合均值αtˉx0\bar{\alpha_t}x_0αtˉx0方差1−αtˉ1-\bar{\alpha_{t}}1αtˉ的分布,只要有了β\betaβx0x_{0}x0就能确定噪声计算出任意时刻的xtx_txt,该噪声为固定的,而非学习的。因此只要有了x0x_0x0和固定好的序列β0,...,βT\beta_0,...,\beta_Tβ0,...,βT,就可以推出任意一步的加噪数据x1,...,xTx_1,...,x_Tx1,...,xT,所以该过程为马尔科夫链过程,即单向依赖不可跳步的。
上述公式表示整体扩散过程的联合分布为q(x1:T∣x0)=q(x1,x2,...,xT∣x0)=∏t=1Tq(xt∣xt−1)=∏t=1TN(xt;αtˉx0,1−αtˉI)q\left(\mathbf{x}_{1: T} \mid \mathbf{x}_{0}\right)=q(x_1,x_2,...,x_T|x_0)=\prod_{t=1}^{T} q\left(\mathbf{x}_{t} \mid \mathbf{x}_{t-1}\right)=\prod_{t=1}^{T} N(x_t;\sqrt{\bar{\alpha_t}}x_0,1-\bar{\alpha_{t}}\mathbf{I})q(x1:Tx0)=q(x1,x2,...,xTx0)=t=1Tq(xtxt1)=t=1TN(xt;αtˉx0,1αtˉI)

反向去噪

直接套用正向公式x0=xt−1−αtˉϵ0αtˉx_0=\frac{x_t-\sqrt{1-\bar{\alpha_t}}\epsilon_0}{\sqrt{\bar{\alpha_t}}}x0=αtˉxt1αtˉϵ0是解不出来的,因为最后获得的只有xtx_txt图像自身,扩散过程中的均值和方差都是未知的,反向去噪需要使用神经网络学习出该均值和方差。
x0=xt−1−αtˉϵ(xt,t)αtˉx_0=\frac{x_t-\sqrt{1-\bar{\alpha_t}}\epsilon(x_t,t)}{\sqrt{\bar{\alpha_t}}}x0=αtˉxt1αtˉϵ(xt,t),DDPM旨在训练一个噪声估计器epsilon(xt,t)=ϵepsilon(x_t,t)=\epsilonepsilon(xt,t)=ϵ用于估计可能添加的噪声,现有图像-可能添加的噪声=生成的图像。

该过程的损失函数可能设置为噪声的差值或重建图像的差值,但该过程的训练效果很差,这么操作所有的中间过程都没用了,而且已知的q(xt∣x0)q(x_t|x_0)q(xtx0),这几乎是一个正态分布,如果每次只逆转一次前向加噪过程来预测噪声就容易得多。

到此问题转为构建单步反向传播的概率函数q(xt−1∣xt)q(x_{t-1}|x_t)q(xt1xt),因为q(xt∣xt−1)q(x_t|x_{t-1})q(xtxt1)已知,所以可以想到用贝叶斯公式
q(xt−1∣xt)=q(xt∣xt−1)q(xt−1)q(xt)q(x_{t-1}|x_t)=\frac{q(x_t|x_{t-1})q(x_{t-1})}{q(x_t)}q(xt1xt)=q(xt)q(xtxt1)q(xt1)
q(xt−1)q(x_{t-1})q(xt1)q(xt)q(x_t)q(xt)都是未知的,借助x0x_0x0将其重新表达,将其视为xxx加噪t−1t-1t1次和ttt次后的概率,上式可修改为:
q(xt−1∣xt)=q(xt∣xt−1)q(xt−1∣x0)q(xt∣x0)q(x_{t-1}|x_t)=\frac{q(x_t|x_{t-1})q(x_{t-1}|x_0)}{q(x_t|x_0)}q(xt1xt)=q(xtx0)q(xtxt1)q(xt1x0)
若都引入x0x_0x0作为条件,则有q(xt−1∣xt,x0)=q(xt∣xt−1,x0)q(xt−1∣x0)q(xt∣x0)=N(xt−1;μ~(xt,x0),β~tI)q\left(x_{t-1} \mid x_{t}, x_{0}\right)=\frac{q(x_t|x_{t-1},x_0)q(x_{t-1}|x_0)}{q(x_t|x_0)}=\mathcal{N}\left(x_{t-1} ; \tilde{\mu}\left(x_{t}, x_{0}\right), \tilde{\beta}_{t} \mathbf{I}\right)q(xt1xt,x0)=q(xtx0)q(xtxt1,x0)q(xt1x0)=N(xt1;μ~(xt,x0),β~tI)

根据前面已经推出的分布q(xt∣x0)=N(xt;αˉtx0,(1−αˉt)I)q(x_t|x_0)=\mathcal{N}\left(\boldsymbol{x}_{t} ; \sqrt{\bar{\alpha}_{t}} \boldsymbol{x}_{0},\left(1-\bar{\alpha}_{t}\right) \mathbf{I}\right)q(xtx0)=N(xt;αˉtx0,(1αˉt)I)
则有
q(xt∣xt−1,x0)=q(xt∣xt−1)=N(xt;αtxt−1(1−αt)I)q\left(x_{t} \mid x_{t-1}, x_{0}\right)=q\left(\mathbf{x}_{t} \mid \mathbf{x}_{t-1}\right)=\mathcal{N}\left(\mathbf{x}_{t} ; \sqrt{\alpha_t} \mathbf{x}_{t-1} (1-\alpha_t) \mathbf{I}\right)q(xtxt1,x0)=q(xtxt1)=N(xt;αtxt1(1αt)I)
q(xt−1∣x0)=N(xt−1;αˉt−1x0,(1−αˉt−1)I)q(x_{t-1}|x_0)=\mathcal{N}\left(\boldsymbol{x}_{t-1} ; \sqrt{\bar{\alpha}_{t-1}} \boldsymbol{x}_{0},\left(1-\bar{\alpha}_{t-1}\right) \mathbf{I}\right)q(xt1x0)=N(xt1;αˉt1x0,(1αˉt1)I)

q(xt∣xt−1,x0)q(xt−1∣x0)q(xt∣x0)=N(xt;αtxt−1,(1−αt)I)N(xt−1;αˉt−1x0,(1−αˉt−1)I)N(xt;αˉtx0,(1−αˉt)I)\frac{q(x_t|x_{t-1},x_0)q(x_{t-1}|x_0)}{q(x_t|x_0)}=\frac{\mathcal{N}\left(\mathbf{x}_{t} ; \sqrt{\alpha_t} \mathbf{x}_{t-1}, (1-\alpha_t) \mathbf{I}\right)\mathcal{N}\left(\boldsymbol{x}_{t-1} ; \sqrt{\bar{\alpha}_{t-1}} \boldsymbol{x}_{0},\left(1-\bar{\alpha}_{t-1}\right) \mathbf{I}\right)}{\mathcal{N}\left(\boldsymbol{x}_{t} ; \sqrt{\bar{\alpha}_{t}} \boldsymbol{x}_{0},\left(1-\bar{\alpha}_{t}\right) \mathbf{I}\right)}q(xtx0)q(xtxt1,x0)q(xt1x0)=N(xt;αˉtx0,(1αˉt)I)N(xt;αtxt1,(1αt)I)N(xt1;αˉt1x0,(1αˉt1)I)

由高斯分布公式,p(x)=12πσe−12(x−μσ)2p(x)=\frac{1}{\sqrt{2\pi \sigma}}e^{-\frac{1}{2}(\frac{x-\mu}{\sigma})^2}p(x)=2πσ1e21(σxμ)2μ=αtˉx0\mu=\sqrt{\bar{\alpha_t}}x_0μ=αtˉx0对应分布中间项,σ=1−αtˉ\sigma=\sqrt{1-\bar{\alpha_t}}σ=1αtˉ对应最后一项的开根号
故不管公共系数12πσ\frac{1}{\sqrt{2\pi \sigma}}2πσ1,这些作除法都消掉后只保留一项,上式的三个分布的指数可分别转化为−(xt−αtxt−1)22(1−αt)-\frac{\left(\boldsymbol{x}_{t}-\sqrt{\alpha_{t}} \boldsymbol{x}_{t-1}\right)^{2}}{2\left(1-\alpha_{t}\right)}2(1αt)(xtαtxt1)2(xt−1−αˉt−1x0)22(1−αˉt−1)\frac{\left(\boldsymbol{x}_{t-1}-\sqrt{\bar{\alpha}_{t-1}} \boldsymbol{x}_{0}\right)^{2}}{2\left(1-\bar{\alpha}_{t-1}\right)}2(1αˉt1)(xt1αˉt1x0)2(xt−αˉtx0)22(1−αˉt)\frac{\left(\boldsymbol{x}_{t}-\sqrt{\bar{\alpha}_{t}} \boldsymbol{x}_{0}\right)^{2}}{2\left(1-\bar{\alpha}_{t}\right)}2(1αˉt)(xtαˉtx0)2
指数上的除法运算可以整合为指数的减法,消掉公共系数也不关心底数e,上式可转化为

=exp{−[(xt−αtxt−1)22(1−αt)+(xt−1−αˉt−1x0)22(1−αˉt−1)−(xt−αˉtx0)22(1−αˉt)]}=exp\left \{ -\left[\frac{\left(\boldsymbol{x}_{t}-\sqrt{\alpha_{t}} \boldsymbol{x}_{t-1}\right)^{2}}{2\left(1-\alpha_{t}\right)}+\frac{\left(\boldsymbol{x}_{t-1}-\sqrt{\bar{\alpha}_{t-1}} \boldsymbol{x}_{0}\right)^{2}}{2\left(1-\bar{\alpha}_{t-1}\right)}-\frac{\left(\boldsymbol{x}_{t}-\sqrt{\bar{\alpha}_{t}} \boldsymbol{x}_{0}\right)^{2}}{2\left(1-\bar{\alpha}_{t}\right)}\right] \right \} =exp{[2(1αt)(xtαtxt1)2+2(1αˉt1)(xt1αˉt1x0)22(1αˉt)(xtαˉtx0)2]}
后续推导在Understanding Diffusion Models: A Unified Perspective从统一视角了解扩散模型中写的很详细,步骤如下:
反向公式推导

获得最后均值和方差的分布作详细解释,承接公式:
q(xt∣xt−1,x0)q(xt−1∣x0)q(xt∣x0)=N(xt;αtxt−1,(1−αt)I),N(xt−1;αˉt−1x0,(1−αˉt−1)I)N(xt;αˉtx0,(1−αˉt)I)\frac{q(x_t|x_{t-1},x_0)q(x_{t-1}|x_0)}{q(x_t|x_0)}=\frac{\mathcal{N}\left(\mathbf{x}_{t} ; \sqrt{\alpha_t} \mathbf{x}_{t-1} ,(1-\alpha_t) \mathbf{I}\right),\mathcal{N}\left(\boldsymbol{x}_{t-1} ; \sqrt{\bar{\alpha}_{t-1}} \boldsymbol{x}_{0},\left(1-\bar{\alpha}_{t-1}\right) \mathbf{I}\right)}{\mathcal{N}\left(\boldsymbol{x}_{t} ; \sqrt{\bar{\alpha}_{t}} \boldsymbol{x}_{0},\left(1-\bar{\alpha}_{t}\right) \mathbf{I}\right)}q(xtx0)q(xtxt1,x0)q(xt1x0)=N(xt;αˉtx0,(1αˉt)I)N(xt;αtxt1,(1αt)I),N(xt1;αˉt1x0,(1αˉt1)I)
先解释推出的公式如何与分布对应
exp表示以e为底数,后续公式为指数。
因为正态分布公式p(x)=12πσe−12(x−μσ)2p(x)=\frac{1}{\sqrt{2\pi \sigma}}e^{-\frac{1}{2}(\frac{x-\mu}{\sigma})^2}p(x)=2πσ1e21(σxμ)2,如果后续公式能凑成该形式即可找到对应均值μ\muμ和方差σ\sigmaσ,最后一步已经中凑出了−12-\frac{1}{2}21,平方形式需要借助常数项C(xt,x0)=−(xt−αtˉx0)21−αˉtC(x_t,x_0)=-\frac{(x_t-\sqrt{\bar{\alpha_t}}x_0)^2}{1-\bar{\alpha}_t}C(xt,x0)=1αˉt(xtαtˉx0)2凑出,期望的常数项应该是[αt(1−αˉt−1)xt+αˉt−1(1−αt)x0]2(1−αˉt)2\frac{[\sqrt{\alpha_t}(1-\bar{\alpha}_{t-1})x_t+\sqrt{\bar{\alpha}_{t-1}}(1-\alpha_t)x_0]^2}{(1-\bar{\alpha}_t)^2}(1αˉt)2[αt(1αˉt1)xt+αˉt1(1αt)x0]2
常数项参与后续运算的过程论文的证明中省略了,其实肯定是对的上的,但是笔者自己作了补充验证:
首先常数项展开为−xt2−2αtˉx0+αˉtx021−αˉt-\frac{x_t^2-2\sqrt{\bar{\alpha_t}}x_0+\bar{\alpha}_tx_0^2}{1-\bar{\alpha}_t}1αˉtxt22αtˉx0+αˉtx02
在提取系数中操作为:−xt2−2αtˉx0+αˉtx021−αˉt⋅(1−αt)(1−αˉt−1)1−αtˉ=−(xt2−2αtˉx0+αˉtx02)(1−αˉt−1−αt+αtαˉt−1)(1−αˉt)2-\frac{x_t^2-2\sqrt{\bar{\alpha_t}}x_0+\bar{\alpha}_tx_0^2}{1-\bar{\alpha}_t}\cdot\frac{(1-\alpha_t)(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha_t}}=-\frac{(x_t^2-2\sqrt{\bar{\alpha_t}}x_0+\bar{\alpha}_tx_0^2)(1-\bar{\alpha}_{t-1}-\alpha_t+\alpha_t\bar{\alpha}_{t-1})}{(1-\bar{\alpha}_t)^2}1αˉtxt22αtˉx0+αˉtx021αtˉ(1αt)(1αˉt1)=(1αˉt)2(xt22αtˉx0+αˉtx02)(1αˉt1αt+αtαˉt1)
分母一致,但是光看xt2x_t^2xt2的系数计算结果也不一致啊,可能中间哪化错了,暂且搁置吧。

最后详细说明系数部分
系数计算结果12πσ\frac{1}{\sqrt{2\pi \sigma}}2πσ112π(1−αt)12π(1−αˉt−1)12παˉt=2παˉt2π(1−αt)2π(1−αˉt−1)=1−αˉt(1−αt)(1−αˉt−1)\frac{\frac{1}{\sqrt{2\pi (1-\alpha_t)}}\frac{1}{\sqrt{2\pi (1-\bar{\alpha}_{t-1})}}}{\frac{1}{\sqrt{2\pi \bar{\alpha}_t}}}=\frac{\sqrt{2\pi \bar{\alpha}_t}}{\sqrt{2\pi (1-\alpha_t)}\sqrt{2\pi (1-\bar{\alpha}_{t-1})}}=\frac{\sqrt{1-\bar{\alpha}_t}}{\sqrt{(1-\alpha_t)}\sqrt{(1-\bar{\alpha}_{t-1})}}2παˉt12π(1αt)12π(1αˉt1)1=2π(1αt)2π(1αˉt1)2παˉt=(1αt)(1αˉt1)1αˉt
正好与前面推出的方差一致,对应σ\sigmaσ

推导后可获得反向去噪的概率均值为μ(xt,x0)=αt(1−αˉt−1)xt+αˉt−1(1−αt)x01−αˉt\mu(x_t,x_0)=\frac{\sqrt{\alpha_t}(1-\bar{\alpha}_{t-1})x_t+\sqrt{\bar{\alpha}_{t-1}}(1-\alpha_t)x_0}{1-\bar{\alpha}_t}μ(xt,x0)=1αˉtαt(1αˉt1)xt+αˉt1(1αt)x0,此时将由xt=αtˉx0+1−αtˉϵ0x_t=\sqrt{\bar{\alpha_t}}x_{0}+\sqrt{1-\bar{\alpha_{t}}}\epsilon_{0}xt=αtˉx0+1αtˉϵ0逆推得到的x0=xt−1−αtˉϵ0αtˉx_0=\frac{x_t-\sqrt{1-\bar{\alpha_t}}\epsilon_0}{\sqrt{\bar{\alpha_t}}}x0=αtˉxt1αtˉϵ0带入上式,可得如下结果:
均值推导

补充第二步计算的解释,有αtˉ=∏i=1tai\bar{\alpha_t}= {\textstyle \prod_{i=1}^{t}} a_iαtˉ=i=1tai,则有αtˉ=at×αˉt−1\bar{\alpha_t}=a_t\times \bar{\alpha}_{t-1}αtˉ=at×αˉt1,故针对单独一项分子分母上下同时除αˉt−1\sqrt{\bar{\alpha}_{t-1}}αˉt1,分子消掉,分母αtˉ\sqrt{\bar{\alpha_t}}αtˉ变为αt\sqrt{\alpha_t}αt

到此我们获得了反向去噪的概率分布q(xt−1∣xt=N(xt−1;αt(1−αˉt−1)xt+αˉt−1(1−αt)x01−αˉt,(1−αt)(1−αˉt−1)1−αˉtI)q(x_{t-1}|x_t=\mathcal{N}({x}_{t-1};\frac{\sqrt{\alpha_{t}}(1-\bar{\alpha}_{t-1}){x}_ {t}+\sqrt{\bar{\alpha}_{t-1}}(1-\alpha_{t}){x}_{0}}{1-\bar{\alpha}_{t}}, \frac{(1-\alpha_{t})(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha}_{t}}\mathbf{I})q(xt1xt=N(xt1;1αˉtαt(1αˉt1)xt+αˉt1(1αt)x0,1αˉt(1αt)(1αˉt1)I),以及均值的确定性表示1αtxt−1−αt1−αˉtαtϵ0\frac{1}{\sqrt{\alpha_{t}}} \boldsymbol{x}_{t}-\frac{1-\alpha_{t}}{\sqrt{1-\bar{\alpha}_{t}} \sqrt{\alpha_{t}}} \boldsymbol{\epsilon}_{0}αt1xt1αˉtαt1αtϵ0,并且通过推导发现去噪过程的均值受超参数α\alphaα和随机噪声ϵ\epsilonϵ影响,方差只由超参数决定,形式为βt(1−αˉt−1)1−αtˉ\frac{\beta_t(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha_t}}1αtˉβt(1αˉt1)

训练噪声预测器

有了正向加噪和反向去噪的概率分布,按理说我们就可以根据样本生成新图像了,但是公式中只有一个未知解,噪声ϵ\epsilonϵ。该如何预测噪声,采用何种损失衡量,是DDPM需要解决的另一个关键问题。

这块的数学原理更复杂,看着就头大,而且又不是我们使用的重点,所以仅贴几个图意思意思。
噪声预测器方法
训练算法

生成图像

假设有一正态分布的采样X∼N(μ,σ2)X\sim N(\mu,\sigma^2)XN(μ,σ2)也可以表示为X=μ+σ×Z,Z∼N(0,1)X=\mu+\sigma\times Z,Z\sim N(0,1)X=μ+σ×Z,ZN(0,1)

在反向去噪部分我们得到了q(xt−1∣xt)∼N(xt−1;μ~(xt,x0),β~tI)q(x_{t-1}|x_t)\sim \mathcal{N}\left(x_{t-1} ; \tilde{\mu}\left(x_{t}, x_{0}\right), \tilde{\beta}_{t} \mathbf{I}\right)q(xt1xt)N(xt1;μ~(xt,x0),β~tI)其中μ~=1αtxt−1−αt1−αˉtαtϵ0,β~=βt(1−αˉt−1)1−αtˉ\tilde{\mu}=\frac{1}{\sqrt{\alpha_{t}}} \boldsymbol{x}_{t}-\frac{1-\alpha_{t}}{\sqrt{1-\bar{\alpha}_{t}} \sqrt{\alpha_{t}}} \boldsymbol{\epsilon}_{0},\tilde{\beta}=\frac{\beta_t(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha_t}}μ~=αt1xt1αˉtαt1αtϵ0,β~=1αtˉβt(1αˉt1),故xt−1x_{t-1}xt1可表示为:
xt−1=μ~+β~⋅z=1αt(xt−1−αt1−αtˉϵ0)+βt(1−αˉt−1)1−αtˉ⋅zx_{t-1}=\tilde{\mu}+\tilde{\beta}\cdot z=\frac{1}{\sqrt{\alpha_t}}(x_t-\frac{1-\alpha_t}{\sqrt{1-\bar{\alpha_t}}}\epsilon_0)+\frac{\beta_t(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha_t}}\cdot zxt1=μ~+β~z=αt1(xt1αtˉ1αtϵ0)+1αtˉβt(1αˉt1)z

生成图像的过程从高斯噪声开始,不断重复上面过程,直到t=0t=0t=0,即恢复出初始图像x0x_0x0,伪代码如下:
生成图像ddpm伪代码
数学原理上是均值+方差x标准正态分布,可直观理解上又有不同。

生成过程更像是(噪声图像−预测噪声×系数)×缩放系数+方差×标准噪声z(噪声图像-预测噪声\times系数)\times缩放系数+方差\times 标准噪声z(噪声图像预测噪声×系数)×缩放系数+方差×标准噪声z

源码分析

源码来自diffusers库的scheduling_ddpm.py文件。

代码首先定义了一个输出格式:

class DDPMSchedulerOutput(BaseOutput):"""Output class for the scheduler's `step` function output.Args:prev_sample (`torch.Tensor` of shape `(batch_size, num_channels, height, width)` for images):Computed sample `(x_{t-1})` of previous timestep. `prev_sample` should be used as next model input in thedenoising loop.pred_original_sample (`torch.Tensor` of shape `(batch_size, num_channels, height, width)` for images):The predicted denoised sample `(x_{0})` based on the model output from the current timestep.`pred_original_sample` can be used to preview progress or for guidance."""prev_sample: torch.Tensorpred_original_sample: Optional[torch.Tensor] = None

DDPM输出继承自BaseOutput,注释中说明prev_sample是反向过程计算出的xt−1x_{t-1}xt1步去噪图像,作为下一次输入使用,pred_original_sample表示当前时间步预测的x0x_0x0去噪样本。

最核心的方法是DDPMScheduler类,注释中说明:

该方法继承自SchedulerMixin和ConfigMixin
参数:
num_train_timesteps (int, 默认值为 1000):
训练模型的扩散步数。
beta_start (float, 默认值为 0.0001):
推理的初始 beta 值。
beta_end (float, 默认值为 0.02):
最终 beta 值。
beta_schedule (str, 默认值为 "linear"):
beta 调度策略,即从 beta 范围到用于推进模型的 beta 序列的映射。可选值包括 linear(线性)、scaled_linear(缩放线性)、squaredcos_cap_v2(平方余弦帽v2)或 sigmoid(sigmoid)。
trained_betas (np.ndarray, 可选):
直接传递给构造函数的 beta 数组(无需使用 beta_start 和 beta_end)。
variance_type (str, 默认值为 "fixed_small"):
在向去噪样本添加噪声时裁剪方差。可选值包括 fixed_small(固定小方差)、fixed_small_log(固定小方差对数)、fixed_large(固定大方差)、fixed_large_log(固定大方差对数)、learned(可学习)或 learned_range(可学习范围)。
clip_sample (bool, 默认值为 True):
裁剪预测样本以确保数值稳定性。
clip_sample_range (float, 默认值为 1.0):
样本裁剪的最大幅度。仅在 clip_sample=True 时有效。
prediction_type (str, 默认值为 epsilon, 可选):
调度器函数的预测类型;可选 epsilon(预测扩散过程的噪声)、sample(直接预测含噪样本)或 v_prediction(参见 Imagen Video 论文第2.4节)。
thresholding (bool, 默认值为 False):
是否使用"动态阈值处理"方法。此方法不适用于 Stable Diffusion 等潜在空间扩散模型。
dynamic_thresholding_ratio (float, 默认值为 0.995):
动态阈值处理的比例。仅在 thresholding=True 时有效。
sample_max_value (float, 默认值为 1.0):
动态阈值处理的阈值。仅在 thresholding=True 时有效。
timestep_spacing (str, 默认值为 "leading"):
时间步的缩放方式。更多信息请参考 Common Diffusion Noise Schedules and Sample Steps are Flawed 论文的表2。
steps_offset (int, 默认值为 0):
添加到推理步的偏移量(部分模型家族需要此设置)。
rescale_betas_zero_snr (bool, 默认值为 False):
是否重新缩放 beta 以获得零终端信噪比。这使模型能够生成非常明亮或黑暗的样本,而非限制为中亮度样本。与 --offset_noise 参数有松散关联。

省略一些参数初始化等设置操作,反向去噪过程通过反向求解随机微分方程(SDE)从上一时间步预测样本。此函数从学习到的模型输出(通常为预测噪声)传播扩散过程。
输入的参数有:

model_output (torch.Tensor):
学习到的扩散模型的直接输出,通常对应噪声epsilon
timestep (float):
扩散链中的当前离散时间步。
sample (torch.Tensor):
扩散过程生成的当前样本实例,对应中间去噪样本x_t
generator (torch.Generator, 可选):
随机数生成器。
return_dict (bool, 可选, 默认值为 True):
是否返回 [~schedulers.scheduling_ddpm.DDPMSchedulerOutput] 对象。

下面对具体操作进行分块解释:

  1. 获取时间步与输出分类
    获取当前时间步并计算下一时间步,若方差类型为learned(可学习方差)或 learned_range(可学习范围方差)时,模型输出会同时包含预测的噪声和方差(形状为两倍特征维度)。此时需要将 model_output 拆分为 model_output(预测噪声)和 predicted_variance(预测方差)。
    代码如下:
t = timestep
prev_t = self.previous_timestep(t)
if model_output.shape[1] == sample.shape[1] * 2 and self.variance_type in ["learned", "learned_range"]:model_output, predicted_variance = torch.split(model_output, sample.shape[1], dim=1)
else:predicted_variance = None
  1. 计算α\alphaαβ\betaβ
    alpha和beta是扩散过程的核心超参数,代码为:
# 1. compute alphas, betas
alpha_prod_t = self.alphas_cumprod[t]	
# 累乘获得bar(alpha_t)
alpha_prod_t_prev = self.alphas_cumprod[prev_t] if prev_t >= 0 else self.one	
# 累乘获得bar(alpha_{t-1})
beta_prod_t = 1 - alpha_prod_t	
# bar(beta_t)=1-bar(alpha_t)
beta_prod_t_prev = 1 - alpha_prod_t_prev	
# bar(beta_{t-1})=1-bar(alpha_{t-1})
current_alpha_t = alpha_prod_t / alpha_prod_t_prev	
# alpha_t=bar(alpha_t)/bar(alpha_{t-1})
current_beta_t = 1 - current_alpha_t
# beta_t=1-alpha_t
  1. 从预测噪声计算预测原始样本x0x_0x0
    该过程来自文章的公式15,x0≈x^0=(xt−1−αˉtϵθ(xt))/αˉt\mathbf{x}_{0} \approx \hat{\mathbf{x}}_{0}=\left(\mathbf{x}_{t}-\sqrt{1-\bar{\alpha}_{t}} \boldsymbol{\epsilon}_{\theta}\left(\mathbf{x}_{t}\right)\right) / \sqrt{\bar{\alpha}_{t}}x0x^0=(xt1αˉtϵθ(xt))/αˉt,其实就是正向过程xt=αtˉx0+1−αtˉϵ0x_t=\sqrt{\bar{\alpha_t}}x_0+\sqrt{1-\bar{\alpha_t}}\epsilon_0xt=αtˉx0+1αtˉϵ0解出的x0x_0x0的表达式。
if self.config.prediction_type == "epsilon":# 预测模式为噪声,(x_t-\sqrt(1-/bar{alpha}epsilon))//sqrt{/bar{alpha}}pred_original_sample = (sample - beta_prod_t ** (0.5) * model_output) / alpha_prod_t ** (0.5)
elif self.config.prediction_type == "sample":# 预测含噪样本,就无需计算,直接赋值pred_original_sample = model_output
elif self.config.prediction_type == "v_prediction":# 预测改进噪声项,让模型学习噪声与初始图像的关系,用以增强训练稳定性pred_original_sample = (alpha_prod_t**0.5) * sample - (beta_prod_t**0.5) * model_output
else:raise ValueError(f"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample` or"" `v_prediction`  for the DDPMScheduler.")
  1. 裁剪或约束预测的x0x_0x0
    对原始预测样本进行数值约束,避免出现异常值,确保生成样本的质量和训练稳定性。
# 3. Clip or threshold "predicted x_0"
if self.config.thresholding:# 如果配置中thresholding=true,截断到阈值水平# 异常值可能导致出现伪影,截断也是动态算法,保留大部分正常数据,仅截断异常值pred_original_sample = self._threshold_sample(pred_original_sample)
elif self.config.clip_sample:# 固定范围剪裁clip_sample=ture,则将数值限制在+-clip_sample_range范围内pred_original_sample = pred_original_sample.clamp(-self.config.clip_sample_range, self.config.clip_sample_range)
  1. 根据公式μ~t(xt,x0):=αˉt−1βt1−αˉtx0+αt(1−αˉt−1)1−αˉtxt\tilde{\boldsymbol{\mu}}_{t}\left(\mathbf{x}_{t}, \mathbf{x}_{0}\right):=\frac{\sqrt{\bar{\alpha}_{t-1}} \beta_{t}}{1-\bar{\alpha}_{t}} \mathbf{x}_{0}+\frac{\sqrt{\alpha_{t}}\left(1-\bar{\alpha}_{t-1}\right)}{1-\bar{\alpha}_{t}} \mathbf{x}_{t}μ~t(xt,x0):=1αˉtαˉt1βtx0+1αˉtαt(1αˉt1)xt计算系数。前者控制预测原始样本x^0\hat{x}_0x^0在生成xt−1x_{t-1}xt1的权重,后者控制xtx_txt在生成过程中的比重。
    t较小时,噪声较弱(βt\beta_tβt较小),原始信号多αt\alpha_tαt大,因此x^0\hat{x}_0x^0的权重较大,模型更信任预测的干净样本。
    t趋近于T,xtx_txt的权重更大,模型更依赖当前含噪样本。
# 4. Compute coefficients for pred_original_sample x_0 and current sample x_t
# See formula (7) from https://arxiv.org/pdf/2006.11239.pdf
# \bar{x_0}的系数
pred_original_sample_coeff = (alpha_prod_t_prev ** (0.5) * current_beta_t) / beta_prod_t
# x_t的系数
current_sample_coeff = current_alpha_t ** (0.5) * beta_prod_t_prev / beta_prod_t
  1. 根据上面得到的系数计算均值utu_tut
# 5. Compute predicted previous sample µ_t
# See formula (7) from https://arxiv.org/pdf/2006.11239.pdf
pred_prev_sample = pred_original_sample_coeff * pred_original_sample + current_sample_coeff * sample
  1. 添加噪声,返回预测值。该部分对应最终的生成部分,均值+方差x标准正态,只是均值的形式没有采用最终噪声预测器的模式,而是结合xtx_txtx0x_0x0的版本。
# 6. Add noise
# t=0时无需添加噪声
variance = 0
if t > 0:device = model_output.device
# 正态分布噪声variance_noise = randn_tensor(model_output.shape, generator=generator, device=device, dtype=model_output.dtype)
if self.variance_type == "fixed_small_log":# 固定方差,噪声乘方差variance = self._get_variance(t, predicted_variance=predicted_variance) * variance_noise
elif self.variance_type == "learned_range":# 学习方差,预测的对数方差转化为标准差 variance = self._get_variance(t, predicted_variance=predicted_variance)variance = torch.exp(0.5 * variance) * variance_noise
else:# 默认直接将方差开方,获取标准差variance = (self._get_variance(t, predicted_variance=predicted_variance) ** 0.5) * variance_noise
# 预测加噪声,均值+方差x标准正态分布噪声
pred_prev_sample = pred_prev_sample + varianceif not return_dict:
# 返回x_{t-1}和x_0
return (pred_prev_sample,pred_original_sample,)
# 返回封装好的输出对象
return DDPMSchedulerOutput(prev_sample=pred_prev_sample, pred_original_sample=pred_original_sample)

结合生成代码来看:

with torch.no_grad():noise_pred = self.unet(latent_model_input, t, encoder_hidden_states=text_embeddings).sample.to(dtype=torch.float16)
# 根据指导权重调整噪声预测
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
noise_pred = noise_pred_uncond + self.guidance_scale * (noise_pred_text - noise_pred_uncond)
-# 计算前一个噪声样本,继续去噪
self.latents = self.scheduler.step(noise_pred, t, self.latents).prev_sample

可以看到,最终潜空间latents的生成是由调度器的step方法直接实现的,unet网络完成噪声预测部分,将预测的噪声noise_pred作为参数model_output传给调度器scheduler,最终获得返回对象中的预测潜向量prev_sample

DDPM小结

DDPM通过模仿热运动的扩散过程提出了一种图像生成新范式,正向是将噪声逐渐添加到图像直到图像完全变成噪声,反向是使用神经网络学习出每次噪声分布的均值和方差,用以估计噪声,从当前图像中去除,直到恢复出图像。

DDPM最主要的问题是慢,一步步加噪去噪要执行大量操作,有时只需要进行几个像素点的操作却要对整个图像进行判定,所以有了后续跳步的DDIM、和目前最先进的DPM-sovler。

ddpm代码可以说是亦步亦趋地实现了文章的方法,最主要的是计算均值,均值与超参数、x0x_0x0xtx_txt有关,图像生成采用均值+方差x标准正态的方式实现,其中均值和方差来自DDPM中推导的计算式,噪声来自unet的预测。

http://www.dtcms.com/a/278946.html

相关文章:

  • 1.2.1 面向对象详解——AI教你学Django
  • git 下载报错:fetch-pack: unexpected disconnect while reading sideband packet
  • 139-CNN-BiLSTM-Selfattention-ABKDE预测模型!
  • 深度学习基础:损失函数(Loss Function)全面解析
  • 搭建k8s高可用集群,“Unable to register node with API server“
  • LINUX714 自动挂载/nfs;物理卷
  • 侧链的出现解决了主链哪些性能瓶颈?
  • Android系统的问题分析笔记 - Android上的调试方式 debuggerd
  • .NET 9 GUID v7 vs v4:时间有序性如何颠覆数据库索引性能
  • 如何快速去除latex表格中的加粗
  • 杨辉三角的认识与学习
  • 图像修复:深度学习GLCIC神经网络实现老照片划痕修复
  • 未来手机会自动充电吗
  • 计算机毕业设计Java医学生在线学习平台系统 基于 Java 的医学生在线学习平台设计与开发 Java 医学在线教育学习系统的设计与实现
  • React 和 Vue的自定义Hooks是如何实现的,如何创建自定义钩子
  • CSP-S 模拟赛 17
  • 单片机(STM32-串口通信)
  • IP相关
  • CSS `:root` 伪类深入讲解
  • Java final 关键字
  • iOS APP 上架流程:跨平台上架方案的协作实践记录
  • STM32F1_Hal库学习UART
  • 【脚本系列】如何使用 Python 脚本对同一文件夹中表头相同的 Excel 文件进行合并
  • 设计模式--工厂模式
  • SSE(Server-Sent Events)和 MQTT(Message Queuing Telemetry Transport)
  • 多线程--单例模式and工厂模式
  • 研究人员利用提示注入漏洞绕过Meta的Llama防火墙防护
  • 隐藏源IP的核心方案与高防实践
  • 缺乏项目进度验收标准,如何建立明确标准
  • 基于STM32的智能抽水灌溉系统设计(蓝牙版)