# DDIMScheduler

Jiaming Song、Chenlin Meng 和 Stefano Ermon 提出的[去噪扩散隐式模型](https://huggingface.co/papers/2010.02502)（DDIM）。

该论文的摘要如下：

*去噪扩散概率模型（DDPMs）无需对抗训练即可实现高质量的图像生成，但生成一个样本需要模拟马尔可夫链的许多步骤。为了加速采样，我们提出了去噪扩散隐式模型（DDIMs），这是一类更高效的迭代隐式概率模型，其训练流程与 DDPMs 相同。在 DDPMs 中，生成过程被定义为马尔可夫扩散过程的逆过程。我们构建了一类非马尔可夫扩散过程，它们具有相同的训练目标，但其逆过程的采样速度可以快得多。我们通过实验证明，与 DDPMs 相比，DDIMs 在墙钟时间上可以将高质量样本的生成速度提高 10 到 50 倍，允许我们在计算量和样本质量之间进行权衡，并且可以直接在潜在空间中执行语义上有意义的图像插值。*

本文的原始代码库可在 [ermongroup/ddim](https://github.com/ermongroup/ddim) 中找到，您可以通过 [tsong.me](https://tsong.me/) 联系作者。

## 提示

The paper [Common Diffusion Noise Schedules and Sample Steps are Flawed](https://huggingface.co/papers/2305.08891) claims that a mismatch between the training and inference settings leads to suboptimal inference generation results for Stable Diffusion. To fix this, the authors propose:

> [!WARNING]
> 🧪 这是一个实验性功能！

1. 重新缩放噪声调度，以强制终端信噪比（SNR）为零

```py
pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config, rescale_betas_zero_snr=True)
```

2. train a model with `v_prediction` (add the following argument to the [train_text_to_image.py](https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image.py) or [train_text_to_image_lora.py](https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image_lora.py) scripts)

```bash
--prediction_type="v_prediction"
```

3. 将采样器更改为始终从最后一个时间步开始

```py
pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config, timestep_spacing="trailing")
```

4. 重新缩放 classifier-free guidance 以防止过度曝光

```py
image = pipe(prompt, guidance_rescale=0.7).images[0]
```

例如：

```py
from diffusers import DiffusionPipeline, DDIMScheduler
import torch

pipe = DiffusionPipeline.from_pretrained("ptx0/pseudo-journey-v2", dtype=torch.float16)
pipe.scheduler = DDIMScheduler.from_config(
    pipe.scheduler.config, rescale_betas_zero_snr=True, timestep_spacing="trailing"
)
pipe.to("cuda")  # or "mps", "xpu", "cpu"

prompt = "A lion in galaxies, spirals, nebulae, stars, smoke, iridescent, intricate detail, octane render, 8k"
image = pipe(prompt, guidance_rescale=0.7).images[0]
image
```

## DDIMScheduler[[diffusers.DDIMScheduler]]

#### diffusers.DDIMScheduler[[diffusers.DDIMScheduler]]

```python
diffusers.DDIMScheduler(num_train_timesteps: int = 1000, beta_start: float = 0.0001, beta_end: float = 0.02, beta_schedule: str = 'linear', trained_betas: numpy.ndarray | list[float] | None = None, clip_sample: bool = True, set_alpha_to_one: bool = True, steps_offset: int = 0, prediction_type: typing.Literal['epsilon', 'sample', 'v_prediction'] = 'epsilon', thresholding: bool = False, dynamic_thresholding_ratio: float = 0.995, clip_sample_range: float = 1.0, sample_max_value: float = 1.0, timestep_spacing: typing.Literal['leading', 'trailing', 'linspace'] = 'leading', rescale_betas_zero_snr: bool = False)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L139)

**参数：**

num_train_timesteps (`int`，默认为 1000)：用于训练模型的扩散步数。

beta_start (`float`，默认值为 0.0001)：推理的初始 `beta` 值。

beta_end (`float`，默认值为 0.02)：最终的 `beta` 值。

beta_schedule (`Literal["linear", "scaled_linear", "squaredcos_cap_v2"]`，默认为 `"linear"`)：beta 调度，即将 beta 范围映射为用于模型步进的一系列 beta 值。必须是 `"linear"`、`"scaled_linear"` 或 `"squaredcos_cap_v2"` 之一。

trained_betas (`np.ndarray`，*可选*)：将 beta 数组直接传递给构造函数，以绕过 `beta_start` 和 `beta_end`。

clip_sample (`bool`，默认为 `True`)：对预测样本进行裁剪，以确保数值稳定性。

clip_sample_range (`float`，默认为 1.0)：样本裁剪的最大幅度。仅在 `clip_sample=True` 时有效。

set_alpha_to_one (`bool`，默认为 `True`)：每个扩散步骤都会使用该步骤及前一步的 alpha 乘积值。对于最后一步，不存在前一个 alpha。当此选项为 `True` 时，前一个 alpha 乘积固定为 `1`；否则，使用第 0 步的 alpha 值。

steps_offset (`int`，默认为 0)：根据某些模型系列的要求，添加到推理步数中的偏移量。

prediction_type (`Literal["epsilon", "sample", "v_prediction"]`，默认为 `"epsilon"`) : 调度器函数的预测类型。必须是 `"epsilon"`（预测扩散过程的噪声）、`"sample"`（直接预测含噪样本）或 `"v_prediction"`（参见 [Imagen Video](https://huggingface.co/papers/2210.02303) 论文的第 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 (`Literal["leading", "trailing", "linspace"]`，默认为 `"leading"`)：时间步的缩放方式。必须是 `"leading"`、`"trailing"` 或 `"linspace"` 之一。更多信息请参阅 [《常见的扩散噪声调度和采样步骤存在缺陷》](https://huggingface.co/papers/2305.08891) 中的表 2。

rescale_betas_zero_snr (`bool`，默认为 `False`)：是否将 betas 重新缩放，使其具有零终端 SNR。这使模型能够生成非常明亮和非常暗的样本，而不是将其限制在中等亮度的样本上。与 [`--offset_noise`](https://github.com/huggingface/diffusers/blob/74fd735eb073eb1d774b1ab4154a0876eb82f055/examples/dreambooth/train_dreambooth.py#L506) 大致相关。

`DDIMScheduler` 在去噪扩散概率模型（DDPM）所引入的去噪过程基础上，扩展了非马尔可夫引导。

该模型继承自 [SchedulerMixin](/docs/diffusers/v0.43.0/zh/api/schedulers/overview#diffusers.SchedulerMixin) 和 [ConfigMixin](/docs/diffusers/v0.43.0/zh/api/configuration#diffusers.ConfigMixin)。有关该库为所有调度器实现的通用方法（例如加载和保存），请参阅父类文档。

#### add_noise[[diffusers.DDIMScheduler.add_noise]]

```python
add_noise(original_samples: Tensor, noise: Tensor, timesteps: IntTensor)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L517)

**参数：**

original_samples (`torch.Tensor`) : 将添加噪声的原始样本。

noise (`torch.Tensor`) : 要添加到样本中的噪声。

timesteps (`torch.IntTensor`)：指示每个样本噪声水平的时间步。

**返回：** `torch.Tensor`

带噪声的样本。

根据每个时间步的噪声幅度，向原始样本添加噪声（即前向扩散过程）。

#### get_velocity[[diffusers.DDIMScheduler.get_velocity]]

```python
get_velocity(sample: Tensor, noise: Tensor, timesteps: IntTensor)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L560)

**参数：**

sample (`torch.Tensor`)：输入样本。

noise (`torch.Tensor`) : 噪声张量。

timesteps (`torch.IntTensor`)：用于速度计算的 timesteps。

**返回：** `torch.Tensor`

计算得到的速度。

根据速度公式，从样本和噪声计算速度预测。

#### scale_model_input[[diffusers.DDIMScheduler.scale_model_input]]

```python
scale_model_input(sample: Tensor, timestep: int = None)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L245)

**参数：**

sample (`torch.Tensor`)：输入样本。

timestep (`int`, *可选*) : 扩散链中的当前时间步。

**返回：** `torch.Tensor`

经过缩放的输入样本。

确保与那些需要根据当前时间步对去噪模型输入进行缩放的调度器保持可互换性。

#### set_timesteps[[diffusers.DDIMScheduler.set_timesteps]]

```python
set_timesteps(num_inference_steps: int, device: typing.Union[str, torch.device] = None)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L334)

**参数：**

num_inference_steps (`int`) : 使用预训练模型生成样本时所用的扩散步数。

device (`str | torch.device`，*可选*)：用于 timesteps 的设备。

**引发：** ``ValueError``

- ``ValueError`` -- 如果 `num_inference_steps` 大于 `self.config.num_train_timesteps`。

设置扩散链所使用的离散时间步（需在推理之前运行）。

#### 步骤[[diffusers.DDIMScheduler.step]]

```python
step(model_output: Tensor, timestep: int, sample: Tensor, eta: float = 0.0, use_clipped_model_output: bool = False, generator: typing.Optional[torch.Generator] = None, variance_noise: typing.Optional[torch.Tensor] = None, return_dict: bool = True)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L384)

