はじめに: 世代の新たなフロンティア
I 普及モデル 彼らは世代の最先端として GAN を上回りました 画像、DALL-E、Stable Diffusion、Midjourney などのシステムに電力を供給します。その背後にある考え方 驚くほどシンプルなプロセスです フォワード 徐々にノイズを加えていく 画像が完全に破壊されるまでガウス関数を適用した後、ニューラル ネットワークが学習します。 プロセス 逆行する、ノイズを段階的に除去して再構築します 元のイメージ (または新しいイメージを生成)。
GAN とは異なり、拡散モデルは安定したトレーニングとより多様性のあるトレーニングを提供します。 結果と厳密な確率的フレームワーク。価格と生成プロセスプラス 低速 (数百のノイズ除去ステップ)、DDIM や潜在拡散などの技術によって軽減されます。
何を学ぶか
- 順方向プロセス: ノイズが画像を徐々に破壊する仕組み
- 逆のプロセス: ニューラル ネットワークがノイズを除去する方法を学習する方法
- DDPM: ノイズ除去拡散確率モデル
- DDIM: 少ない手順で高速に生成
- テキストコンディショニング: CLIP を使用してテキストの説明から画像を生成
- 安定拡散:潜在空間での拡散
- ハグフェイスディフューザーの実用化
前進プロセス: ノイズを追加する
Il 前進プロセス 徐々にノイズを追加するマルコフ連鎖 T ステップで画像にガウスを適用します。各ステップ t で、少量のノイズが追加されます。 ある人によると スケジュール デフォルト (線形またはコサイン)。十分な手順を踏んだ上で (通常は T=1000)、元の画像は完全に破壊され、純粋なノイズになります。 ガウス。
基本的な特性は、計算せずに任意のステップ t に直接ジャンプできることです。 閉じた式のおかげで、すべての中間ステップが完了します。
import torch
import torch.nn as nn
import numpy as np
class DiffusionSchedule:
"""Schedule per il processo di diffusione"""
def __init__(self, num_timesteps=1000, beta_start=1e-4, beta_end=0.02):
self.num_timesteps = num_timesteps
# Schedule lineare dei beta
self.betas = torch.linspace(beta_start, beta_end, num_timesteps)
self.alphas = 1.0 - self.betas
# Alpha cumulativo: prodotto di tutti gli alpha fino a t
self.alpha_cumprod = torch.cumprod(self.alphas, dim=0)
self.sqrt_alpha_cumprod = torch.sqrt(self.alpha_cumprod)
self.sqrt_one_minus_alpha_cumprod = torch.sqrt(1.0 - self.alpha_cumprod)
def add_noise(self, x_0, t, noise=None):
"""Forward process: q(x_t | x_0) - aggiunge rumore a x_0"""
if noise is None:
noise = torch.randn_like(x_0)
sqrt_alpha = self.sqrt_alpha_cumprod[t].view(-1, 1, 1, 1)
sqrt_one_minus = self.sqrt_one_minus_alpha_cumprod[t].view(-1, 1, 1, 1)
# x_t = sqrt(alpha_cumprod_t) * x_0 + sqrt(1 - alpha_cumprod_t) * noise
return sqrt_alpha * x_0 + sqrt_one_minus * noise
# Demo: rumore progressivo
schedule = DiffusionSchedule()
image = torch.randn(1, 3, 64, 64) # Immagine originale
for t in [0, 250, 500, 750, 999]:
t_tensor = torch.tensor([t])
noisy = schedule.add_noise(image, t_tensor)
print(f"Step {t}: noise level = {schedule.sqrt_one_minus_alpha_cumprod[t]:.4f}")
逆のプロセス: ノイズを除去する
Il 逆のプロセス そして魔法が起こる場所。ニューラル ネットワーク (通常は 1 つ) ユーネット) 各ステップで追加されるノイズを予測する方法を学習します。純粋なノイズから始める ガウス型では、モデルは T ステップで徐々にノイズを除去し、一貫した画像を生成します。
トレーニングの目標はシンプルです。追加される実際のノイズの差を最小限に抑えることです。 およびネットワークによって予測されるノイズ。この MSE ノイズ損失は非常に効果的であることが証明されています。
class SimpleUNet(nn.Module):
"""U-Net semplificata per noise prediction"""
def __init__(self, channels=3, time_emb_dim=256):
super().__init__()
# Time embedding: trasforma timestep in vettore
self.time_mlp = nn.Sequential(
nn.Linear(1, time_emb_dim),
nn.SiLU(),
nn.Linear(time_emb_dim, time_emb_dim)
)
# Encoder
self.enc1 = self._block(channels, 64)
self.enc2 = self._block(64, 128)
self.enc3 = self._block(128, 256)
# Bottleneck
self.bottleneck = self._block(256, 512)
# Decoder con skip connections
self.dec3 = self._block(512 + 256, 256)
self.dec2 = self._block(256 + 128, 128)
self.dec1 = self._block(128 + 64, 64)
self.final = nn.Conv2d(64, channels, 1)
self.pool = nn.MaxPool2d(2)
self.up = nn.Upsample(scale_factor=2, mode='bilinear')
def _block(self, in_ch, out_ch):
return nn.Sequential(
nn.Conv2d(in_ch, out_ch, 3, padding=1),
nn.GroupNorm(8, out_ch),
nn.SiLU(),
nn.Conv2d(out_ch, out_ch, 3, padding=1),
nn.GroupNorm(8, out_ch),
nn.SiLU()
)
def forward(self, x, t):
# t_emb = self.time_mlp(t.float().unsqueeze(-1))
e1 = self.enc1(x)
e2 = self.enc2(self.pool(e1))
e3 = self.enc3(self.pool(e2))
b = self.bottleneck(self.pool(e3))
d3 = self.dec3(torch.cat([self.up(b), e3], dim=1))
d2 = self.dec2(torch.cat([self.up(d3), e2], dim=1))
d1 = self.dec1(torch.cat([self.up(d2), e1], dim=1))
return self.final(d1)
# Training: predici il rumore
model = SimpleUNet()
schedule = DiffusionSchedule()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
def training_step(x_0):
t = torch.randint(0, 1000, (x_0.size(0),))
noise = torch.randn_like(x_0)
x_t = schedule.add_noise(x_0, t, noise)
noise_pred = model(x_t, t)
loss = nn.functional.mse_loss(noise_pred, noise)
return loss
DDPM と DDIM: 速度 vs 品質
PMDD
Il PMDD (ノイズ除去拡散確率モデル) 内のすべての T ステップを使用します。 サンプリングプロセス、高品質を保証しますが、数百または数千の評価が必要です ネットワークの。
DDIM
Il DDIM (ノイズ除去拡散暗黙的モデル) を使用してサンプリングを高速化します。 ステップをスキップできる非マルコフプロセス。わずか 50 ~ 100 のステップで品質が得られます 1000 ステップの DDPM に匹敵し、生成時間を 10 ~ 20 分の 1 に短縮します。
安定拡散:潜在空間での拡散
安定した拡散 ピクセル空間ではない拡散プロセスを適用します しかし、1つでは 圧縮された潜在空間 (通常は 512x512 ではなく 64x64)。 オートエンコーダ (VAE) は画像を潜在空間に圧縮し、この空間で拡散が機能します。 スペースが削減され、デコーダが最終画像を再構築します。これにより要件が軽減されます 計算コストが約 50 倍になり、コンシューマ GPU での生成が可能になります。
テキストから画像へ: CLIP を使用したコンディショニング
テキストから画像への生成の用途 クリップ (対照言語イメージ事前トレーニング) テキスト プロンプトを、ノイズ除去プロセスを駆動する埋め込みにエンコードします。そこには 分類子を使用しないガイダンス 要求と多様性の遵守のバランスをとる: 価値観 値が高いほど、テキストにより近い画像が生成されますが、変化が少なくなります。
from diffusers import StableDiffusionPipeline
import torch
# Caricare Stable Diffusion
pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16
)
pipe = pipe.to("cuda")
# Generare un'immagine da testo
prompt = "A serene Japanese garden with cherry blossoms, digital art"
image = pipe(
prompt,
num_inference_steps=50,
guidance_scale=7.5 # Classifier-free guidance
).images[0]
image.save("japanese_garden.png")
print(f"Immagine generata: {image.size}")
ControlNet と未来
コントロールネット 生成に正確な空間制御を追加します: ハンドスケッチ、 深度マップ、人間のポーズ、キャニー エッジは生成をガイドし、 モデルがディテールとスタイルを追加しながら、希望の構成を作成します。
生成モデルの分野は急速に進化しています。 一貫性モデル 彼らは約束します ワンステップで生成、 ビデオの拡散 一貫したビデオとテンプレートを生成します マルチモーダルは、テキスト、画像、音声を単一のフレームワークに結合します。
シリーズの次のステップ
- 次の記事では、 強化学習
- エージェントが報酬からどのように学習するかを見ていきます: Q ラーニング、DQN、PPO
- OpenAI Gymnasium で遊び方を学習するエージェントを実装します







