# 哲学

🧨 Diffusers は、**最先端の**事前学習済み拡散モデルを、複数のモダリティにわたって提供しています。その目的は、推論と学習の両方において**モジュール化されたツールボックス**として機能することです。

私たちは、長期的な信頼性を備えたライブラリを構築することを目標としており、そのためAPI設計を非常に重視しています。

要するに、DiffusersはPyTorchの自然な拡張として構築されています。そのため、私たちの設計上の判断の多くは[PyTorchの設計原則](https://pytorch.org/docs/stable/community/design.html#pytorch-design-philosophy)に基づいています。最も重要なポイントをいくつか見ていきましょう。

## 使いやすさを性能より優先

- Diffusersには多くのパフォーマンス向上機能が組み込まれていますが（[メモリと速度](https://huggingface.co/docs/diffusers/optimization/fp16)を参照）、モデルは常に最高精度かつ最低限の最適化で読み込まれます。そのため、ユーザーが明示的に指定しない限り、デフォルトでは拡散パイプラインはCPU上でfloat32精度でインスタンス化されます。これにより、異なるプラットフォームやアクセラレーター間で利用可能であり、ライブラリを実行するために複雑なインストールは不要です。
- Diffusersは**軽量**なパッケージであることを目指しており、必須の依存関係は非常に少ないものの、パフォーマンスを向上させることができる多くのソフト依存関係（`accelerate`、`safetensors`など）があります。他のパッケージへの依存関係として、大きな懸念なく追加できるように、ライブラリをできるだけ軽量に保つよう努めています。
- Diffusersでは、凝縮されたマジックなコードよりも、シンプルで自己説明可能なコードを優先しています。そのため、ラムダ関数などの短縮記法や、高度なPyTorch演算子は、多くの場合望ましくありません。

## シンプルでかんたん

PyTorchが述べているように、**明示的であることは暗黙的であることより良い**、そして**単純であることは複雑であることより良い**です。この設計思想は、ライブラリの複数の部分に反映されています。
- PyTorch の API に従い、[`DiffusionPipeline.to`](https://huggingface.co/docs/diffusers/main/en/api/diffusion_pipeline#diffusers.DiffusionPipeline.to) のようなメソッドを提供することで、ユーザーがデバイス管理を処理できるようにしています。
- 誤った入力を黙って修正するよりも、簡潔なエラーメッセージを送出することが推奨されます。Diffusersは、ライブラリをできるだけ使いやすくすることよりも、ユーザーに学習させることを目的としています。
- 複雑なモデルとスケジューラのロジックが内部で自動的に処理されるのではなく、明示的に公開されています。Scheduler/Samplerは拡散モデルから分離されており、相互の依存関係は最小限に抑えられています。これにより、ユーザーは展開されたデノイジングループを自分で記述する必要があります。ただし、この分離によりデバッグが容易になり、デノイジングプロセスの適応や拡散モデルおよびスケジューラの切り替えにおいて、ユーザーにより多くの制御が可能になります。
- 拡散パイプラインの個別に学習されたコンポーネント、*例えば*テキストエンコーダー、unet、変分オートエンコーダーは、それぞれ独自のモデルクラスを持ちます。これにより、ユーザーは異なるモデルコンポーネント間の相互作用を処理する必要があり、シリアライズ形式ではモデルコンポーネントが異なるファイルに分離されます。ただし、これによりデバッグやカスタマイズが容易になります。DreamBoothやTextual Inversionの学習
Diffusersは拡散パイプラインの単一コンポーネントを分離できるため、非常にシンプルです。

## 調整可能で、コントリビューターフレンドリーな抽象化

ライブラリの大部分において、Diffusers は [Transformers ライブラリ](https://github.com/huggingface/transformers) の重要な設計原則を採用しています。それは、急ぎ足で抽象化を行うよりも、コードのコピー&ペーストを優先するというものです。この設計原則は非常に強い主張を含んでおり、[DRY（Don't Repeat Yourself）](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) といった一般的な設計原則とは対照的です。要するに、Transformers がモデリングファイルに対して行っているのと同様に、Diffusers もパイプラインとスケジューラに対して、極めて低い抽象度と非常に自己完結的なコードを維持することを好みます。関数、長いコードブロック、場合によってはクラス自体が複数のファイル間でコピーされるため、一見すると、ライブラリをメンテナンス不能にするような粗末で不適切な設計選択に見えるかもしれません。**しかし**、この設計は Transformers において極めて成功を収めており、コミュニティ主導のオープンソース機械学習ライブラリにとって非常に理にかなっています。その理由は以下の通りです。
- 機械学習は、パラダイム、モデルアーキテクチャ、アルゴリズムが急速に変化する非常に動きの速い分野であり、そのため長期的に持続可能なコードの抽象化を定義することが非常に困難です。
- 機械学習の実務者は、アイデア出しや研究のために既存のコードを素早く調整できることを好むため、多くの抽象化を含むコードよりも、自己完結型のコードを好みます。
- オープンソースのライブラリはコミュニティの貢献に依存しているため、貢献しやすいライブラリを構築する必要があります。コードが抽象的であればあるほど、依存関係が増え、読み解くのが難しくなり、貢献しにくくなります。貢献者は、重要な機能が壊れてしまうことを恐れ、非常に抽象度の高いライブラリへの貢献を止めてしまう傾向があります。ライブラリへの貢献が他の基本的なコードを壊すリスクがなければ、潜在的な新規貢献者にとって参加しやすくなるだけでなく、複数の部分へのレビューや並行した貢献もしやすくなります。

Hugging Face では、この設計を**単一ファイルポリシー**と呼び、あるクラスのコードのほとんどは、単一の自己完結型ファイルに記述されるべきであることを意味します。この哲学について詳しく知りたい場合は、[このブログ記事](https://huggingface.co/blog/transformers-design-philosophy)をご覧ください。

Diffusersでは、パイプライン、スケジューラ、モデルのすべてにおいて、この哲学を踏襲しています。この慣例より前に登場した一部の古いモデルはそのままの形で維持されていますが、すべての新しいモデルアーキテクチャは、自己完結型の個別ファイルに配置されています。詳細は、以下の[Models](#models)セクションを参照してください。

素晴らしいですね。これで、🧨 Diffusers がなぜこのように設計されているのか、その理由が概ねご理解いただけたと思います 🤗。私たちは、これらの設計原則をライブラリ全体に一貫して適用しています。ただし、この哲学に対する些細な例外や、残念ながら好ましくなかった設計判断が存在する箇所もあります。設計に関するフィードバックをいただければ、[GitHub 上で直接](https://github.com/huggingface/diffusers/issues/new?assignees=&labels=&template=feedback.md&title=)お聞かせいただければ ❤️ 幸いです。

## 設計思想の詳細

次に、設計思想の詳細な点について説明します。Diffusersでは、[モデル](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models)と[スケジューラ](https://github.com/huggingface/diffusers/tree/main/src/diffusers/schedulers)を実行可能なワークフローとして構成する2つの方法が提供されています。1つは、1つのパイプラインクラスごとに1つのタスクを処理する単一構造の標準的な[パイプライン](https://github.com/huggingface/diffusers/tree/main/src/diffusers/pipelines)です。もう1つは、ブロックベースで組み合わせ可能なModular Diffusersです。以下のセクションでは、パイプライン、モジュラーパイプライン、モデル、スケジューラについて順に説明します。

### パイプライン

Pipelines は、標準型でもモジュラー型でも、推論のみを目的としています。使いやすさを重視して設計されているため（[Simple over easy](#simple-over-easy) を 100% には従っていません）、読みやすく、自己完結的で、調整が容易であり、[models](#models) と [schedulers](#schedulers) の使い方の例として捉えるのが最も適切です。機能は完全ではありません。Diffusers を基盤として機能の揃ったユーザーインターフェースを構築するには、[Modular Diffusers](../modular_diffusers/overview) を使用してください。

以下の設計原則が遵守されています:
- Pipelines follow the single-file policy. All pipelines can be found in individual directories under src/diffusers/pipelines. One pipeline folder corresponds to one diffusion paper/project/release. Multiple pipeline files can be gathered in one pipeline folder, as it’s done for [`src/diffusers/pipelines/stable-diffusion`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/pipelines/stable_diffusion). If pipelines share similar functionality, one can make use of the [# Copied from mechanism](https://github.com/huggingface/diffusers/blob/125d783076e5bd9785beb05367a2d2566843a271/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_img2img.py#L251).
- すべてのPipelinesは[DiffusionPipeline](/docs/diffusers/v0.43.0/ja/api/pipelines/overview#diffusers.DiffusionPipeline)を継承しています。
- すべてのパイプラインは、[`model_index.json` ファイル](https://huggingface.co/stable-diffusion-v1-5/stable-diffusion-v1-5/blob/main/model_index.json)にドキュメント化された異なるモデルとスケジューラのコンポーネントで構成されており、パイプラインの属性として同名でアクセスでき、[`DiffusionPipeline.components`](https://huggingface.co/docs/diffusers/main/en/api/diffusion_pipeline#diffusers.DiffusionPipeline.components) 関数を用いてパイプライン間で共有できます。
- すべてのパイプラインは、[`DiffusionPipeline.from_pretrained`](https://huggingface.co/docs/diffusers/main/en/api/diffusion_pipeline#diffusers.DiffusionPipeline.from_pretrained) 関数によって読み込める必要があります。
- すべてのパイプラインには、`__call__` メソッド経由で実行するための方法が1つだけ、かつ1つだけ存在する必要があります。`__call__` の引数の命名は、すべてのパイプライン間で一貫性を持たせる必要があります。
- Pipelines は、解決しようとするタスクにちなんで命名されるべきです。

### モジュール型 Diffusers

Modular Diffusers は、標準的なパイプラインの代替として、コンポーザブルなアプローチを提供します。再利用可能な*パイプラインブロック*からワークフローを構築し、それらを組み合わせ、交換、共有できます。標準的なパイプラインは、モデルとスケジューラーの使用方法を示す緩やかな参考例です。Modular Diffusers は、Diffusers の上に機能完全なユーザーインターフェースを構築するための推奨される方法であり、コミュニティが分散的な形で新しいパイプラインを構築・共有するための基盤です。

以下の設計原則が遵守されています:
- Modular pipelines は単一ファイルポリシーに従います。それぞれは [src/diffusers/modular_pipelines/](https://github.com/huggingface/diffusers/tree/main/src/diffusers/modular_pipelines) 配下の独自のフォルダに配置され、そのフォルダ内でワークフローをステージごとに1ファイルずつに分割します: `encoders.py`、`before_denoise.py`、`denoise.py`、および `decoders.py`。さらに2つのファイルでパイプラインが完成します。`modular_blocks_<model>.py` が各ステージを組み立て、`modular_pipeline.py` がモデルごとの [ModularPipeline](/docs/diffusers/v0.43.0/ja/api/modular_diffusers/pipeline#diffusers.ModularPipeline) サブクラスを定義します。Modular pipelines は相互にインポートしません。
- 各モジュラーパイプラインは、[ModularPipelineBlocks](/docs/diffusers/v0.43.0/ja/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks) の集合として定義されます。リーフブロックはステージファイル（`encoders.py`、`before_denoise.py`、`denoise.py`、`decoders.py`）に配置され、`modular_blocks_<model>.py` では [SequentialPipelineBlocks](/docs/diffusers/v0.43.0/ja/api/modular_diffusers/pipeline_blocks#diffusers.SequentialPipelineBlocks) や [AutoPipelineBlocks](/docs/diffusers/v0.43.0/ja/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks) といったコンテナクラスを用いて、それらを完全なワークフローに組み立てます。これにより、`DiffusionPipeline combines` で混在していた2つの概念が分離されます。ブロックは純粋な定義です。入力、出力、コンポーネントの依存関係を宣言しますが、重みを保持せず、単体では実行できません。`.init_pipeline(repo_id)` で作成される [ModularPipeline](/docs/diffusers/v0.43.0/ja/api/modular_diffusers/pipeline#diffusers.ModularPipeline) は、実行可能な対応物です。ブロックをステートレスかつ重みを持たない状態に保つことで、ワークフロー間で自由に組み合わせ、交換、共有できるようになります。
- 新しいタスクをサポートするには、タスク固有のブロックを作成し、既存のブロックと組み合わせ、トップレベルのブロックアセンブリにある`_workflow_map`にワークフローを登録します。単一の`ModularPipeline`は、テキストから画像への変換、画像から画像への変換、インペインティングなど、複数のワークフローをサポートできますが、`DiffusionPipeline`は1つのワークフローのみを実行します。

完全な設計と使用ガイドについては、[Modular Diffusers ドキュメント](../modular_diffusers/overview)を参照してください。

### モデル

モデルは、[PyTorchのModuleクラス](https://pytorch.org/docs/stable/generated/torch.nn.Module.html)の自然な拡張として設計された、設定可能なツールボックスです。*単一ファイルポリシー*に従う必要があります。この慣例より前に作成された一部の古いモデルは、そのまま維持されています。これらは新しいモデルで模倣すべきパターンではなく、レガシーな例外として扱ってください。例えば、元の[UNet2DConditionModel](/docs/diffusers/v0.43.0/ja/api/models/unet2d-cond#diffusers.UNet2DConditionModel)クラスは、複数のUNetバリエーションに使用されていました。

以下の設計原則が遵守されています:
- 各モデルアーキテクチャのタイプは、[src/diffusers/models](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models) 配下の個別のフォルダに配置されています。例えば [transformers/](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/transformers)、[autoencoders/](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/autoencoders)、または [unets/](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/unets) などです。各モデルファミリーには、そのフォルダ内に専用のファイルが用意されており、[transformer_flux.py](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_flux.py) や [transformer_wan.py](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_wan.py) などが該当します。
- モデルは単一ファイルポリシーに従います。各モデルファイルは自己完結型であるべきですが、タイムステップ埋め込みや正規化レイヤーなど、すべてのモデルが同一に使用する標準モジュールの少数を除きます。それらは [embeddings.py](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/embeddings.py) および [normalization.py](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/normalization.py) からインポートしてください。
- モデルは、PyTorchの`Module`クラスと同様に、複雑さを明示的に公開し、明確なエラーメッセージを提供することを意図しています。
- すべてのモデルは`ModelMixin`と`ConfigMixin`を継承します。
- モデルは、大幅なコード変更を必要とせず、後方互換性を保ちながら、メモリや計算リソースに大きな改善をもたらす場合に、パフォーマンスの最適化を行うことができます。
- モデルは、デフォルトで最高精度かつ最低パフォーマンスの設定を持つべきです。
- 既存のモデルアーキテクチャに類似した新しいモデルアーキテクチャを統合するには、既存のファイルをコピーして起点とし、それに基づいて適応させます。同一のままのレイヤーには [`# Copied from`](./contribution#copied-from-mechanism) アノテーションを付与し、`make fix-copies` によってそれらが同期されるようにします。

### スケジューラー

**単一ファイルポリシー**を厳密に遵守した個別クラスとして設計されており、読み込み可能な設定ファイルを持つ Scheduler は、推論時のノイズ除去プロセスの制御と、学習時のノイズスケジュールの定義を担当します。

以下の設計原則が遵守されています:
- すべてのスケジューラは、[`src/diffusers/schedulers`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/schedulers) にあります。
- Scheduler は大きな utils ファイルからのインポートが**許可されていません**。非常に自己完結型に保たれる必要があります。
- 1つのスケジューラ用のPythonファイルは、1つのスケジューラアルゴリズム（論文などで定義されるもの）に対応します。
- スケジューラが類似した機能を持つ場合、`# Copied from` メカニズムを活用できます。
- すべての Scheduler は `SchedulerMixin` と `ConfigMixin` を継承しています。
- [`ConfigMixin.from_config`](https://huggingface.co/docs/diffusers/main/en/api/configuration#diffusers.ConfigMixin.from_config) メソッドを使用することで、スケジューラーを簡単に交換できます。詳細は[こちら](../using-diffusers/schedulers)を参照してください。
- すべてのスケジューラには、`set_num_inference_steps` と `step` 関数が必要です。`set_num_inference_steps(...)` は、すべてのノイズ除去プロセスの前に、*つまり* `step(...)` が呼び出される前に呼び出す必要があります。
- すべてのスケジューラは、`timesteps` 属性を通じて、ループで反復されるべきタイムステップを公開します。これは、モデルが呼び出されるタイムステップの配列です。
- `step(...)` 関数は、予測されたモデルの出力と「現在の」サンプル (x_t) を受け取り、「前の」、わずかにノイズ除去されたサンプル (x_t-1) を返します。
- 拡散スケジューラーの複雑さから、`step`関数はすべての複雑さを公開しておらず、ある種の「ブラックボックス」になり得ます。
- ほぼすべての場合において、新しいスケジューラーは新しいスケジューリングファイルに実装されるべきです。