**参数：**

model_output (`torch.Tensor`)：学习到的扩散模型的直接输出。

timestep (`int`)：扩散链中当前的离散时间步。

sample (`torch.Tensor`)：扩散过程生成的当前样本实例。

eta (`float`, *可选*，默认为 0.0)：扩散步骤中新增噪声的权重。值为 0 对应 DDIM（确定性），值为 1 对应 DDPM（完全随机）。

use_clipped_model_output (`bool`，*可选*，默认为 `False`)：如果为 `True`，则从经过裁剪的预测原始样本计算“校正后的”`model_output`。当 `self.config.clip_sample` 为 `True` 时，预测原始样本会被裁剪到 [-1, 1] 范围内，因此需要进行此操作。如果未发生裁剪，则“校正后的”`model_output` 将与作为输入提供的那个一致，`use_clipped_model_output` 将不起作用。

generator (`torch.Generator`，*可选*)：用于可复现采样的随机数生成器。

variance_noise (`torch.Tensor`, *可选*) : 直接提供方差本身的噪声，作为使用 `generator` 生成噪声的替代方案。适用于 `CycleDiffusion` 等方法。

return_dict (`bool`，*可选*，默认为 `True`)：是否返回 [DDIMSchedulerOutput](/docs/diffusers/v0.43.0/zh/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) 或 `tuple`。

**返回：** [DDIMSchedulerOutput](/docs/diffusers/v0.43.0/zh/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) 或 `tuple`

If return_dict is `True`, [DDIMSchedulerOutput](/docs/diffusers/v0.43.0/zh/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) is returned, otherwise a tuple is returned where the first element is the sample tensor.

通过逆向 SDE 预测上一时间步的样本。此函数将扩散过程从学习到的模型输出（通常是预测的噪声）进行传播。

## DDIMSchedulerOutput[[diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput]]

#### diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput[[diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput]]

```python
diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput(prev_sample: Tensor, pred_original_sample: typing.Optional[torch.Tensor] = None)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L33)

**参数：**

prev_sample （对于图像，形状为 `(batch_size, num_channels, height, width)` 的 `torch.Tensor`）：计算得到的前一时间步的样本 `(x_{t-1})`。在去噪循环中，应将 `prev_sample` 用作下一个模型输入。

pred_original_sample （对于图像，形状为 `(batch_size, num_channels, height, width)` 的 `torch.Tensor`）：基于当前时间步的模型输出预测的去噪样本 `(x_{0})`。`pred_original_sample` 可用于预览进度或进行引导。

调度器 `step` 函数输出的输出类。

