画像生成AIについての調査(2025/4)

# この記事について
最近、GPT-4oの画像生成がすごいという話題を見かけ、近年の画像生成モデルがどのように進化しているのか気になって調べてみました。
結論としては、テキストや画像（さらには他のモダリティも含めて）をそれぞれトークン化し、Transformerによって自己回帰的に入力・生成を行う方式が主流のようです。

## ざっくりとした関連性
**VAE周り**
```mermaid
graph TD

AE
VAE["<u><b>VAE</b></u> <br>・潜在空間に確率分布を導入して生成モデルに"]
VQ-VAE["<u><b>VQ-VAE</b></u> <br>・画像をパッチに分割し、それぞれに離散の潜在表現を割り当て"]
VQ-GAN["<u><b>VQ-GAN</b></u> <br>・VAEにGANのLossを導入<br>・画像の潜在表現をTransformerで自己回帰的に生成"]
ViT-VQGAN["<u><b>ViT-VQGAN</b></u> <br>・エンコーダデコーダをViTに"]

GAN["<u><b>GAN</b></u> <br>・画像を生成するGeneratorと実画像と生成画像を見破るDiscriminatorを敵対的に学習"]

Transformer["<u><b>Transformer</b></u> <br>・Attentionで系列データを処理"]
ViT["<u><b>ViT</b></u> <br>・画像を1Dのパッチ系列にして、Transofrmerに通す"]



Transformer-->ViT-->ViT-VQGAN
Transformer-.->VQ-GAN
GAN-->VQ-GAN

AE-->VAE-->VQ-VAE-->VQ-GAN-->ViT-VQGAN
```

**GPTまわり**
```mermaid
graph TD

BERT["<u><b>BERT</b></u> <br>・事前学習済みTransformer Encoderのファインチューニングで様々なタスクを行える"]
GPT["<u><b>GPT</b></u> <br>・事前学習済みTransformer Decoderのファインチューニングで様々なタスクを行える<br>BERTと違い生成モデルで色々なことができる"]
GPT2["<u><b>GPT2</b></u> <br>・ファインチューニング無しで様々なタスクを行える(zero-shot)"]
GPT3["<u><b>GPT3</b></u> <br>・モデルサイズを巨大化。<br>・プロンプト内に例示や指示を埋め込むだけで新しいタスクに適応可能"]

Transformer-.->BERT-.->GPT-->GPT2-->GPT3
```

**DALL-Eまわり**
```mermaid
graph TD

Diffusion["<u><b>Diffusion</b></u> <br>・拡散モデルで画像を生成"]
GLIDE["<u><b>GLIDE</b></u> <br>・テキスト条件付けの有無を合わせて学習(cfg)<br>・Unetとattentionを組み合わせる"]
DALL-E["<u><b>DALL-E</b></u> <br>・Transformerを使いテキストのエンコード、画像のでコードと一つのストリームとして扱い、自己回帰的に学習"]
DALL-E2["<u><b>DALL-E2</b></u> <br>・prior diffusionでテキストから潜在表現を取得<br>・decoder diffusionで画像生成"]
DALL-E3["<u><b>DALL-E3</b></u> <br>・詳細なキャプションを自動生成して、生成画像のテキスト忠実度向上"]

Diffusion-.->GLIDE
Transformer-.->DALL-E
GLIDE-.->DALL-E2
VQ-VAE-.->DALL-E-->DALL-E2-->DALL-E3
PixelRNN-.->DALL-E
```

**最近の画像生成まわり**
```mermaid
graph TD

Parti["<u><b>Parti</b></u> <br>・テキストから画像を生成する問題を、Sequence-to-Sequence（seq2seq）モデリングとして定式化"]
CM3Leon["<u><b>CM3Leon</b></u> <br>・テキストと画像を統一的なトークン系列で扱える"]
AnyGPT["<u><b>AnyGPT</b></u> <br>・画像・音声・音楽・テキストのすべてのモダリティを離散トークン化し、統一的にLLMで処理可能に"]

ViT-VQGAN-.->Parti
DALL-E-.->Parti
Parti-.->CM3Leon-.->AnyGPT
```

# 以下各技術紹介(by GTP4-o)

## VAE
論文名: Auto-Encoding Variational Bayes
URL: https://arxiv.org/abs/1312.6114	
発表日: 2013-12-20


### ✅ ポイント
- AutoEncoderでは、入力データを**固定ベクトル（潜在変数）**で表現していたが、VAEでは**確率分布（平均と分散）**で表現する。
- 潜在空間からのサンプリングにより、**新しいデータの生成**が可能になり、VAEは**生成モデルとしての能力**を持つ。
- **再パラメータ化トリック**によって、サンプリングを含む処理でも**勾配を通して学習**できるようになった。

### 🧪 学習の疑似コード

```python
# パラメータ初期化
initialize(encoder, decoder)

while not converged:
    x = sample_from_dataset()

    # 平均と log 分散を取得
    μ, logvar = encoder(x)
    std = torch.exp(0.5 * logvar)
    ε = sample_normal(0, 1)
    z = μ + std * ε  # reparameterization trick

    # デコーダで再構成
    x_recon = decoder(z)

    # ロス計算
    loss_recon = loss_fn(x_recon, x)  # 例: binary cross entropy or mean squared error
    loss_kl = -0.5 * torch.sum(1 + logvar - μ.pow(2) - logvar.exp())
    loss = loss_recon + loss_kl

    # パラメータ更新
    update(loss, encoder, decoder)
```

### 🔎 推論時の疑似コード

```python
x = input_sample()
μ, logvar = encoder(x)
std = torch.exp(0.5 * logvar)

# 通常は推論時に z = μ を使う（再現性を保つためノイズなし）
z = μ  
x_recon = decoder(z)
```

### 🧠 モデル例（MNIST）

#### ・Encoder
```text
Input (784次元) → Linear(784→500) → tanh → Linear(500→μ, logσ²) → 出力 μ(200次元), logvar(200次元)
```

#### ・Decoder
```text
Input z (200次元) → Linear(200→500) → tanh → Linear(500→784) → 出力 x(784次元)
```

### ❓ よくある質問

#### Q. なぜ σ ではなく log(σ²)（logvar）を推定するの？

- 分散（σ²）は常に**正の値**である必要があるが、ニューラルネットの出力は正負どちらにもなり得る。
- そのため、log(σ²) を出力しておけば、**実数全体をカバーしながら σ² を安全に得る**ことができる（`σ = exp(0.5 * logvar)`）。
- また、KLダイバージェンスの式にも log(σ²) が登場するため、**計算も簡単かつ安定**になる。

#### Q. なぜ log(σ) の推定ではダメなの？

- `log(σ)` は数学的には可能だが、KLダイバージェンスの計算では `log(σ²)` が必要なので、**2倍するなどの変換が必要になり、実装が煩雑に**なる。
- 勾配の安定性や慣習を考慮しても、**log(σ²)（= logvar）を推定するのが標準的**。

#### Q. 結局、VAEではどんなタスクが解けるの？

- データを「**圧縮 → 再構成**」するだけでなく、**ランダムサンプリングから新しいデータを生成**できる。
- **異常検知**（再構成誤差が大きい入力を検出）、**潜在空間でのクラスタリング・可視化**、**入力の意味的な変換（条件付き生成）** など、幅広い応用が可能。


## GAN
**論文名**: Generative Adversarial Nets  
**URL**: https://arxiv.org/abs/1406.2661  
**発表日**: 2014-06-10  

### ✅ ポイント
- GANは、**生成モデル G** と **識別モデル D** の**敵対的なゲーム**によって訓練される。Gは本物に似たデータを生成しようとし、Dはそれを見破ろうとする。
- 学習は**2プレイヤーのミニマックスゲーム**として定式化される。理想的には、Dは常に正しく判別しようとし、GはDを騙すように学習する。
- 理論的には、**Gが完全に学習されると、本物のデータ分布と同じ分布を生成する**ようになる。
- GANでは**マルコフ連鎖や明示的な確率分布の定義を必要としない**ため、高速かつ柔軟な生成が可能。

### 🧪 学習の疑似コード

```python
# パラメータ初期化
initialize(G, D)

while not converged:
    # 識別器の更新（k回）
    for _ in range(k):
        x_real = sample_real_data()      # 本物データ
        z = sample_noise()               # ノイズ
        x_fake = G(z).detach()           # 生成データ（G固定）

        # 識別器 D の損失（本物: 1, 偽物: 0）
        loss_D = -log(D(x_real)) - log(1 - D(x_fake))
        update(loss_D, D)

    # 生成器の更新（1回）
    z = sample_noise()
    x_fake = G(z)
    # Dを騙すようにGを更新（本物と判定されるように）
    loss_G = -log(D(x_fake))  # 実用的には log(D(G(z)))
    update(loss_G, G)
```

### 🔎 推論時の疑似コード

```python
z = sample_noise()
x_gen = G(z)  # 学習済みの生成器で新しいデータを生成
```

### 🧠 モデル例（MNIST）

#### ・Generator（G）
```text
Input z (100次元) → Linear(100→500) → ReLU → Linear(500→784) → Sigmoid → 出力 x (784次元画像)
```

#### ・Discriminator（D）
```text
Input x (784次元画像) → Linear(784→500) → ReLU → Linear(500→1) → Sigmoid → 出力 D(x)∈[0,1]
```


### ❓ よくある質問

#### Q. GANは何がすごいの？

- 生成結果が**非常にシャープでリアル**。多くの生成モデル（VAE等）が**ぼやけた画像を出力する**のに対し、GANは**鋭い画像が得られる**。
- **明示的な確率密度関数を定義する必要がなく、マルコフ連鎖も不要**なので、学習・生成ともにシンプル。

#### Q. なぜ論文中の`log(1 - D(G(z)))`より `log(D(G(z)))` の方がいいの？
- `log(1 - D(G(z)))` は、Dが強いと勾配が小さくなり、Gの学習が進まない（勾配消失）。
- そのため、Dが「Gを騙された」と感じた分だけ**大きな勾配を得る** `log(D(G(z)))` が実用的。

| D(G(z))の値 | log(1 - D(G(z))) | -log(D(G(z))) | 勾配の大きさ（学習のしやすさ） |
|-------------|------------------|----------------|--------------------------------|
| 0.01（ヘタ）| ≈ log(0.99) ≈ 0.01  | ≈ 4.6          | log(1 - D):小さい（ダメ）<br>log D:大きい（よい） |
| 0.5（まぁまぁ）| ≈ log(0.5) ≈ -0.69 | ≈ 0.69         | 両方まあまあ学習できる        |
| 0.99（成功）| ≈ log(0.01) ≈ -4.6 | ≈ 0.01         | log D:もう十分学習したので勾配は小さい |


#### Q. GANにはどんな課題があるの？

- **モード崩壊**: Gが多様性を失い、似た画像ばかり生成してしまう。
- **訓練が不安定**: GとDのバランスが崩れると学習が破綻しやすい。
- **評価が難しい**: 明示的な確率分布がないため、log-likelihoodのような評価ができない。

#### Q. GANはどんな応用がある？

- 高品質な画像生成（例: 顔画像、風景画など）
- スタイル変換（例: モネ→写真）
- 画像の補完、超解像、データ拡張、異常検知 など


## PixelRNN
**論文名**: Pixel Recurrent Neural Networks  
**URL**: https://arxiv.org/abs/1601.06759  
**発表日**: 2016-01-25

### ✅ ポイント

