# DDIMScheduler

Jiaming Song、Chenlin Meng、Stefano Ermon による [Denoising Diffusion Implicit Models](https://huggingface.co/papers/2010.02502) (DDIM)。

論文の抄録は以下の通りです：

*デノイジング拡散確率モデル（DDPM）は、敵対的学習なしで高品質な画像生成を実現していますが、サンプルを生成するには多くのステップでマルコフ連鎖をシミュレートする必要があります。サンプリングを高速化するために、DDPMと同じ訓練手順を持つ、より効率的な反復型暗黙的確率モデルのクラスであるデノイジング拡散暗黙的モデル（DDIM）を提案します。DDPMでは、生成過程はマルコフ拡散過程の逆過程として定義されます。我々は、同じ訓練目的関数に導く非マルコフ拡散過程のクラスを構築し、その逆過程からのサンプリングを大幅に高速化します。実験により、DDIMはDDPMと比較して実時間ベースで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"`) : ベータスケジュールです。モデルのステップ処理において、ベータの範囲からベータのシーケンスへのマッピングを行います。`"linear"`、`"scaled_linear"`、`"squaredcos_cap_v2"`のいずれかである必要があります。

trained_betas (`np.ndarray`、*任意*) : `beta_start` と `beta_end` をバイパスして、ベータの配列を直接コンストラクタに渡す。

clip_sample (`bool`、デフォルトは`True`) : 数値の安定性を確保するために、予測サンプルをクリップします。

clip_sample_range (`float`、デフォルト値は 1.0) : サンプルクリッピングの最大振幅。`clip_sample=True` の場合のみ有効です。

set_alpha_to_one (`bool`、デフォルトは`True`) : 各拡散ステップでは、そのステップと直前のステップのアルファの積の値が使用されます。最終ステップには直前のアルファが存在しません。このオプションが`True`の場合、直前のアルファの積は`1`に固定され、それ以外の場合はステップ0のアルファの値が使用されます。

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"]`, defaults to `"leading"`) : The way the timesteps should be scaled. Must be one of `"leading"`, `"trailing"`, or `"linspace"`. Refer to Table 2 of the [Common Diffusion Noise Schedules and Sample Steps are Flawed](https://huggingface.co/papers/2305.08891) for more information.

rescale_betas_zero_snr (`bool`、デフォルトは`False`) : ベータを再スケーリングして、終端SNRをゼロにするかどうか。これにより、モデルは中間の明るさに限定されず、非常に明るく暗いサンプルを生成できるようになります。[`--offset_noise`](https://github.com/huggingface/diffusers/blob/74fd735eb073eb1d774b1ab4154a0876eb82f055/examples/dreambooth/train_dreambooth.py#L506)とゆるく関連しています。

`DDIMScheduler` は、デノイジング拡散確率モデル（DDPM）で導入されたデノイジング手順を、非マルコフ的ガイダンスによって拡張します。

このモデルは [SchedulerMixin](/docs/diffusers/v0.43.0/ja/api/schedulers/overview#diffusers.SchedulerMixin) と [ConfigMixin](/docs/diffusers/v0.43.0/ja/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`) : 速度計算用のタイムステップ。

**戻り値:** `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`、*optional*、デフォルト値は 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/ja/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) を返すか、`tuple` を返すかを指定します。

**戻り値:** [DDIMSchedulerOutput](/docs/diffusers/v0.43.0/ja/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) または `tuple`

`True` の場合、[DDIMSchedulerOutput](/docs/diffusers/v0.43.0/ja/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) が返され、それ以外の場合は、最初の要素がサンプルテンソルであるタプルが返されます。

前回のタイムステップからのサンプルを、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 (`torch.Tensor`、画像の場合は `(batch_size, num_channels, height, width)` の形状) : 前のタイムステップの計算済みサンプル `(x_{t-1})`。`prev_sample` は、デノイジングループの次のモデル入力として使用する必要があります。

pred_original_sample (`torch.Tensor`、画像の場合は形状 `(batch_size, num_channels, height, width)`) : 現在のタイムステップにおけるモデルの出力に基づいて予測された、ノイズ除去されたサンプル `(x_{0})`。`pred_original_sample` は、進捗のプレビューやガイダンスに使用できます。

スケジューラの`step`関数の出力用のクラス。

