Files
DiffSynth-Studio/docs/zh/Training/Understanding_Diffusion_models.md
Hong Zhang b3b63fef3e Add readthedocs for diffsynth-studio
* add conf docs

* add conf docs

* add index

* add index

* update ref

* test root

* add en

* test relative

* redirect relative

* add document

* test_document

* test_document
2026-02-10 19:51:04 +08:00

140 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Diffusion 模型基本原理
本文介绍 Diffusion 模型的基本原理,帮助你理解训练框架是如何构建的。为了让读者更轻松地理解这些复杂的数学理论,我们重构了 Diffusion 模型的理论框架,抛弃了复杂的随机微分方程,用一种更简洁易懂的形式进行介绍。
## 引言
Diffusion 模型通过多步迭代式地去噪denoise生成清晰的图像或视频内容我们从一个数据样本 $x_0$ 的生成过程开始讲起。直观地,在完整的一轮 denoise 过程中,我们从随机高斯噪声 $x_T$ 开始,通过迭代依次得到 $x_{T-1}$、$x_{T-2}$、$x_{T-3}$、$\cdots$,在每一步中逐渐减少噪声含量,最终得到不含噪声的数据样本 $x_0$。
![Image](https://github.com/user-attachments/assets/6471ae4c-a635-4924-8b36-b0bd4d42043d)
这个过程是很直观的,但如果要理解其中的细节,我们就需要回答这几个问题:
* 每一步的噪声含量是如何定义的?
* 迭代去噪的计算是如何进行的?
* 如何训练这样的 Diffusion 模型?
* 现代 Diffusion 模型的架构是什么样的?
* 本项目如何封装和实现模型训练?
## 每一步的噪声含量是如何定义的?
在 Diffusion 模型的理论体系中,噪声的含量是由一系列参数 $\sigma_T$、$\sigma_{T-1}$、$\sigma_{T-2}$、$\cdots$、$\sigma_0$ 决定的。其中
* $\sigma_T=1$,对应的 $x_T$ 为纯粹的高斯噪声
* $\sigma_T>\sigma_{T-1}>\sigma_{T-2}>\cdots>x_0$,在迭代过程中噪声含量逐渐减小
* $\sigma_0=0$,对应的 $x_0$ 为不含任何噪声的数据样本
至于中间 $\sigma_{T-1}$、$\sigma_{T-2}$、$\cdots$、$\sigma_1$ 的数值,则不是固定的,满足递减的条件即可。
那么在中间的某一步,我们可以直接合成含噪声的数据样本 $x_t=(1-\sigma_t)x_0+\sigma_t x_T$。
![Image](https://github.com/user-attachments/assets/e25a2f71-123c-4e18-8b34-3a066af15667)
## 迭代去噪的计算是如何进行的?
在理解迭代去噪的计算前,我们要先搞清楚,去噪模型的输入和输出是什么。我们把模型抽象成一个符号 $\hat \epsilon$,它的输入通常包含三部分
* 时间步 $t$,模型需要理解当前处于去噪过程的哪个阶段
* 含噪声的数据样本 $x_t$,模型需要理解要对什么数据进行去噪
* 引导条件 $c$,模型需要理解要通过去噪生成什么样的数据样本
其中,引导条件 $c$ 是新引入的参数,它是由用户输入的,可以是用于描述图像内容的文本,也可以是用于勾勒图像结构的线稿图。
而模型的输出 $\hat \epsilon(x_t,c,t)$,则近似地等于 $x_T-x_0$,也就是整个扩散过程(去噪过程的反向过程)的方向。
接下来我们分析一步迭代中发生的计算,在时间步 $t$,模型通过计算得到近似的 $x_T-x_0$ 后,我们计算下一步的 $x_{t-1}$
$$
\begin{aligned}
x_{t-1}&=x_t + (\sigma_{t-1} - \sigma_t) \cdot \hat \epsilon(x_t,c,t)\\
&\approx x_t + (\sigma_{t-1} - \sigma_t) \cdot (x_T-x_0)\\
&=(1-\sigma_t)x_0+\sigma_t x_T + (\sigma_{t-1} - \sigma_t) \cdot (x_T-x_0)\\
&=(1-\sigma_{t-1})x_0+\sigma_{t-1}x_T
\end{aligned}
$$
完美!与时间步 $t-1$ 时的噪声含量定义完美契合。
> (这部分可能有点难懂,请不必担心,首次阅读本文时建议跳过这部分,不影响后文的阅读。)
>
> 完成了这段有点复杂的公式推导后,我们思考一个问题,为什么模型的输出要近似地等于 $x_T-x_0$ 呢?可以设定成其他值吗?
>
> 实际上Diffusion 模型依赖两个定义形成完备的理论。在以上的公式中,我们可以提炼出这两个定义,并导出迭代公式:
>
> * 数据定义:$x_t=(1-\sigma_t)x_0+\sigma_t x_T$
> * 模型定义:$\hat \epsilon(x_t,c,t)=x_T-x_0$
> * 导出迭代公式:$x_{t-1}=x_t + (\sigma_{t-1} - \sigma_t) \cdot \hat \epsilon(x_t,c,t)$
>
> 这三个数学公式是完备的,例如在刚才的推导中,我们把数据定义和模型定义代入迭代公式,可以得到与数据定义吻合的 $x_{t-1}$。
>
> 这是基于 Flow Matching 理论构建的两个定义,但 Diffusion 模型也可用其他的两个定义来实现,例如早期基于 DDPMDenoising Diffusion Probabilistic Models的模型其两个定义及导出的迭代公式为
>
> * 数据定义:$x_t=\sqrt{\alpha_t}x_0+\sqrt{1-\alpha_t}x_T$
> * 模型定义:$\hat \epsilon(x_t,c,t)=x_T$
> * 导出迭代公式:$x_{t-1}=\sqrt{\alpha_{t-1}}\left(\frac{x_t-\sqrt{1-\alpha_t}\hat \epsilon(x_t,c,t)}{\sqrt{\sigma_t}}\right)+\sqrt{1-\alpha_{t-1}}\hat \epsilon(x_t,c,t)$
>
> 更一般地,我们用矩阵描述迭代公式的导出过程,对于任意数据定义和模型定义,有:
>
> * 数据定义:$x_t=C_T(x_0,x_T)^T$
> * 模型定义:$\hat \epsilon(x_t,c,t)=C_T^{[\epsilon]}(x_0,x_T)^T$
> * 导出迭代公式:$x_{t-1}=C_{t-1}(C_t,C_t^{[\epsilon]})^{-T}(x_t,\hat \epsilon(x_t,c,t))^T$
>
> 其中,$C_t$、$C_t^{[\epsilon]}$ 是 $1\times 2$ 的系数矩阵,不难发现,在构造两个定义时,需保证矩阵 $(C_t,C_t^{[\epsilon]})^T$ 是可逆的。
>
> 尽管 Flow Matching 与 DDPM 已被大量预训练模型广泛验证过,但这并不代表这是最优的方案,我们鼓励开发者设计新的 Diffusion 模型理论实现更好的训练效果。
## 如何训练这样的 Diffusion 模型?
搞清楚迭代去噪的过程之后,接下来我们考虑如何训练这样的 Diffusion 模型。
训练过程不同于生成过程,如果我们在训练过程中保留多步迭代,那么梯度需经过多步回传,带来的时间和空间复杂度是灾难性的。为了提高计算效率,我们在训练中随机选择某一时间步 $t$ 进行训练。
以下是训练过程的伪代码
> 从数据集获取数据样本 $x_0$ 和引导条件 $c$
>
> 随机采样时间步 $t\in(0,T]$
>
> 随机采样高斯噪声 $x_T\in \mathcal N(O,I)$
>
> $x_t=(1-\sigma_t)x_0+\sigma_t x_T$
>
> $\hat \epsilon(x_t,c,t)$
>
> 损失函数 $\mathcal L=||\hat \epsilon(x_t,c,t)-(x_T-x_0)||_2^2$
>
> 梯度回传并更新模型参数
## 现代 Diffusion 模型的架构是什么样的?
从理论到实践,还需要填充更多细节。现代 Diffusion 模型架构已经发展成熟,主流的架构沿用了 Latent Diffusion 所提出的“三段式”架构,包括数据编解码器、引导条件编码器、去噪模型三部分。
![Image](https://github.com/user-attachments/assets/43855430-6427-4aca-83a0-f684e01438b1)
### 数据编解码器
在前文中,我们一直将 $x_0$ 称为“数据样本”,而不是图像或视频,这是因为现代 Diffusion 模型通常不会直接在图像或视频上进行处理而是用编码器Encoder-解码器Decoder架构的模型通常是 VAEVariational Auto-Encoders模型将图像或视频编码为 Embedding 张量,得到 $x_0$。
数据经过编码器编码后,再经过解码器解码,重建后的内容与原来近似地一致,会有少量误差。那么,为什么要在编码后的 Embedding 张量上处理,而不是在图像或视频上直接处理呢?主要原因有亮点:
* 编码的同时对数据进行了压缩,编码后处理的计算量更小。
* 编码后的数据分布与高斯分布更相似,更容易用去噪模型对数据进行建模。
在生成过程中,编码器部分不参与计算,迭代完成后,用解码器部分解码 $x_0$ 即可得到清晰的图像或视频。在训练过程中,解码器部分不参与计算,仅编码器用于计算 $x_0$。
### 引导条件编码器
用户输入的引导条件 $c$ 可能是复杂多样的,需要由专门的编码器模型将其处理成 Embedding 张量。按照引导条件的类型,我们把引导条件编码器分为以下几类:
* 文本类型,例如 CLIP、Qwen-VL
* 图像类型,例如 ControlNet、IP-Adapter
* 视频类型,例如 VAE
> 前文中的模型 $\hat \epsilon$ 指代此处的所有引导条件编码器和去噪模型这一整体,我们把引导条件编码器单独拆分列出,因为这类模型在 Diffusion 训练中通常是冻结的,且输出值与时间步 $t$ 无关,因此引导条件编码器的计算可以离线进行。
### 去噪模型
去噪模型是 Diffusion 模型真正的本体,其模型结构多种多样,例如 UNet、DiT模型开发者可在此结构上自由发挥。
## 本项目如何封装和实现模型训练?
请阅读下一文档:[标准监督训练](../Training/Supervised_Fine_Tuning.md)