- **全ての過去ピクセルをコンテキストとして考慮**できるように、**画像の対角方向に沿って情報を伝播**させる2次元LSTM。
- **左上 → 右下**の対角方向に **双方向LSTM（BiLSTM）** を用いることで、**グローバルな依存関係**を捉えることが可能。
- **並列計算**を実現するため、**入力マップをスキュー変換（rowごとにシフト）**し、対角方向の処理を**列方向の畳み込みに置き換え**て実装。
- Masked convolutionとsoftmaxにより、**未来のピクセルやRGBチャネルへの情報漏洩を防ぐ**。
- MNISTでは最も良い負の対数尤度（NLL: 79.20 nats）を記録。


### 🧪 学習の疑似コード（Diagonal BiLSTM）

```python
# 1. モデル初期化
initialize(
    conv7x7_A,                         # 最初の特徴抽出 conv（mask A）
    diag_bilstm_layers,                # Diagonal BiLSTM層
    softmax_layer                      # RGBごとの分類器
)

# 2. 学習ループ
while not converged:
    x = sample_image()  # 例: shape = (H, W, 3)

    # 3. 初期特徴抽出（mask A）
    x_feat = conv7x7_A(x)  # → shape = (H, W, h)

    # 4. skew変換：行ごとに右に1ずつずらして H×(2W-1)
    x_skewed = skew_input(x_feat)  # shape: (H, 2W-1, h)

    # 5. L層のDiagonal BiLSTM
    for layer in diag_bilstm_layers:
        # 入力→状態（共通）
        gate_inputs = conv1x1_input2state(x_skewed)  # → shape: (H, 2W-1, 4h)

        # 左→右の対角方向（BiLSTM）
        h_L, c_L = zeros(), zeros()
        for col in range(2W - 1):
            gate_L = gate_inputs[:, col, :]
            state_L = conv2x1_state2state(h_L)  # 前列方向の状態を畳み込み
            gates = gate_L + state_L
            i, f, o, g = split_gates(gates)
            c_L = f * c_L + i * tanh(g)
            h_L = o * tanh(c_L)
            save h_L into h_L_seq[:, col, :]

        # 右→左方向も同様に
        h_R, c_R = zeros(), zeros()
        for col in reversed(range(2W - 1)):
            gate_R = gate_inputs[:, col, :]
            state_R = conv2x1_state2state(h_R)
            gates = gate_R + state_R
            i, f, o, g = split_gates(gates)
            c_R = f * c_R + i * tanh(g)
            h_R = o * tanh(c_R)
            save h_R into h_R_seq[:, col, :]

        # 右向き出力は1行下にずらして合成
        h_combined = h_L_seq + shift_down(h_R_seq)

        # 残差接続あり
        x_skewed = h_combined + x_skewed

    # 6. skew解除して画像サイズに戻す
    x_processed = unskew(h_combined)

    # 7. RGB×256 softmaxで各ピクセル生成分布
    y_pred = softmax_layer(x_processed)

    # 8. ロスと更新
    loss = cross_entropy(y_pred, x)
    update(loss)
```


### 🔎 推論時の疑似コード（Diagonal BiLSTM）

```python
# 1. 入力初期化（空画像）
x_generated = zeros(H, W, 3)  # RGB画像の空テンソル

# 2. 画像全体を上から下、左から右へ生成
for i in range(H):
    for j in range(W):
        for channel in [R, G, B]:  # RGB順に

            # (1) 現在の部分生成画像を用意
            x_context = x_generated.clone()

            # (2) conv7x7（mask A）で特徴抽出（未来情報遮断）
            feat_map = conv7x7_A(x_context)  # shape: (H, W, h)

            # (3) skew（対角方向を列に変換）
            feat_skewed = skew_input(feat_map)  # shape: (H, 2W-1, h)

            # (4) 各BiLSTM層を順に処理
            for layer in diag_bilstm_layers:
                # 入力→状態（1×1 conv, mask B）
                gate_inputs = conv1x1_input2state(feat_skewed)  # → shape: (H, 2W-1, 4h)

                # 左→右方向
                h_L, c_L = zeros_like_state()
                h_L_seq = zeros(H, 2W-1, h)

                for col in range(2W - 1):
                    gate_L = gate_inputs[:, col, :]
                    state_L = conv2x1_state2state(h_L)  # 前列の状態（2×1 conv）
                    gates = gate_L + state_L
                    i, f, o, g = split_gates(gates)
                    c_L = f * c_L + i * tanh(g)
                    h_L = o * tanh(c_L)
                    h_L_seq[:, col, :] = h_L

                # 右→左方向
                h_R, c_R = zeros_like_state()
                h_R_seq = zeros(H, 2W-1, h)

                for col in reversed(range(2W - 1)):
                    gate_R = gate_inputs[:, col, :]
                    state_R = conv2x1_state2state(h_R)
                    gates = gate_R + state_R
                    i, f, o, g = split_gates(gates)
                    c_R = f * c_R + i * tanh(g)
                    h_R = o * tanh(c_R)
                    h_R_seq[:, col, :] = h_R

                # 右向きは1段下にシフトして加算
                h_combined = h_L_seq + shift_down(h_R_seq)

                # 残差接続
                feat_skewed = h_combined + feat_skewed

            # (5) 最終出力をunskewして元画像サイズに戻す
            feat_final = unskew(h_combined)  # → shape: (H, W, h)

            # (6) RGBごとの softmax 出力（256値）
            logits = softmax_layer(feat_final)  # shape: (H, W, 3×256)

            # (7) 現在位置のchannelに対する分布を抽出しサンプル
            prob = logits[i, j, channel * 256 : (channel + 1) * 256]
            value = sample_from(prob)

            # (8) 生成画像に書き込み
            x_generated[i, j, channel] = value

```


### 🧠 モデル構成（例: MNIST）

#### ・Diagonal BiLSTM（7層, h=16）
```text
Input: (28×28×1)

Conv2D (7×7, Mask A, padding=3)

Layer 1: 
  - Skew input → size = 28×(2×28−1)
  - Input-to-state: 1×1 conv (mask B)
  - State-to-state: 2×1 conv（列方向）

Layers 2〜7:
  - 同様のDiagonal BiLSTMブロック（残差接続あり）

Output:
  - Unskewして元の画像サイズに戻す
  - 1×1 conv → ReLU → 1×1 conv
  - Sigmoid（MNIST）または Softmax（カラー画像）
```


### ❓ よくある質問

#### Q. なぜskew（斜めにシフト）するの？

- 対角方向に沿った依存関係を **列方向の畳み込みで効率的に処理**するため。
- skew → conv（列方向）→ unskew によって **並列計算と対角依存の両立**を実現。

#### Q. なぜ双方向LSTMを使うの？

- 単方向だと片側のコンテキストしか見れない。
- 双方向にすることで、**対角方向における情報の流れを最大化**できる。
- ただし未来の情報を見ないよう、**片方の出力を1段ずらして加算**している。

#### Q. どんな場面でDiagonal BiLSTMが有効？

- ピクセルの**全領域にわたる依存関係**が重要な場面（例: 画像生成、補完、インペインティング）
- 実験ではPixelCNNやRow LSTMよりも**CIFAR-10やMNISTで高性能**（低bits/dimまたは低NLL）だった。


## Transformer  
**論文名**: Attention Is All You Need  
**URL**: https://arxiv.org/abs/1706.03762  
**発表日**: 2017-06-12

### ✅ ポイント

- **再帰や畳み込みを排除し、Attentionのみで構成**される新しいネットワーク「Transformer」を提案。
- Attentionにより、**系列長に依存せずに全体の依存関係を学習**できる。特に**Self-Attention**により、系列内の関係性を柔軟に捉える。
- **Multi-Head Attention**により、異なる視点での注目が可能となり、表現力が向上。
- 全ての処理が**並列化可能**で、**学習速度と性能が大幅に改善**。
- **位置情報を埋め込み（Positional Encoding）** で補完。RNNが持つ「順序性」を別手法で担保。


### 🧪 学習の疑似コード（翻訳タスク例）

```python
# モデル初期化
initialize(encoder, decoder)

while not converged:
    x_src, x_tgt = sample_parallel_sentences()

    # エンコーダとデコーダの出力取得
    z = encoder(x_src, pos_enc=True)
    y_pred = decoder(x_tgt, z, pos_enc=True)

    # クロスエントロピー + label smoothing
    loss = label_smoothing_cross_entropy(y_pred, x_tgt)

    # 重み更新
    update(loss, transformer)
```


### 🔎 推論時の疑似コード

```python
x_src = input_sentence()
z = encoder(x_src, pos_enc=True)

y_gen = [BOS_token]
while not finished:
    y_partial = decoder(y_gen, z, pos_enc=True)
    next_token = sample(y_partial[-1])
    y_gen.append(next_token)
```


### 🧠 モデル構成（Baseモデル）

#### ・Encoder Layer (6層)
- **Self-Attention (Multi-Head)**
- **Position-wise FFN（ReLU付き2層MLP）**
- 各サブ層に**Residual + LayerNorm**
- 入力には**Positional Encoding**を加算

#### ・Decoder Layer (6層)
- **Masked Self-Attention (Multi-Head)**
- **Encoder-Decoder Attention**
- **Position-wise FFN**
- 同様に Residual + LayerNorm、Positional Encoding使用

#### ・各種サイズ
| 名前 | 値 |
|------|----|
| `d_model` | 512 |
| `d_ff` | 2048 |
| `num_heads` | 8 |
| `head_dim` | 64 (= 512 / 8) |
| `dropout` | 0.1 (base), 0.3 (big) |


### 📊 注意メカニズム（Scaled Dot-Product Attention）

数式（Q: query, K: key, V: value）:
```math
\text{Attention}(Q, K, V) = \text{softmax} \left( \frac{QK^T}{\sqrt{d_k}} \right) V

```
- `Q = XW_Q`, `K = XW_K`, `V = XW_V`
- マルチヘッド: 複数の W を使って並列に attention 実行し、結果を concat + 線形変換

---

### ❓ よくある質問

#### Q. なぜ再帰を捨てたの？

- RNNは逐次処理のため**並列化が困難**。
- Self-Attentionでは**全入力を同時に処理可能**で、**計算速度と依存関係の長距離把握**に優れる。

#### Q. Positional Encodingのsin/cosを使うのはなぜ？

- 順序情報が欠落するため、位置に応じた情報を加算。
- sin/cosで周期的なエンコーディングを行い、**系列長を超えた汎化も可能**と仮定。
- 学習済み埋め込みと同程度の性能だが、**固定で使える**という利点がある。


## VQ-VAE  
**論文名**: Neural Discrete Representation Learning  
**URL**: https://arxiv.org/abs/1711.00937  
**発表日**: 2017-11-02  

### ✅ ポイント

- 通常のVAEでは潜在変数を**連続値のベクトル**で表現するが、VQ-VAEでは**離散的なインデックス**として表現し、コードブックからベクトルを選ぶ。
- 離散化には **ベクトル量子化（Vector Quantization, VQ）** を用い、**posterior collapse（潜在変数が無視される問題）を回避**できる。
- 再パラメータ化できない量子化処理に対しては、**straight-through estimator** によって近似的に勾配を通して学習する。
- 潜在変数に対して PixelCNN や WaveNet による **自己回帰的事前分布（prior）** を後付けで学習することで、新たなサンプル生成が可能。
- **音声・画像・映像など多様なドメインで高品質な生成が可能**で、特に無監督で音素のような意味的単位を抽出できることが注目された。

