---
# System prepended metadata

title: Diffusion Model原理剖析-李宏毅教授課程筆記(1/4)

---

# Diffusion Model原理剖析-李宏毅課程筆記(1/4)
>講者：李宏毅
主題：Diffusion Model 原理剖析 (1/4)（optional）
影片連結：[【生成式AI】Diffusion Model 原理剖析 (1/4) (optional)](https://youtu.be/ifCDXFdeaaM?si=1qExlH2mYighQnTc)

## 前情提要：Diffusion Model 的基本概念
![image](https://hackmd.io/_uploads/HkTTlpreZe.png)

Diffusion 的直觀概念，可以用兩個過程來描述：

1. Forward process（前向擴散）
從一張乾淨的 image 開始，逐步加入 noise。
噪聲越加越多，最後變成一張完全看不出原圖的「純雜訊」影像。
2. Reverse process（反向生成）
一開始給模型一張「全部都是 noise」的影像。
每一步執行 denoise，把一點點噪聲移除、讓結構慢慢浮現。
多次重複後，最後得到一張完整、清晰的生成影像。

>**Diffusion Model 的核心概念：**
>把「加噪」當作 forward process，把「去噪生成」當作 reverse process。
 
 ## Diffusion Model 與 VAE 的對應關係
老師先將 Diffusion Model 和 VAE 進行比較，因為兩者其實非常像。
![image](https://hackmd.io/_uploads/rJLXp2Bl-e.png)
### VAE 的結構回顧
- **Encoder**：把 image 映射到 latent representation
 $$x \xrightarrow{\text{encoder}} z$$
 
- **Decoder**：再從 latent 還原回 image  
  
  $$z \xrightarrow{\text{decoder}} \hat{x}$$
  

### 把 Diffusion 看成一種「奇怪的 VAE」
在 Diffusion Model 裡：
  - **加噪的過程** 可以視為一種 encoder：
    - 把乾淨圖片 $(x_0)$ 加上N次 Gaussian noise，直到最後變成純雜訊 $(x_T)$。
    - 這個「加噪 encoder」**不是 neural network**，而是**人為設計的固定 process**。
  - 最後的「只有雜訊的 image $(x_T)$」就扮演類似 VAE 裡 latent representation 的角色。
  - **Denoise 的過程** 則扮演 decoder 的角色：
    - 從雜訊圖開始，逐步去噪，最後還原出原始影像。
> 對應關係：
> VAE：  
>   - encoder：\(x \rightarrow z\)（學出來的 NN）  
>   - decoder：\(z \rightarrow x\)（學出來的 NN）  
>
>Diffusion：  
>   - encoder：\(x_0 \rightarrow x_T\)（加噪，**人設計、不學習**）  
>   - decoder：\(x_T \rightarrow x_0\)（去噪，**用 NN 學**）



## DDPM 演算法在做什麼
DDPM（Denoising Diffusion Probabilistic Model）的訓練演算法，也就是原始 DDPM 論文中的 training procedure。
![image](https://hackmd.io/_uploads/BkjhCOXlbx.png)
### Training

演算法的第一行是 `repeat`：
  - 意思是重複執行後面第 2～5 行，直到收斂`converged`。

### 第一步：從資料庫抽乾淨圖 $x_0$

從資料庫中 **sample 一張乾淨的圖片**：
$$
x_0 \sim q(x_0)
$$

在 Diffusion 相關文獻中的慣例：
$x_0$代表**乾淨的圖（真實的 data）**。

### 第二步：從 $\{1, \dots, T\}$ 抽一個時間步 $t$

從 $1$ 到 $T$ 之間均勻隨機抽一個整數：
$$
t \sim \text{Uniform}(\{1, \dots, T\})
$$

- $T$ 通常設為一個較大的數，例如 $T = 1000$。
- 例如這次可能抽到 $t = 968$。

### 第三步：Sample 一個 Gaussian noise $\epsilon$

從標準常態分布 sample 一個 noise：
$$
\epsilon \sim \mathcal{N}(0, I)
$$

- $\epsilon$ 的維度大小跟 image $x_0$ 一樣。
- 內容全部是雜訊，看不出任何有意義的結構。



### 第四步：直接從 $x_0$ 生成 noisy image $x_t$
![image](https://hackmd.io/_uploads/SJ0VdaHeZx.png)
接下來是訓練演算法中最重要的一步：  
**利用 closed-form 公式直接生成某個時間步 $t$ 的 noisy image。**

#### 4.1 事先定義好的 noise schedule：$\bar{\alpha}_1, \dots, \bar{\alpha}_T$

在訓練前先定義一個序列：
$$
\bar{\alpha}_1, \bar{\alpha}_2, \dots, \bar{\alpha}_T
$$

- 這些 $\bar{\alpha}_t$：
  - 全部是**人為設計的常數**。
  - 通常設計為：$t$ 越大，$\bar{\alpha}_t$ 越小（由大到小）
直覺：

- $t$ 越大 $\Rightarrow$ $\bar{\alpha}_t$ 越小  
  $\Rightarrow$ 類似「原始訊號比例減少、雜訊比例增加」。

#### 4.2 用單一步驟混出 noisy image

在 DDPM 訓練中，對於任意時間步 $t$，直接用下式生成 $x_t$：
$$
x_t = \sqrt{\bar{\alpha}_t}\, x_0 + \sqrt{1 - \bar{\alpha}_t}\, \epsilon
$$

- $\sqrt{\bar{\alpha}_t}$：乾淨圖 $x_0$ 的權重。
- $\sqrt{1 - \bar{\alpha}_t}$：noise $\epsilon$ 的權重。
- $t$ 越大：
  - $\bar{\alpha}_t$ 越小 $\Rightarrow$ 原圖所占比例越少。
  - $1 - \bar{\alpha}_t$ 越大 $\Rightarrow$ 雜訊所占比例越多。

> **重要差異：**
> - 「直覺上的 diffusion」：每一步加一點點 noise，連續加很多步。
> - **DDPM 的實際訓練作法**：  
>   對每個 $t$，直接用上式 **一次** 生出對應噪音程度的 $x_t$，  
>   並沒有真的模擬「加噪 $t$ 次」。

![image](https://hackmd.io/_uploads/r1Cauarx-e.png)

![image](https://hackmd.io/_uploads/BkLx5prlZe.png)


#### 5. Noise Predictor 網路 $\varepsilon_\theta$ 的訓練目標

#### 5.1 定義 Noise Predictor

定義一個網路：
$$
\varepsilon_\theta(x_t, t)
$$

- **輸入：**
  - noisy image $x_t$
  - 時間步 $t$（通常會做 time embedding）
- **輸出：**
  - 模型對「當初混入的 noise」的預測，記作：
    $$
    \hat{\epsilon} = \varepsilon_\theta(x_t, t)
    $$

#### 5.2 Ground truth 是什麼？

因為在第三步，我們已經從 $\mathcal{N}(0, I)$ 取樣過真正的 noise $\epsilon$，  
所以訓練時的正確答案（ground truth）就是：

$$
\epsilon_{\text{GT}} = \epsilon
$$

也就是說，noise predictor 的任務是：

> 給定 $(x_t, t)$，去預測當初「混入」$x_t$ 的那個 $\epsilon$。

#### 5.3 Loss function（概念形式）

雖然老師這段還沒有寫完整的 loss 推導，但概念上是：

$$
\mathcal{L}(\theta) = 
\mathbb{E}_{x_0, t, \epsilon}\Big[
\big\|\epsilon - \varepsilon_\theta(x_t, t)\big\|^2
\Big]
$$

也就是：

1. 從資料庫 sample 一張 $x_0$。
2. 從 $\{1, \dots, T\}$ sample 一個 $t$。
3. 從 $\mathcal{N}(0, I)$ sample 一個 $\epsilon$。
4. 用
   $$
   x_t = \sqrt{\bar{\alpha}_t} x_0 + \sqrt{1-\bar{\alpha}_t}\epsilon
   $$
   算出 noisy image。
5. 把 $(x_t, t)$ 丟進網路，得到 $\varepsilon_\theta(x_t, t)$。
6. 用 **MSE** 讓預測的 noise 接近真實的 $\epsilon$。


#### 6. 「概念上的 Diffusion」vs「DDPM 真的在做的事」

這裡是李宏毅老師特別強調的重點：  
**演算法實際在做的事情，跟我們直覺想像的流程不太一樣。**

#### 6.1 我們「想像中」的運作方式

直覺上會這樣想：

- Forward（加噪）：
  $$
  x_0 \rightarrow x_1 \rightarrow x_2 \rightarrow \dots \rightarrow x_T
  $$
  每一步加一點點 noise，圖片越來越糊。

- 訓練 noise predictor 時：
  - 每一步學的是：  
    $$
    x_t \xrightarrow{\text{denoise}} x_{t-1}
    $$
  - 也就是「把這一步額外加進來的那一點點噪訊去掉」。

#### 6.2 DDPM 訓練「實際上」在做的事

- 訓練時 **並沒有真的一步一步加噪**：
  - 不會平常先算出 $x_1, x_2, \dots, x_{t-1}$ 再來算 $x_t$。
  - 而是直接用 closed-form：
    $$
    x_t = \sqrt{\bar{\alpha}_t} x_0 + \sqrt{1-\bar{\alpha}_t} \epsilon
    $$
    一次得到對應時間步 $t$ 的 noisy image。

- Noise predictor 的目標是：
  - **直接預測整個 $x_t$ 裡混入的 noise $\epsilon$**，  
    而不是僅僅預測「$x_{t-1} \rightarrow x_t$ 這一小步」。

> 老師的總結：  
> 想像中：noise 是一點一點加、denoise 也是一點一點抹。  
> 實際訓練：針對每個 $t$，一次把「對應程度的 noise」加進去，  
> 再一次預測整個 $\epsilon$。

---
### 生成（Sampling）過程：Reverse Process 的演算法
![image](https://hackmd.io/_uploads/B1olCarlZe.png)

接下來老師說明 DDPM 「生圖」時的 reverse process 演算法，  
這裡會再出現一個讓人困惑的地方：**為什麼 denoise 的同時還要再加 noise？**

#### 第一步：從純雜訊開始

首先 sample 一張「全部都是 noise」的影像：
$$
x_T \sim \mathcal{N}(0, I)
$$

在文獻中，一般把 $x_T$ 當成：

- 一張完全由雜訊構成的起始圖。

#### 第二步：Reverse Process 的迭代公式

從 $t = T$ 一直到 $t = 1$，重複以下步驟：

1. 每一個 $t$，先再 sample 一個 noise：
   $$z \sim \mathcal{N}(0, I)$$
2. 將 $x_t$ 轉成 $x_{t-1}$ 的公式大致如下（概念結構）：
    $$x_{t-1}=\frac{1}{\sqrt{\alpha_t}}\left(x_t- \frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}}\varepsilon_\theta(x_t, t)\right)+ \sigma_t z$$

   - $\varepsilon_\theta(x_t, t)$：noise predictor 預測的 noise。
   - $\alpha_t$、$\bar{\alpha}_t$、$\sigma_t$：事先設計好的參數或由 schedule 推導而得。
   - 注意：最後還加上一個 $\sigma_t z$ 的隨機噪聲項。

#### 用圖像化的角度來理解
![image](https://hackmd.io/_uploads/rygu36rgbe.png)

- 手上有上一輪的結果 $x_t$。
- 準備好兩組數列：
  - $\bar{\alpha}_1, \dots, \bar{\alpha}_T$
  - $\alpha_1, \dots, \alpha_T$
- 把 $x_t$ 和 $t$ 丟進 noise predictor，得到：
  $$
  \hat{\epsilon} = \varepsilon_\theta(x_t, t)
  $$
- 然後：
  - 把 $\hat{\epsilon}$ 乘上一個係數 $\dfrac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}}$。
  - 從 $x_t$ 中「減掉」這個噪聲項。
  - 再乘上 $\dfrac{1}{\sqrt{\alpha_t}}$，  
    得到一張「看起來更乾淨」的影像。
- 按理說，這時候就應該得到 $x_{t-1}$，  
  但演算法還會再加上：$+\ \sigma_t z$
  又丟進一點新的 noise。

#### 為什麼還要再加一個 noise？(本節還沒說出原因)

這裡是第二個暗藏玄機的地方：

- 直覺上，我們以為：
  去噪就是把噪音預測出來，然後從 $x_t$ 減掉，就結束了。

- 但在 DDPM 裡：
  - 即使在 reverse process 中，  
    每一步仍然會再 sample 一個新的 noise $z$，再加回影像中。
  - 這看起來像是「一邊去噪、一邊再加噪」，非常違反直覺。

李宏毅老師也形容這部分是「令人匪夷所思的操作」，  
這也是他說 DDPM 演算法「暗藏玄機」的原因之一。

---

下一節：[Diffusion Model原理剖析-李宏毅課程筆記(2/4)](https://hackmd.io/@1I0zSdF_QSi-tPfJXnBEXA/Hy5EXRSlbl)


