目前,GAN 在大多数成像任务中都取得了 SOTA 结果。图像质量指标通常是 FID、Inception Score 和 Precision。然而,这些指标并不能反映多样性。 GAN 在生成多样性方面弱于基于概率的模型。此外,GAN 通常很难训练,如果没有选择合适的超参数或正则化,很容易崩溃。
搜索历史记录
基于GANs的缺点,有很多工作改进基于概率的模型,希望能提高成像质量,但在GANs和成像速度上还有差距。样品相对较慢。
扩散模型属于似然模型,具有分布覆盖面广、使用静态训练目标、易于扩展等优点。目前,他们已经在 CIFAR-10 中取得了 SOTA 的成绩。但是在LSUN和ImageNet数据集上与GAN相比,还是有差距的。
文章认为造成上述差距的原因有:
-
GAN 网络的架构得到了细化;
-
GAN 可以在多样性和保真度之间取得平衡,可以产生高质量的图像,但它们不能覆盖整个分布。
基于此,本文将改进现有扩散模型的架构,并提出一种能够平衡多样性和图像保真度的方案。
文章的详细解释。
架构改进
文章1个探索了以下架构改进:
- 增加模型深度,同时减小模型宽度,以保持模型尺寸不变;
- 增加注意力头的数量;
- 注意32×32、16×16、8×8的分辨率;
- 使用 o bloco 残差 BigGAN 进行上采样和下采样;
- 对残差连接使用比例因子\(\frac{1}{\sqrt{2}}\);
经过以上改进,取得了显着的改进:
![[理解论文]扩散模型在图像合成方面优于GAN (1) [理解论文]扩散模型在图像合成方面优于GAN (1)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506202914970.png)
![[理解论文]扩散模型在图像合成方面优于GAN (2) [理解论文]扩散模型在图像合成方面优于GAN (2)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506203012618.png)
值得注意的是,虽然增加模型的深度可能会提高效果,但会增加训练时间;因此,此措施未用于以下实验。
表 2 中的结果表明,每头使用更多的头或更少的屠体可以提高 FID,每头使用 64 个屠体可提供最佳结果。
适应性群体归一化
参考自适应组归一化(AdaGN),组归一化后,将时间范围和类嵌入添加到每个残差块中:
\[\text{AdaGN}(h,y)=y_s \text{群范数}(h)+y_b,\]
式中,\(h\)表示第一次卷积后残差块的激活函数,\(y=[y_s,y_b]\)是时间间隔和class embedding的线性投影。
品类指南
除了在上一节的归一化层中添加类别信息外,文章还探讨了添加一个 \(p(y\mid x)\) 分类器来改进扩散生成器,具体来说,训练噪声的 \(x_t\ )图像 \(p_{\phi}(y\mid x_t,t)\),所以使用 \(\nabla_{x_t} \log p_{\phi}({x_t} \mid {y})\) 来引导传输带有\(y\)类别的生成图像,具体方法分为以下两种情况:
随机扩散抽样
使用\(y\)标签作为条件时,使用如下方法进行采样:
\[\begin{alineado}p(x_t \mid x_{t+1},y) &= \frac{p(x_t,x_{t+1},y)}{p(x_{t+1}, y)} \\&= \frac{p(x_t,x_{t+1},y)}{p(y \mid x_{t+1})p(x_{t+1})} \\& = \frac{p(x_t \mid x_{t+1})p(y \mid x_t,x_{t+1})p(x_{t+1})}{p(y \mid x_{t+ 1 })p(x_{t+1})} \\&= \frac{p(x_t \mid x_{t+1})p(y \mid x_t,x_{t+1})}{p( y \mid x_{t+1})} \\&= \frac{p(x_t \mid x_{t+1})p(y \mid x_t)}{p(y \mid x_{t+1} ) } \\\end{alinhado},\]
鉴于类别的分布 \(y\) 独立于 \(x_{t+1}\),那么:
\[\begin{alineado}p(y \mid x_t,x_{t+1})&=p(x_{t+1} \mid x_t,y) \frac{p(y \mid x_t)}{p (x_{t+1}\mid x_t)}\\&=p(x_{t+1} \mid x_t) \frac{p(y \mid x_t)}{p(x_{t+1}\mid x_t)}\\&=p(y \mid x_t)\end{alineado}\]
代入上式可得:
\[\begin{alineado}p(x_t \mid x_{t+1},y) &= \frac{p(x_t \mid x_{t+1})p(y \mid x_t,x_{t+1 })}{p(y \mid x_{t+1})} \\&= \frac{p(x_t \mid x_{t+1})p(y \mid x_t)}{p(y \mid x_{t+1})} \\\end{alinhado},\]
由于每个样本的标签是已知的,\(p(y \mid x_{t+1})\) 可以认为是一个常数,所以:
\[p_{\theta,\phi}\left(x_{t}\mid x_{t+1}, y\right)=Z\cdot p_{\theta}\left(x_{t}\mid x_{ t+1}\straight)\cdot p_{\phi}\square(和 \mid x_{t}\straight),\]
式中,\(Z\)为归一化常数,上式是难解的,可以近似为扰动高斯分布。
(1) \(p_{\theta}\left(x_{t} \mid x_{t+1}\right)\) 项
我们的模型使用高斯分布从 \(x_{t+1}\) 预测 \(x_{t}\):
\[\begin{alineado}p_{\theta}\left(x_{t} \mid x_{t+1}\right) &=\mathcal{N}(\mu, \Sigma) \\\log p_{ \theta}\left(x_{t} \mid x_{t+1}\right) &=-\frac{1}{2}\left(x_{t}-\mu\right)^{T} \西格玛^{-1}\left(x_{t}-\mu\right)+C\end{alinhado}\]
(2) \(p_{\phi}\left(y \mid x_{t}\right)\) 项
在无限扩散时间步长 \(\|\Sigma\| \rightarrow 0\),可以假设 \(\log_{\phi} p(y\mid x_{t})\) 与 \ ( \Sigma^ {-1}\) 的曲率较小,所以我们可以用 \(\text{log} p_{\phi}(y \mid x_{t})\) 在 \(x_{t} = \ mu \ ) 在泰勒展开中:
\[\begin{aligned}\log p_{\phi}\left(y \mid x_{t}\right) &\left.\approx \log p_{\phi}\left(y \mid x_{t} \right)\right|_{x_{t}=\mu}+\left.\left(x_{t}-\mu\right) \nabla_{x_{t}} \log p_{\phi}\left (y \mid x_{t}\right)\right|_{x_{t}=\mu} \\&=\left(x_{t}-\mu\right) g+C_{1}\end{排列整齐}\]
式中,\(C_1\)为常数,且:
\[g=\左。 \nabla_{x_{t}} \log p_{\phi}\left(y \mid x_{t}\right)\right|_{x_{t}=\mu},\]
总之:
\[\begin{aligned}\log \left(p_{\theta}\left(x_{t}\mid x_{t+1}\right) p_{\phi}\left(y \mid x_{t} \direct)\direct) & \approx-\frac{1}{2}\square(x_{t}-\mu\straight)^{T} \Sigma^{-1}\square(x_{t}- \mu\straight)+\square(x_{t}-\straight) g+C_{2} \\&=-\frac{1}{2}\square(x_{t}-\mu-\ Sigma g \straight)^{T} \Sigma^{-1}\square(x_{t}-\mu-\Sigma g\straight)+\frac{1}{2} g^{T} \Sigma g +C_ {2} \\&=-\frac{1}{2}\left(x_{t}-\mu-\straight sigma)^{T} \sigma^{-1}\left(x_ {t}- \mu-\Sigma g\right)+C_{3} \\&=\log p(z)+C_{4}, z \sim \mathcal{N}(\mu+\Sigma g,\ Sigma)\end {对齐},\]
从上式可以看出,条件转换操作类似于使用高斯分布逼近的无条件操作,只是平均值需要加上shift\(\Sigma g\)。具体采样过程如下:
![[理解论文]扩散模型在图像合成方面优于GAN (3) [理解论文]扩散模型在图像合成方面优于GAN (3)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506231348507.png)
硬条件抽样 否
不2个对于确定性采样,不能使用上述采样方法。
通过贝叶斯公式:
\[p(\mathbf{x} \mid \mathbf{y}) = \frac{p(\mathbf{x}) p(\mathbf{y} \mid \mathbf{x}) }{p(\mathbf {y})},\]
对上式两边同时对\(\mathbf{x}\)求导,得:
\[\nabla_\mathbf{x} \log p(\mathbf{x} \mid \mathbf{y}) = \nabla_\mathbf{x} \log p(\mathbf{x}) + \nabla_\mathbf{ x} \log p(\mathbf{y} \mid \mathbf{x}),\]
如果模型可以预测添加到样本中的噪声 \(\epsilon_{\theta}\left(\mathbf{x_{t}}\right)\),则可以得到:
\[\nabla_{\mathbf{x}_{t}} \log p_{\theta}\left(\mathbf{x}_{t}\right)=-\frac{1}{\sqrt{1- \bar{\alpha}_{t}}}\epsilon_{\theta}\left(\mathbf{x}_{t}\right),\]
然后:
\[\begin{aligned}\nabla_\mathbf{x_t} \log p(\mathbf{x_t} \mid \mathbf{y}) &=\nabla_{\mathbf{x}_{t}} \log p_{ \theta}\left(\mathbf{x}_{t}\right)+\nabla_{\mathbf{x}_{t}} \log p_{\phi}\left(\mathbf{y}\mid\ mathbf{x}_{t}\direct) \\&=-\frac{1}{\sqrt{1-\bar{\alpha}_{t}}} \epsilon_{\theta}\left(\mathbf {x}_{t}\direct)+\equal_{x_{t}} \log p_{\phi}\left(\mathbf{y} \mid \mathbf{x}_{t}\direct)\end {对齐},\]
这样我们就可以定义一个新的预测值 \(\hat{\epsilon}\left(\mathbf{x_{t}}\right)\) :
\[\hat{\epsilon}\left(\mathbf{x_{t}}\right):=\epsilon_{\theta}\left(\mathbf{x_{t}}\right)-\sqrt{1- \bar{\alpha}_{t}} \nabla_{\mathbf{x_{t}}} \log p_{\phi}\left(\mathbf{y}\mid \mathbf{x_{t}}\right ),\]
然后就可以使用正常的DDIM采样过程,只需将\(\epsilon_{\theta}\left(\mathbf{x_{t}}\right)\)替换为\(\hat \epsilon_{\theta}\left( \mathbf{x_{t}}\right)\) ,具体方法如下:
![[理解论文]扩散模型在图像合成方面优于GAN (4) [理解论文]扩散模型在图像合成方面优于GAN (4)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506230402699.png)
尺度分类器梯度
分类器网络使用 UNet 模型的下采样部分,并使用 8x8 特征层中的注意力组来产生最终结果。
分类器训练完成后,可以加入扩散采样过程生成样本。
作者在实验中发现,需要将分类器的梯度乘以一个大于1的常数因子。如果该因子为1,分类器会给期望类50%的机会生成最终样本,如果分类器增加梯度,就可以做出分类器类别。概率增加到几乎 100%,下图显示了效果。
![[理解论文]扩散模型在图像合成方面优于GAN (5) [理解论文]扩散模型在图像合成方面优于GAN (5)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506213350653.png)
分类器梯度的尺度效应
\[s\cdot \nabla_\mathbf{x} \log p(\mathbf{y} \mid \mathbf{x})=\nabla_\mathbf{x} \log \frac{1}{Z}p(\ mathbf{y}\mid \mathbf{x})^s,\]
式中,\(Z\)为常数,当\(s>1\)时,分布\(p(\mathbf{y}\mid \mathbf{x})^s\)大于\( p (\mathbf{ y}\mid \mathbf{x})\) 更陡峭,因此使用较大的梯度尺度会使模型更关注分类器,从而产生更真实的样本(降低多样性)。
综上所述,本文最重要的两个结论是:
-
梯度缩放可用于平衡图像保真度和多样性。
-
使用分类器指南可以生成更逼真的图像。基于这一观察,分类指南可用于从条件样本\(p(x\mid y)\)生成分配,也可用于从无条件样本\(p(x)\)生成分配。
实验结果
引导影响
从表 4 的结果来看,增加分类器的方向可以提高条件和无条件模型的样本生成质量。当规模足够大时,guided unconditional model可以获得与unguided conditional model相似的FID。
![[理解论文]扩散模型在图像合成方面优于GAN (6) [理解论文]扩散模型在图像合成方面优于GAN (6)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506214520229.png)
同时,表 4 还表明,分类器定向可以提高准确率(以降低召回率为代价),从而平衡样本多样性和保真度。下图显示了梯度缩放的影响。可以看出,改进梯度缩放可以平衡高精度恢复(度量多样性)和IS(度量保真度)。
![[理解论文]扩散模型在图像合成方面优于GAN (7) [理解论文]扩散模型在图像合成方面优于GAN (7)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506215315812.png)
作者进一步将使用指南的扩散模型与 BigGAN 进行了比较,发现了 2 个有趣的现象:
- 分类器指导在平衡 FID 和 IS 方面比 BigGAN 好得多;
- 一旦分类器指南达到准确度限制,它就无法获得更好的准确度。
![[理解论文]扩散模型在图像合成方面优于GAN (8) [理解论文]扩散模型在图像合成方面优于GAN (8)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506215709594.png)
结果
使用 LSUN 数据集(房间、马和猫)评估改进模型架构在生成硬核图像时的性能,并使用 ImageNet 数据集(128×128 分辨率、256×256 和 512×512)评估分类器方向的性能),大多数 Broadcast 模型在所有任务中都达到了 SOTA 结果。
![[理解论文]扩散模型在图像合成方面优于GAN (9) [理解论文]扩散模型在图像合成方面优于GAN (9)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506220830451.png)
![[理解论文]扩散模型在图像合成方面优于GAN (10) [理解论文]扩散模型在图像合成方面优于GAN (10)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506221451148.png)
代码分析
推荐过程
测试日历
高斯扩散。 get_named_beta_schedule()
如果 num_diffusion_timesteps 设置为 100 并选择线性程序:
num_diffusion_timesteps=100电子 日历名称 == “线性”: 规模 = 1000 / num_diffusion_timesteps # 规模:10 start_beta = 规模 * 0,0001 #beta_start:0,001 final_beta = 规模 * 0,02 #beta_end:0,2 测试版= 公证人.线性空间(start_beta, final_beta, num_diffusion_timesteps, 有点d=公证人.弗洛塔尔64)
\(\beta\) 的计算结果如下:
![[理解论文]扩散模型在图像合成方面优于GAN (11) [理解论文]扩散模型在图像合成方面优于GAN (11)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220510141314281.png)
如果选择线性程序:
确实 betas_for_alpha_bar(num_diffusion_timesteps, alpha_bar, 最大测试版=0,999): """ 创建一个离散化给定函数 alpha_t_bar 的 beta 程序,它定义了自 t = [0,1] 以来 (1-beta) 随着时间的累积乘积。:param num_diffusion_timesteps: 要产生的 beta 的数量。:param alpha_bar : 一个 lambda,它采用从 0 到 1 的 t 参数,并输出 (1-beta) 的累积乘积,直到扩散过程的那一部分 :param max_beta : 要使用的最大 beta;使用小于 1 的值来避免奇点”“” 测试版 = [] 为了 欧洲联盟 时间 范围(num_diffusion_timesteps): t1 = 欧洲联盟 / num_diffusion_timesteps t2 = (欧洲联盟 + 1个) / num_diffusion_timesteps 测试版.附(分钟(1个 - alpha_bar(t2) / alpha_bar(t1), 最大测试版)) 回报 公证人.训练(测试版)电子 日历名称 == “余弦”:betas_for_alpha_bar(num_diffusion_timesteps, 拉姆达 吨: 数学.为什么(((吨 + 0,008) / 1.008 * 数学.π / 2个) ** 2个)
\(\beta\) 的计算结果如下:
![[理解论文]扩散模型在图像合成方面优于GAN (12) [理解论文]扩散模型在图像合成方面优于GAN (12)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220510141328096.png)
参数计算
alfas: \(\alpha_t=1-\beta_t\)
alphas_cumprod: \(\bar \alpha_t = \prod_{i=1}^T \alpha_i\)
alphas_cumprod_prev: \(\bar \alpha_{t-1}\)
alphas_cumprod_next:\(\bar \alpha_{t+1}\)
sqrt_alphas_cumprod:\(\sqrt{\bar \alpha_t}\)
sqrt_one_minus_alphas_cumprod:\(\sqrt{1-\bar \alpha_t}\)
log_one_minus_alphas_cumprod:\(\log (1-\bar \alpha_t)\)
sqrt_recip_alphas_cumprod:\(\frac{1}{\sqrt{\bar \alpha_t}}\)
sqrt_recipm1_alphas_cumprod::\(\sqrt{\frac{1}{\bar \alpha_t}-1}\)
variação_posterior:\(\frac{\beta_t\cdot (1-\bar \alpha_{t-1})}{1-\bar \alpha_t}\)
posterior_mean_coef1:\(\frac{\beta_t\cdot \sqrt{\bar \alpha_{t-1}}}{1-\bar \alpha_t}\)
posterior_mean_coef2:\(\frac{(1-\bar \alpha_{t-1})\cdot \sqrt{\alpha_t}}{1-\bar \alpha_t}\)
# 使用 float64 以获得更高的精度。n_steps=100测试版=get_named_beta_schedule('线性', num_diffusion_timesteps=n_steps)测试版 = 公证人.训练(测试版, 有点d=公证人.弗洛塔尔64)num_timesteps = 乙(测试版.形式[0])阿尔法 = 1,0 - 测试版alphas_comprod = 公证人.达到(阿尔法, 轴=0)alphas_comprod_prev = 公证人.附(1,0, alphas_comprod[:-1个])alphas_cumprod_next = 公证人.附(alphas_comprod[1个:], 0,0)# 计算扩散 q(x_t | x_{t-1}) 和其他sqrt_alphas_cumprod = 公证人.正方形(alphas_comprod)sqrt_one_minus_alphas_cumprod = 公证人.正方形(1,0 - alphas_comprod)log_one_minus_alphas_cumprod = 公证人.记录(1,0 - alphas_comprod)sqrt_recip_alphas_cumprod = 公证人.正方形(1,0 / alphas_comprod)sqrt_recipm1_alphas_cumprod = 公证人.正方形(1,0 / alphas_comprod - 1个)# 在 (x_{t-1} | x_t, x_0) 之后计算 q反向变化 = (测试版 * (1,0 - alphas_comprod_prev) / (1,0 - alphas_comprod))# 对数计算被修剪,因为在扩散链的开头最终方差为 0。post_record_trimmed_variance = 公证人.记录(公证人.附(反向变化[1个], 反向变化[1个:]))posterior_mean_coef1 = (测试版 * 公证人.正方形(alphas_comprod_prev) / (1,0 - alphas_comprod))posterior_mean_coef2 = (((1,0 - alphas_comprod_prev)* 公证人.正方形(阿尔法)/ (1,0 - alphas_comprod))
使用线性规划时,posterior_mean_coef1和posterior_mean_coef2曲线如下:
![[理解论文]扩散模型在图像合成方面优于GAN (13) [理解论文]扩散模型在图像合成方面优于GAN (13)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220510143659591.png)
![[理解论文]扩散模型在图像合成方面优于GAN (14) [理解论文]扩散模型在图像合成方面优于GAN (14)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220510143725411.png)
推荐过程
直接过程,从 \(\mathbf{x_0}\) 计算 \(\mathbf{x_t}\):
\[q(\mathbf{x_t}\vert \mathbf{x_0}) = \mathcal{N}(\mathbf{x_t};\sqrt{\bar{\alpha_t}}\mathbf{x_0}, (1 - \ bar{\alpha_t})\mathbf{I}),\]
这里涉及到一个函数_extract_in_tensor()
,其作用是将broadcast_shape中某个时间区间的值的形状展开,例如:
一个arr值为[1.00250941, 1.57537666, 6.38749852, 56.82470788, 2.5753766],时间步长为3,所以对应的值为56.82470788,因为后面计算公式时需要代入,形状需要展开,比如要展开的形状是(2, 3, 128, 128),所以通过_extract_in_tensioner
你可以得到一个所有值为 56,82470788 且形式为 (2, 3, 128, 128) 的张量。
确实 _extract_in_tensioner(到达, 时间步长, 传输形状): """ 从numpy一维数组中提取值到一批索引中。:param arr: numpy一维数组。:param timesteps: 索引张量到要提取的数组中。:param broadcast_shape:多出 K 维,批次维等于时间步长的长度:返回:形状张量 [batch_size, 1, ...] 其中形状具有 K 维“”” 解决 = 他.来自_numpy(到达).A(设备=时间步长.设备)[时间步长].漂浮() 尽管 伦(解决.形式) < 伦(传输形状): 解决 = 解决[..., 没有任何] 回报 解决.扩张(传输形状)
到达=公证人.训练([1.00250941,1.57537666,6.38749852, 56.82470788,2.5753766])传输形状=[2个, 3个, 128, 128]时间步长=他.张量([3个, 3个])解决=_extract_in_tensioner(到达, 时间步长, 传输形状)打印(解决.形式)打印(他.单身的(解决))
输出结果:
火炬.尺寸([2个, 3个, 128, 128])张量([56.8247])
所以看功能。q_mean_variance()
,直接过程中的均值为\(\sqrt{\bar{\alpha_t}} \mathbf{x_0}\),方差为\(1 - \bar{\alpha_t}\),实现如下:
确实 q_mean_variance(成为, x_start, 吨): """ 获取分布 q(x_t | x_0)。:param x_start: 静默输入的张量 [N x C x ...]。:param t: 扩散步数(负 1)。这里,0表示一步。:return: 一个元组 (mean, variance, log_variance), x_start 的任何形式。""" 意思是 = ( _extract_in_tensioner(成为.sqrt_alphas_cumprod, 吨, x_start.形式) * x_start) 不同之处 = _extract_in_tensioner(1,0 - 成为.alphas_comprod, 吨, x_start.形式) 对数方差 = _extract_in_tensioner(成为.log_one_minus_alphas_cumprod, 吨, x_start.形式) 回报 意思是, 不同之处, 对数方差
据此,可得 \(q(\mathbf{x_t} \vert \mathbf{x_0})\) :
\[\begin{aligned}\mathbf{x}_t = \sqrt{\bar{\alpha}_t}\mathbf{x_0} + \sqrt{1 - \bar{\alpha}_t}\mathbf{z}\ \\最终{对齐},\]
实现代码如下:
确实 q_sample(成为, x_start, 吨, 噪音=没有任何): """ 在给定的分布步骤数上分布数据。换句话说,从 q(x_t | x_0) 中采样。:param x_start: 初始批数据。:param t: 分布步骤数(负 1) .这里,0 表示一步。:param noise:如果指定,正常噪声分离。:return:x_start 的噪声版本。""" 电子 噪音 是 没有任何: 噪音 = 他.randn_like(x_start) 宣称 噪音.形式 == x_start.形式 回报 ( _extract_in_tensioner(成为.sqrt_alphas_cumprod, 吨, x_start.形式) * x_start + _extract_in_tensioner(成为.sqrt_one_minus_alphas_cumprod, 吨, x_start.形式) * 噪音 )
逆向过程
逆过程计算如下:
\[\mathbf{x_{t-1}} =\mu_{\theta}(\mathbf{x}_{t},t) + \sigma_{\theta}(\mathbf{x}_{t}, t)\cdot\mathbf{z},\]
您需要计算方差 \(\sigma_{\theta}(\mathbf{x}_{t},t)\) 和均值 \(\mu_{\theta}(\mathbf{x}_{t} , t ) 分别为 \) ,实现如下:
计算方差
存在 2 个 model_var_type 类型:ModelVarType.LEARNED 和 ModelVarType.LEARNED_RANGE。
如果 model_var_type 是 ModelVarType.LEARNED ,那么:
模型对数方差 = 模型变量值型号变体 = 他.指数(模型对数方差)
请参阅 model_var_type 的 ModelVarType.LEARNED_RANGE ,然后:
最小日志 = _extract_in_tensioner(成为.post_record_trimmed_variance, 吨, X.形式)最大日志 = _extract_in_tensioner(公证人.记录(成为.测试版), 吨, X.形式)# 模型变量值 es [-1, 1] para [min_var, max_var].断裂 = (模型变量值 + 1个) / 2个模型对数方差 = 断裂 * 最大日志 + (1个 - 断裂) * 最小日志型号变体 = 他.指数(模型对数方差)
计算媒体
(1) 无条件
model_mean_type 元素 3:ModelMeanType.PREVIOUS_X,ModelMeanType.START_X,ModelMeanType.EPSILON,
方法一:ModelMeanType.PREVIOUS_X
如果 model_mean_type 是 ModelMeanType.PREVIOUS_X ,它会计算:
\[\mu_{\theta}=\frac{1-\bar \alpha_t}{\beta_t\cdot \sqrt{\bar \alpha_{t-1}}}\cdot \mathbf{x_{t-1}} -\frac{(1-\bar \alpha_{t-1})\cdot \sqrt{\alpha_t}}{\beta_t\cdot \sqrt{\bar \alpha_{t-1}}}\mathbf{x_{ t}},\]
variação_posterior:\(\frac{\beta_t\cdot (1-\bar \alpha_{t-1})}{1-\bar \alpha_t}\)
posterior_mean_coef1:\(\frac{\beta_t\cdot \sqrt{\bar \alpha_{t-1}}}{1-\bar \alpha_t}\)
posterior_mean_coef2:\(\frac{(1-\bar \alpha_{t-1})\cdot \sqrt{\alpha_t}}{1-\bar \alpha_t}\)
确实 _predict_xstart_from_xprev(成为, x_t, 吨, xprev): 宣称 x_t.形式 == xprev.形式 回报 ( # (xprev - coef2*x_t) / coef1 _extract_in_tensioner(1,0 / 成为.posterior_mean_coef1, 吨, x_t.形式) * xprev - _extract_in_tensioner( 成为.posterior_mean_coef2 / 成为.posterior_mean_coef1, 吨, x_t.形式 )* x_t )
方法二:ModelMeanType.EPSILON
如果model_mean_type为ModelMeanType.EPSILON,则使用DDIM计算的计算方法:
_predict_xstart_from_eps
因为 \(\mathbf{x}_t = \sqrt{\bar{\alpha}_t}\mathbf{x}_0 + \sqrt{1 - \bar{\alpha}_t}\mathbf{\epsilon}\) , \(\mathbf{x}_0\) 可以从 \(\mathbf{x}_t\) 预测:
\[\mathbf{x}_0= \frac{1}{\sqrt{\bar \alpha_t}}\mathbf{x}_t- \sqrt{\frac{1}{\bar \alpha_t}-1}\cdot \mathbf{\epsilon}_{\theta}^{(t)}(\mathbf{x}_t),\]
sqrt_recip_alphas_cumprod:\(\frac{1}{\sqrt{\bar \alpha_t}}\)
sqrt_recipm1_alphas_cumprod:\(\sqrt{\frac{1}{\bar \alpha_t}-1}\)
确实 _predict_xstart_from_eps(成为, x_t, 吨, 每股收益): 宣称 x_t.形式 == 每股收益.形式 回报 ( _extract_in_tensioner(成为.sqrt_recip_alphas_cumprod, 吨, x_t.形式) * x_t - _extract_in_tensioner(成为.sqrt_recipm1_alphas_cumprod, 吨, x_t.形式) * 每股收益 )
所以根据 \(\mathbf{x}_{t}\) 和 \(\mathbf{x}_{0}\),通过 \(q\left(\mathbf{x}_{t- 1 } \ mid \mathbf{x}_{t}, \mathbf{x}_{0}\right)\) 计算 \(\mathbf{x}_{t-1}\),得到model_mean:
\[\mu_{\theta}=\frac{\sqrt{\bar{\alpha}_{t-1}} \beta_{t}}{1-\bar{\alpha}_{t}} \mathbf {x}_{0}+\frac{\sqrt{\alpha_{\iota}}\left(1-\bar{\alpha}_{t-1}\right)}{1-\bar{\alpha }_{t}} \mathbf{x}_{t},\]
根据1.2节的参数计算:
posterior_mean_coef1:\(\frac{\beta_t\cdot \sqrt{\bar \alpha_{t-1}}}{1-\bar \alpha_t}\)
posterior_mean_coef2:\(\frac{(1-\bar \alpha_{t-1})\cdot \sqrt{\alpha_t}}{1-\bar \alpha_t}\)
variação_posterior:\(\frac{1-\bar \alpha_{t-1}}{1-\bar \alpha_t}\cdot \beta_t\)
实现代码如下:
确实 q_posterior_mean_variance(成为, x_start, x_t, 吨): """ 计算反向散射的均值和方差:q(x_{t-1} | x_t, x_0) """ 宣称 x_start.形式 == x_t.形式 半后 = ( _extract_in_tensioner(成为.posterior_mean_coef1, 吨, x_t.形式) * x_start + _extract_in_tensioner(成为.posterior_mean_coef2, 吨, x_t.形式) * x_t ) 反向变化 = _extract_in_tensioner(成为.反向变化, 吨, x_t.形式) post_record_trimmed_variance = _extract_in_tensioner( 成为.post_record_trimmed_variance, 吨, x_t.形式 ) 宣称 ( 半后.形式[0] == 反向变化.形式[0] == post_record_trimmed_variance.形式[0] == x_start.形式[0] ) 回报 半后, 反向变化, post_record_trimmed_variance
计算方差和均值的完整实现代码如下:
确实 p_mean_variance(成为, 模型, X, 吨, 剪辑去噪=真的, 去噪_fn=没有任何, model_kwargs=没有任何): """ 应用模型得到 p(x_{t-1} | x_t) 以及对初始 x, x_0 的预测。:param model: 模型,它将一个信号和一批时间间隔作为输入. :param x: 时间 t 的张量 [N x C x ...] :param t: 时间间隔的一维张量 :param clip_denoised: 如果为真,则将无噪声信号剪辑在 [-1, 1 ] . :param denoised_fn: 如果不是 None,一个在 x_start 预览之前应用于采样的函数。在 clip_denoised 之前应用。:param model_kwargs: 如果不是 None,则为传递给模型的附加关键字参数的字典。这可用于条件 :return:具有以下键的字典: - 'mean':模型的平均输出 - 'variance':方差输出 - 'log_variance':'variance' 的对数 - 'pred_xstart ' : x_0 """ 的预测 电子 model_kwargs 是 没有任何: model_kwargs = {} 乙, C = X.形式[:2个] 宣称 吨.形式 == (乙,) 输出模型 = 模型(X, 成为._scale_timesteps(吨), **model_kwargs) #----------------------------# # 方差 #----------------------------# 电子 成为.模型变量类型 时间 [模型变量类型.学到了, 模型变量类型.学习范围]: 宣称 输出模型.形式 == (乙, C * 2个, *X.形式[2个:]) 输出模型, 模型变量值 = 他.划分(输出模型, C, 黑暗的=1个) 电子 成为.模型变量类型 == 模型变量类型.学到了: 模型对数方差 = 模型变量值 型号变体 = 他.指数(模型对数方差) 其余的部分: 最小日志 = _extract_in_tensioner(成为.post_record_trimmed_variance, 吨, X.形式) 最大日志 = _extract_in_tensioner(公证人.记录(成为.测试版), 吨, X.形式) # 模型变量值 es [-1, 1] para [min_var, max_var]. 断裂 = (模型变量值 + 1个) / 2个 模型对数方差 = 断裂 * 最大日志 + (1个 - 断裂) * 最小日志 型号变体 = 他.指数(模型对数方差) 其余的部分: 型号变体, 模型对数方差 = { # 对于 fixedlarge,像这样设置初始(log-)方差 # 以获得更好的解码器注册概率。 模型变量类型.FIXED_LARGE: ( 公证人.附(成为.反向变化[1个], 成为.测试版[1个:]), 公证人.记录(公证人.附(成为.反向变化[1个], 成为.测试版[1个:])), ), 模型变量类型.FIXED_SMALL: ( 成为.反向变化, 成为.post_record_trimmed_variance, ), }[成为.模型变量类型] 型号变体 = _extract_in_tensioner(型号变体, 吨, X.形式) 模型对数方差 = _extract_in_tensioner(模型对数方差, 吨, X.形式) #----------------------------# # 意思是 #----------------------------# 确实 process_xstart(X): 电子 去噪_fn 是 不 没有任何: X = 去噪_fn(X) 电子 剪辑去噪: 回报 X.夹钳(-1个, 1个) 回报 X 电子 成为.medium_type_model == 模型均值类型.前_X: pred_xstart = process_xstart( 成为._predict_xstart_from_xprev(x_t=X, 吨=吨, xprev=输出模型)) 模型均值 = 输出模型 小精灵 成为.medium_type_model 时间 [模型均值类型.START_X, 模型均值类型.爱普西隆]: 电子 成为.medium_type_model == 模型均值类型.START_X: pred_xstart = process_xstart(输出模型) 其余的部分: pred_xstart = process_xstart(成为._predict_xstart_from_eps(x_t=X, 吨=吨, 每股收益=输出模型)) 模型均值, _, _ = 成为.q_posterior_mean_variance(x_start=pred_xstart, x_t=X, 吨=吨) 其余的部分: 增加 错误未实施(成为.medium_type_model) 宣称 ( 模型均值.形式 == 模型对数方差.形式 == pred_xstart.形式 == X.形式) 回报 { “意思是”: 模型均值, “不同之处”: 型号变体, “log_variance”: 模型对数方差, “pred_xstart”: pred_xstart, }
(2) 有条件的
(1) 方法 condition_mean
当条件存在时,需要添加基于无条件平均的偏移量。采样过程如下:
![[理解论文]扩散模型在图像合成方面优于GAN (15) [理解论文]扩散模型在图像合成方面优于GAN (15)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506231348507.png)
\(\nabla_{\mathbf{x_{t}}} \log p_{\phi}\left(\mathbf{y} \mid \mathbf{x_{t}}\right)\) O计算代码éo next :
确实 条件函数(X, 吨, 是=没有任何): 宣称 是 是 不 没有任何 骗子 他.enable_grad(): x_in = X.脱掉().要求毕业_(真的) 对数 = 分类器(x_in, 吨) log_probs = F.registro_softmax(对数, 黑暗的=-1个) 已选择 = log_probs[范围(伦(对数)), 是.远景(-1个)] 回报 他.自动毕业.毕业(已选择.添加(), x_in)[0] * 争论.尺度分类器
还有语法 \(\log p_{\phi}\left(\mathbf{y}\mid \mathbf{x_{t}}\right)\)?
部分计算代码\(\log p_{\phi}\left(\mathbf{y} \mid \mathbf{x_{t}}\right)\)如下:
log_probs = F.registro_softmax(对数, 黑暗的=-1个)已选择 = log_probs[范围(伦(对数)), 是.远景(-1个)]已选择.添加()
上面的计算过程真的是cross_entropy,不过大家可以对比一下系数和负号的区别:
事情 火炬事情 蚁链 作为 nn事情 非功能性.torch 作为 Fnum_calsses=1000是=火炬.张量([2个,10])对数=火炬.馊(((2个,num_calsses))## 记录 p(y|x)log_probs = F.registro_softmax(对数, 黑暗的=-1个)已选择 = log_probs[范围(伦(对数)), 是.远景(-1个)]解决=已选择.添加()打印(解决)##交叉熵(x,y)解决=F.交叉熵(对数,是)打印(解决)
结果是:
记录 页(是|X): 张量(-17.0620)交叉熵: 张量(8.5310)秒
cross_entropy取平均值,所以有系数2和负号的差,所以 \(\log p_{\phi}\left(\mathbf{y} \mid \mathbf{x_{t}} \对 )\) 测量了 \ (\mathbf{x_{t}}\) 和 \(\mathbf{y}\) 之间的距离如下:
\[\log p_{\phi}\left(\mathbf{y}\mid \mathbf{x_{t}}\right)=-N\cdot \text{交叉熵}(\mathbf{x_{t}} , \mathbf{y}),\]
所以条件均值更新本质上就是使用的SGD梯度下降法:
\[\begin{aligned}\mathbf{\mu_{t-1}}&=\mu_t+s\Sigma\cdot \nabla_{\mathbf{x_{t}}} \log p_{\phi}\left( \mathbf{y} \mid \mathbf{x_{t}}\right)\\&=\mathbf{\mu_{t}}-\alpha \nabla_{J_{\phi}}(\mathbf{x_{t }},\mathbf{y})\end{对齐},\]
\(\mathbf{\mu_{t-1}}\) 的更新代码如下:
确实 平均条件(成为, 条件函数, p_media_var, X, 吨, model_kwargs=没有任何): """ 计算上一步的平均值,给定一个 cond_fn 函数,该函数计算相对于 x 的条件对数概率的梯度。特别地,cond_fn 计算 grad(log(p(y|x))) 并且我们想要Y 上的条件。这使用了 Sohl-Dickstein 等人 (2015) 的条件策略。 降级 = 条件函数(X, 成为._scale_timesteps(吨), **model_kwargs) 新媒体 = ( p_media_var[“意思是”].漂浮() + p_media_var[“不同之处”] * 降级.漂浮() ) 回报 新媒体
(2) condition_score 方法
![[理解论文]扩散模型在图像合成方面优于GAN (16) [理解论文]扩散模型在图像合成方面优于GAN (16)](https://i0.wp.com/sunlin-ai.github.io/images/image-20220506230402699.png)
代码如下所示:
确实 条件分数(成为, 条件函数, p_media_var, X, 吨, model_kwargs=没有任何): """ 计算如果模型的评分函数受 cond_fn 约束,p_mean_variance 输出会是什么。有关 cond_fn 的详细信息,请参阅 condition_mean()。与 condition_mean() 不同,它使用 Song 等人 (2020) 的调节策略。"" “ alpha_bar = _extract_in_tensioner(成为.alphas_comprod, 吨, X.形式) 每股收益 = 成为._predict_eps_from_xstart(X, 吨, p_media_var[“pred_xstart”]) 每股收益 = 每股收益 - (1个 - alpha_bar).正方形() * 条件函数( X, 成为._scale_timesteps(吨), **model_kwargs ) 为一个 = p_media_var.复制() 为一个[“pred_xstart”] = 成为._predict_xstart_from_eps(X, 吨, 每股收益) 为一个[“意思是”], _, _ = 成为.q_posterior_mean_variance( x_start=为一个[“pred_xstart”], x_t=X, 吨=吨 ) 回报 为一个
生成样本
确实 p_样本( 成为, 模型, X, 吨, 剪辑去噪=真的, 去噪_fn=没有任何, 条件函数=没有任何, model_kwargs=没有任何,): """ 在给定时间间隔从模型中采样 x_{t-1}。:param model: 要采样的模型。:param x: x_{t-1} 处的当前张量。:param t: 值的 t,从 0 开始用于第一个广播步骤:param clip_denoised - 如果为 True,则将 x_start 预览剪辑到 [-1, 1]:param denoised_fn - 如果为 None,则在用于 x_start 预览之前应用于sampling :param cond_fn :如果不是 None,这是一个梯度函数,其行为类似于模型:param model_kwargs :如果不是 None,则传递给模型的附加关键字参数的字典。 : - 'sample': 模型的随机样本 - 'pred_xstart': x_0 """ 的预测 为一个 = 成为.p_mean_variance( 模型, X, 吨, 剪辑去噪=剪辑去噪, 去噪_fn=去噪_fn, model_kwargs=model_kwargs, ) 噪音 = 他.randn_like(X) 非零掩码 = ( (吨 != 0).漂浮().远景(-1个, *([1个] * (伦(X.形式) - 1个))) ) # 当 t == 0 时没有噪音 电子 条件函数 是 不 没有任何: 为一个[“意思是”] = 成为.平均条件( 条件函数, 为一个, X, 吨, model_kwargs=model_kwargs ) 样本 = 为一个[“意思是”] + 非零掩码 * 他.指数(0,5 * 为一个[“log_variance”]) * 噪音 回报 {“样本”: 样本, “pred_xstart”: 为一个[“pred_xstart”]}
参考
-
Prafulla Dhariwal,亚历克斯尼科尔,“扩散模型在图像合成方面优于 GAN”, 机器视觉和模式识别,2021 年。代码↩
(Video) 研究人员尝试用稳定扩散方法压缩图像 结果竟然优于JPEG -
索林,[论文理解】隐含噪声去除扩散模型↩