- Authors
- Name
- 1. 論文概要
- 2. 背景:熱力学から生成モデルへ
- 3. Forward Process:体系的にノイズを追加する
- 4. 核心数学:Reparameterization Trick
- 5. Reverse Process:ノイズから画像を復元する
- 6. 学習目標の導出:ELBOからSimplified Lossへ
- 7. ノイズスケジューリング:$\beta_t$の設計
- 8. サンプリングアルゴリズム
- 9. アーキテクチャ:Time-conditioned U-Net
- 10. 実験結果
- 11. 後続研究の総整理:Diffusionの進化
- 12. PyTorchコード例:簡単なDDPM実装
- 13. Diffusion Model vs GAN vs VAE:比較分析
- 14. Diffusion Modelの現在と未来
- 15. References
1. 論文概要
「Denoising Diffusion Probabilistic Models」(DDPM)は2020年のNeurIPSで発表された論文で、UC BerkeleyのJonathan Ho、Ajay Jain、Pieter Abbeelが共同執筆した。この論文は拡散確率モデル(Diffusion Probabilistic Model)を通じて高品質な画像合成が可能であることを実証的に示した記念碑的な研究である。
核心アイデアは驚くほどシンプルだ。データに段階的にガウシアンノイズを追加するForward Processと、このノイズを段階的に除去して元のデータを復元するReverse Processを学習するのである。最終的な学習目標は「モデルが予測したノイズ」と「実際に追加されたノイズ」間の単純なMSE損失に帰結する。
DDPMはCIFAR-10でFID 3.17、Inception Score 9.46を達成し、当時のGANベースモデルと同等以上の性能を示した。さらに重要なのは、この論文がその後のDALL-E 2、Imagen、Stable Diffusion、Midjourneyなど現代の画像生成AIの土台となったという事実である。
論文情報
- タイトル: Denoising Diffusion Probabilistic Models
- 著者: Jonathan Ho, Ajay Jain, Pieter Abbeel
- 学会: NeurIPS 2020
- arXiv: 2006.11239
- 公式コード: hojonathanho/diffusion
2. 背景:熱力学から生成モデルへ
2.1 非平衡熱力学からのインスピレーション
Diffusion Modelの知的起源は非平衡統計力学(Non-equilibrium Thermodynamics)にある。物理学における拡散(Diffusion)とは、粒子が濃度の高い場所から低い場所へランダムに移動し、最終的に熱的平衡状態(最大エントロピー)に到達する過程を指す。この過程の核心的な洞察は以下の通りである。
- Forward:複雑な構造を持つ状態 無秩序な平衡状態(情報の破壊)
- Reverse:平衡状態 構造を持つ状態への復元(情報の生成)
Sohl-Dickstein et al.(2015)がこのアイデアを初めて機械学習に適用し、「Deep Unsupervised Learning using Nonequilibrium Thermodynamics」を発表した。複雑なデータ分布をシンプルな既知の分布(ガウシアン)に変換する拡散過程を定義し、その逆過程を学習すれば生成モデルになるというものである。
2.2 Score Matchingとの接続
Diffusion Modelのもう一つの理論的支柱はScore Matchingである。Score functionは対数確率密度の勾配として定義される。
このscore functionを推定できれば、Langevin Dynamicsを通じてサンプルを生成できる。
Yang SongとStefano Ermon(2019)は「Generative Modeling by Estimating Gradients of the Data Distribution」でNoise Conditional Score Networks(NCSN)を提案し、さまざまなノイズレベルでのscore functionを推定する方法を提示した。Ho et al.のDDPMはこのScore Matching観点と深く結びついており、論文でも「denoising score matching with Langevin dynamicsとの新たな接続」を核心的貢献として言及している。
2.3 SDE観点:統一フレームワーク
Song et al.(2021)は「Score-Based Generative Modeling through Stochastic Differential Equations」でDDPMとScore Matchingを確率微分方程式(SDE)という統一フレームワークで結びつけた。Forward Processを連続時間SDEで記述すると以下の通りである。
ここではdrift coefficient、はdiffusion coefficient、は標準Wiener processである。このSDEに対応する逆時間SDEが存在する。
核心は、逆方向SDEを解くために必要なものが時間に依存するscore function のみであるという点だ。DDPMのノイズ予測ネットワークは、実質的にこのscore functionを推定することと等価である。
この関係がDDPMとScore Matchingを理論的に統合する核心的なつながりである。
3. Forward Process:体系的にノイズを追加する
3.1 マルコフ連鎖としてのForward Process
Forward Process(またはDiffusion Process)は元のデータに段階的にガウシアンノイズを追加する固定マルコフ連鎖である。学習可能なパラメータはなく、事前に定義されたVariance Schedule によって完全に決定される。
各時間ステップでの遷移確率は以下のように定義される。
これを展開すると、各ステップで前の時点のデータを倍に縮小し、分散のガウシアンノイズを追加するということである。
**なぜでスケーリングするのか?**各ステップで全体の分散が保存されるようにするためである。の分散が1であれば、の分散はであり、分散のノイズを加えると全体の分散はとなる。
が十分に大きくが適切に設定されると、はほぼ純粋な等方性ガウシアンノイズに収束する。
3.2 全体Forward Process
ステップにわたる全体Forward Processの結合分布は以下の通りである。
これはマルコフ性による もので、各ステップが直前のステップにのみ依存する。DDPMではを使用し、からまで線形的に増加させる。
4. 核心数学:Reparameterization Trick
4.1 任意の時間へ一度にジャンプ
Forward Processの最も強力な数学的性質は、から任意の時間でのを中間ステップを経ずに直接計算できるということである。これが学習を効率的にする核心である。
まず表記法を定義する。
はの累積積で、時間まで元の信号がどれだけ保存されているかを表す。
4.2 導出過程
から始めて帰納的に導出してみよう。
をに代入すると、
ここで独立ガウシアンの和の法則を適用する。2つの独立ガウシアンとの和はに従う。
ノイズ項の分散を合算すると、
したがって、
これを一般化すると以下の通りである。
4.3 最終結果:閉形式表現
すなわち、任意の時間でのを以下のように一度にサンプリングできる。
この式の意味を直感的に解釈すると以下の通りである。
| 項 | 意味 | 時間に伴う変化 |
|---|---|---|
| 元の信号(signal) | なら 、信号減少 | |
| 追加ノイズ | なら 、ノイズ増加 |
のときなのでそのままであり、のときなのでほぼ純粋なノイズとなる。この**Signal-to-Noise Ratio(SNR)**の段階的な減少がForward Processの本質である。
5. Reverse Process:ノイズから画像を復元する
5.1 Reverse Processの定義
Reverse Processは純粋なノイズから始めて段階的にノイズを除去しながらデータを生成する過程である。Forward Processの各ステップが小さなガウシアン摂動であるなら、その逆過程もガウシアンで近似できるというのが核心的な仮定である。(が十分に小さいとき)
ここでとはニューラルネットワークが学習すべき平均と分散である。DDPMでは分散を学習せずに固定し、またはを使用する。
5.2 Posterior の導出
学習の核心は、が与えられたときの逆方向条件付き分布(posterior)が閉形式で計算可能だという点にある。ベイズの定理を適用すると、
マルコフ性によりなので、3項すべてがガウシアンである。ガウシアンの積もガウシアンなので、指数部分を展開してに対する二次式で整理すると以下を得る。
ここでposterior平均は、
posterior分散は、
5.3 をに置換
モデルはを直接知ることができないので、Reparameterization公式を逆に解いてを表現する。
これをposterior平均に代入すると、
モデルがノイズを予測するネットワークを学習すれば、Reverse Processの平均は以下のように計算される。
これがDDPMのReverse Processにおいてノイズ予測が平均予測と等価になる理由である。
6. 学習目標の導出:ELBOからSimplified Lossへ
6.1 最大尤度とELBO
生成モデルの究極的な目標はデータの対数尤度を最大化することである。しかしこれを直接計算することは困難なので、変分下限(Evidence Lower Bound, ELBO)を最適化する。
Jensenの不等式を適用すると、
6.2 ELBOの分解
ELBOをKL divergence項に分解すると以下の通りである。
各項の意味を分析すると以下の通りである。
(Prior Matching):が事前分布とどれだけ一致するかを測定する。が十分に大きければこの項は0に収束し、学習可能なパラメータがないため定数として無視する。
(Reconstruction):からを復元する能力を測定する。とが非常に類似しているため、全体の学習に及ぼす影響は小さい。
(Denoising Matching):モデルのReverse遷移が実際のposterior とどれだけ一致するかを測定する核心的な学習信号である。
6.3 KL Divergenceの計算
2つのガウシアン間のKL divergenceは閉形式で計算可能である。かつなので、
ここでは分散関連の定数項である。分散を固定すれば平均の差だけが学習目標となる。
6.4 ノイズ予測への再パラメータ化
先に導出したとの表現を代入すると、
重み係数を除去したSimplified Lossは以下の通りである。
ここで、、である。
これがDDPMの最も重要な貢献である。複雑なELBOから出発して、最終的に**「実際のノイズと予測ノイズのMSE」**という機械学習で最もシンプルな損失関数に到達した。実験的にもこのsimplified lossが重み付きのvariational boundよりも良いサンプル品質を生成する。
6.5 学習アルゴリズムの要約
Algorithm 1: Training
─────────────────────────────────
repeat
x_0 ~ q(x_0) # データセットからサンプル
t ~ Uniform({1, ..., T}) # ランダム時間ステップを選択
ε ~ N(0, I) # 標準ガウシアンノイズをサンプル
x_t = √ᾱ_t · x_0 + √(1-ᾱ_t) · ε # ノイズ画像を生成
∇_θ ||ε - ε_θ(x_t, t)||² # 勾配計算と更新
until converged
7. ノイズスケジューリング:の設計
7.1 Linear Schedule(DDPMオリジナル)
Ho et al.はをからまで線形的に増加させるスケジュールを使用した。
このスケジュールの直感は、初期には小さなノイズを追加してデータ構造を徐々に破壊し、後半にはより大きなノイズを追加して素早くガウシアンに収束させるというものである。
7.2 Linear Scheduleの問題点
Nichol & Dhariwal(2021、「Improved Denoising Diffusion Probabilistic Models」)はLinear Scheduleの2つの問題を指摘した。
第一に、初期に情報が早く破壊されすぎる。が初期に急激に減少するため、の低い値でもすでにかなりのノイズが追加される。これは特に高解像度画像で問題となる。
第二に、後半の時間ステップが浪費される。が大きい値ではで、がすでに純粋なノイズに近く、学習に有意義な寄与をしない。
7.3 Cosine Schedule
Nichol & Dhariwalが提案したCosine Scheduleはを直接定義する。
ここでは小さなオフセットで、付近でが小さくなりすぎるのを防ぐ。
Cosine Scheduleの核心的な特性は以下の通りである。
- が中盤でほぼ線形に減少し、すべての時間ステップで均等に有用な学習信号を提供する
- 初期に過剰なノイズが追加されるのを防ぎ、細かいディテールが保存される
- 後半部でも完全なノイズへの遷移が滑らかに行われる
import torch
import math
def cosine_beta_schedule(timesteps, s=0.008):
"""Cosine schedule as proposed in Nichol & Dhariwal (2021)."""
steps = timesteps + 1
t = torch.linspace(0, timesteps, steps) / timesteps
alphas_cumprod = torch.cos((t + s) / (1 + s) * math.pi * 0.5) ** 2
alphas_cumprod = alphas_cumprod / alphas_cumprod[0]
betas = 1 - (alphas_cumprod[1:] / alphas_cumprod[:-1])
return torch.clip(betas, 0.0001, 0.9999)
def linear_beta_schedule(timesteps, beta_start=1e-4, beta_end=0.02):
"""Linear schedule as proposed in Ho et al. (2020)."""
return torch.linspace(beta_start, beta_end, timesteps)
7.4 スケジュール比較
| 属性 | Linear Schedule | Cosine Schedule |
|---|---|---|
| 減少パターン | 初期急激、後半緩やか | 中盤でほぼ線形 |
| 初期の情報保存 | 低い | 高い |
| 後半時間ステップの活用 | 非効率的(すでに純粋ノイズ) | 効率的 |
| 高解像度画像への適合性 | 低い | 高い |
| オリジナルDDPM使用 | O | X |
| Improved DDPM使用 | X | O |
8. サンプリングアルゴリズム
8.1 DDPM Sampling
学習完了後、新しい画像を生成するDDPMサンプリングアルゴリズムは以下の通りである。
Algorithm 2: Sampling
─────────────────────────────────
x_T ~ N(0, I) # 純粋ノイズから開始
for t = T, T-1, ..., 1:
z ~ N(0, I) if t > 1, else z = 0 # 最終ステップではノイズ追加なし
x_{t-1} = 1/√α_t · (x_t - β_t/√(1-ᾱ_t) · ε_θ(x_t, t)) + σ_t · z
return x_0
8.2 ステップごとの解釈
Step 1: 初期化。から純粋なガウシアンノイズをサンプリングする。これが生成プロセスの出発点である。
**Step 2: ノイズ予測。**現在のノイズ画像と時間ステップをネットワークに入力し、に含まれるノイズを予測する。
**Step 3: 平均計算。**予測されたノイズを使用してReverse遷移の平均を計算する。
**Step 4: 確率的遷移。**計算された平均にスケーリングされたガウシアンノイズを追加してを生成する。最終ステップ()ではノイズを追加しない。
Step 5: 反復。からまで上記の過程を繰り返す。
8.3 サンプリングの限界
DDPMサンプリングの最大の欠点は速度である。ステップの逐次的ノイズ除去が必要なため、単一画像の生成にも1000回のニューラルネットワーク順伝播が必要である。これはGANの単一順伝播に比べて極めて遅く、以降DDIM、DPM-Solverなどの高速サンプラー研究を促した。
9. アーキテクチャ:Time-conditioned U-Net
9.1 U-Netベース設計
DDPMのノイズ予測ネットワークはU-Netアーキテクチャを基盤としている。U-Netはもともと医療画像セグメンテーションのためにRonneberger et al.(2015)が提案した構造で、Encoder-Decoder構造にSkip Connectionを追加してさまざまな解像度の特徴を結合するのが特徴である。
DDPMのU-NetはPixelCNN++の構造を基盤とし、以下の修正を加えた。
9.2 核心構成要素
Time Embedding:時間ステップをネットワークに注入するためにTransformerのSinusoidal Positional Encodingを使用する。
このembeddingはMLPを経て各ResNet Blockに注入される。具体的には、time embeddingを線形変換した後、ResNet Blockの中間feature mapに加算する(additive)かスケーリングする(FiLM conditioning)方式で適用する。
ResNet Block:各ブロックは以下の順序で構成される。
- Group Normalization
- SiLU(Swish)Activation
- Convolution
- Time Embedding注入
- Group Normalization
- SiLU Activation
- Dropout
- Convolution
- Residual Connection
Self-Attention:解像度のfeature mapでMulti-Head Self-Attentionを適用する。空間次元を系列長に展開して標準的なScaled Dot-Product Attentionを実行する。
Group Normalization:Batch Normalizationの代わりにGroup Normalizationを使用する。バッチサイズに依存せず、生成モデルでより安定した学習を提供する。
9.3 具体的なアーキテクチャ仕様
入力: x_t ∈ R^(C×H×W), t ∈ {1,...,T}
Encoder:
[128] → [128] → ↓2 →
[256] → [256] → ↓2 →
[256] → [256] → ↓2 → (+ Self-Attention at 16×16)
[512] → [512] → ↓2
Bottleneck:
[512] → Self-Attention → [512]
Decoder (with skip connections):
[512] → [512] → ↑2 →
[256] → [256] → ↑2 → (+ Self-Attention at 16×16)
[256] → [256] → ↑2 →
[128] → [128] → ↑2
出力: ε_θ ∈ R^(C×H×W) (入力と同一次元の予測ノイズ)
DDPMは解像度で約114Mパラメータを使用した。
10. 実験結果
10.1 定量的評価
DDPMは以下のベンチマークで評価された。
CIFAR-10(Unconditional, ):
| モデル | FID () | IS () |
|---|---|---|
| DDPM | 3.17 | 9.46 |
| StyleGAN2 + ADA | 2.92 | 9.83 |
| NCSN | 25.32 | 8.87 |
| ProgressiveGAN | 15.52 | 8.80 |
| NVAE | 23.5 | - |
DDPMは当時のunconditional生成モデルの中でSOTA FIDを達成し、GANベースのStyleGAN2と比較可能な水準の品質を示した。
LSUN ():
| データセット | FID |
|---|---|
| LSUN Bedroom | 4.90 |
| LSUN Cat | - |
| LSUN Church | 7.89 |
10.2 定性的分析
DDPMのサンプルはGANと比較していくつかの顕著な特性を示した。
高い多様性:GANはmode collapse問題により生成の多様性が制限されるのに対し、DDPMはデータ分布のさまざまなモードをバランスよくカバーする。
段階的生成:ノイズから画像への段階的な変換過程を可視化でき、モデルがまず全体構造を形成し、その後細部ディテールを追加するcoarse-to-fine生成パターンを確認できる。
安定した学習:GANの慢性的な問題である学習不安定性(mode collapse、training oscillation)がなく、シンプルなMSE損失で安定的に収束する。
10.3 Progressive Lossy Compression解釈
Ho et al.はDDPMが自然に段階的損失圧縮スキーム(Progressive Lossy Decompression)を実装すると解釈した。各Reverseステップで段階的に情報が追加され、これはAutoregressive Decodingの一般化と見なすことができる。Rate-Distortion曲線分析で、大部分のビットが知覚的に無意味な細部よりも全体構造に割り当てられることを確認した。
11. 後続研究の総整理:Diffusionの進化
11.1 DDIM(Denoising Diffusion Implicit Models)
Song et al., 2021 | arXiv: 2010.02502
DDPMの最大の限界である遅いサンプリング速度を解決した研究。核心アイデアはForward ProcessをNon-Markovianに一般化することである。
DDIMは同一の学習済みモデルを使用しながら、サンプリング過程のみを変更する。
に設定すると完全に決定論的なサンプリングとなり、以下を得る。
- 高速サンプリング:ステップの代わりに50〜100ステップで同等品質の画像を生成(10〜20倍の高速化)
- 意味論的補間:決定論的マッピングのおかげでlatent spaceでの補間が意味のある画像変換につながる
- 一貫性:同一の初期ノイズから常に同一の画像を生成し、再現可能な結果を保証する
11.2 Improved DDPM
Nichol & Dhariwal, 2021 | arXiv: 2102.09672
オリジナルDDPMの2つを改善した研究。
学習可能な分散:DDPMはをまたはに固定したが、Improved DDPMはこれを学習可能にした。具体的には、をとの補間としてパラメータ化する。
ここではネットワークが出力する値である。
Cosine Schedule:先述のCosine Variance Scheduleを導入し、特に高解像度画像での学習効率を大幅に改善した。
Hybrid Loss:にvariational lower bound を少量追加してlog-likelihoodも改善した。
11.3 Classifier Guidance
Dhariwal & Nichol, 2021 | arXiv: 2105.05233
「Diffusion Models Beat GANs on Image Synthesis」で提案された技法で、事前学習された分類器の勾配をReverse Processに注入して条件付き生成を行う。
ここではguidance scale、はノイズ画像に対して学習された分類器である。を増加させると多様性は減少するが特定クラスへの忠実度(fidelity)は向上する。この論文でDiffusion Modelが初めてFIDでGANを凌駕した(CIFAR-10 FID 2.97、ImageNet 256x256 FID 4.59)。
限界:別途の分類器をノイズデータに対して学習する必要があり、学習パイプラインが複雑になる。
11.4 Classifier-Free Guidance(CFG)
Ho & Salimans, 2022 | arXiv: 2207.12598
別途の分類器なしでguidance効果を得る革新的な技法で、現代のDiffusion Modelの事実上の標準となった。
核心アイデアは1つのネットワークが条件付きと無条件の生成を両方学習することである。学習時に一定確率(通常10〜20%)で条件情報をnullトークンに置換する。
推論時、条件付き予測と無条件予測を線形結合する。
ここではguidance weightである。なら標準的な条件付き生成、なら条件への忠実度が増加する。
これを再配列すると以下のように解釈できる。
無条件予測から条件方向に押し出すものとして解釈でき、が大きいほどこの押し出す力が強くなる。DALL-E 2、Stable Diffusion、Imagenなどほぼすべての最新Text-to-ImageモデルがCFGを使用している。
11.5 Latent Diffusion Models(LDM)/ Stable Diffusion
Rombach et al., 2022 | arXiv: 2112.10752
LDMはDiffusion Processを**ピクセル空間ではなく潜在空間(Latent Space)**で実行することで計算効率を劇的に改善した研究。
核心構造:
Perceptual Compression:事前学習されたAutoencoder(VQ-VAEまたはKL-regularized VAE)のEncoder で画像を低次元latent に圧縮する。一般的にの画像がのlatentに圧縮される(約48倍の次元削減)。
Latent Diffusion:このlatent spaceでDDPMのForward/Reverse Processを実行する。計算量がピクセル空間対比で大幅に削減される。
Cross-Attention Conditioning:テキスト、セグメンテーションマップなどの条件情報をCross-Attentionを通じてU-Netに注入する。テキストの場合CLIPまたはBERTの埋め込みを使用する。
ここで、、であり、は条件情報のエンコーディングである。
Stable DiffusionはこのLDMアーキテクチャにCLIP text encoderと大規模データセット(LAION-5B)を組み合わせて学習したもので、オープンソースText-to-Imageモデルの事実上の標準となった。
11.6 Score SDE
Song et al., 2021 | arXiv: 2011.13456
ICLR 2021 Oral発表のこの研究は、DDPMとScore Matchingを確率微分方程式(SDE)という統一フレームワークで接続した。
核心的な貢献は以下の通りである。
- Variance Exploding(VE)SDE:NCSN/SMLD系列に対応
- Variance Preserving(VP)SDE:DDPMに対応
- Sub-VP SDE:より良いlikelihoodを提供する変形
連続時間への拡張を通じて、正確なlog-likelihood計算(ODEを通じて)、より柔軟なサンプラー設計、およびInpainting、Colorizationなどの条件付き生成が可能になった。
11.7 Consistency Models
Song et al., 2023 | arXiv: 2303.01469
OpenAIのYang Songが提案したConsistency Modelsは、Diffusion Modelの多段階サンプリング問題を根本的に解決しようとする試みである。
核心アイデアはODE trajectory上のすべての点を同一の出発点(元のデータ)にマッピングする関数を学習することである。
このself-consistency特性により、任意の時間のノイズサンプルから1回のネットワーク評価でデータを復元できる。すなわち、1ステップ生成が可能である。
2つの学習方式がある。
- Consistency Distillation(CD):事前学習されたDiffusion Modelから蒸留
- Consistency Training(CT):事前学習なしで独立に学習
2024年には**Easy Consistency Models(ECM)**が登場し、iCT対比33%の学習コストでより良い2ステップ生成性能を達成した。
11.8 Flow Matching / Rectified Flow
Lipman et al., 2023; Liu et al., 2023 | arXiv: 2210.02747, arXiv: 2209.03003
Flow MatchingはDiffusion Modelの代替的アプローチで、データ分布とノイズ分布を接続する**確率フロー(Probability Flow)**を直接学習する。
核心アイデア:ノイズからデータへの直線経路(straight path)を定義する。
この経路に沿う速度場(velocity field)を学習する。
Rectified Flowはこの直線経路を「まっすぐにする」過程を反復(reflow)し、少ないステップでも高品質のサンプルを生成する。
Stable Diffusion 3がRectified Flowを採用し、U-NetからTransformerへの転換とともにDiffusion Modelの新たなパラダイムを提示した。
11.9 DiT(Diffusion Transformer)
Peebles & Xie, 2023 | arXiv: 2212.09748
DiTはDiffusion ModelのbackboneをU-Netから**Vision Transformer(ViT)**に置き換えた研究である。
核心的な設計選択:
- 画像をパッチに分割してトークンとして処理
- 時間ステップとクラスラベルを**Adaptive Layer Normalization(adaLN-Zero)**で注入
- 層のTransformer Blockで構成
DiTはLatent Diffusionと組み合わせて、ImageNet class-conditional生成でFID 2.27を達成し、以前のすべてのDiffusion Modelを凌駕した。
DiTの意義:Transformerのscaling lawをDiffusion Modelに適用できることを実証した。モデルサイズと学習コンピュートを増加させると一貫して性能が向上する。この発見はSora(OpenAI、Video生成)、Stable Diffusion 3など最新の大規模生成モデルのアーキテクチャ選択に直接的な影響を与えた。
12. PyTorchコード例:簡単なDDPM実装
以下はDDPMの核心構成要素をPyTorchで実装した簡素化された例である。実際の学習にはより精巧なU-Netとハイパーパラメータチューニングが必要である。
12.1 Noise ScheduleとForward Process
import torch
import torch.nn as nn
import torch.nn.functional as F
import math
class DDPMScheduler:
"""DDPMのForward Processを管理するスケジューラ。"""
def __init__(self, num_timesteps=1000, beta_start=1e-4, beta_end=0.02, schedule='linear'):
self.num_timesteps = num_timesteps
if schedule == 'linear':
self.betas = torch.linspace(beta_start, beta_end, num_timesteps)
elif schedule == 'cosine':
self.betas = self._cosine_schedule(num_timesteps)
else:
raise ValueError(f"Unknown schedule: {schedule}")
# 核心変数の事前計算
self.alphas = 1.0 - self.betas
self.alphas_cumprod = torch.cumprod(self.alphas, dim=0) # ᾱ_t
self.alphas_cumprod_prev = F.pad(self.alphas_cumprod[:-1], (1, 0), value=1.0)
# Forward process係数
self.sqrt_alphas_cumprod = torch.sqrt(self.alphas_cumprod) # √ᾱ_t
self.sqrt_one_minus_alphas_cumprod = torch.sqrt(1.0 - self.alphas_cumprod) # √(1-ᾱ_t)
# Reverse process係数
self.sqrt_recip_alphas = torch.sqrt(1.0 / self.alphas) # 1/√α_t
self.posterior_variance = (
self.betas * (1.0 - self.alphas_cumprod_prev) / (1.0 - self.alphas_cumprod)
) # β̃_t
def _cosine_schedule(self, timesteps, s=0.008):
steps = timesteps + 1
t = torch.linspace(0, timesteps, steps) / timesteps
alphas_cumprod = torch.cos((t + s) / (1 + s) * math.pi * 0.5) ** 2
alphas_cumprod = alphas_cumprod / alphas_cumprod[0]
betas = 1 - (alphas_cumprod[1:] / alphas_cumprod[:-1])
return torch.clip(betas, 0.0001, 0.9999)
def add_noise(self, x_0, t, noise=None):
"""Forward process: q(x_t | x_0)を一度に計算。"""
if noise is None:
noise = torch.randn_like(x_0)
sqrt_alpha_cumprod = self.sqrt_alphas_cumprod[t].view(-1, 1, 1, 1)
sqrt_one_minus_alpha_cumprod = self.sqrt_one_minus_alphas_cumprod[t].view(-1, 1, 1, 1)
# x_t = √ᾱ_t · x_0 + √(1-ᾱ_t) · ε
x_t = sqrt_alpha_cumprod * x_0 + sqrt_one_minus_alpha_cumprod * noise
return x_t
12.2 簡素化されたU-Net
class SinusoidalPositionEmbedding(nn.Module):
"""TransformerスタイルのSinusoidal Time Embedding。"""
def __init__(self, dim):
super().__init__()
self.dim = dim
def forward(self, t):
device = t.device
half_dim = self.dim // 2
emb = math.log(10000) / (half_dim - 1)
emb = torch.exp(torch.arange(half_dim, device=device) * -emb)
emb = t[:, None].float() * emb[None, :]
emb = torch.cat([emb.sin(), emb.cos()], dim=-1)
return emb
class ResBlock(nn.Module):
"""Time-conditioned Residual Block。"""
def __init__(self, in_ch, out_ch, time_emb_dim):
super().__init__()
self.norm1 = nn.GroupNorm(8, in_ch)
self.conv1 = nn.Conv2d(in_ch, out_ch, 3, padding=1)
self.time_mlp = nn.Sequential(
nn.SiLU(),
nn.Linear(time_emb_dim, out_ch),
)
self.norm2 = nn.GroupNorm(8, out_ch)
self.conv2 = nn.Conv2d(out_ch, out_ch, 3, padding=1)
self.skip = nn.Conv2d(in_ch, out_ch, 1) if in_ch != out_ch else nn.Identity()
def forward(self, x, t_emb):
h = self.conv1(F.silu(self.norm1(x)))
h = h + self.time_mlp(t_emb)[:, :, None, None] # Time embedding注入
h = self.conv2(F.silu(self.norm2(h)))
return h + self.skip(x) # Residual connection
class SimpleUNet(nn.Module):
"""DDPM学習のための簡素化されたU-Net。"""
def __init__(self, in_channels=3, base_channels=64, time_emb_dim=256):
super().__init__()
# Time embedding
self.time_mlp = nn.Sequential(
SinusoidalPositionEmbedding(base_channels),
nn.Linear(base_channels, time_emb_dim),
nn.SiLU(),
nn.Linear(time_emb_dim, time_emb_dim),
)
# Encoder
self.enc1 = ResBlock(in_channels, base_channels, time_emb_dim)
self.enc2 = ResBlock(base_channels, base_channels * 2, time_emb_dim)
self.enc3 = ResBlock(base_channels * 2, base_channels * 4, time_emb_dim)
self.pool = nn.MaxPool2d(2)
# Bottleneck
self.bot = ResBlock(base_channels * 4, base_channels * 4, time_emb_dim)
# Decoder (with skip connections)
self.dec3 = ResBlock(base_channels * 8, base_channels * 2, time_emb_dim)
self.dec2 = ResBlock(base_channels * 4, base_channels, time_emb_dim)
self.dec1 = ResBlock(base_channels * 2, base_channels, time_emb_dim)
self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
# Output
self.out = nn.Conv2d(base_channels, in_channels, 1)
def forward(self, x, t):
t_emb = self.time_mlp(t)
# Encoder
e1 = self.enc1(x, t_emb)
e2 = self.enc2(self.pool(e1), t_emb)
e3 = self.enc3(self.pool(e2), t_emb)
# Bottleneck
b = self.bot(self.pool(e3), t_emb)
# Decoder with skip connections
d3 = self.dec3(torch.cat([self.up(b), e3], dim=1), t_emb)
d2 = self.dec2(torch.cat([self.up(d3), e2], dim=1), t_emb)
d1 = self.dec1(torch.cat([self.up(d2), e1], dim=1), t_emb)
return self.out(d1) # 予測ノイズ ε_θ
12.3 学習ループ
def train_ddpm(model, dataloader, scheduler, epochs=100, lr=2e-4, device='cuda'):
"""DDPM学習ループ(Algorithm 1の実装)。"""
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
model.train()
for epoch in range(epochs):
total_loss = 0
for batch_idx, (x_0, _) in enumerate(dataloader):
x_0 = x_0.to(device)
# 1. ランダム時間ステップ選択: t ~ Uniform({1, ..., T})
t = torch.randint(0, scheduler.num_timesteps, (x_0.shape[0],), device=device)
# 2. ノイズサンプリング: ε ~ N(0, I)
noise = torch.randn_like(x_0)
# 3. Forward process: x_t = √ᾱ_t · x_0 + √(1-ᾱ_t) · ε
x_t = scheduler.add_noise(x_0, t, noise)
# 4. ノイズ予測: ε_θ(x_t, t)
noise_pred = model(x_t, t)
# 5. Simplified loss: L = ||ε - ε_θ(x_t, t)||²
loss = F.mse_loss(noise_pred, noise)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
avg_loss = total_loss / len(dataloader)
print(f"Epoch {epoch+1}/{epochs}, Loss: {avg_loss:.4f}")
12.4 サンプリング
@torch.no_grad()
def sample_ddpm(model, scheduler, image_shape, device='cuda'):
"""DDPMサンプリング(Algorithm 2の実装)。"""
model.eval()
# x_T ~ N(0, I)
x = torch.randn(image_shape, device=device)
for t in reversed(range(scheduler.num_timesteps)):
t_batch = torch.full((image_shape[0],), t, device=device, dtype=torch.long)
# ノイズ予測
predicted_noise = model(x, t_batch)
# Reverse process係数
alpha_t = scheduler.alphas[t]
alpha_cumprod_t = scheduler.alphas_cumprod[t]
beta_t = scheduler.betas[t]
# 平均計算: μ_θ = 1/√α_t · (x_t - β_t/√(1-ᾱ_t) · ε_θ)
mean = (1.0 / torch.sqrt(alpha_t)) * (
x - (beta_t / torch.sqrt(1.0 - alpha_cumprod_t)) * predicted_noise
)
if t > 0:
# 確率的ノイズの追加(最終ステップを除く)
noise = torch.randn_like(x)
sigma_t = torch.sqrt(scheduler.posterior_variance[t])
x = mean + sigma_t * noise
else:
x = mean
return x
12.5 使用例
# ハイパーパラメータ
device = 'cuda' if torch.cuda.is_available() else 'cpu'
image_size = 32
batch_size = 128
num_timesteps = 1000
# スケジューラおよびモデルの初期化
scheduler = DDPMScheduler(num_timesteps=num_timesteps, schedule='cosine')
model = SimpleUNet(in_channels=3, base_channels=64).to(device)
# データセット(例:CIFAR-10)
from torchvision import datasets, transforms
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # [-1, 1]正規化
])
dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)
# 学習
train_ddpm(model, dataloader, scheduler, epochs=100, device=device)
# サンプリング
samples = sample_ddpm(model, scheduler, (16, 3, image_size, image_size), device=device)
# samples: [-1, 1]範囲の生成画像16枚
13. Diffusion Model vs GAN vs VAE:比較分析
13.1 総合比較表
| 特性 | Diffusion Model(DDPM) | GAN | VAE |
|---|---|---|---|
| 学習方式 | ノイズ予測(MSE) | 敵対的学習(Min-Max) | 変分推論(ELBO) |
| 学習安定性 | 非常に安定 | 不安定(mode collapse、oscillation) | 安定 |
| 生成品質 | 非常に高い | 非常に高い | 普通(blurry) |
| 多様性 | 高い(分布全体をカバー) | 低い(mode collapseリスク) | 高い |
| 生成速度 | 遅い(1000ステップ) | 非常に速い(1ステップ) | 速い(1ステップ) |
| Log-likelihood | 計算可能(ELBO) | 計算不可 | 計算可能(ELBO) |
| Latent Space | 暗黙的 | なし(または制限的) | 明示的、連続的 |
| モードカバレッジ | 高い | 低い | 高い |
| 条件付き生成 | CFGで非常に効果的 | cGANで可能 | 条件付きVAE可能 |
| 解像度拡張 | LDMで効率的 | 段階的学習が必要 | 階層的VAEが必要 |
| 理論的基盤 | 熱力学、Score Matching | ゲーム理論 | 変分ベイズ |
| 代表モデル | Stable Diffusion, DALL-E 2 | StyleGAN, BigGAN | VQ-VAE-2, NVAE |
| CIFAR-10 FID | ~2.0(最新) | ~2.9(StyleGAN2) | ~23.5(NVAE) |
13.2 いつどのモデルを選択すべきか?
Diffusion Modelを選択する場合:
- 生成品質と多様性の両方が重要なとき
- テキスト-画像生成など複雑な条件付き生成が必要なとき
- 学習安定性が重要なとき
- 生成速度が最優先でないとき
GANを選択する場合:
- リアルタイム生成が必要なとき
- 特定ドメインの高品質画像が必要なとき(顔、風景など)
- データセットが比較的小さく均一なとき
VAEを選択する場合:
- 意味のあるLatent Space操作が必要なとき
- Likelihoodベースの異常値検出が必要なとき
- 高速なエンコード/デコードが必要なとき
- 半教師あり学習または表現学習が主な目的のとき
14. Diffusion Modelの現在と未来
14.1 2024〜2025年の主要な流れ
**アーキテクチャ転換:U-NetからTransformerへ。**Stable Diffusion 3、FLUX、Soraなどの最新モデルはDiTベースアーキテクチャを採用している。TransformerのScaling LawがDiffusion Modelにも適用されることが確認され、モデル規模の拡張(8B以上のパラメータ)が活発に進行中である。
**サンプリング効率化。**Consistency Models、Flow Matching、DPM-Solverなどの発展により1〜4ステップの生成が可能になった。Rectified Flowは直線経路を学習して少ないステップでも高品質を達成する。
マルチモーダル拡張。Diffusion Modelは画像を超えて動画(Sora、Runway Gen-3)、オーディオ(AudioLDM)、3D(DreamFusion、Zero-1-to-3)、ロボティクス(Diffusion Policy)などさまざまなドメインに拡張されている。
**高速化と最適化。**Distillation、Quantization、Cachingなどの技法で推論速度が大幅に向上し、リアルタイム画像生成が可能な水準に近づいている。
14.2 DDPMの歴史的意義
DDPMは以下の点で生成モデル史の転換点である。
- GANが支配していた画像生成分野でLikelihoodベースモデルの競争力を実証した
- 極めてシンプルな学習目標()で高品質生成が可能であることを示した
- 熱力学とScore Matchingを接続する理論的フレームワークを確立した
- Stable Diffusion、DALL-E 2、Midjourneyなど現代AI革命の直接的な土台となった
15. References
Ho, J., Jain, A., & Abbeel, P. (2020). Denoising Diffusion Probabilistic Models. NeurIPS 2020. arXiv:2006.11239
Sohl-Dickstein, J., Weiss, E., Maheswaranathan, N., & Ganguli, S. (2015). Deep Unsupervised Learning using Nonequilibrium Thermodynamics. ICML 2015. arXiv:1503.03585
Song, J., Meng, C., & Ermon, S. (2021). Denoising Diffusion Implicit Models (DDIM). ICLR 2021. arXiv:2010.02502
Nichol, A. & Dhariwal, P. (2021). Improved Denoising Diffusion Probabilistic Models. ICML 2021. arXiv:2102.09672
Dhariwal, P. & Nichol, A. (2021). Diffusion Models Beat GANs on Image Synthesis. NeurIPS 2021. arXiv:2105.05233
Ho, J. & Salimans, T. (2022). Classifier-Free Diffusion Guidance. NeurIPS Workshop 2021. arXiv:2207.12598
Rombach, R., Blattmann, A., Lorenz, D., Esser, P., & Ommer, B. (2022). High-Resolution Image Synthesis with Latent Diffusion Models. CVPR 2022. arXiv:2112.10752
Song, Y., Sohl-Dickstein, J., Kingma, D.P., Kumar, A., Ermon, S., & Poole, B. (2021). Score-Based Generative Modeling through Stochastic Differential Equations. ICLR 2021. arXiv:2011.13456
Song, Y., Dhariwal, P., Chen, M., & Sutskever, I. (2023). Consistency Models. ICML 2023. arXiv:2303.01469
Lipman, Y., Chen, R.T.Q., Ben-Hamu, H., Nickel, M., & Le, M. (2023). Flow Matching for Generative Modeling. ICLR 2023. arXiv:2210.02747
Peebles, W. & Xie, S. (2023). Scalable Diffusion Models with Transformers (DiT). ICCV 2023. arXiv:2212.09748
Song, Y. & Ermon, S. (2019). Generative Modeling by Estimating Gradients of the Data Distribution. NeurIPS 2019. arXiv:1907.05600
Weng, L. (2021). What are Diffusion Models? lilianweng.github.io
Hugging Face. The Annotated Diffusion Model. huggingface.co/blog/annotated-diffusion