### 🧪 学習の疑似コード（VQ + AutoEncoder）

```python
# 初期化
initialize(encoder, decoder, codebook)  # codebook: (K, D)

while not converged:
    x = sample_from_dataset()

    # エンコーダの出力（連続ベクトル）
    ze = encoder(x)  # shape: (B, H, W, D)

    # コードブックから最近傍インデックスを取得
    k = argmin_j ||ze - e_j||^2  # shape: (B, H, W)
    zq = codebook[k]             # shape: (B, H, W, D)

    # 再構成
    x_recon = decoder(zq)

    # ロス計算（3項）
    loss_recon = loss_fn(x_recon, x)
    loss_vq = ||sg[ze] - e_k||^2         # codebook更新用
    loss_commit = β * ||ze - sg[e_k]||^2 # encoder更新用
    loss = loss_recon + loss_vq + loss_commit

    update(loss, encoder, decoder, codebook)
```

### 🔎 推論時の疑似コード（PixelCNNによる生成）

```python
# 潜在インデックス z ∈ ℤ^{H×W} を自己回帰的にサンプリング
z = zeros(H, W)

for i in range(H):
    for j in range(W):
        logits = pixelcnn(z)
        probs = softmax(logits[:, i, j])
        z[i, j] = sample_from(probs)

# コードブックから埋め込みベクトルを取得
zq = codebook[z]  # shape: (H, W, D)

# デコーダで生成画像を得る
x_hat = decoder(zq)
```

### 🧠 モデル例（CIFAR-10）

#### ・Encoder
```text
Input (32×32×3) → Conv ×2 + Residual Block ×2 → 出力 ze (8×8×D)
```

#### ・Codebook
```text
K=512 個のベクトル e_j ∈ ℝ^D（例: D=64）
```

#### ・Decoder
```text
Input (8×8×D) → Residual Block ×2 + Deconv ×2 → 出力 x_hat (32×32×3)
```

#### ・Prior（後付け）
```text
PixelCNN（8×8×1のインデックスマップに対して p(z) をモデル化）
```

### ❓ よくある質問

#### Q. なぜ離散表現にするの？

- 言語・音声など**本質的に離散的なデータ**に対して適している。
- **解釈性・クラスタリングのしやすさ**が向上。
- VAEでありがちな「潜在を無視する問題（posterior collapse）」を自然に回避できる。

#### Q. 連続VAEより性能が劣るのでは？

- CIFAR-10のlog-likelihood評価では、**連続VAEと同等性能**を達成（例: 4.67 bits/dim）。
- 離散でありながら、自己回帰的priorを活用することで**高品質な生成が可能**。

#### Q. 生成の多様性はコードブックの数に制限されるの？

- いいえ。コードブックの語彙数 K は固定でも、**空間サイズ（例: 32×32）との組み合わせ**で表現力は指数的に増える。
- さらに、PixelCNNで各位置を文脈依存で生成するため、**多様性と整合性を両立**できる。

#### Q. 再パラメータ化トリックは使えないのでは？

- 離散化操作には使えないが、代わりに**straight-through estimator（STE）** で近似的に勾配を通している。
- 勾配は `zq` から `ze` にそのままコピーされる（STE）。


## GPT1
**論文名**: Improving Language Understanding by Generative Pre-Training  
**URL**: https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf  
**発表日**: 2018-06-11  

### ✅ ポイント

- 事前学習済みの**生成的Transformer（GPT）**を、下流の自然言語理解タスクに**微調整（fine-tuning）**。
- タスクごとの入力を1列のトークン列に変換し、追加の**線形層**で出力。
- 必要な変更は**分類ヘッドとトークンの特殊embedding**のみ。
- **自然言語含意、質問応答、文類似度、文分類**など多数のタスクでSOTA。
- 学習時に**言語モデル損失（補助目的）** を加えることで精度と汎化力が向上。

### 🧪 学習の疑似コード（自然言語含意タスク）

```python
# モデル構築（事前学習済みGPT＋分類ヘッド）
model = load_pretrained_gpt()
classifier_head = Linear(hidden_size, num_classes)

for x, y in dataloader:  # 入力例: "premise $ hypothesis"
    input_ids = tokenizer(x)
    hidden_states = model(input_ids)

    # 最終トークンの出力を取得して分類
    h_last = hidden_states[-1]
    logits = classifier_head(h_last)
    loss_cls = cross_entropy(logits, y)

    # 任意: 言語モデル損失も加える
    lm_logits = model.lm_head(hidden_states)
    loss_lm = language_model_loss(lm_logits, input_ids)
    loss = loss_cls + λ * loss_lm

    loss.backward()
    optimizer.step()
```

---

### 🔎 推論時の疑似コード

```python
x = "A man is playing guitar $ A person is performing music"
input_ids = tokenizer(x)
hidden_states = model(input_ids)
h_last = hidden_states[-1]
logits = classifier_head(h_last)
prediction = argmax(softmax(logits))
```

### 🧠 モデル構成と各次元（例：GPT-base相当）

#### 🔹 トークン処理

| ステップ | 処理 | 入出力次元 |
|--|--|--|
| 1 | 入力トークン列 | `[batch, seq_len]` |
| 2 | Embedding | `token_id → [hidden_dim]` → `[batch, seq_len, 768]` |
| 3 | Positional Encoding | 学習済み位置ベクトルを加算 → `[batch, seq_len, 768]` |

#### 🔹 Transformer Block（12層）

1ブロックあたりの構成（×12）

| モジュール | 詳細 | 入出力次元 |
|--|--|--|
| **Masked Self-Attention** | 12ヘッド、各 `64 dim`（合計 `768`） | `[batch, seq_len, 768]` → `[batch, seq_len, 768]` |
| **Add & LayerNorm** | 残差接続と正規化 | `[batch, seq_len, 768]` |
| **Feed Forward** | `768 → 3072 → 768`（GELU） | `[batch, seq_len, 768]` |
| **Add & LayerNorm** | 同上 | `[batch, seq_len, 768]` |

#### 🔹 出力処理

| ステップ | 処理 | 次元 |
|--|--|--|
| 最終トークンの出力 h_m | `[batch, hidden_dim=768]` |
| 線形分類器 W_y | `[768 → num_classes]` |
| softmax | 出力確率 `[batch, num_classes]` |


### ❓ よくある質問

#### Q. fine-tuningで何を学習するの？

- 事前学習済みの**Transformer全体の重み**（12層）と、
- 新たに追加された**線形分類層（W_y）**
を一緒に微調整します（end-to-end fine-tuning）。

#### Q. なぜトークン列に変換するの？

- GPTは「**左から右に予測する生成モデル**」なので、文対やQA形式のような構造化入力はそのままでは扱えません。
- そこで、**Premise + $ + Hypothesis** のように**1つの連続テキスト列**に変換します。

#### Q. なぜ言語モデル損失を加えるの？

- 微調整の過程で**事前学習の知識を保ちやすく**なり、
- **小規模データでも過学習しにくく**なります。


#### 🆚 Q. BERTなど先行研究との違いは？

| 比較項目 | GPT (本論文) | BERT |
|---|---|---|
| モデル構造 | **Decoder-only**（左から右） | **Encoder-only**（双方向） |
| 事前学習目標 | **次トークン予測**（言語モデリング） | **マスクされたトークンの復元**（MLM） |
| 入力形式 | 連続文列（例: `A $ B`） | `[CLS] A [SEP] B`（セグメント構造） |
| 出力利用法 | 最終トークン出力で分類 | `[CLS]`トークン出力で分類 |
| 転用の柔軟性 | **高い**（タスクに応じて入力整形のみ） | 高い（だが専用ヘッドをよく使う） |

📌 **要点**：  
GPTは「生成的に学習したモデルを分類にも流用可能」であることを初めて明確に示した。  
BERTは構造的にはより強力だが、GPTのほうがシンプルな枠組みでありながら**汎用性の高さと事前学習の効果**を証明した点が革新的。


## GPT2
論文名: Language Models are Unsupervised Multitask Learners  
URL: https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf  
発表日: 2019-02-14  


### ✅ ポイント

- **タスク固有のデータやFine-tuningなし**に、**Zero-shotで多数のNLPタスク**をこなすことができる、**事前学習だけで使える言語モデル**。
- Transformerベースの自己回帰型モデル（GPT）を大規模化し、**WebText（45Mページ、40GB）**という多様なコーパスで事前学習。
- 入力に自然言語でタスクの指示（例: "Translate to French:", "TL;DR:"）を与えるだけで、翻訳・要約・質問応答などに対応。
- モデルサイズを大きくすることで、**log-linearに性能が向上**することを実証（最大モデルは**1.5Bパラメータ**）。
- **BERTとの大きな違い**は、教師なしでタスクに即対応できる点（BERTは微調整が必須）。

---

### 🧪 学習の疑似コード（簡略）

```python
# WebTextから自然文をサンプル
x = sample_from_webtext()

# Transformer による事前学習（次トークン予測）
for t in range(1, len(x)):
    # ある位置 t における次トークン x[t] を予測
    context = x[:t]
    logits = transformer(context)
    loss = cross_entropy(logits, x[t])

    # パラメータ更新
    update(loss, transformer)
```


### 🔎 推論時の疑似コード（Zero-shot）

```python
# 例：要約タスクの場合
input_text = """
Article: AI research is accelerating rapidly due to transformer models.
TL;DR:"""  # タスクヒントをつけて入力

# トークンを自動生成
summary = generate_text(transformer, input_text, max_tokens=50)
print(summary)
```


### 🧠 モデル構成（GPT-2）

| モデル | 層数 | 隠れ次元 | ヘッド数 | パラメータ数 |
|--------|------|----------|----------|--------------|
| small  | 12   | 768      | 12       | 117M         |
| medium | 24   | 1024     | 16       | 345M         |
| large  | 36   | 1280     | 20       | 762M         |
| **GPT-2** | 48   | 1600     | 25       | **1.5B**       |

- 入力長: 最大1024トークン  
- トークナイザー: **Byte-Level BPE（語彙サイズ 50,257）**  
- 特徴: LayerNormの位置、残差スケーリングなどを改良


### ❓ よくある質問

#### Q. なぜZero-shotでタスクが解けるの？

- 学習時に明示的にタスクを教えていなくても、WebTextに含まれる「自然な形のタスク実演（例: 翻訳例やFAQ形式）」から、
  **暗黙的にタスクの構造を学習**している。
- そのため、タスクの説明を**自然言語で提示**すれば、それに従って出力することができる。

#### Q. GPT-1との違いは？

| 項目 | GPT (2018) | GPT-2 (2019) |
|------|------------|--------------|
| データ | BooksCorpus (小説中心) | WebText (多ジャンル) |
| 出力対応 | Fine-tune 必須 | **Zero-shot対応可能** |
| モデルサイズ | 117M | 最大1.5B |
| 入力長 | 512 | 1024 |
| 語彙 | 通常BPE | **ByteレベルBPE**（Unicode完全対応） |

#### Q. なぜDecoderのみ（GPT系）なのに多様なタスクに対応できるの？

- 自然言語で入力と出力が明示できるタスク（QA, 翻訳, 要約など）は、
  **シーケンス予測の形式**にうまくマッピングできるため、**Decoderのみで完結**する。



## BERT  
論文名: BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding  
URL: https://arxiv.org/abs/1810.04805  
発表日: 2018-10-11  


