生成模型顧名思義就是從機率分布中生成出新的樣本,比如說隨機變數就是從 uniform distribution 中生成的樣本。但是當此機率分布很複雜的時候,我們該怎麼依照這個複雜的機率分布生成新的樣本呢?前文提過可以用 rejection sampling 讓我們從無法積分的機率函數中產生樣本,問題是利用 rejection sampling 一次只能生成一個樣本,也就是說假如現在想要生成的是一張圖片,一次 rejection sampling 就只能生成一個像素,因此本篇文章要介紹的流生成模型是一種可以一次生成與訓練資料同類型樣本(例如一張圖片、一段文字)的方法。
流模型的概念是設計出一個函數,讓我們可以將一個我們已知如何生成樣本的分布(例如高斯分布)轉換成訓練資料的分布。
上圖取自於 Lilian Weng 的文章 Flow-based Deep Generative Models [1]。\(p(z_0)\) 是一個高斯分布,經過一步一步的轉換以後, x 便是最後我們想要生成的樣本。可以看出來在這個過程中機率分布會變得越來越複雜,意思是在學習過程中機率分布會越來越逼近於訓練資料的分布,這也是這個機器學習問題的目的:要學出一個機率分布 \(p(x)\) 使其逼近於訓練資料的機率分布。另外我們也看到在中間我們透過了 K 個函數 \(f_1, f_2, ... f_K\) 來轉換機率變數,要達成生成模型的目的時,這樣的函數需要滿足一些特定的條件,以下就要來介紹要怎麼設計這個函數。
Change of Variable Theorem
這邊要先用到一個工具:Change of Variable Theorem。這個定理是在描述從一個已知的機率分布 \(z \sim \pi(z)\),經由一個 1-1 mapping 的函數 f 轉換成 x:\(f(z) = x\),機率變數 x 的機率密度函數是什麼。首先因為 z 跟 x 都是機率變數,因此可以寫成:
\[
\int p(x)\ dx = \int \pi(z)\ dz = 1
\\
p(x) = \pi(z) \left | \frac{dz}{dx}\right | = \pi(f^{-1}(x))\left | \frac{df^{-1}}{dx}\right | = \pi(f^{-1}(x))\left | (f^{-1})'(x) \right |
\]
上面式子是 x 跟 z 都是一維的情形,而當 x 跟 z 都是多維時關係式如下:
\[
p(x) = \pi(z) \left | det \frac{dz}{dx}\right | = \pi(f^{-1}(x))\left | det \frac{df^{-1}}{dx}\right |
\]
這裡可以做個行列式的代換,而 \(df/dx\) 就是 f 的 Jaconbian 矩陣:
\[
det \frac{df^{-1}}{dx} = (det \frac{df}{dx})^{-1}
\]
上面的式子說明了 f 必須滿足兩個條件:
- 要能容易算出 f 的反函數
- 要能算出 f 的 Jaconbian 矩陣的行列式
為什麼叫做流模型?
上面討論的 f 其實就是一個輸入為 z,輸出為 x 的類神經網路,但是這個類神經網路必須滿足以上兩個條件,因此我們便無法隨意設計這個類神經網路,或者換句話說,這個類神經網路 f 的表達能力會因為這兩個條件而受限。為了解決這個問題,流模型的概念就如同上面的示意圖,把 K 個類神經網路串起來,這樣此類神經網路組合的表達能力就會比單個類神經網路還要強了,因此我們接下來要推導 \(\pi(z_0)\) 與經由 K 個類神經網路轉換而成的 \(p(x) = p(z_K)\) 他們之間的關係式。
現在假設 \(z_i = f_i(z_{i-1})\),則可以寫出 \(p_{i-1}(z_{i-1})\) 與 \(p_i(z_i)\) 的關係:
\[
p_i(z_i) = p_{i-1}(f_i^{-1}(z_i))\left | det \frac{df_i^{-1}}{dz_i}\right | = p_{i-1}(f_i^{-1}(z_i))\left | (det \frac{df_i}{dz_i})^{-1}\right |
\]
兩邊取 log:
\[
log\ p_i(z_i) = log\ p_{i-1}(f_i^{-1}(z_i)) - log\left | (det \frac{df_i}{dz_i})\right |
\\
= log\ p_{i-2}(f_{i-1}^{-1}(z_{i-1})) - log\left | (det \frac{df_{i-1}}{dz_{i-1}})\right | - log\left | (det \frac{df_i}{dz_i})\right |
\\ =
\cdots
= log\ p_0(z_0) - \sum_{k=1}^{i} log \left | (det \frac{df_{k}}{dz_{k}})\right |
\]
如何衡量學到的機率分布與訓練資料的分布的關係
現在把上面提到的類神經網路組合稱為 G,因此 \(G(z_0) = x\)。我們想要讓 \(P_G(x)\) 與訓練資料的分布最小,那就是用最大似然估計 Maximum Likelihood Estimation(請看前文)來讓 log likelihood 最大:
\[
arg\ \underset{G}{max} \sum_{i=1}^{m} log\ P_G(x_i)
\]
拿這個式子與上式做比較就很清楚我們的訓練目標了,也就是找到這 K 個類神經網路的參數來最大化 log likelihood,而 \(log\ P_G(x_i)\) 正是上面提到的 \(log\ p_i(z_i)\),有了這個 loss function 就能訓練類神經網路了。
最後一個問題:怎麼設計符合那兩個條件的類神經網路
先列上兩篇相關的 paper:
本文想要簡介的是 Glow: Generative Flow with Invertible 1x1 Convolutions 這篇 paper。這篇 paper 的概念是使用 1x1 convolution。比如說輸入為一個像素的 RGB 值,則輸入為三維向量 z,輸出也是一個像素的 RGB 值,因此也是個三維向量 x。而 1x1 convolution 就可以看成是一個 3x3 的矩陣 W,也就是 \(x = f(z) = Wz\),則此函數 f 的 Jaconbian 矩陣就是 W,因此這個模型滿足了兩個條件:要計算反函數及 Jaconbian 的行列式都相當容易。
最後值得一提的是 GLOW 是由 OpenAI 發表的,他們也寫了一篇部落格 [3] 來介紹 GLOW,並且有個有趣的小 demo 讓大家來嘗試。
參考資料
[1] Flow-based Deep Generative Models, Lilian Weng, 2018
[2] Flow-based Generative Model, Hung-Yi Lee, 2019
[3] Glow: Better Reversible Generative Models, OpenAI, 2018
沒有留言:
張貼留言