目前常见的前向扩散过程的公式表达如下:
xt=1−αt⋅xt−1+αt⋅ϵtx_t=\sqrt{1-\alpha_t}\cdot x_{t-1}+\sqrt{\alpha_t}\cdot\epsilon_txt=1−αt⋅xt−1+αt⋅ϵt前段时间投稿一篇有关扩散模型的文章,被审稿人问道为什么要采用这种 1−αt+α\sqrt{1-\alpha_t}+\sqrt{\alpha}1−αt+α 的加权设计?遂前去搜寻资料和博客,大多数回答都讲是为了最终能够采样到高斯分布,但都不具体说原因。总不能这样给审稿人回复吧,怕不是分分钟被拒。因此,没有办法,只能自己研究一下原因。
先声明:奈何本人能力有限,这种方法只能算是一种探究,欢迎大家指正和交流。
这里我不去关注使用这样加权的原因,而是关注使用不同加权方式分别会产生什么效果。首先我们假设存在 ata_tat 和 btb_tbt 满足:
xt=atxt−1+btϵt(1)x_t=a_t x_{t-1}+b_t \epsilon_t \tag{1}xt=atxt−1+btϵt(1)
对上式按照递推的方式逐步展开得:
xt=atxt−1+btϵt=at(at−1xt−2+bt−1ϵt−1)+btϵt=at[at−1(at−2xt−3+bt−2ϵt−2)+bt−1ϵt−1]+btϵt=⋯⋯=(atat−1⋯a1)x0+(atat−1⋯a2)b1ϵ1+(atat−1⋯a3)b2ϵ2+⋯+atbt−1ϵt−1+btϵt\begin{equation*} \begin{aligned} x_t & = a_t x_{t-1}+ b_t \epsilon_t \\ ~ & = a_t \left(a_{t-1} x_{t-2}+b_{t-1} \epsilon_{t-1}\right)+ b_t \epsilon_t \\ ~ & = a_t\left[ a_{t-1} \left(a_{t-2} x_{t-3}+b_{t-2} \epsilon_{t-2}\right)+b_{t-1\epsilon_{t-1}}\right] + b_t\epsilon_t \\ ~ & = \cdots\cdots \\ ~ & = \left(a_ta_{t-1}\cdots a_1 \right)x_0+\left(a_ta_{t-1}\cdots a_2\right)b_1\epsilon_1+\left(a_ta_{t-1}\cdots a_3\right)b_2\epsilon_2+\cdots+a_tb_{t-1}\epsilon_{t-1}+b_t\epsilon_t \end{aligned} \end{equation*} xt =atxt−1+btϵt=at(at−1xt−2+bt−1ϵt−1)+btϵt=at[at−1(at−2xt−3+bt−2ϵt−2)+bt−1ϵt−1]+btϵt=⋯⋯=(atat−1⋯a1)x0+(atat−1⋯a2)b1ϵ1+(atat−1⋯a3)b2ϵ2+⋯+atbt−1ϵt−1+btϵt由于高斯噪声的叠加性质,当p∼N(0,σ12)p\sim \mathcal{N}(0, \sigma_1^2)p∼N(0,σ12),q∼N(0,σ22)q\sim \mathcal{N}(0, \sigma_2^2)q∼N(0,σ22)时,p+q∼N(0,σ12+σ22)p+q\sim \mathcal{N}(0, \sigma_1^2+\sigma_2^2)p+q∼N(0,σ12+σ22),而上式中的ϵi\epsilon_iϵi均是标准高斯分布,即ϵi∼N(0,I)\epsilon_i\sim \mathcal{N}(0, \textbf{I})ϵi∼N(0,I)。因此上式可以进一步简化为
xt=(atat−1⋯a1)x0+(atat−1⋯a2)b1ϵ1+(atat−1⋯a3)b2ϵ2+⋯+atbt−1ϵt−1+btϵt=(atat−1⋯a1)x0+(atat−1⋯a2)2b12+⋯+at2bt−12+bt2ϵ\begin{equation*} \begin{aligned} x_t & = \left(a_ta_{t-1}\cdots a_1 \right)x_0+\left(a_ta_{t-1}\cdots a_2\right)b_1\epsilon_1+\left(a_ta_{t-1}\cdots a_3\right)b_2\epsilon_2+\cdots+a_tb_{t-1}\epsilon_{t-1}+b_t\epsilon_t \\ ~ & = \left(a_ta_{t-1}\cdots a_1 \right)x_0 + \sqrt{\left(a_ta_{t-1}\cdots a_2\right)^2b_1^2+\cdots+a_t^2b_{t-1}^2+b_t^2}\epsilon\\ \end{aligned} \end{equation*} xt =(atat−1⋯a1)x0+(atat−1⋯a2)b1ϵ1+(atat−1⋯a3)b2ϵ2+⋯+atbt−1ϵt−1+btϵt=(atat−1⋯a1)x0+(atat−1⋯a2)2b12+⋯+at2bt−12+bt2ϵ其中,ϵ∼N(0,I)\epsilon\sim\mathcal{N}(0, \textbf{I})ϵ∼N(0,I),根据扩散模型的参数设置可知 0
这里取bt∈(0,1)b_t\in(0, 1)bt∈(0,1),实际上是与原扩散模型保持一致,bt∈(0.0001,0.02)b_t\in(0.0001, 0.02)bt∈(0.0001,0.02)。对于第一种情况,可以发现其在不同扩散步长时的收敛情况如图:
显然不论扩散步长如何设置,最终的噪声系数还是无法收敛到1,即前向扩散过程无法收敛为一个标准的高斯噪声分布。对于第二种加权方式,其在不同扩散步长时的收敛情况如图:
对于第二种加权方式,噪声分布的系数最终会收敛到1,而且过程是平稳的,时间无关的。同时,在选择第二种加权方式的时候,我们可以对噪声的系数表达式进行简化:
(atat−1⋯a2)2b12+⋯+at2bt−12+bt2=at2{at−12[at−22⋯
很明显,这种加权方式是无法让噪声系数收敛到1的,也就无法令前向扩散过程收敛为一个标注的高斯分布。以下是我们做该部分仿真是用的 Python 代码:
import numpy as np
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimSun'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题num = 100000b = np.linspace(0.0001, 0.02, num, dtype=np.float64)
a = np.sqrt(1 - np.square(b))
# a = b
# a = 1 - b
c = []
result = 0
for i in range(num):if i == 0:result = np.square(b[0])c.append(np.sqrt(result))else:result = np.square(a[i]) * result + np.square(b[i])c.append(np.sqrt(result))plt.figure()
plt.plot(range(num), c)
plt.xlabel('扩散步数')
plt.ylabel('噪声系数值')
plt.show()
虽然我们上边的方法从结果导向地解释了使用这种加权方式的合理性,但其具体的原因没有分析。而我作为一个初学者,也存在几个问题仍然存在疑惑,希望能与大家交流。