### ✅ ポイント
- BERTは、Transformer Encoderをベースにした**双方向的な文脈理解モデル**。各単語の意味を**前後の文脈を同時に考慮**して捉える。
- 学習は2つの事前タスクを使う：  
  ① **Masked Language Model (MLM)** → ランダムに隠した単語を前後の文脈から予測  
  ② **Next Sentence Prediction (NSP)** → 2つの文が連続しているかを分類
- **事前学習＋ファインチューニング**の枠組みにより、分類・QA・NERなどの多様なタスクに対応可能。
- 特別な構造の変更なしに、**文単位・トークン単位のNLPタスクでSOTA性能**を達成。


### 🧪 学習の疑似コード（事前学習）

```python
# パラメータ初期化
initialize(transformer_encoder)

while not converged:
    tokens = tokenize(sample_from_corpus())  # WordPiece
    tokens, labels = apply_masking(tokens)   # MLM: 15%マスク
    is_next_label = sample_nsp_label()       # NSP: 正しい/ランダム文

    outputs = transformer_encoder(tokens)    # [CLS] + 文A + [SEP] + 文B + [SEP]
    loss_mlm = cross_entropy(outputs[mask_positions], labels)
    loss_nsp = binary_cross_entropy(outputs[CLS_position], is_next_label)

    loss = loss_mlm + loss_nsp
    update(loss, transformer_encoder)
```

### 🔎 推論時の疑似コード（分類タスクなど）

```python
tokens = tokenize("input sentence or sentence pair")
outputs = transformer_encoder(tokens)

# 例えば文分類なら、[CLS]トークンの出力を使う
cls_vector = outputs[0]
prediction = classifier(cls_vector)
```

### 🧠 モデル例（BERTBASE）

#### ・ハイパーパラメータ
```text
L = 12層（Transformer Encoder）
H = 768次元の隠れ状態
A = 12ヘッドの自己注意
パラメータ数: 約110M
```

#### ・入力構成
```text
[CLS] 文Aのトークン ... [SEP] 文Bのトークン ... [SEP]
+ トークン埋め込み（WordPiece）
+ セグメント埋め込み（文A/Bの識別）
+ 位置埋め込み（系列順）
```

### ❓ よくある質問

#### Q. なぜ「双方向」だと生成できないの？

- BERTは**前後のトークンを同時に見て1つのトークンを予測**するよう学習されており、**順に次の単語を出す自己回帰的生成**には向いていない。
- GPTなど生成モデルでは、**未来の単語を遮断するマスク（causal mask）**を使うのに対し、BERTは**マスクなしの完全自己注意**で全体を見てしまう。

#### Q. [CLS]トークンとは何？なぜ[CLS]必要？
- [CLS]はTransformer Encoderの最初に強制的に挿入される、**文全体の特徴表現**を担う特殊トークンで、分類やNSPなどに使われる。
- 学習時に[CLS]の最終ベクトルを分類タスクのロス計算に使うことで、文全体の意味を凝縮させる。

#### Q. BERTの応用例は？
- 文分類（感情分析、トピック分類）
- QA（SQuADなど）：出力ベクトルから答えのスパンを予測
- NER：各トークンの出力をラベル分類に使用
- 文のペア関係：自然言語推論、類似判定（NSPを活かす）

## GPT3
論文名: Language Models are Few-Shot Learners  
URL: https://arxiv.org/abs/2005.14165  
発表日: 2020-07-22  


### ✅ ポイント
- GPT-3 は、**1750億パラメータの巨大な自己回帰型Transformerモデル**で、前例のないスケールを実現。
- 特徴は、**ファインチューニングなしで、多様なNLPタスクに対応できる "in-context learning" 能力**。
- in-context learning とは、**プロンプト内に例示や指示を埋め込むだけで新しいタスクに適応できる**能力のこと。
- GPT-3 は、**Zero-shot, One-shot, Few-shot** の各設定で多くのNLPベンチマークにおいて強力な性能を発揮。
- 様々なタスクにおいて、**モデルサイズが大きくなるほど in-context learning の性能が向上**する傾向が見られた。

### 🧪 学習の疑似コード（自己回帰言語モデル）

```python
# モデル初期化（Transformer Decoderベース）
initialize(gpt3_model)

while not converged:
    x = get_tokenized_sequence()  # 入力トークン列（例：長文）

    # 自己回帰的な次トークン予測タスク
    logits = gpt3_model(x[:, :-1])         # 入力: 前のトークン
    loss = cross_entropy(logits, x[:, 1:]) # 出力: 次のトークン

    # パラメータ更新
    update(loss, gpt3_model)
```

### 🔎 推論時の疑似コード（Few-shot 学習）

```python
# 例示を含んだプロンプトを準備
prompt = """
Q: Translate English to French: "book"
A: livre
Q: Translate English to French: "house"
A: maison
Q: Translate English to French: "apple"
A:
"""

# 次のトークンを順に生成（自己回帰）
output = generate_tokens(prompt, max_new_tokens=10)
```

### 🧠 モデル構成（GPT-3 各サイズ）

| モデル名       | パラメータ数 | 層数 | 隠れ次元 | ヘッド数 | トークン長 (n_ctx) |
|----------------|--------------|------|----------|----------|--------------------|
| GPT-3 Small    | 125M         | 12   | 768      | 12       | 2048               |
| GPT-3 Medium   | 350M         | 24   | 1024     | 16       | 2048               |
| GPT-3 Large    | 760M         | 24   | 1536     | 16       | 2048               |
| GPT-3 XL       | 1.3B         | 24   | 2048     | 24       | 2048               |
| GPT-3 2.7B     | 2.7B         | 32   | 2560     | 32       | 2048               |
| GPT-3 6.7B     | 6.7B         | 32   | 4096     | 32       | 2048               |
| GPT-3 13B      | 13B          | 40   | 5140     | 40       | 2048               |
| **GPT-3 175B** | **175B**     | 96   | 12288    | 96       | 2048               |

### ❓ よくある質問

#### Q. GPT-3 はファインチューニング不要なの？

- はい。**タスクの説明や例を直接プロンプトに与えるだけ**で動作します（few-shot learning）。
- モデルのパラメータ自体は更新されません（no gradient update）。

#### Q. "Few-shot" とは何ですか？

- **数個の例示（10〜100）を与えるだけでタスクを解く**設定です。
- 他に Zero-shot（例示なし）や One-shot（例示1つ）もあり、**人間のような柔軟性を目指した学習形式**です。

#### Q. なぜトークン長が固定（2048）なの？

- Transformer は Positional Encoding によって位置情報を与えるため、**事前に最大長を決めておく必要**があります。
- GPT-3 ではこの最大長 `n_ctx = 2048` を超える文脈は扱えません。

#### Q. GPT-3 はどんなタスクに強いの？

- 翻訳、質問応答、長文補完、クロズテスト、常識推論、アナロジー、文法訂正、文章生成など。
- 特に、**few-shotで最先端性能に迫る精度**を出したことが注目されました。

