搜尋課程與筆記

搜尋筆記

輸入主題、關鍵字或單元編號,例如 Flow Matching、U4。

    按 Esc 關閉 · ⌘ / Ctrl K 開啟搜尋

    U1.5 11 分鐘閱讀 2026年10月

    U1.5 實作:建立這個單元的 Toy

    本篇重用9 篇

    先在淺水區把每件事看清楚

    這個單元的理論講完了,但還沒有一行程式跑過。接下來要做的,是把整個單元的東西縮成一個幾秒就能重跑的小實驗。

    之後三個單元的理論都要對回同一組實驗,所以這個 toy 值得認真建。選 2D 有三個很實際的好處:

    • 有標準答案。 資料點是有限的,所以 ptp_t 就是一個混合 Gaussian——真實的 ptp_t、score、後驗均值全部可以精確算出來。網路學得好不好不用猜,可以直接比。
    • 看得見。 軌跡、向量場都能直接畫在平面上,不必靠指標想像。
    • 跑得快。 訓練幾秒鐘結束,改一行就能重跑;想試一個念頭不用等半天。

    設定:資料是兩個月牙(sklearn.datasets.make_moons,n=2000n=2000,噪聲 0.05),標準化到零均值單位變異數。網路是三層 MLP、寬 128,輸入 (xt,t)(x_t,t),tt 用 sinusoidal embedding。T=1000T=1000,linear schedule β1=10−4→βT=0.02\beta_1=10^{-4}\to\beta_T=0.02。

    下載 Week 3:Gaussian diffusion 與解析 score notebook(.ipynb)

    Notebook 內容。 用可解析的 2D Gaussian mixture 實作 forward noising、精確 score 與 Tweedie posterior mean;內含固定 seed、三組可重跑視覺化與改變 mixture 重疊程度的 TODO。這是解析 toy,不依賴任何 checkpoint。

    步驟 1:forward 與訓練

    def q_sample(x0, t, eps):                 # forward process 的 closed form
        ab = alpha_bar[t][:, None]
        return ab.sqrt() * x0 + (1 - ab).sqrt() * eps
    
    for step in range(n_steps):               # denoising 回歸的五行
        x0  = sample_data(batch)
        t   = torch.randint(1, T + 1, (batch,))
        eps = torch.randn_like(x0)
        xt  = q_sample(x0, t, eps)
        loss = ((model(xt, t) - eps) ** 2).mean()
        loss.backward(); opt.step(); opt.zero_grad()

    跑起來之後,loss 會在幾百步內從 ~1 掉到 0.3 附近,然後就停在那裡不動了。

    loss 停住、而且離 0 很遠,
    是哪裡寫錯了嗎?

    課堂提問Q1

    一般的回歸任務,我們會期待 loss 一路往 0 掉。所以看到它停在 0.3,直覺的下一步是:把網路加寬、學習率調一調、多訓十倍步數。

    這樣做 loss 會掉下去嗎?

    先想一想,再展開看整理後的答案

    不會,而且一點都不會——那個 0.3 不是訓練不夠,是理論算得出來的地板。

    U1.3 已經把這條寫出來了:ϵθ\epsilon_\theta 的最佳解是 E[ϵ∣xt]\mathbb E[\epsilon\mid x_t],不是訓練時抽到的那一個 ϵ\epsilon,所以即使訓到最佳,loss 也只會停在條件變異數上:

    min⁡θL=Et,xt[tr⁡Var⁡(ϵ∣xt)].\min_\theta \mathcal L=\mathbb E_{t,x_t}\Big[\operatorname{tr}\operatorname{Var}\big(\epsilon\mid x_t\big)\Big].

    加寬網路只會讓你更快走到這條地板,不會穿過它。而且這個下界隨 tt 變,兩端剛好相反:

    • tt 很小:xtx_t 幾乎就是 x0x_0。看到 xtx_t 等於看到原圖——但那不會告訴你當初抽到的是哪一個 ϵ\epsilon,因為它的貢獻被 σt\sigma_t 壓到幾乎看不見。條件變異數接近 1,loss 下界接近 1。
    • tt 很大:xtx_t 幾乎就是 σtϵ\sigma_t\epsilon 本身,ϵ\epsilon 幾乎可以直接讀出來。條件變異數接近 0,loss 下界接近 0。

    x0x_0 是 Gaussian 時這個下界算得出精確值:Var⁡(ϵ∣xt)=αˉt\operatorname{Var}(\epsilon\mid x_t)=\bar\alpha_t。所以那條曲線就是 αˉt\bar\alpha_t 本身,而把所有 tt 平均起來就是那個停住的非零數字——DDPM 的 linear schedule 下 αˉt‾≈0.28\overline{\bar\alpha_t}\approx0.28。

    該看的不是 loss 停在多少,而是它隨 tt 長什麼形狀。

    實作建議: 把 loss 依 tt 分箱畫出來(例如每 100 個 tt 一箱),你會看到一條從 ~1 掉到 ~0 的曲線。這條曲線比單一個平均 loss 有用得多——它讓你看得出模型是在哪一段 tt 沒學好。

    ε-prediction loss 的 Gaussian 解析對照:紅色下界隨 timestep 下降,藍點為分箱 loss 示意,虛線表示跨 timestep 的平均;左右比較資料主導與 noise 主導時的條件不確定性。

    圖:loss 的下界隨 tt 下降。 這張圖用互相獨立的 X0,ϵ∼N(0,I)X_0,\epsilon\sim\mathcal N(0,I) 作解析對照;loss 按維度平均時,紅線為 αˉt\bar\alpha_t,藍點只是分箱 loss 的示意,不是 notebook 的實測值。虛線 ≈0.28\approx0.28 是跨 timestep 的平均,不是每個 tt 都有同一條地板。兩個月牙 toy 的下界仍由 posterior uncertainty 決定,不能直接套用這個 Gaussian 例子的 αˉt\bar\alpha_t。

    步驟 2:畫 score field(圖 a)

    在 [−3,3]2[-3,3]^2 的網格上,對 t∈{50,300,700,950}t\in\lbrace 50,300,700,950 \rbrace 各畫一張,每張疊兩組箭頭:

    • 模型:−ϵθ(x,t)/σt-\epsilon_\theta(x,t)/\sigma_t
    • 真值:exact_score(x, t)

    會看到的事情:tt 大時箭頭整片指向原點,tt 小時箭頭指向月牙——跟 U1.3 的 demo 一樣。而模型與真值在資料密集的地方吻合,在遠離資料的角落偏差變大,因為那裡幾乎沒有訓練樣本落過。

    這個偏差不是無害的,步驟 4 會看到它的後果。

    步驟 3:三種 parametrization 真的等價嗎?(圖 b)

    不重訓。取一批 (xt,t)(x_t,t),只從 ϵθ\epsilon_\theta 換算:

    同一個 noise predictor,怎麼換成另兩種輸出?

    x^0=xt−σtϵθαˉt,v^=αˉt ϵθ−σt x^0, \begin{gathered} \reveal{1}{\hat x_0=} \reveal{3}{\frac{\reveal{1}{x_t}\reveal{2}{-\sigma_t\epsilon_\theta}}{\sqrt{\bar\alpha_t}}},\\[.2em] \reveal{4}{\hat v=\sqrt{\bar\alpha_t}\,\epsilon_\theta-\sigma_t\,\hat x_0,} \end{gathered}
    1. 先拿同一批 xtx_t,不改模型,也不重新訓練。
    2. 模型已經給出 ϵθ\epsilon_\theta,先扣掉它在 xtx_t 中對應的 σtϵθ\sigma_t\epsilon_\theta。
    3. 再除以信號係數 αˉt\sqrt{\bar\alpha_t},就得到 x^0\hat x_0。
    4. 把同一份 ϵθ\epsilon_\theta 與剛算出的 x^0\hat x_0 組合成 v^\hat v,仍然不用重訓。

    先做一件一行就能做完的事:從 v^\hat v 和 xtx_t 反解回 ϵ^\hat\epsilon,確認它和原本的 ϵθ\epsilon_\theta 只差在浮點誤差(≲10−6\lesssim10^{-6})之內。三種寫法真的是同一個東西,這一步就是 U1.2 說的「親手驗證一次」。

    驗完之後再拿 x^0\hat x_0 跟 exact_posterior_mean 比對,畫出「x^0\hat x_0 的誤差對 tt」的曲線。

    會看到的事情:tt 大時誤差被放大——因為換算要除以趨近 0 的 αˉt\sqrt{\bar\alpha_t}。U1.2 說三種 parametrization 在數學上等價,這條曲線就是它們在數值上不等價的地方;而 vv 之所以在兩端都不退化,正是因為它不需要做這種除以趨近 0 的係數的換算。

    步驟 4:DDPM 與 DDIM 軌跡(圖 c)

    下面分別沿用 Ho、Jain 與 Abbeel 的 DDPM [1],以及 Song、Meng 與 Ermon 的 DDIM [2],只把它們放進同一支函數裡比較。

    def ddim_step(xt, t, s, eta=0.0):
        eps = model(xt, t)
        x0_hat = (xt - sig[t] * eps) / ab[t].sqrt()
        sigma_s = eta * ((1 - ab[s]) / (1 - ab[t]) * (1 - ab[t] / ab[s])).sqrt()
        dir_xt = (1 - ab[s] - sigma_s**2).sqrt() * eps
        return ab[s].sqrt() * x0_hat + dir_xt + sigma_s * torch.randn_like(xt)

    η=0\eta=0 是 DDIM,η=1\eta=1 是 DDPM——一支函數就夠,這正是 U1.4 那條一般式。固定 32 個起點 xTx_T,對步數 {10,50,1000}\lbrace 10,50,1000 \rbrace 各跑一次,把完整軌跡畫出來。

    會看到的事情:DDIM 10 步的軌跡是彎的,而且終點常常落在月牙外側;1000 步時終點幾乎收在同一組位置,但路徑仍然是彎的。這張圖要留好,U2 開頭會直接用它。

    補充這裡和課文 demo 的差別:現在的 score 有誤差了

    U1.4 的互動 demo 用的是精確的 score,所以看不到「網路不準」造成的效果。這裡你手上是一個真的訓出來的網路——它在低密度區會不準(步驟 2 看到的),於是取樣時如果軌跡跑到那些地方,誤差會被進一步放大。

    這也是為什麼作業 3 值得做:帶噪聲的取樣器(η>0\eta \gt 0)有機會把偏離的樣本拉回當下的 ptp_t,而這件事只有在 score 有誤差時才看得出好處。

    用精確的 score 看不到加噪聲的好處——那個好處是拿來對付網路誤差的。

    作業

    1. Parametrization 等價。 分別以 x0x_0-、ϵ\epsilon-、vv-prediction 訓練三個網路,換算成 ϵ\epsilon 之後比較 DDIM 50 步終點的 W2W_2(Wasserstein-2 距離,兩堆樣本之間的距離)。它們應該接近但不相同——說明差異來自 U1.2 的哪一節。
    2. 加權。 以 ϵ\epsilon-prediction 訓練,但把 loss 乘上 1/SNR(t)1/\mathrm{SNR}(t)。比較 score field 在 tt 小與 tt 大時的誤差分布,跟均勻加權的版本有什麼不同。
    3. 把 U1.4 的判準做成定量版。 對步數 {5,10,20,50,100,1000}\lbrace 5,10,20,50,100,1000 \rbrace,畫 DDPM(η=1\eta=1)與 DDIM(η=0\eta=0)終點的 W2W_2 曲線。先寫下你的猜測再跑。 這個 toy 的 score 是精確算出來的,所以照 U1.4 的判準,你應該預期確定性那一端不太會輸;如果你量到相反的結果,先去檢查是不是 score 不夠精確。
    4. (選)Anderson 反向 SDE。 讀 Anderson 1982 [3] 第 2 節,說明 reverse SDE 的 score 項是從哪一個條件期望冒出來的,並指出它與 U1.3 的 Tweedie 公式是什麼關係。

    消化一下

    想一想

    訓練 loss 的下界隨 tt 怎麼變?

    想一想

    步驟 2 發現模型 score 在遠離資料的角落偏差很大。這件事會在哪裡造成問題?

    想一想

    為什麼同一支 ddim_step 函數可以同時當 DDPM 與 DDIM 用?

    參考文獻

    1. Ho, J., Jain, A., Abbeel, P. Denoising Diffusion Probabilistic Models. NeurIPS 2020.
    2. Song, J., Meng, C., Ermon, S. Denoising Diffusion Implicit Models. ICLR 2021. (步驟 4 的 ddim_step 一般式。)
    3. Anderson, B. D. O. Reverse-time diffusion equation models. Stochastic Processes and their Applications, 1982. (作業 4。)