M5.3 只看得到樣本,怎麼調機器:對 Generator 微分
本篇重用M0.0霧中下山:Gradient 與方向·M5.1用錯的機率表下注一年會多輸多少:KL Divergence 與 Cross-Entropy·M0.3漂流的溫度計:全導數、微分穿過積分與 JVP
一台把亂數變成產品的機器
工廠裡有一台機器:每次按下按鈕,它內部擲一把骰子(亂數 ),然後照它的設定 把骰子的結果加工成一個產品 。你看不到骰子、看不到內部,只看得到吐出來的產品。
客戶給了你一個目標:產品的分佈要像某個規格 ——不是每個產品都一樣,而是整體的散佈要對。你可以轉機器上的旋鈕 。你要往哪個方向轉?
先用直覺回答:你會怎麼做?拿一批產品、跟規格比、然後怎麼把「比出來的差距」變成「旋鈕該轉的方向」?寫下你有多確定。
課堂上的回答通常是「多抽一些,看哪邊多了就往反方向調」。這是對的方向,但它說不出每個旋鈕該轉多少——尤其當旋鈕很多( 是幾百萬維)時,「哪邊多了」根本無法逐一看。我們需要的是一個梯度:分佈的差距對每個旋鈕的偏導數。
課堂提問Q1
翻成數學。「產品的分佈」是 的什麼函數?「跟規格的差距」用哪個量寫?直接對它微分會卡在哪裡?
先想一想,再展開看整理後的答案
產品 ,(骰子的分佈,固定、與 無關)。產品的分佈 是 經 的 pushforward——同一把骰子、不同的 ,吐出不同的分佈。差距用 M5.1 的 KL:
(方向是 :對「機器把產品放在規格幾乎不允許的地方」罰得重——這正是「不要生出不合規格的產品」要的方向。)
直接微分會卡在兩處。第一,期望是對 取的,而 本身隨 變——「抽樣」這個動作不可微,你沒辦法對「從一個分佈抽一個數」這件事求導。第二,被積函數裡有 ,它也隨 變。兩個 糾在一起。
解開第一個結的方法,就是這一篇的物件:把隨機性搬到 外面。 與「 然後 」是同一件事,但第二種寫法裡隨機的只有 ,它不依賴 ; 只出現在一個普通的、可微的函數 裡。這叫 reparameterization(重參數化)。
先抓住這個畫面:固定骰子,只轉旋鈕
想像你把機器內部的骰子換成一疊預先擲好的紙條:。現在機器不再隨機——同一張紙條、同一個 ,永遠吐出同一個產品 。轉一點旋鈕,每個產品都往某個方向動一點,動多少由 決定:旋鈕對第 個產品的靈敏度。
現在「分佈的差距」怎麼變?每個產品 站在一個地形上:地形的高度是 ——「機器認為這裡多常出現」減「規格認為這裡該多常出現」。產品站在高處(機器放太多、規格要太少)時,把它往地形低處推會讓差距變小。往低處推的方向是 (M0.0),而旋鈕能把它推的方向是 。兩者的內積,對所有紙條平均,就是梯度。
所以整條公式的畫面是:每個樣本站在「機器分佈 vs 規格」的地形上,地形的坡告訴它該往哪走,旋鈕的靈敏度告訴我們轉哪個旋鈕能讓它那樣走。
在一維上把它算出來
一維、 是一個實數。reparameterize 之後:
期望現在是對固定的 取的,可以直接把 搬進去(M0.3 的微分穿過積分)。被積函數裡 出現在兩處: 裡、以及 的下標裡。用 chain rule 全部展開:
(B) 看起來很麻煩——它是「分佈本身對 的變化率」在樣本處的值。但它的期望是零:
(第一個等號只是把 換回名字 ;最後一步又是微分穿過積分。)所以
多維時 換成 、 換成 Jacobian,形狀是「向量 矩陣」,其餘一字不改。
讀一遍每個符號。 是密度的對數梯度——有時叫 score function,它指向「密度上升最快」的方向,並且不需要知道 normalizing constant: 對 微分時 消失(M0.0 裡 的意義)。 是旋鈕的靈敏度,由機器本身給。整條公式說:梯度 在每個樣本處,機器的 score 減規格的 score,乘上靈敏度,取平均。
展開細節為什麼 (B) 消失這件事重要:兩種估計量與變異數
若不用 reparameterization,另一條路是「score-function estimator」(REINFORCE):∂θ E{p_θ}[f(x)] = E_{p_θ}[f(x)·∂_θ log p_θ(x)]。它不需要 G 可微、連 x 是離散的都能用,但變異數通常很大——f(x) 的絕對大小整個進入估計量。reparameterization 把「分佈怎麼變」換成「每個樣本怎麼動」,估計量只含 f 的梯度,變異數小得多(Mohamed et al. [3] 的系統比較)。
而 (B) 這一項:它的期望是零,但單一樣本上不是零。實作時若把 log p_θ(G_θ(z)) 對 θ 直接自動微分,autodiff 會忠實地算出 (A)+(B)——(B) 平均下來是零,卻帶進額外的雜訊。Roeder et al. [4] 指出把 (B) 手動去掉(對 p_θ 的參數做 stop-gradient、只讓梯度從 G_θ 流過)會得到變異數更低的估計量;在 p_θ = p* 的最佳點,去掉 (B) 的估計量每個樣本都恰好為零,保留 (B) 的則仍在抖。「一個期望為零的項,留著或去掉」是實作品質的分水嶺。
回到工廠:公式能用,但缺一樣東西
回答起點問題。要轉旋鈕,你需要在每個產品 處算三樣東西:
- ——機器的靈敏度。機器是你自己的,可微就有。
- ——規格的 score。若客戶給的規格是一條公式(例如「常態、均值 5、標準差 1」),直接算。若客戶只給了一批合規格的樣本、沒有公式——這是現實中最常見的情形——這一項你沒有。從樣本估一個分佈的 score 是一個獨立的問題(score matching [5]),要另外訓一個模型。
- ——機器自己的 score。這也不是免費的:你知道 ,但你不知道 的密度——pushforward 的密度要算 的 Jacobian,一般的 做不到。所以這一項也要另外估:拿機器吐出來的樣本、訓一個 score 模型。
於是「只看得到樣本、要調分佈」這件事的完整流程是:兩個 score 模型(一個學規格、一個學機器)加一個可微的機器,梯度是兩個 score 的差乘靈敏度。直覺「哪邊多了就往反方向調」的精確版本正是這樣——「哪邊多」由兩個 score 的差說出,「怎麼調」由靈敏度說出。
這個判斷依賴的假設: 對 可微、對 是連續的(產品若是離散的類別,reparameterization 就沒有直接版本,要用展開框裡的 score-function estimator 或其他 relaxation);兩個 score 估得夠準(尤其在樣本稀疏的區域,估錯的 score 會把產品推向錯的方向);以及 KL 的方向—— 允許機器「漏掉」規格的某一塊(mode dropping),若客戶要求每一種合規格的產品都要出現,該用另一個方向或另一個距離。
回到工廠:一維跑一次,然後把 (B) 留著看它抖
一維、、,所以 ;規格 。此時一切都有 closed form:,真梯度是 。兩個 score:、,差是 ——與 無關,每個樣本都給出精確的梯度;靈敏度 。
import numpy as np
rng = np.random.default_rng(0)
theta, target, lr = 0.0, 5.0, 0.1
for step in range(60):
z = rng.standard_normal(256)
x = theta + z # reparameterization:固定骰子 z,x 是 θ 的可微函數
score_model = -(x - theta) # ∇ₓ log p_θ(x)
score_target = -(x - target) # ∇ₓ log p*(x)
grad_A = np.mean((score_model - score_target) * 1.0) # (A):兩個 score 的差 × ∂G/∂θ
grad_B = np.mean((x - theta)) # (B):∂_θ log p_θ 在樣本處 —— 期望為零、單樣本不為零
theta -= lr * grad_A
if step % 15 == 0: print(step, round(theta, 3), round(grad_A, 3), round(grad_B, 3))
print(theta) # → 5.0
從 0 走到 5,grad_A 每步恰等於 (因為兩個 score 的差不依賴 ,這個例子裡 (A) 沒有抽樣雜訊)。grad_B 每步在 附近抖——它的期望是零,但每一批都不是零;若把它加進更新, 收斂後仍會在 5 附近抖動,而只用 (A) 的版本在最佳點每一步都精確為零。
刻意違反一個假設。 把 score_target 換成一個從 的 200 個樣本估出來的粗糙版本(例如用核密度估計取對數再差分):在樣本稀疏的尾端 score 估錯, 會收斂到 5 附近但帶偏差;樣本越少偏得越多。再把 換成 ——機器只會吐正的產品,pushforward 的密度 你不再有 closed form,score_model 那一行必須改成從機器樣本估——這就是「第三樣東西也不免費」的意思。
先消化一下
參考文獻
- Kingma, D. P., Welling, M. Auto-Encoding Variational Bayes. ICLR 2014.(reparameterization trick 的出處之一。)
- Rezende, D. J., Mohamed, S., Wierstra, D. Stochastic Backpropagation and Approximate Inference in Deep Generative Models. ICML 2014.(同時期獨立提出的「stochastic backpropagation」。)
- Mohamed, S., Rosca, M., Figurnov, M., Mnih, A. Monte Carlo Gradient Estimation in Machine Learning. JMLR 21, 2020.(score-function 與 pathwise(reparameterization)兩類估計量的系統比較與變異數分析。)
- Roeder, G., Wu, Y., Duvenaud, D. Sticking the Landing: Simple, Lower-Variance Gradient Estimators for Variational Inference. NeurIPS 2017.(把期望為零的 (B) 項去掉可以降低變異數。)
- Hyvärinen, A. Estimation of Non-Normalized Statistical Models by Score Matching. JMLR 6, 2005.(只有樣本時如何估 。)