## DALL-E1
**論文名**: Zero-Shot Text-to-Image Generation  
**URL**: [arXiv:2102.12092](https://arxiv.org/abs/2102.12092)  
**発表日**: 2021-02-26

### ✅ ポイント

- **テキストと画像トークンを一つのストリーム**として扱い、Transformerで自己回帰的に学習。
- 高解像度画像を直接扱わず、**dVAEで画像を圧縮し離散トークンに変換**（32×32、各トークンは8192種類）。
- テキスト（最大256トークン）＋画像トークン（1024個）をTransformerで統一的にモデリング。
- **Contrastive reranking（CLIP）でサンプルを再ランキング**し、整合性の高い画像を選出。
- **ゼロショット性能が高く、MS-COCOのキャプションから直接画像生成が可能**。

### 🧪 学習の疑似コード

```python
# Stage 1: dVAEの学習（画像→トークン化と再構成）
for x in image_dataset:
    z = encoder_dVAE(x)  # 32x32個の離散トークン
    x_recon = decoder_dVAE(z)
    loss = reconstruction_loss(x_recon, x) + β * KL(q(z|x) || p(z))
    update(loss, encoder_dVAE, decoder_dVAE)

# Stage 2: Transformerによる事前学習
for (text, image) in text_image_dataset:
    text_tokens = BPE_encode(text, max_len=256)
    image_tokens = encoder_dVAE(image)  # 32x32 = 1024 tokens
    tokens = text_tokens + image_tokens
    loss = cross_entropy(transformer(tokens), tokens[1:])
    update(loss, transformer)
```

### 🔎 推論時の疑似コード

```python
text = "a cat wearing sunglasses"
text_tokens = BPE_encode(text, max_len=256)

# 画像トークンを自己回帰的に生成
tokens = text_tokens
for _ in range(1024):
    next_token = transformer(tokens).sample()
    tokens.append(next_token)

image_tokens = tokens[-1024:]
image = decoder_dVAE(image_tokens)
```


### 🎨 dVAEの説明

dVAE（**Discrete Variational Autoencoder**）は、本モデルの画像トークン化を担う重要な構成要素です。

#### 🔷 なぜ画像を離散トークンに変換するのか？

- 高解像度画像（256×256×3）は76800次元と非常に高次元。
- Transformerで直接モデリングすると**メモリと計算量が爆発**する。
- **dVAEで圧縮（32×32=1024トークン）し、各トークンは8192種類の辞書から選ぶ**ことで、**約192倍の圧縮**が可能に。

#### 🔷 アーキテクチャ概要

- **Encoder**: 7×7 Conv → ResNet（Bottleneck）→ 1×1 Conv → 出力: 32×32×8192 のロジット（softmaxでカテゴリに変換）
- **Decoder**: 1×1 Conv → ResNet → 1×1 Conv → 出力: 256×256 RGB画像
- 損失関数は **Logit-Laplace分布** に基づいた再構成誤差 + KL項（VAE的学習）

#### 🔷 離散化の課題とGumbel-Softmax

VAEでは潜在変数が連続なので再パラメータ化トリックで勾配を通せるが、**dVAEでは離散トークン（one-hot）**のため、勾配が通らない。

そこで導入されるのが **Gumbel-Softmax（Concrete Distribution）**：

```math
y_i = \frac{\exp((\log(\pi_i) + g_i)/\tau)}{\sum_j \exp((\log(\pi_j) + g_j)/\tau)}
```

- \( \pi_i \)：カテゴリiの確率（softmax前のロジット）
- \( g_i \)：Gumbelノイズ（= \(-\log(-\log(U))\), U∼Uniform(0,1)）
- \( \tau \)：温度パラメータ（小さいほどone-hotに近づく）

→ これにより、「ほぼ離散」の確率ベクトルを通じて**勾配が流れるように**なる。

> ✅ 補足: 学習では Gumbel-Softmax を使い、推論時には `argmax` でトークンを確定。

#### 🔷 Logit-Laplace分布とは？

- ピクセルは \([0, 255]\) の離散値 → 正規分布やLaplace分布はサポート範囲が \((−∞, ∞)\) なので**不自然**。
- 解決策として、Laplace分布を sigmoidで \((0,1)\) にマッピング → **logit-Laplace分布** を定義：

```math
f(x | \mu, b) = \frac{1}{2bx(1 - x)} \exp\left(-\frac{|logit(x) - \mu|}{b}\right)
```

- これにより、**出力が [0,1] に制限された画像再構成が可能**。

#### 🔷 dVAEの学習スケジュール

- KL係数 \( \beta \): 0 → 6.6 に徐々に上昇（最初は再構成優先、後半は潜在空間の正則化）
- 温度 \( \tau \): 1 → 1/16 にアニーリング（より離散的な出力へ）
- Optimizer: **AdamW + Cosine decay**, mixed precision 16-bit training
- 全更新数: 約300万ステップ、バッチサイズ512（V100 x 64台）



### 🧠 モデル例と構成

#### ・dVAE（Stage 1）

- **Encoder**:  
  7×7 Conv → ResNet（Bottleneck）→ 1×1 Conv → 出力：32×32×8192（ロジット）

- **Decoder**:  
  1×1 Conv → ResNet → 1×1 Conv → 出力：256×256 RGB画像

- **損失関数**:  
  Logit-Laplace（再構成）+ KL（Gumbel-softmax緩和）

#### ・Transformer（Stage 2）

- **構造**:  
  Decoder-only Sparse Transformer（12Bパラメータ、64層、注意ヘッド62）

- **入力**:  
  テキスト（最大256トークン, vocab=16384） + 画像トークン（1024個, vocab=8192）

- **マスク**:  
  Row/Column/Conv Attention（11×11カーネル）


### ❓ よくある質問

#### Q. なぜ画像をdVAEで離散トークン化するの？

- 高解像度画像を直接扱うのは非効率。**トークン化によりメモリ使用量と依存関係を圧縮**でき、Transformerの学習が現実的になる。

#### Q. Gumbel-softmaxを使うのはなぜ？

- トークンは離散値だが、そのままだと**勾配が流れない**。Gumbel-softmaxで連続化することで**勾配による最適化が可能**になる。

#### Q. 推論時はzにノイズを加えるの？

- 通常は再現性を重視して `z = μ` のみを使う。**生成の多様性が必要な場合はノイズを加える**ことも可能。

#### Q. このモデルでできるタスクは？

- ゼロショット画像生成  
- キャプションからの**構造的な画像生成**  
- **画像スタイル変換や編集**（例: スケッチ化や反転）  
- **構成的理解**（「アコーディオンでできたバク」などの新規概念の合成）


**dVAEとVQ-VAEの違い**を、初心者でも直感的にわかるようにまとめます。

#### Q. VQ-VAEとdVAEの違いは？

| 項目          | **VQ-VAE**                     | **dVAE（Gumbel-Softmax版）**        |
|---------------|---------------------------------|------------------------------------|
| 離散化方法     | 量子化（nearest neighbor search）| Gumbel-Softmax近似（soft）         |
| 勾配の流し方   | Straight-Through Estimator（無理やり流す） | Gumbel-Softmaxでスムーズに流す      |
| 離散値の更新   | 埋め込みコードブックを直接更新（EMAなど） | クラス確率でsoftmax近似 → 最終的にhard選択 |
| 温度パラメータ | なし                            | あり（訓練中に徐々に低くする）      |
| 実装の複雑さ   | 簡単（ただしSTトリックが不安定な場合あり） | やや複雑（Gumbel noise生成・温度管理） |
| 学習安定性     | ⚠️ 難しいことがある               | ✅ 比較的安定                      |


## GLIDE

**論文名**: GLIDE: Towards Photorealistic Image Generation and Editing with Text-Guided Diffusion Models  
**URL**: [arXiv:2112.10741](https://arxiv.org/abs/2112.10741)  
**発表日**: 2021-12-21

### ✅ ポイント

- **拡散モデル (Diffusion Model)** をベースに、テキスト条件付きでフォトリアルな画像を生成・編集。
- 生成モデルには**Classifier-Free Guidance**を採用し、**テキスト条件なし・ありの出力を補間**して誘導。
- **インペインティング（部分修復）も自然言語プロンプトで制御可能**。
- 画像生成は2段階：  
  - **64×64のベース拡散モデル**  
  - **256×256へのアップサンプラー拡散モデル**  
- **DALL-Eより高品質な生成結果**を達成（人間評価、FIDスコアともに上回る）。

### 🧪 学習の擬似コード

```python
# 拡散モデル学習
for (image, caption) in dataset:
    t = random_time_step()  # ランダムな時刻を選ぶ
    noise = random_noise()
    noisy_image = add_noise(image, noise, t)  # ノイズ付加

    if random() < 0.2:
        caption = None  # 20%の確率で無条件に（Classifier-Free用）

    pred_noise = diffusion_model(noisy_image, t, caption)
    loss = mse_loss(pred_noise, noise)
    update(loss, diffusion_model)
```

### 🔎 推論時の擬似コード

```python
# 生成開始（完全なノイズから）
xt = random_noise()  # x_T

for t in reversed(range(1, T+1)):
    noise_pred_cond   = diffusion_model(xt, t, caption)
    noise_pred_uncond = diffusion_model(xt, t, None)

    # Classifier-Free Guidance適用
    noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_cond - noise_pred_uncond)

    xt = denoise_step(xt, noise_pred, t)  # 次時刻 x_{t-1}
```

### 🎨 Classifier-Free Guidanceの説明

Classifier-Free Guidanceは、  
「条件あり」と「条件なし」の出力を補間することで  
**サンプルの忠実度と多様性のトレードオフを制御**します。

#### 🔷 数式

\[
\hat{\varepsilon}_{\theta}(x_t|c) = \varepsilon_{\theta}(x_t|\emptyset) + s \left( \varepsilon_{\theta}(x_t|c) - \varepsilon_{\theta}(x_t|\emptyset) \right)
\]

- \(c\)：キャプション
- \(s\)：ガイダンススケール（大きいと忠実度↑、多様性↓）

#### 🔷 なぜClassifier-Free Guidanceを使う？

- 外部分類器(CLIPなど)に依存せず、**モデル単体で誘導できる**。
- CLIP Guidanceに比べて**安定して高品質な生成ができる**。

### 🧠 モデル例と構成

#### ・ベース拡散モデル（64×64）

- **UNet構造**:
  - ダウンサンプル→ボトルネック→アップサンプル
  - 中間層に**Self-Attention**（低解像度層のみ）
  - アップサンプル側で**Cross-Attention**（テキスト条件注入）
- **時間埋め込み**:
  - 各時刻\(t\)を埋め込んで各ResBlockに加算
- **テキスト埋め込み**:
  - 独自のTransformerエンコーダ（24層、幅2048）

#### ・アップサンプラー（256×256）

- 拡散モデルによる超解像（64→256）
- より少ないステップ、より強い条件付き

### ❓ よくある質問

#### Q. なぜ拡散モデルを使うの？

- GANに比べて**学習が安定**しやすく、モード崩壊（多様性喪失）も起きにくい。
- 少しずつノイズを除去するプロセスが、**細かい制御と自然な生成**を両立できる。

#### Q. DALL-Eとの違いは？

| 項目 | DALL-E | GLIDE |
|:---|:---|:---|
| モデルタイプ | 自己回帰Transformer + dVAE | 拡散モデル |
| 画像表現 | 離散トークン列 | 連続画像空間 |
| 誘導方法 | Contrastive Reranking (CLIP) | Classifier-Free Guidance |
| インペインティング | 弱い | 強力 |
| 生成品質 | 良好 | DALL-Eより高い |

#### Q. テキスト条件なし（NULLキャプション）の出力はどう扱う？

- 学習時に「NULL条件」のサンプルを20%混ぜることで、モデルに**無条件生成能力**も学ばせている。
- 推論時はこの無条件出力をベースに補間して誘導する。

#### Q. インペインティングはどうやる？

- マスク領域をノイズで初期化。
- コンテキスト（周辺画素）を固定しながら、拡散過程を実行。
- プロンプトに従って自然な穴埋めができる。

## DALL-E2

**論文名**: Hierarchical Text-Conditional Image Generation with CLIP Latents  
**URL**: [arXiv:2204.06125](https://arxiv.org/abs/2204.06125)  
**発表日**: 2022-04-12

### ✅ ポイント

- **テキストから直接画像を生成せず**、いったん**CLIPの画像埋め込み（latent）を生成**（Prior）。
- **Prior（DiffusionまたはAR）でテキストからCLIP latentを生成**。
- **Decoder（拡散モデル）でCLIP latentから画像を復元**。
- テキスト情報もDecoderに補助的に入力できる（スタイル＋意味の細部制御）。
- **意味・スタイル・多様性を高次元で両立**でき、DALL·EやGLIDEより高品質。


### 🧪 学習の擬似コード

```python
# --- CLIPエンコーダで意味表現を取得 ---
z_i = clip_image_encoder(x)    # (B, 1024) 画像の埋め込み
z_t = clip_text_encoder(y)     # (B, 512) テキストの埋め込み

# --- Prior（Diffusion Prior）学習 ---
t = random.randint(1, T)
z_i_noised = q_sample(z_i, t)

prior_inputs = [
    text_tokens(y),       # (B, 77, 512) テキストトークン列
    z_t,                  # (B, 512) テキスト埋め込み
    timestep_embedding(t),# (B, 512) 拡散ステップ埋め込み
    z_i_noised,           # (B, 1024) ノイズ付き埋め込み
    output_placeholder(), # (B, 1024) 出力トークン
]

z_i_pred = prior_transformer(prior_inputs)
prior_loss = mse_loss(z_i_pred, z_i)
update(prior_loss, prior_transformer)

# --- Decoder（拡散モデル）学習 ---
x_t = add_noise(x, t)

decoder_inputs = {
    "x_t": x_t,    # (B, 3, 256, 256)
    "t": t,
    "z_i": z_i,    # (B, 1024)
    "optional_z_t": z_t,
}

epsilon_pred = decoder_unet(decoder_inputs)
decoder_loss = mse_loss(epsilon_pred, true_noise)
update(decoder_loss, decoder_unet)
```


### 🔎 推論時の擬似コード

```python
# --- Priorによる潜在生成 ---
z_t = clip_text_encoder(input_text)
z_i = diffusion_prior_sample(z_t)

# --- Decoderで画像生成 ---
x_T = random_noise_image(shape=[1, 3, 64, 64])
for t in reversed(range(T)):
    x_t = decoder_unet(x_T, t=t, cond=z_i)
    x_T = denoise(x_T, x_t)
```

---

### 🎨 Diffusion PriorとDecoderの説明

#### 🔷 Diffusion Prior（P(zᵢ|y)）

- テキストからCLIP画像潜在 \( z_i \) を生成するモデル。
- 拡散モデル（DDPM）により、ノイズから意味ある潜在へ復元。
- 多様性が自然に表現できる上、意味も保持できる。

#### 🔷 Diffusion Decoder（P(x|zᵢ,y)）

- 画像潜在 \( z_i \) を条件に64×64の画像を生成。
- GLIDEベースのU-Net型拡散モデル。
- テキスト埋め込み \( z_t \) はオプション補助。
- Classifier-Free Guidance (CFG) により、意味強調と画質を両立。


### 🧠 モデル例と構成

#### ・Prior Transformer

- **Decoder-only Transformer**
- テキスト・z_t・タイムステップ・ノイズ付きz_iを順に並べたトークン列を入力。

#### ・Decoder U-Net

- **エンコーダ・ボトルネック・デコーダ構造**
- Cross-Attentionで z_i, (optional z_t) を条件付け。


### ❓ よくある質問

#### Q. なぜ直接テキスト→画像ではなく、一度zᵢを経由するの？

- テキストだけだとスタイルやリアリズムの細部制御が難しい。
- CLIPの画像潜在を経由することで、**意味・スタイル・多様性を同時に満たせる**。

#### Q. zᵢとzₜはどう違う？

| 項目           | zᵢ（画像潜在） | zₜ（テキスト潜在） |
|----------------|----------------|------------------|
| 役割           | スタイル・意味のコア | 属性や関係性の補助 |
| 使用方法       | デコーダの主条件 | (optional)補助情報 |

#### Q. Diffusion PriorとAR Priorどっちがいい？

- **Diffusion Priorのほうが多様性・意味一致度ともに優秀**。
- AR Priorは離散トークン列扱いなので少し重いし、性能も劣る。

#### Q. CFG（Classifier-Free Guidance）はどこで使う？

- PriorとDecoderの両方で使用。
- 無条件と条件付きの出力を線形補間して、意味との整合性を高める。


### DALL·E 1との違いは？

| 項目           | DALL·E 1                        | unCLIP                         |
|----------------|----------------------------------|---------------------------------|
| 基本戦略       | テキスト＋画像トークン列を自己回帰的生成 | テキスト→CLIP埋め込み→画像復元の2段階 |
| モデル         | Transformerのみ                 | Prior（Transformer）＋Decoder（拡散） |
| 中間表現       | 画像トークン（離散）             | CLIP潜在ベクトル（連続）        |
| 離散/連続      | 離散（dVAE）                     | 連続（CLIP latent）             |
| 多様性         | やや低い                         | 非常に高い                      |


### GLIDEとの違いは？

| 項目           | GLIDE                            | unCLIP                         |
|----------------|----------------------------------|---------------------------------|
| 基本戦略       | テキスト→拡散モデル（直接画像復元） | テキスト→CLIP latent→拡散復元 |
| 条件情報       | テキスト埋め込みのみ               | CLIP画像埋め込みが主、テキスト補助 |
| 多様性         | 高いが意味崩れが起きやすい         | 多様性と意味一致が両立          |
| 編集タスク性能  | 高い（inpainting可能）             | 高い（さらに意味一致度が高い） |
| モデル規模      | 小型版（64x64→256x256）もあり       | 基本は64x64（後段Upsamplerで1024x1024） |


## DALL-E3

**論文名**: Improving Image Captioning with Better Use of Captions  
**URL**: [arXiv:2006.11807](https://arxiv.org/abs/2006.11807)  
**発表日**: 2020-06-21

### ✅ ポイント

- **キャプションから抽出した関係情報**を使い、画像内の**物体・関係ノードを構成**（CGVRG）。
- **弱教師ありMulti-Instance Learning**により、物体ペアと関係（predicate）をマッチング。
- **Graph Convolutional Network (GCN)**で物体・関係ノードの文脈表現を学習。
- **マルチタスク学習**で、単語生成＋タグ（物体/関係/なし）分類を同時に行い、意味的整合性を高める。
- **MSCOCOでSOTA性能を達成**（特にCIDEr-Dスコアが大幅向上）。


### 🧪 学習の擬似コード

```python
# --- 物体検出と関係トリプル抽出 ---
object_regions = faster_rcnn(image)
triples = text_scene_graph_parser(caption)

# --- Weakly Supervised Predicate Matching ---
region_pairs = all_pairs(object_regions)
predicate_probs = predict_predicate(region_pairs, triples)
loss_predicate = multi_instance_loss(predicate_probs, triples)
update(loss_predicate)

# --- Graph Convolution（CGVRG Encoding）---
object_feats = visual_features(object_regions)
predicate_feats = predicate_embeddings(triples)
contextualized_feats = GCN(object_feats, predicate_feats)

# --- Multi-task Caption Generation ---
for each step t:
    h1_t = bottom_LSTM(h1_t-1, contextualized_feats, previous_word)
    attended_feats = attention(h1_t, contextualized_feats)
    h2_t = top_LSTM(h2_t-1, [h1_t, attended_feats])
    
    # マルチタスク出力
    word_pred = word_predictor(h2_t)
    tag_pred = tag_predictor(h2_t)
    
    loss = cross_entropy(word_pred, target_word) + γ * cross_entropy(tag_pred, target_tag)
    update(loss)
```


### 🔎 推論時の擬似コード

```python
# --- グラフ構築 ---
object_regions = faster_rcnn(input_image)
triples = text_scene_graph_parser(training_captions)
region_pairs = all_pairs(object_regions)
predicate_probs = predict_predicate(region_pairs, triples)

# --- 文脈特徴抽出 ---
contextualized_feats = GCN(object_feats, predicate_feats)

# --- 生成 ---
h1_0, h2_0 = initialize()
generated_caption = []
for each step:
    h1_t = bottom_LSTM(h1_t-1, contextualized_feats, previous_word)
    attended_feats = attention(h1_t, contextualized_feats)
    h2_t = top_LSTM(h2_t-1, [h1_t, attended_feats])
    
    word = sample(word_predictor(h2_t))
    generated_caption.append(word)
```


### 🎨 CGVRGとMulti-task学習の説明

#### 🔷 Caption-Guided Visual Relationship Graph (CGVRG)

- キャプションの**主語-述語-目的語トリプル**を解析。
- 画像内の**物体領域**と**関係**を弱教師ありでマッチング。
- 物体ノードと関係ノードを持つ**グラフ構造**を生成。

#### 🔷 Multi-task Learning（単語＋タグ予測）

- 1ステップごとに
  - 単語を生成（例："man"）
  - タグを分類（例：これは物体か？関係か？なし？）
- タグによる情報強調（物体ノード or 関係ノード or 言語状態）を適応的に切り替え。


### 🧠 モデル例と構成

#### ・Faster R-CNN（物体検出）

- ResNet-101ベース。
- RoI Pooling後の2048次元特徴量を使用。

#### ・Weakly Supervised Predicate Matcher

- 物体ペア間に**predicate確率**を出力するMLP。
- ノイズを許容するMulti-Instance Learning (Noisy-OR)。

#### ・Graph Convolutional Network (GCN)

- Object Node ↔ Predicate Node 間で情報伝搬。
- Visual FeatureとTextual Featureを融合。

#### ・2層LSTM＋マルチタスクブロック

- 下層: 画像と単語を融合するLSTM
- 上層: 文を生成するLSTM
- マルチタスクブロックでタグ分類＆単語生成。


### ❓ よくある質問

#### Q. なぜキャプションに沿った関係グラフを作るの？

- 普通のVRD（Visual Relationship Detection）では、キャプションに必要な細かな関係（例："grab"など）が抜け落ちる。
- キャプション誘導により、**キャプションに必要な意味だけを抽出できる**。

#### Q. Multi-Instance Learningって何？

- 「この袋（bag）に**1個でも正しい組み合わせ**があればOK」という弱い制約で学習。
- 物体検出の曖昧さ（例：同じ犬が2匹いる）に強い。

#### Q. マルチタスク学習の効果は？

- 単語生成時に「いま物体を言うべき？関係を言うべき？」を動的に判断できる。
- これにより**文の一貫性と情報量が向上**。

### 🆚 既存手法との違い

| 項目            | 従来（Up-Down, GCN-LSTM） | 本論文（CGVRG）           |
|-----------------|---------------------------|---------------------------|
| 関係グラフ       | VRDモデルベース             | キャプションベースで生成  |
| 学習方法         | 完全教師あり                | 弱教師あり (Multi-Instance) |
| 文生成           | 単純なAttention             | マルチタスク (単語＋タグ) |
| 意味理解         | 不十分な場合あり            | キャプションに沿った理解  |
| 性能 (CIDEr-D)   | 120付近                    | 129超え                  |

## Vision Transformer (ViT)  
**論文名**: An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale  
**URL**: https://arxiv.org/abs/2010.11929  
**発表日**: 2020-10-22（ICLR 2021 採択）


### ✅ ポイント

- CNNを一切使わず、**Transformerを画像パッチ列に直接適用**して画像分類を実現。
- 入力画像を**固定サイズ（例：16×16）のパッチに分割**し、それぞれをトークン（ベクトル）として処理。
- BERTの `[class]` トークンと同様に、分類用トークンを先頭に追加。
- **位置情報は1Dの学習可能な位置埋め込み**で補完（2D位置埋め込みよりもシンプルで効果も十分）。
- **自己注意層により画像全体の情報をグローバルに統合可能**。
- 小規模データセットではCNNに劣るが、**大規模データセット（JFT-300Mなど）での事前学習によりSOTA性能を達成**。



### 🧪 モデル構成（疑似コード風）

```python
# 画像のパッチ化と埋め込み
image = load_image()  # サイズ H x W x C
patches = split_into_patches(image, patch_size=16)  # N個のパッチ (N = H*W/patch_size^2)
patch_embeddings = linear_projection(patches)  # 各パッチをD次元に

# クラストークンと位置埋め込みを追加
cls_token = learnable_vector(D)
tokens = concat(cls_token, patch_embeddings)  # 長さ N+1
tokens += positional_embedding  # shape: (N+1, D)

# Transformer Encoder（L層）
for l in range(L):
    tokens = tokens + MSA(LN(tokens))
    tokens = tokens + MLP(LN(tokens))

# 出力：classトークンのベクトルにMLPを適用して分類
class_representation = LN(tokens[0])
output = MLP_head(class_representation)  # 分類結果
```


### 🔎 推論時の流れ

```python
image = input_image()
patches = split_into_patches(image, patch_size=16)
patch_embeddings = linear_projection(patches)
tokens = concat(cls_token, patch_embeddings) + positional_embedding

# Transformerエンコーダ通過
encoded = transformer_encoder(tokens)
cls_repr = encoded[0]
logits = MLP_head(cls_repr)
```

### 🧠 モデル例（ViT-Base）

| 名称     | 値           |
|----------|--------------|
| 層数     | 12           |
| 隠れ次元 D | 768         |
| MLP隠れ層 | 3072         |
| ヘッド数 | 12 (MSA)     |
| パラメータ数 | 約86M     |
| 入力画像 | 224×224×3    |
| パッチ   | 16×16サイズ ⇒ 196パッチ + 1 `[cls]` トークン |


### ❓ よくある質問

#### Q. なぜCNNのような畳み込みを使わなかったの？

- CNNは画像特化の**強い帰納バイアス**（局所性・平行移動不変性）を持つが、ViTは**データ主導の表現学習**を目指す。
- **十分なデータ量があれば、帰納バイアスなしでも高性能が可能**であることを示した。

#### Q. 小さなデータセットではViTが弱い理由は？

- ViTは**画像固有のバイアスを持たないため、少数データでは学習が不安定**。
- CNNのように局所構造を活用できず、**過学習しやすい**。

#### Q. ViTの位置埋め込みはどうして1D？

- パッチを平坦化した後、**系列として扱うため1D位置埋め込みで十分**。
- 2D-awareな位置埋め込みも試したが、性能向上は限定的だった。

#### Q. ViTで画像生成や自己教師あり学習もできる？

- 本論文では分類のみだが、ViTの構造は**生成タスクや自己教師あり学習**にも応用可能。
- 例えば**Masked Patch Prediction（BERT風）**による事前学習も有望。


## VQGAN  
**論文名**: Taming Transformers for High-Resolution Image Synthesis  
**URL**: https://arxiv.org/abs/2012.09841  
**発表日**: 2021-06-23  

### ✅ ポイント

- 高解像度画像生成にはTransformerの表現力が有効だが、**直接ピクセル列を扱うと計算コストが爆発的に増大**。
- **CNNベースのVQGAN（改良版VQVAE）で画像を離散表現に変換**し、Transformerでそのシーケンスを効率的にモデリング。
- VQGANは**知覚損失（perceptual loss）とGAN損失**を導入し、**高品質な再構成画像を得つつコード長を圧縮**。
- Transformerは、VQGANのコードブックインデックス列を自己回帰的に学習することで、**画像のグローバル構成を捉える**。
- **semantic segmentation、depth、pose、classラベルなど多様な条件付き生成**に対応。


### 🧪 学習の疑似コード

```python
# === ステージ1: VQGANの学習 ===
initialize(encoder=E, decoder=G, codebook=Z, discriminator=D)

for x in dataset:
    # エンコードして量子化
    z_hat = E(x)                     # ℝ^{h×w×nz}
    z_q = quantize(z_hat, Z)        # 最近傍codebookベクトルへ量子化
    x_hat = G(z_q)                  # 再構成画像

    # 損失計算
    perceptual = perceptual_loss(x, x_hat)
    gan_loss = log(D(x)) + log(1 - D(x_hat))
    codebook_loss = ||stopgrad(z_hat) - z_q||^2
    commitment_loss = ||z_hat - stopgrad(z_q)||^2

    # 総合損失
    loss = perceptual + λ * gan_loss + codebook_loss + commitment_loss
    update(E, G, Z, D)

# === ステージ2: Transformerの学習 ===
initialize(transformer)

for s in code_sequences:  # VQGANで得たコードインデックス列
    for i in range(len(s)):
        pred = transformer(s[:i])  # 先行トークンから次を予測
        loss = cross_entropy(pred, s[i])
        update(transformer)
```


### 🔎 推論時の疑似コード

```python
# 条件付き生成（任意のc: ラベルやセグマップなど）
context = encode_condition(c) if c else None

s = []
for i in range(sequence_length):
    pred = transformer(s, context)     # p(s_i | s_{<i}, c)
    s_i = sample(pred)                 # top-k, nucleus samplingなど
    s.append(s_i)

# 復元
z_q = codebook[s]
x_gen = G(z_q)
```


### 🧠 モデル例

#### ・VQGAN（Encoder/Decoder）

```text
Encoder:
Input: 画像 ℝ^{H×W×3}
↓ Conv2D
↓ m回の Residual Block + Downsampling
↓ Non-local Attention
↓ GroupNorm + Swish + Conv2D
Output: 潜在ベクトル ℝ^{h×w×nz}

Decoder:
Input: z_q ∈ ℝ^{h×w×nz}
↓ Conv2D
↓ m回の Residual Block + Upsampling
↓ Non-local Attention
↓ GroupNorm + Swish + Conv2D
Output: 再構成画像 ℝ^{H×W×3}
```

#### ・Transformer（GPT2ベース）

```text
Input: 離散インデックス列 s = [z_1, z_2, ..., z_N]
↓ Positional Embedding
↓ L層の Transformer Block（Self-Attention + FFN）
↓ Softmax による次インデックス予測
Output: p(z_i | z_{<i})
```

### ❓ よくある質問

#### Q. VQVAEとの違いは？

- VQVAEは単なるL2再構成損失に依存していたが、VQGANでは**GAN損失 + 知覚損失**を導入。
- これにより、より**リアルで高精細な再構成画像**が得られ、より意味的に圧縮されたコードブックが学習可能。
- 結果としてTransformerが**長距離の意味的依存を捉えやすくなる**。

#### Q. なぜTransformerで画像を直接扱わないの？

- 高解像度画像（例: 256×256）では、ピクセル列の長さが 65536 になり、**Self-Attentionの計算が非現実的（O(N²））**。
- VQGANでシーケンス長を 16×16 などに圧縮し、**圧縮表現に対してのみTransformerを適用**。

#### Q. どんな応用ができるの？

- クラス条件付き生成（ImageNetなど）
- セマンティック画像合成（セグマップ → 画像）
- Depth/Edge-to-Image
- Pose-guided人物画像生成
- 超解像（Super-Resolution）
- 高解像度画像（Megapixel）生成


## ViT-VQGAN  
**論文名**: VECTOR-QUANTIZED IMAGE MODELING WITH IMPROVED VQGAN  
**URL**: https://arxiv.org/abs/2110.04627  
**発表日**: 2022年6月（ICLR 2022 掲載）

### ✅ ポイント

- Vision Transformer（ViT）を用いた**自己注意型のEncoder/Decoder構造**を導入し、CNNベースのVQGANより**高精度かつ高速**な画像トークナイザを実現。
- エンコーダ出力 `z_e ∈ ℝ^D` を**低次元空間（ℝ^d）へ線形射影**してコードブック検索する **Factorized Codebook** を提案。これによりコード使用率と再構成精度を大幅改善。
- ViT-VQGANのトレーニングでは、**Logit-Laplace損失、L2損失、Perceptual損失、Adversarial損失**を組み合わせて、再構成品質とコードブック学習を同時に最適化。


### 🧪 学習の擬似コード（Stage 1: ViT-VQGAN）

```python
# 初期化
initialize(encoder_vit, decoder_vit, codebook, W_lookup)

for x in dataset:
    z_e = encoder_vit(x)          # (B, 1024, D)
    z_proj = normalize(W_lookup(z_e))  # (B, 1024, d)

    # コードブックも射影
    code_proj = normalize(W_lookup(codebook))  # (K, d)
    dist = ((z_proj.unsqueeze(2) - code_proj)**2).sum(-1)  # (B, 1024, K)
    index = dist.argmin(dim=-1)      # 最近傍インデックス (B, 1024)
    z_q = codebook[index]            # 量子化後特徴 (B, 1024, D)

    x_recon = decoder_vit(z_q)

    # 損失
    loss_vq = ((z_q.detach() - z_e)**2).mean() + β * ((z_e - z_q.detach())**2).mean()
    loss_l2 = ((x - x_recon)**2).mean()
    loss_laplace = torch.mean(torch.abs(x - x_recon))  # Laplace近似
    loss_perc = perceptual_loss(x, x_recon)
    loss_gan = gan_loss(x, x_recon)

    loss = loss_vq + 0.1*loss_gan + 0.1*loss_perc + 0.1*loss_laplace + 1.0*loss_l2
    update(loss)
```

### 🔎 推論時の擬似コード（ViT-VQGANによる画像復元）

```python
# 推論時は z_e のままでも再構成可能
x = input_image()
z_e = encoder_vit(x)
z_proj = normalize(W_lookup(z_e))
code_proj = normalize(W_lookup(codebook))
dist = ((z_proj.unsqueeze(2) - code_proj)**2).sum(-1)
index = dist.argmin(dim=-1)
z_q = codebook[index]

x_recon = decoder_vit(z_q)
```

### 🧠 モデル構成例（ViT-VQGAN）

#### ・Encoder（ViTベース）
```text
Input (3×256×256) → Patchify (8×8) → Linear(192→D) → L層 ViT → MLP+tanh → 出力 z_e (1024, D)
```

#### ・Decoder（ViTベース）
```text
Input z_q (1024, D) → PosEmbed追加 → L層 ViT → MLP → Reshape → ConvTranspose → 画像復元 (3×256×256)
```

### ❓ よくある質問

#### Q. Factorized Codebook の「線形射影」は学習されるの？

- **はい、W_lookup ∈ ℝ^{d×D} は学習可能パラメータ**で、バックプロパゲーションで更新されます。
- 同じ射影行列で `z_e` も `codebook` も低次元空間に投影し、そこで距離比較します。

#### Q. L2正規化はなぜ使うの？

- 射影後のベクトルを**球面に正規化（L2 norm = 1）**することで、距離計算が**コサイン類似度**と等価になり、学習が安定。
- 正規化しないとベクトルのスケールに依存して**コードブック使用率が偏る（＝死んだコードが多発）**問題が起きやすい。

#### Q. Perceptual loss を使うと教師ありになるのでは？

- その通り。VGG特徴空間はImageNetで学習された分類器なので、**完全な教師なし表現学習には使わない**（評価時は除外）。
- ただし**生成品質向上のためには有効**なので、生成モデルの学習には用いる。

#### Q. どの損失が何に効いている？

| 損失項目         | 効果                                 |
|------------------|--------------------------------------|
| `L_vq`           | コードブック学習とコミットメント    |
| `L_l2`           | 低周波の構造維持、数値安定           |
| `L_laplace`      | ノイズ耐性、L1に近くエッジ保持        |
| `L_perceptual`   | 高次特徴の整合性                     |
| `L_adv`          | 視覚的にリアルな質感（局所的品質）   |



## Parti  
**論文名**: Scaling Autoregressive Models for Content-Rich Text-to-Image Generation  
**URL**: https://arxiv.org/abs/2206.10789  
**発表日**: 2022-06-21  

### ✅ ポイント

- **テキストから画像を生成**する問題を、**Sequence-to-Sequence（seq2seq）モデリング**として定式化。  
- **画像はViT-VQGANで離散トークンに変換**し、Transformerで**テキスト → 画像トークン列**を生成。  
- Transformerベースの**Encoder-Decoder構成を採用**（最大20Bパラメータ）。  
- 評価指標である**FIDスコアで最先端性能**（MS-COCO: Zero-shot 7.23 / Finetuned 3.22）を達成。  
- 多様なカテゴリと難易度を含む**新ベンチマーク「PartiPrompts (P2)」を提案**（全1600プロンプト）。  
- **Classifier-Free Guidance（CFG）**と**Contrastive Reranking（CoCa）**により、テキストとの整合性を強化。  

### 🧪 学習の疑似コード（2段階構成）

```python
# Stage 1: ViT-VQGANのトレーニング
train_vit_vqgan(image_dataset)
# 得られる：image_tokenizer (encoder, decoder, codebook)

# Stage 2: テキスト → 画像トークンのseq2seqトレーニング
for (text, image) in paired_data:
    text_tokens = tokenizer.encode(text)
    image_tokens = image_tokenizer.encode(image)  # 離散トークン列 (32x32 = 1024)

    pred_tokens = encoder_decoder.transformer(text_tokens)
    loss = cross_entropy(pred_tokens, image_tokens)

    update(loss, encoder_decoder)
```


### 🔎 推論時の擬似コード（CFG + CoCa使用）

```python
# CFGありの生成
def generate_image(prompt, model, lambda_cfg=1.2):
    cond_embed = model.encode_text(prompt)
    uncond_embed = model.encode_text("")  # 無条件

    image_tokens = []
    for t in range(1024):  # 32x32
        logits_cond = model.decode(image_tokens, cond_embed)
        logits_uncond = model.decode(image_tokens, uncond_embed)
        logits = logits_uncond + lambda_cfg * (logits_cond - logits_uncond)
        token = sample_from_logits(logits)
        image_tokens.append(token)

    image = image_tokenizer.decode(image_tokens)
    return image

# CoCaで再ランキング
def rerank_images(prompt, image_list, coca_model):
    prompt_embed = coca_model.encode_text(prompt)
    scores = [(img, cosine_similarity(prompt_embed, coca_model.encode_image(img)))
              for img in image_list]
    return max(scores, key=lambda x: x[1])[0]  # 最も一致する画像を返す
```


### 🧠 モデル例（20B構成）

#### ・ViT-VQGAN（トークナイザー）
- 入出力: 256×256画像 → 32×32 の 8192種類トークン（合計1024）
- encoder: ViTベース
- decoder: transformer型デコーダを後から拡張して微調整（最大600Mパラメータ）

#### ・Text-to-Image Transformer
| モデル        | Encoder層数 | Decoder層数 | 次元数 | 総パラメータ |
|---------------|--------------|--------------|--------|----------------|
| **Parti-20B** | 16           | 64           | 4096   | 20B             |

---

### ❓ よくある質問

#### Q. PartiはDiffusion系（DALL-E 2やImagen）と何が違うの？

- Partiは**Autoregressive Transformerベース**で、**トークン列として画像を生成**。
- Diffusion系は**ノイズ除去による画像再構成**を反復する形式。
- PartiはTransformerのスケーリング技術（LLMの経験）をそのまま活かせる。

#### Q. PartiはなぜEncoder-Decoder型？GPT型（decoder-only）ではダメ？

- Decoder-only（GPT型）よりも、**テキスト理解力が強化**され、少パラメータでも高性能。
- 実験により、350M〜750Mパラメータ時点で明らかに優位。

#### Q. CFGとCoCaはどう使い分けるの？

- CFG：**生成中に強制的にプロンプト整合性を高める**。
- CoCa：**複数生成後にもっともプロンプトに一致した画像を選ぶ**。

#### Q. なぜ画像トークンを使うの？

- テキストと同じように扱えるため、Transformerの**シーケンスモデリングの知見をそのまま使える**。
- ViT-VQGANによるトークン化で**圧縮・抽象化された表現が得られる**。

#### Q. Partiは公開されてるの？

- モデル自体は未公開。ただし、**PartiPrompts (P2)**や高解像度生成例は [公式サイト](https://parti.research.google) で閲覧可能。


## CM3Leon  
**論文名**: *Scaling Autoregressive Multi-Modal Models: Pretraining and Instruction Tuning*  
**URL**: [https://arxiv.org/abs/2309.02591](https://arxiv.org/abs/2309.02591)  
**発表日**: 2023-09-05  


### ✅ ポイント

- **CM3Leon（カメレオン）は、テキストと画像を統一的なトークン系列で扱える自己回帰型マルチモーダルモデル**。
- モデルは Decoder-only Transformer（GPT型）で構成され、**トークン化されたテキストと画像を順番に自己回帰的に予測**。
- 画像は **VQトークナイザで8192語彙のcodebook ID（整数）列**に変換され、モデルは**そのIDを予測**する（ベクトルではなく番号）。
- テキストと画像トークンは共通の語彙空間（例：text: 56K、image: 8K → 合計64K）にマッピングされ、**softmax over 64K**でトークンを逐次予測。
- **Pretrainingではretrieval（検索強化）とmasked infilling学習**を組み合わせ、**Finetuningでは指示付きのマルチタスク学習**を行う。


### 🧪 Pretraining（Retrieval + CM3 Objective）擬似コード

```python
# テキスト・画像のトークン化
caption = "A dog running in snow"
text_tokens = text_tokenizer(caption)              # shape: (Lt,)
image_tokens = image_tokenizer(image)              # shape: (Li=1024,)

# クエリ系列（text + image）
query_tokens = text_tokens + ["<break>"] + image_tokens + ["<break>"]  # shape: (Lt + 1 + Li + 1,)

# Retrieval（CLIPベース）
query_vec = clip_encoder(caption, image)           # shape: (512,)
retrieved = dense_retrieve(query_vec, memory_bank, top_k=2)
retrieved_tokens = flatten([
    text_tokenizer(t) + ["<break>"] + image_tokenizer(img) + ["<break>"]
    for t, img in retrieved
])  # shape: (Lr ≈ 2×(Lt+Li+2),)

# ランダムスパンをマスク
mask_start, mask_end = select_span(query_tokens)
masked_span = query_tokens[mask_start:mask_end]
masked_query = (
    query_tokens[:mask_start] + ["<mask>"] +
    query_tokens[mask_end:] + ["<infill>"] +
    masked_span
)

# モデル入力（retrieved + masked_query）
input_tokens = retrieved_tokens + masked_query
logits = transformer(input_tokens[:-1])            # shape: (L-1, V=64K)
targets = input_tokens[1:]                         # shape: (L-1,)
loss = cross_entropy(logits, targets)
update(model, loss)
```


### 🧪 Finetuning（Instruction Tuning）擬似コード

```python
# タスク例：画像編集
instruction = "Edit the image: Make the sky look like sunset"
instr_tokens = text_tokenizer(instruction)         # shape: (L_instr,)
input_img_tokens = image_tokenizer(input_img)      # shape: (1024,)
target_img_tokens = image_tokenizer(target_img)    # shape: (1024,)

# 構成：[prefix] + <break> + [画像] + <break> + [出力画像]
input_tokens = (
    instr_tokens + ["<break>"] +
    input_img_tokens + ["<break>"] +
    target_img_tokens
)

logits = transformer(input_tokens[:-1])            # shape: (2047, 64K)
targets = input_tokens[1:]                         # shape: (2047,)
loss = cross_entropy(logits, targets)
update(model, loss)
```


### 🔎 推論時の擬似コード（テキスト→画像）

```python
prompt = text_tokenizer("A golden retriever in a forest") + ["<break>"]

generated_tokens = []
for _ in range(1024):
    logits = transformer(prompt + generated_tokens)
    probs = softmax(logits[-1])                    # shape: (64K,)
    token_id = sample_or_argmax(probs)
    generated_tokens.append(token_id)

image = vq_decoder(generated_tokens)
```


### 🧠 モデル例（CM3Leon-7B）

| 項目 | 内容 |
|------|------|
| アーキテクチャ | Decoder-only Transformer |
| 層数 | 32 |
| 埋め込み次元 | 4096 |
| 語彙数 | 56,320 (text) + 8,192 (image) = 約64K |
| 入力系列長 | 最大 4096トークン（text + image） |
| トークンタイプ | 全て整数ID（textもimageも） |
| 出力 | トークンIDのsoftmax分布 |
| 画像復元 | VQ decoder（Gafni et al. 2022）で復元 |


### ❓ よくある質問

#### Q. テキストと画像で語彙が違うのに、どうやってsoftmaxするの？
- 両方を**単一の語彙空間**にまとめる（text: 0〜56K、image: 56K〜64K）→ softmax対象は64K次元。

#### Q. Decoderは埋め込みベクトルを予測する？
- **予測しない**。**codebookのインデックス（ID）を予測**し、Decoderがそれを画像に復元。

#### Q. <mask> / <infill> / <break> の役割は？
- `<mask>`：マスク対象の場所
- `<infill>`：補完出力の開始点
- `<break>`：モダリティ（text/image）の切り替えを示すマーカー

#### Q. PretrainingとFinetuningの違いは？
| 項目 | Pretraining | Finetuning |
|------|-------------|------------|
| 構文 | `<mask>...<infill>` | `prefix + <break> + input + <break> + output` |
| 学習目的 | in-filling（補完） | instruction理解 + 自己回帰出力 |
| Retrieval | 使用（CLIPで検索） | 使用しない |
| タスク形式 | 自己教師あり | 教師あり（指示付き） |


### 📦 CM3Leonのタスク例（SFTで使用）

| タスク | 入力例（prefix） | 出力 |
|--------|------------------|------|
| 画像編集 | `"Edit the image: Add sunset sky"` + image | 変換画像 |
| キャプション生成 | `"Describe the image"` + image | テキスト |
| VQA | `"Question: What is the dog doing?"` + image | `"Running"` |
| ポーズ条件生成 | `"Generate from pose"` + pose map | 人物画像 |

## AnyGPT

**論文名**: AnyGPT: Unified Multimodal LLM with Discrete Sequence Modeling
**URL**: [https://arxiv.org/abs/2402.12226](https://arxiv.org/abs/2402.12226)
**発表日**: 2024-03-07（v3）

### ✅ ポイント

* **画像・音声・音楽・テキストのすべてのモダリティを離散トークン化し、統一的にLLMで処理可能に**。
* **モデルアーキテクチャや学習パラダイムを変更せずにマルチモーダル対応**（LLaMA-2など既存LLMをそのまま利用）。
* **入力も出力も任意のモダリティ**（Any-to-Any）を扱えるマルチモーダル汎用LLM。
* **Instruction dataset（AnyInstruct-108k）を自動合成**し、多ターン対話でマルチモーダル生成を学習。
* 音声生成（SoundStorm）、画像生成（Diffusion）、音楽生成（Encodec）などを**分離構成で効率良く復元**。

### 🧪 学習の疑似コード（モダリティ共通・離散トークン列でのNext Token Prediction）

```python
# Step 1: すべてのモダリティをトークン化
tokens = [<sos>] + image_tokens + speech_tokens + text_tokens + music_tokens + [<eos>]

# Step 2: 自己回帰的に次のトークンを予測
for step in range(training_steps):
    logits = LLM(tokens[:-1])  # 入力を1つ前まで
    loss = cross_entropy(logits, tokens[1:])  # 次トークンを予測
    loss.backward()
    optimizer.step()
```


### 🔎 推論時の疑似コード（例：音声→画像）

```python
# 入力音声をトークン化
speech_tokens = SpeechTokenizer.encode(audio_input)
prompt = [<sos>] + speech_tokens + ["Please generate an image."]

# 自己回帰的に画像トークンを生成
generated_tokens = autoregressive_sampling(LLM, prompt)

# 出力トークンから画像を復元
image_tokens = extract_image_tokens(generated_tokens)
output_image = ImageDetokenizer.decode(image_tokens)
```

### 🧠 モデル例（構成）

#### 1. Tokenizer（すべて離散トークン列に変換）

| モダリティ  | Tokenizer       | vocab         | 特徴                          |
| ------ | --------------- | ------------- | --------------------------- |
| Image  | SEED Tokenizer  | 8192          | ViT + Q-Former + VQ         |
| Speech | SpeechTokenizer | 1024          | RVQ（8層、semantic + acoustic） |
| Music  | Encodec         | 8192 (2048×4) | RVQ（4層、50Hz）                |

#### 2. LLM本体

* LLaMA-2（7B）をベース
* モダリティごとの語彙を追加 → Embedding行列と出力層を拡張

#### 3. De-tokenizer

| モダリティ  | 復元方法                                    |
| ------ | --------------------------------------- |
| Image  | SEED latent → Diffusion Decoder（unCLIP） |
| Speech | SoundStorm（acoustic token生成）→ Decoder   |
| Music  | Encodec decoder                         |

### ❓ よくある質問（FAQ）

#### Q. なぜLLM本体を改変せずに済むの？

* 離散トークン列に変換することで、テキストと同じ形式に統一されるため。
* 語彙表とEmbeddingの拡張だけで対応可能。Transformer本体や学習目標はそのまま。

#### Q. モダリティごとにトークンが異なるのに統一処理できるの？

* トークン列には `<soi>`（start of image）や `<som>`（start of music）などの**特殊トークンを挿入**。
* モダリティの境界が明確になり、Transformerが区別できるようになる。

#### Q. なぜ離散表現（VQ-VAE、RVQ）を使うの？

* モダリティごとの高周波・ノイズ成分を除去し、意味的な低周波情報だけを抽出できる。
* テキストと同じ形式で学習可能にし、モデルの安定性と効率性が向上する。

#### Q. CM3Leonとの違いは？
* CM3Leonは画像とテキストのみ、AnyGPTは音声・音楽も含む**4モダリティ対応**。

# 参考
- [GPT-4oとGemini-2.0の画像生成能力はいかにして作られているのか](https://zenn.dev/discus0434/articles/gemini-2-0-mm)