--- created: 2025-08-03 21:19:11 tags: - "Research" - "基础" - "Diffusion" - "扩散模型" - "生成模型" --- # 1. Diffusion是什么? Diffusion是一种生成模型, 用于从给定的数据集中学习数据的分布,并生成新的、与训练数据相似的样本。当前常用于图像生成处理, 文本生成编辑, 音频生成编辑等领域. 常见的生成模型包括变分自编码器([[VAE]])、生成对抗网络([[GAN]])和流模型(Flow Models)。近年来,扩散模型(Diffusion Models)因其在生成高质量图像方面的优异表现而受到广泛关注。 # 2. Diffusion Model产生的目的 扩散模型最初是为了克服传统生成模型在高分辨率图像生成任务中的局限性而提出的。传统的生成模型如[[VAE]]和[[GAN]]在 *生成低分辨率图像时表现良好,但在生成高分辨率图像时面临以下挑战* : - **训练不稳定**:GAN在训练过程中容易出现模式崩溃(mode collapse)和[[梯度消失]]等问题。 - **生成质量不高**:VAE生成的样本往往模糊不清,缺乏细节。 - **采样困难**:基于能量模型的方法(如基于得分匹配和朗之万方程的方法)在高维数据上采样效率低下,且生成的样本常常带有噪声。 扩散模型通过逐步添加和移除噪声的方式,解决了这些问题,能够在生成高分辨率图像时保持高质量和多样性。 # 3. Diffusion Model与前辈相比的提升 ### 3.1 生成质量上的提升 1. **图像细节** 与 GAN 等模型相比,Diffusion 模型生成的图像在细节方面有显著提升。GAN 生成的图像可能会出现模糊、不真实的纹理等问题。而 Diffusion 模型由于其逐步去噪的过程,可以更精细地恢复图像的细节,例如毛发、树叶的纹理等都能更加清晰和自然。 2. **多样性** 如前面提到的 GAN 的模式崩溃问题,Diffusion 模型很好地解决了这一点。它可以生成多种多样的图像,不会局限于少数几种模式。在生成具有特定语义内容的图像时,比如生成不同风格的人物画像,Diffusion 模型能够提供更丰富的变化。 ### 3.2 训练稳定性的提升 众所周知, GAN是及其难训练的, GAN 的训练对超参数和初始化非常敏感,微小的变化可能导致训练失败或生成质量急剧下降。 Diffusion 模型的训练过程相对更加稳定,它基于扩散过程的数学原理,在训练中不需要像 GAN 那样精心调整判别器和生成器之间的平衡,减少了训练不稳定的因素。 ### 3.3 对复杂分布建模能力的提升 一些传统的基于概率分布假设的生成模型,在处理复杂的高维数据分布时可能会出现偏差。 Diffusion 模型通过其独特的扩散和逆扩散过程,可以更准确地捕捉数据在不同噪声水平下的变化,从而更好地适应复杂的数据分布,无论是图像、音频还是其他类型的数据。 # 4. Diffusion的实现原理 ## 4.1 前向过程 前向过程就是在原始图像上**不断加高斯噪音**的过程. (加的噪声我们需要记作成一个**标签**, 用于还原图像, 在反向过程中会用上, 按下不表) 我们把在 $t$ 时刻的***图像分布**记为 $x_t$. 这样我们就碰上了第一个问题, 该如何得到 $x_t$ 的分布呢? ### 4.1.1 添加噪音 ![](http://oss.student.work:9078/blog-img/20250711163659915.webp) 我们要如何添加噪音呢? 是在每一个时刻加上同样的噪音吗? 其实并不是, 就拿上图从 $x_0$ 的图像到下一个 $x_1$ 来举例, 我们可能只添加了很少的噪声就能让图像 *分布得更不规律*. 而从第六个图到第七个图, 我们可能需要添加*更多的噪声*, 才能从直观上来看使得图像分布得更不规律. 所以我们粗略地得出我们噪音添加的趋势: **前面的噪音添加的更少, 后面的噪音添加的更多, 也就是加噪的过程要不断地越来越多** 现在从公式角度分析, 我们是如何来添加噪音的: 首先 $t$ 时刻的图像分布是由**上一时刻的图像分布加上噪音得来的**, 所以我们可以大致得到这样的式子 $x_t = Ax_{t-1}+Bz_t$ 其中 $z_t$ 就是我们添加的**噪音**, 且它是**服从高斯分布的** 显然在上一时刻的图像分布和噪音之间存在 *权重* , 我们要合理设计这个权重, 使得 *前面的噪音添加得更少, 后面的噪音添加的更多* . 于是我们设计出 $\alpha_t$ 与 $1-\alpha_t$ 作为权重, 其中$$\alpha_t = 1 - \beta_{t}$$$\beta$ 要越来越大, 在论文中是从 $0.0001 \sim 0.002$, 这样 $\alpha$ 就会越来越小, 然后我们设计计算$t$时刻的图像分布如下:$$x_t=\sqrt{a_t}x_{t-1}+\sqrt{1-\alpha_t}z_1 \tag{1}$$ 可以看出, 随着$\beta$越来越大, $\alpha$越来越小, $x_{t-1}$的权重越来越小, 而加上的噪音$z_t$的权重越来越大. 至于为什么需要给$\alpha$加个根号? 需要从 *概率论* 的角度去解释, 这里为了简化解释, 直接将这一项看作**权重**. ~~概率论还没学, 解释了也不懂~~ ### 4.1.2 从初始时刻到任意时刻的计算 从公式 $(1)$ 我们可以得出, 任意时刻的图像分布都是 *由前一时刻的图像分布加上噪声得到的* (这就很像RNN的递归, 每一次计算都依赖于上一次的输出, 这样效率就会很慢), 那么这是不是意味着要得到最终时刻的图像分布$x_t$就需要进行$t$次计算呢? 如果是这样的话, 那么当$t$很大的时候, 计算开销也许会很恐怖. 那么有没有可能优化公式, 有了初始的图像分布就能一次算得$x_t$呢? 首先我们尝试一下跳一步: 从$x_{t-2}$来得到$x_t$. 这个其实很简单, $x_{t-1}=\sqrt{a_t}x_{t-2}+\sqrt{1-\alpha_t}z_{2}$ , 然后将$x_{t-1}$代入到 $(1)$ 式中, 就能得到 $x_t\:=\sqrt{a_t}(\sqrt{a_{t-1}}x_{t-2}+\sqrt{1-\alpha_{t-1}}z_2)+\sqrt{1-\alpha_t}z_1$, 这样$x_{t-2}$就能直接得到$x_t$. 再对上式展开, 得到 $x_{t}=\sqrt{a_ta_{t-1}}x_{t-2}+(\sqrt{a_t(1-\alpha_{t-1})}z_2+\sqrt{1-\alpha_t}z_1)$ #### 高斯分布的合并 我们知道, 我们加入的$z_i$是服从[[正态分布|高斯分布]]的, 而对高斯分布的乘除(就是在前面乘系数, 这里的根号就是)就是改变分布的 *方差*, (BTW加减是改变均值), $z_1 \sim {\mathcal N (0, 1-\alpha_t)}$, $z_2 \sim {\mathcal N (0, a_t(1-\alpha_{t-1})})$, (其实这里就体现出所谓权重为什么要加根号了). 然后我们又知道 **一个高斯分布加上另一个高斯分布, 其结果仍然服从高斯分布**:$$\mathcal{N}(0,\sigma_{1}^{2}\mathbf{I})+\mathcal{N}(0,\sigma_{2}^{2}\mathbf{I})\sim\mathcal{N}(0,(\sigma_{1}^{2}+\sigma_{2}^{2})\mathbf{I})$$ 所以, 我们就可以将$z_1$和$z_2$合并了, 其中合并后的方差, 也就是二者的方差之和: $a_t(1-\alpha_{t-1}) + 1-\alpha_t = 1- \alpha_{t}\alpha_{t-1}$ 以上是将$x_{t-1}$代入, 如果不断地将$x_{t-2}, x_{t-3} \cdots$代入 $(1)$ 中, 就能得到$$x_{t}=\sqrt{\overline{\alpha}_t}x_0+\sqrt{1-\overline{\alpha}_t}z_t \tag{2}$$ 其中 $\overline{\alpha}_t$ 是 $\alpha$ 的 **累乘** . 这样, 我们就能知道 *任意时刻* 的图像分布了 ## 4.2 逆向过程 Diffusion的目的是生成一张图片, 前向过程是在图片中添加噪声, 那么反向过程就应当是去掉噪声, 让一幅纯噪声的图像变回一张与数据集中 *某种程度上类似* 的图像. 也就是说, 我们现在有一张充满噪声的图片分布 $x_t$, 现在要求的是 $x_0$. ~~从常理而言~~, 我们显然不可能一步到位直接从$x_t$得到$x_0$, 那么就先退而求其次, 求$x_t$到$x_{t-1}$. ### 4.2.1 如何从$x_t$求得$x_{t-1}$? 所以我们是现在这样的状态: $\text{given}$ $x_{t}$, 要求$x_{t-1}$, 这就很像一个 *概率* 的角度来去噪, 也就是 $q(\mathbf{x}_{t-1}|\mathbf{x}_{t})$. 实际上论文原文也是全文依靠概率论的角度来证明的. ~~所以为什么有xt求xt-1会想到这样的概率~~ 然而 $\text{given}$ $x_t$, 求 $x_{t-1}$ 我们并没有什么思路求, 不过反过来看, $\text{given}$ $x_{t-1}$, 求 $x_{t}$, 也就是 $q(\mathbf{x}_{t}|\mathbf{x}_{t-1})$ 我们是知道的, 因为这就是我们之前提到的加噪的 *前向过程* $$q(\mathbf{x}_{t}|\mathbf{x}_{t-1})=\sqrt{a_t}x_{t-1}+\sqrt{1-\alpha_t}z \qquad \qquad \sim\mathcal{N}(\begin{array}{c}\sqrt{a_t}x_{t-1}\end{array},\begin{array}{c}1-\alpha_t\end{array})$$ 然后根据 [[贝叶斯定理]] 我们可以列出以下式子: $$q(\mathbf{x}_{t-1}|\mathbf{x}_{t})=q(\mathbf{x}_{t}|\mathbf{x}_{t-1})\frac{q(\mathbf{x}_{t-1})}{q(\mathbf{x}_{t})}$$ 由于 $x_0$ 一直是已知的条件($given \quad x_0$), 我们再来完善一下上面的公式: (主要是方便求后面两项) $$q(\mathbf{x}_{t-1}|\mathbf{x}_{t},x_{0})=q(\mathbf{x}_{t},x_{0}|\mathbf{x}_{t-1},x_{0})\frac{q(\mathbf{x}_{t-1}|x_{0})}{q(\mathbf{x}_{t}|x_{0})}\tag{3}$$ 其中, 由前向过程的公式可得$q(\mathbf{x}_{t}|\mathbf{x}_{t-1},x_{0})$ ,$q(\mathbf{x}_{t-1}|\mathbf{x}_0)$ ,$q(\mathbf{x}_{t}|\mathbf{x}_0)$如下: $$ \begin{aligned} q(\mathbf{x}_{t}|\mathbf{x}_{t-1},x_{0})=\sqrt{a_t}x_{t-1}+\sqrt{1-\alpha_t}z \qquad \qquad &\sim\mathcal{N}(\sqrt{a_t}x_{t-1},1-\alpha_t) \\ {q(\mathbf{x}_{t-1}|\mathbf{x}_0)}=\sqrt{\overline{a}_{t-1}}x_0+\sqrt{1-\overline{a}_{t-1}}z\qquad\qquad&\sim\mathcal{N}(\sqrt{\overline{a}_{t-1}}x_0\:,\:1-\overline{a}_{t-1}) \\ {q(\mathbf{x}_{t}|\mathbf{x}_0)}=\sqrt{\overline{a}_{t}}x_0+\sqrt{1-\overline{a}_{t}}z\qquad\qquad&\sim\mathcal{N}(\sqrt{\overline{a}_{t}}x_0\:,\:1-\overline{a}_{t}) \end{aligned} $$ 这三者中的$z$是服从正态分布的, $z \sim \mathcal{N}(0,1)$ , 所以 经过加减乘除得到的 $q(x_{blabla}|x_{bla})$ 也是服从正态分布的, 由[[正态分布]]的性质可知, **加减改变分布的均值 $\mu$, 乘除改变分布的方差 $\sigma$**. 所以计算得出的 $q(x_{blabla}|x_{bla})$ 得到的分布对应上面公式的右边. #### 公式的化简 首先我们知道[[正态分布#3. 公式|正态分布的公式]]: $$f(x)=\frac{1}{\sigma\sqrt{{2\pi}}}e^{-\frac{1}{2}(\frac{x-\mu}{\sigma})^2}$$ 也就是说一个正态分布的值 $\propto exp(-\frac{1}{2}(\frac{x-\mu}{\sigma})^2)$ 我们由于指数函数的乘除在指数上面体现为: 乘为加, 除为减, 我们将各项代入 $(3)$ 中可以得到上一时刻的分布将会正比于: $$ \begin{aligned} \propto\exp\Big(-\frac{1}{2}\Big(\frac{(\mathbf{x}_t-\sqrt{\alpha_t}\mathbf{x}_{t-1})^2}{\beta_t}+\frac{(\mathbf{x}_{t-1}-\sqrt{\bar{\alpha}_{t-1}}\mathbf{x}_0)^2}{1-\bar{\alpha}_{t-1}}-\frac{(\mathbf{x}_t-\sqrt{\bar{\alpha}_t}\mathbf{x}_0)^2}{1-\bar{\alpha}_t})\Big) \end{aligned}$$ 因为我们现在求的是$x_{t-1}$, 所以我们将上式化简(就是普普通通的拆项再合并同类项), 将所有$x_{t-1}$相关项提出来得到: $$ 上式\propto\exp\left(-\frac12\big((\frac{\alpha_t}{\beta_t}+\frac1{1-\bar{\alpha}_{t-1}})\mathbf{x}_{t-1}^2-(\frac{2\sqrt{\alpha_t}}{\beta_t}\mathbf{x}_t+\frac{2\sqrt{\bar{\alpha}_{t-1}}}{1-\bar{\alpha}_{t-1}}\mathbf{x}_0)\mathbf{x}_{t-1}+C(\mathbf{x}_t,\mathbf{x}_0)\big)\right) $$ 其中$x_t$和$x_0$等都是已知值, 所以当作是常数. 然后由于标准正态分布是这样的$$\exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)=\exp\left(-\frac1{2}(\frac1{\sigma^2}x^2-\frac{2\mu}{\sigma^2}x+\frac{\mu^2}{\sigma^2})\right)$$ 我们将化简后的$x_{t-1}$与标准的$x$对应, $(\frac{\alpha_t}{\beta_t}+\frac1{1-\bar{\alpha}_{t-1}})$ 就对应 $\frac1{\sigma^2}$ , $(\frac{2\sqrt{\alpha_t}}{\beta_t})$ 对应 $\frac{2\mu}{\sigma^2}$ , 解出均值得: $$\tilde{\boldsymbol{\mu}}_t(\mathbf{x}_t,\mathbf{x}_0)\:=\frac{\sqrt{\alpha_t}(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha}_t}\mathbf{x}_t+\frac{\sqrt{\bar{\alpha}_{t-1}}\beta_t}{1-\bar{\alpha}_t}\mathbf{x}_0$$ 这里的$\alpha_t$ $\beta_t$ 都是我们设定的, 所以都是已知的, 各种累乘当然也是已知的. 所以要求分布的均值, 需要知道$x_t$, 和$x_0$. $x_t$是已知的, 毕竟我们是从$x_t$求$x_{t-1}$, 而$x_0$呢, 当然是**未知**的, 因为我们就是从$x_t$求$x_{0}$, 太难才退而求其次的. 不过好在, 我们在 $式(2)$ 中已知$x_0$估计出$x_t$, 那我们就将其反过来, 不就可以将$x_0$用$x_t$表示了: $\mathbf{x}_0=\frac1{\sqrt{\bar{\alpha}_t}}(\mathbf{x}_t-\sqrt{1-\bar{\alpha}_t}\mathbf{z}_t)$ 然后将$x_0$代入上式, 一顿化简得到均值的最终表达式: $$\tilde{\mu}_t=\frac1{\sqrt{a_t}}(x_t-\frac{\beta_t}{\sqrt{1-\overline{a_t}}}z_{t})\tag{4}$$ 不过问题又来了: $z_t$ 我们也还是不知道... #### 如何求$z_t$? 现在我们知道$x_t$, $z_t$ 我们目前应该是无法直接求解的, 那么无法直接求解我们可不可以得到一个 $z_t$ 的 *近似解* 呢? 也就是说, 我们可不可以 *训练一个模型* , 输入$x_t$ 来得到 $z_t$ 呢? 实际上就是这样做的, 一般的Diffusion实现都是以当前时刻分布$x_t$+时刻$t$作为输入, 利用[[U-net]]结构来训练, 输出当前时刻添加的噪声的 输入中的时刻$t$就类似[[Transformer]]中的[[位置编码 (Positional Encoding)|位置编码]], 实际上在实操中我们也会将它转换成一个向量, 达成类似位置编码的效果 ## 4.3 流程总结 ### Training 在DDPM论文中训练网络的流程如下: $$ \begin{aligned}&\mathbf{repeat}\\&\quad\mathbf{x}_{0}\sim q(\mathbf{x}_{0})\\&\quad t\sim\mathrm{Uniform}(\{1,\ldots,T\})\\&\quad\boldsymbol{\epsilon}\sim\mathcal{N}(\mathbf{0},\mathbf{I})\\&\quad\text{Take gradient descent step on}\\&\qquad\nabla_{\theta}\left\|\epsilon-\epsilon_{\theta}(\sqrt{\bar\alpha_{t}}\mathbf{x}_{0}+\sqrt{1-\bar{\alpha}_{t}}\boldsymbol{\epsilon},t)\right\|^{2}\\&\textbf{until}\text{ converged}\end{aligned} $$ 1. 首先从数据集中取出数据 ($x_0$为一个batch) 2. $x_0$中的图像扩散$t$次(取第$t$时刻的噪音), 但是这个$t$不是固定的, 是在一个范围内: $t \in [1,T]$ 3. $\epsilon$就是**采样得到的真实添加的噪声**, 是已知的, 严格服从[[正态分布|高斯分布]] 4. $\epsilon_\theta$就是我们训练的模型, 模型的**输入**是$x_t$(根据 $式(2)$ 转换成了$x_0$的表达式: $\sqrt{\bar\alpha_{t}}\mathbf{x}_{0}+\sqrt{1-\bar{\alpha}_{t}}\boldsymbol{\epsilon}$) 与 $t$ (因为添加的噪声和时刻有关系, 输入中加入时刻$t$有助于模型变得更好), **输出预测的噪声**. 可以抽象成 $\epsilon_{\theta}=model(x_t, t)$ DDPM并没有规定神经网络的结构。根据任务的难易程度,我们可以自己定义简单或复杂的网络结构。这里只需要把$\epsilon_{\theta}(x_{t},t)$当成一个普通的映射即可。 ### Sampling Sample过程, 也就是逆向过程(从$x_T$不断往回传得到$x_0$的过程), 流程如下: $$ \begin{aligned}&\mathbf{x}_{T}\sim\mathcal{N}(\mathbf{0},\mathbf{I})\\&\mathbf{for}\:t=T,\ldots,1\:\mathbf{do}\\&\quad\mathbf{z}\sim\mathcal{N}(\mathbf{0},\mathbf{I})\:\mathrm{if}\:t>1,\mathrm{else~}\mathbf{z}=\mathbf{0}\\&\quad\mathbf{x}_{t-1}=\frac{1}{\sqrt{\alpha_{t}}}\left(\mathbf{x}_{t}-\frac{1-\alpha_{t}}{\sqrt{1-\bar\alpha_{t}}}\boldsymbol{\epsilon}_{\theta}(\mathbf{x}_{t},t)\right)+\sigma_{t}\mathbf{z}\\&\mathbf{end \:for}\\&\mathbf{return} \: x_{0}\end{aligned} $$ 1. $x_T$是从[[正态分布#^b6efe4|标准正态分布]]中随机采样得到的 2. 然后从最后的$T$一步步往回传直到最后一步 - 如果是最后一步($t=0$)就**不加噪音** - 不是最后一步就从正态分布中随机采样出一个噪声$z$ 3. 根据[[重参数化]]的$x = \mu + \sigma \cdot z$, - 将 $式(4)$ 推导出的 $\tilde{\mu}_t=\frac1{\sqrt{a_t}}(x_t-\frac{\beta_t}{\sqrt{1-\overline{a_t}}}z_{t})\tag{4}$代入$\mu$ (其中$z_t$就是$\epsilon_\theta$模型输出的预测的噪音) - 后面的 $+\sigma_{t}\mathbf{z}$ 是为了**增加样本的多样性并避免过拟合**,在重建步骤中引入额外的噪声 4. 一步向前走, 就得到了$x_0$, 也就是我们生成的图像分布 # 0. 参考资料 \[0] [唐宇迪Diffusion扩散模型2022新版教程](https://www.bilibili.com/video/BV1Re4y1s7uV/)--公式推导很好理解 \[1] [扩散模型(Diffusion Model)详解:直观理解、数学原理、PyTorch 实现 | 周弈帆的博客](https://zhouyifan.net/2023/07/07/20230330-diffusion-model/)--总体都非常不错 \[2] [生成扩散模型漫谈(一):DDPM = 拆楼 + 建楼 - 科学空间|Scientific Spaces](https://kexue.fm/archives/9119)--数学推导不错 \[3] [Diffusion Models:生成扩散模型](https://yinglinzheng.netlify.app/diffusion-model-tutorial/)--主流的详细推导 \[4] [由浅入深了解Diffusion Model](https://zhuanlan.zhihu.com/p/525106459)-- 也是主流的数学推导 \[5] [扩散模型\[译\]unet-CSDN博客](https://blog.csdn.net/yujianmin1990/article/details/129143157)--分模块讲解SD \[6] [由浅入深剖析Diffusion Model:从直观理解到数学原理](https://zhuanlan.zhihu.com/p/689182573)--流程总结很棒 \[7] [超详细的扩散模型(Diffusion Models)原理+代码](https://zhuanlan.zhihu.com/p/624221952)--流程总结不错, 代码分块讲解 \[8] [Intro to Diffusion Model — Part 5 | by DZ | Medium](https://dzdata.medium.com/intro-to-diffusion-model-part-5-d0af8331871)--U-net代码很详细, 整个系列也不错 \[9] [Stable Diffusion 图片生成原理简述](https://blog.cnbang.net/tech/3766/)--SD分模块的概述, 引用的质量都很高