Math AI – Variational Autoencoder (VAE) 變分自編碼器

機器學習的起手式是 MNIST 的手寫數字辨識率,這是 supervised learning. 使用的 Neural network 是 discriminative model, 可以是 MLP (multi-layer perceptron) 或是 CNN.

另一個機器學習的分支是 MNIST 影像 dimension reduction/compression, reconstruction, denoise, 這是 unsupervised learning, 也稱為 self-supervised learning. 使用的 neural network (decoder) 是 generative model, 可以是 autoencoder (AE) 以及變形 (sparse AE, convolution AE, variational AE, etc.) 或是更 fancy 的 GAN, 如下圖。
AE 以及變形在 training 都用 encoder-decoder 架構,self-supervised training.

本文主要聚焦在 VAE. VAE 其實和 AE 有很大的差別。AE 可以視為 (nonlinear) dimension reduction 如下圖,本質上很 PCA 非常類似。Hinton 發表在 Science 的 autoencoder paper 可說是開山之作[@hintonReducingDimensionality2006]. AE paper 引入的 encoder-decoder 架構,至今如 transformer 持續使用中。Encoder-decoder 的重要性在機器學習無所不在。大概只有 GAN 的 discriminator-generator 才創造另一種新的架構,普遍性還是比不上 encoder-decoder。

下圖是 MNIST 經過 AE 降維後再影射到 2D 空間的(樣本)分佈。這個分佈可以幫助判斷降維 feature extraction 的好壞。

原則上不同數字(0-9)對應的分佈愈集中代表 intra-class 的 variation 愈小,降維的 feature extraction 有抓到同一類別 “dominating feature". Inter-class 分佈愈分開,降維的 feature extraction 有抓到不同類別的 "differentiated feature"。

這是分類網絡最大的挑戰,maximize inter-class distribution distance and minimize intra-class distribution variation. AE 降維網絡 (encoder) 提供了這個工具。之後的各種變形 (CNN AE, sparse AE, etc.) 都是 AE 延伸。

AE 一個大問題:我們無法控制這個樣本分佈。為什麼這是一個大問題?因為無法控制樣本分佈就無法用於 generative model! 試試用 AE generate 一個數字或是人臉。基本無從下手。

Why VAE?

簡單來說就是把 AE 無法控制的樣本分佈 z (下圖中),變成可以控制的樣本分佈 q_{\phi}(\mathbf{z} \mid \mathbf{x}) \sim N(0, I) (下下圖中左). 注意 VAE 想要控制的樣本分佈是指整體的樣本分佈,不是個別類別的樣本分佈。實務上 VAE 常用於 unsupervised learning, 只有整體的樣本分佈,沒有個別的樣本分佈。

VAE 雖然繼承了 AE encoder-decoder 架構,以及 unsupervised/self-supervised training procedure, 但和 AE 卻有本質的差異。簡單來說
* 最基本/重要:VAE 是 probabilistic encoder/decoder, AE 則是 deterministic encoder/decoder. VAE decoder 是 true generative model, 可以用在 image generation 重要的功能。
* Inference: AE 一般使用 encoder 降維,或是 encoder-decoder denoise image. VAE 一般使用 decoder for image generation.
* z 是 Gaussian distribution with mean/variance.

How VAE work?

VAE training 部分是最難理解的部分。因為會加入 “random sample”, \epsilon, from Gaussian distribution. 這和 AE “deterministic” 降維再升維的觀念似乎完全不同。

1. "Robust" AE

我們可以直觀理解 by setting \epsilon = 0. . 此時 z = \mu 就變成 deterministic 降維,和一般的 AE 相同。因此 \epsilon sampled from Gaussian distribution 可以視為 additive noise, 目的是加強這個 AE 的 robustness. 從這個角度,Gaussian distribution 只是配角,也就是 ”noise".

2. Probability Distribution Conversion (分布變換)

另一個角度,VAE (encoder) 可以想成分布變換。接下來詳細說明。在這個 picture 中 z \sim N(\mu, \sigma) 經過 decoder map to x' distribution close to input x distribution. 從這個角度,Gaussian distribution 反而是主角。

目前主流的觀點是 (2),因為應用廣泛。問題是如何在 training 時達成這種分布變換?

用下圖表示我們想要達成的目的。

  • 訓練出一個生成器 (generator, i.e. decoder) 可以把 normal distribution 的樣本 Z_i (sample) 變換成 \hat{X}_i , sample distribution 和原來的 input X_i sample distribution 相等。
  • 通常我們會拿VAE跟GAN比較,的確,它們兩個的目標基本是一致的——希望構建一個從隱變量Z 生成目標數據X 的模型,但是實現上有所不同。更準確地講,它們是假設了Z 服從某些常見的分布(比如正態分布或均勻分布),然後希望訓練一個模型 X=g(Z) ,這個模型能夠將原來的機率分布映射到訓練集的機率分布,也就是說,它們的目的都是進行分布之間的變換。
  • Z 的維度遠小於 \hat{X} or X ,因此 generator (or decoder) 同時執行升維和分布變換。

如何 Train Generator?

重點是如何定義 loss function.

假設 Z 服從標準的正態分布,那麼我就可以從中採樣得到若干個 Z_1,Z_2,...,Z_n ,然後對它做變換得到 \hat{X}_1=g(Z_1),\hat{X}_2=g(Z_2),...,\hat{X}_n=g(Z_n). 我們怎麼判斷這個通過 g 構造出來的數據集,它的分布跟我們目標的數據集分布是不是一樣?有讀者說不是有KL散度嗎?當然不行,因為KL散度是根據兩個機率分布的表達式來算它們的相似度的,然而目前我們並不知道它們的機率分布的表達式,我們只有一批從構造的分布採樣而來的數據 {\hat{X_1},\hat{X_2},...,\hat{X_n} },還有一批從真實的分布採樣而來的數據 {X_1,X_2,...,X_n }(也就是我們希望生成的訓練集)。我們只有樣本本身,沒有分布表達式,當然也就沒有方法算KL散度。

雖然遇到困難,但還是要想辦法解決的。GAN的思路很直接粗獷:既然沒有合適的度量(loss function?),那我乾脆把這個度量也用神經網絡訓練出來吧。就這樣,WGAN就誕生了,詳細過程請參考《互懟的藝術:從零直達WGAN-GP》。而VAE則使用了一個精緻迂迴的技巧。[@suVariationalAutoencoder2018]

VAE Encoder-Decoder Training 傳統理解和誤解

首先我們有一批數據樣本 {X_1,X_2,...,X_n },其整體用X 來描述,我們本想根據 {X_1,X_2,...,X_n } 得到X的分布 p(X) ,如果能得到的話,那我直接根據 p(X) 來採樣,就可以得到所有可能的X 了(包括{{X_1,X_2,...,X_n } 以外的),這是一個終極理想的生成模型了。當然,這個理想很難實現,於是我們將分布改一改

p(X)=\sum_{Z} p(X \mid Z) p(Z)

此時 p(X|Z) 就描述了一個由Z 來生成X 的模型,而我們假設Z 服從標準正態分布,也就是 p(Z)=N(0,I) 。如果這個理想能實現,那麼我們就可以先從標準正態分布中採樣一個Z ,然後根據Z 來算一個X ,也是一個很棒的生成模型。接下來就是結合自編碼器來實現重構,保證有效信息沒有丟失,再加上一系列的推導,最後把模型實現。框架的示意圖如下:

問題在哪裡?在 training!
如果如上圖的話,我們其實完全不清楚:究竟經過重新採樣出來的Z_k ,是不是還對應著原來的X_k ,所以我們如果直接最小化 loss function as D(\hat{X}_k,X_k)^2 (這裡D 代表某種距離函數)是很不科學的,而事實上你看代碼也會發現根本不是這樣實現的。也就是說,很多教程說了一大通頭頭是道的話,然後寫代碼時卻不是按照所寫的文字來寫,可是他們也不覺得這樣會有矛盾~

VAE 正確理解?

其實,在整個VAE模型中,我們並沒有去使用 p(Z) (隱變量空間的分布)是正態分布的假設,我們用的是假設 p(Z|X) (後驗分布)是正態分布!

具體來說,給定一個真實樣本X_k ,我們假設存在一個專屬於X_k 的分布p(Z|X_k) (學名叫後驗分布),並進一步假設這個分布是(獨立的、多元的)正態分布。為什麼要強調「專屬」呢?因為我們後面要訓練一個生成器 X=g(Z) ,希望能夠把從分布p(Z|X_k) 採樣出來的一個Z_k 還原為X_k 。如果假設p(Z) 是正態分布,然後從p(Z) 中採樣一個Z ,那麼我們怎麼知道這個Z 對應於哪個真實的X 呢?現在p(Z|Xk) 專屬於X_k ,我們有理由說從這個分布採樣出來的Z 應該要還原到X_k 中去。如下圖:

上圖和上上圖差別在哪裡?就是均值 (mean) 和方差 (variance)在 after training finished, i.e. inference 是一個固定值(和 X_i 無關,上上圖)或是隨 input X_i 而改變 (和 X_i 有關,上圖)。可以參考 Appendix A 的 code snippet.

事實上,在論文《Auto-Encoding Variational Bayes》的應用部分,也特別強調了這一點。注意下式中的 \mu^{(i)} {\sigma}^{2(i)} 都有 superscript i .

In this case, we can let the variational approximate posterior be a multivariate Gaussian with a diagonal covariance structure:
\log q_{\phi}\left(z \mid \boldsymbol{x}^{(i)}\right)=\log N\left(z ; \boldsymbol{\mu}^{(i)}, \boldsymbol{\sigma}^{2(i)} \boldsymbol{I}\right)

論文中的上式是實現整個模型的關鍵,不知道為什麼很多教程在介紹VAE時都沒有把它凸顯出來。儘管論文也提到p(Z) 是標準正態分布,然而那其實並不是本質重要的。

順便說明為什麼 p(Z) 是標準正態分布 (normal distribution, Gaussian distribution). 如下式 p(Z) 是一堆正態分布 p(Z \mid X_i) , 各有不同的 \mu^{(i)} {\sigma}^{2(i)} ),乘上 X_i 出現的機率 (一個常數),p(X_i) 的 weighted sum.

p(Z)=\sum_{X_i} p(Z \mid X_i) p(X_i)

我們知道一堆正態分布的 weighted sum 還是正態分布,所以 p(Z) 仍然是正態分布。其實這就是上上圖的 picture. 並非完全不正確,但是各X \mu^{(i)} {\sigma}^{2(i)} 的 information 被平均掉了。上圖則是保持各自 \mu^{(i)} {\sigma}^{2(i)}

VAE Details

回到本文,這時候每一個X_k 都配上了一個專屬的正態分布,才方便後面的生成器做還原,如上圖。但這樣有多少個X 就有多少個正態分布了。我們知道正態分布有兩組參數:均值\mu 和方差 \sigma^2 (多元的話,它們都是向量),如下圖。

那我怎麼找出專屬於X_k 的正態分布p(Z|X_k) 的均值和方差呢?好像並沒有什麼直接的思路。那好吧,那我就用神經網絡來擬合出來吧!這就是神經網絡時代的哲學:難算的我們都用神經網絡來擬合,在WGAN那裡我們已經體驗過一次了,現在再次體驗到了。

VAE Encoder

於是我們構建兩個神經網絡\mu_k =f_1(X_k), \log \sigma^2_k = f_2(X_k) 來算它們了,相當于 AE encoder! AE/VAE encoder 主要的作用是(1)降維;(2)產生 input x dependent latent variables.

比較 AE encoder 和 VAE encoder

  • 兩者都會降維。
  • AE encoder 是 deterministic; VAE encoder 觀念上是 probabilistic,實際 implementation 是 deterministic 和 AE encoder 一樣。 只有在 encoder-decoder training 和 decoder generator 時才有 Gaussian random variable.
  • AE encoder 只產生一個 input X_k dependent latent variable Z_k ; VAE 產生兩個 input X_k dependent latent variables,\mu_k and \log \sigma^2_k .

我們選擇擬合\log \sigma^2_k 而不是直接擬合\sigma^2_k ,是因為\sigma^2_k 總是非負的,需要加激活函數處理,而擬合\log \sigma^2_k 不需要加激活函數,因為它可正可負。到這裡,我能知道專屬於X_k 的均值和方差了,也就知道它的正態分布長什麼樣了,然後從這個專屬分布中採樣一個Z_k 出來,然後經過一個生成器得到\hat{X}_k=g(Z_k) ,現在我們可以放心地最小化D(\hat{X}_k,X_k)^2 ,因為Z_k 是從專屬X_k 的分布中採樣出來的,這個生成器應該要把開始的X_k 還原回來,如上圖。

VAE Training

讓我們來思考一下,根據上圖的訓練過程,最終會得到什麼結果。

首先,我們希望重構X ,也就是最小化D(\hat{X}_k,X_k)^2 ,但是這個重構過程受到噪聲的影響,因為Z_k = \mu_k + \sigma_k \cdot \epsilon (\epsilon 是 Gaussian random variable) 是通過重新採樣過,不是直接由encoder算出來的。顯然噪聲會增加重構的難度,不過好在這個噪聲強度(也就是方差)通過一個神經網絡算出來的,所以最終模型為了重構得更好,肯定會想盡辦法讓方差為0。而方差為0的話,也就沒有隨機性了,所以不管怎麼採樣其實都只是得到確定的結果(也就是均值),只擬合一個當然比擬合多個要容易,而均值是通過另外一個神經網絡算出來的。

說白了,模型會慢慢退化成普通的AutoEncoder,噪聲不再起作用。

這樣不就白費力氣了嗎?說好的生成模型呢?

別急別急,其實VAE還讓所有的p(Z|X) 都向標準正態分布看齊,這樣就防止了噪聲為零,同時保證了模型具有生成能力。怎麼理解「保證了生成能力」呢?如果所有的p(Z|X) 都很接近標準正態分布N(0,I) , 那麼根據定義
p(Z)=\sum_{X} p(Z \mid X) p(X)=\sum_{X} \mathcal{N}(0, I) p(X)=\mathcal{N}(0, I) \sum_{X} p(X)=\mathcal{N}(0, I)
這樣我們就能達到我們的先驗假設:p(Z) 是標準正態分布。然後我們就可以放心地從N(0,I) 中採樣來生成圖像了。

Really? 這代表 \mu_k \sim 0 and \sigma_k \sim 1 ? => 這應該只是一個 constraint, 避免 \sigma_k \to 0 以及 \mu_k go out of bound.

How? By define the loss function!

"Variational" Latent Loss

那怎麼讓所有的p(Z|X) 都向N(0,I) 看齊呢?如果沒有外部知識的話,其實最直接的方法應該是在重構誤差(reconstruction loss)的基礎上中加入額外的 loss:
\mathcal{L}_{\mu}=\left\|f_{1}\left(X_{k}\right)\right\|^{2} \quad\text{and}\quad \mathcal{L}_{\sigma^{2}}=\left\|f_{2}\left(X_{k}\right)\right\|^{2}

因為它們分別代表了均值\mu_k 和方差的對數\log \sigma^2_k ,達到N(0,I) 就是希望二者盡量接近於0了。不過,這又會面臨著這兩個損失的比例要怎麼選取的問題,選取得不好,生成的圖像會比較模糊。所以,原論文直接算了一般(各分量獨立的)正態分布與標準正態分布的KL散度 KL(N(\mu,\sigma^2)\|N(0,I)) 作為這個額外的loss,計算結果為 (Appendix B)

\mathcal{L}_{\mu, \sigma^{2}}=\frac{1}{2} \sum_{i=1}^{d}\left(\mu_{(i)}^{2}+\sigma_{(i)}^{2}-\log \sigma_{(i)}^{2}-1\right)

這裡的d 是隱變量Z 的維度,而\mu_{(i)} \sigma^2_{(i)} 分別代表一般正態分布的均值向量和方差向量的第i 個分量。直接用這個式子做補充loss,就不用考慮均值損失和方差損失的相對比例問題了。

  • 這個 loss 也稱為 latent loss 代表隱變數 (\mu_i and \sigma^2_i ) 和 N(0, I) 差距。
  • VAE 的 "variation, 變分" 在數學上是一個函數積分(或是其他 operations)的極值,變數不是一個值,而是一個函數。KL divergence 就是以函數為變數的積分 (Appendix B),因此 latent loss minimization 就相當 variation, 沒有其他神奇之處。

顯然,latent loss 也可以分兩部分理解:
$latex \begin{array}{l}
\mathcal{L}_{\mu, \sigma^{2}}=\mathcal{L}_{\mu}+\mathcal{L}_{\sigma^{2}} \\
\mathcal{L}_{\mu}=\frac{1}{2} \sum_{i=1}^{d} \mu_{(i)}^{2}=\frac{1}{2}\left\|f_{1}(X)\right\|^{2} \\
\mathcal{L}_{\sigma^{2}}=\frac{1}{2} \sum_{i=1}^{d}\left(\sigma_{(i)}^{2}-\log \sigma_{(i)}^{2}-1\right)
\end{array} $

\mathcal{L}_{\mu} 是 parabolic dependency on \mu_i. The minimum occurs when \mu_i=0. \mathcal{L}_{\mu} 的作用是 drive \mu_i\to 0 .

\mathcal{L}_{\sigma^{2}} 對於 \sigma^2_i 的關係如下圖。The minimum occurs when \sigma^2_i = 1. \mathcal{L}_{\sigma^{2}} 的作用是 drive \sigma^2_i \to 1.

注意任一 \sigma^2_i \to 0 會導致 \mathcal{L}_{\sigma^{2}}, \mathcal{L}_{\mu, \sigma^{2}} \to \infty . 因此 latent loss, \mathcal{L}_{\mu, \sigma^{2}}, 會阻止 VAE 從 probabilistic 變成 deterministic (\sigma^2_i \to 0 ).

除了 latent loss, XAE (AE, VAE, SAE, CAE) 的基本 loss term 是重構誤差(reconstruction loss)。 所以 VAE training 完整的 loss 包含 latent loss 加上 reconstruction loss, 見 Appendix A code.

Re-parmeterization Trick (for Gradient Back Propagation)

最後是實現模型的一個技巧,reparameterization trick。其實很簡單,就是我們要從 p(Z|X_k) 中採樣一個 Z_k 出來,儘管我們知道了 p(Z|X_k) 是正態分布,但是均值方差都是靠模型算出來的,我們要靠這個過程反過來優化均值方差的模型,但是「採樣」這個操作是不可微分的,而採樣的結果是可微分的。我們利用
\begin{aligned} & \frac{1}{\sqrt{2 \pi \sigma^{2}}} \exp \left(-\frac{(z-\mu)^{2}}{2 \sigma^{2}}\right) d z \\=& \frac{1}{\sqrt{2 \pi}} \exp \left[-\frac{1}{2}\left(\frac{z-\mu}{\sigma}\right)^{2}\right] d\left(\frac{z-\mu}{\sigma}\right) \end{aligned}

這說明 (z-\mu)/\sigma=\varepsilon 是服從均值為0、方差為1的標準正態分布的,要同時把dz 考慮進去,是因為乘上dz 才算是概率,去掉dz是概率密度而不是概率。

這時候我們得到:從 N(\mu,\sigma^2) 中採樣一個Z ,相當於從N(0,I) 中採樣一個\varepsilon ,然後讓 Z=\mu+\varepsilon \times\sigma 。如下圖:

於是,我們將從N(\mu,\sigma^2) 採樣變成了從N(0,I) 中採樣,然後通過參數變換得到從N(\mu,\sigma^2) 中採樣的結果。這樣一來,「採樣」這個操作就不用參與梯度下降了,改為採樣的結果參與,使得整個模型可訓練了。

Training Forward and Backward Paths

Forward path

  • Encoder: \mu_k =f_1(X_k), \log \sigma^2_k = f_2(X_k) 兩者都是 d dimension vector/tensor.
  • Sample an \varepsilon from N(0, I) , compute Z_k = \mu_k+\varepsilon \times \sigma_k . \varepsilon 的 dimension?
  • 使用 Z_k in decoder to reconstruct X'_k

Compute loss term 包含 reconstruction loss and latent loss

  • \mathcal{L} = |X_k - X'_k|^2 + \mathcal{L}_{\mu, \sigma^2}

Backward path (自動微分)

  • Back propagation 先 update decoder weights.
  • Back propagation update 到 Z_k , given the fixed sample \varepsilon and based on Z_k = \mu_k+\varepsilon\times\sigma_k , 可以 update \mu_k and \sigma_k .
  • 繼續 back propagation update encoder.

VAE 的本質

以下 from [@suVariationalAutoencoder2018], 很好總結 VAE 的本質。

VAE的本質是什麼?VAE雖然也稱是AE(AutoEncoder)的一種,但它的做法(或者說它對網絡的詮釋)是別具一格的。在VAE中,它的Encoder有兩個,一個用來計算均值,一個用來計算方差,這已經讓人意外了:Encoder不是用來Encode的,是用來算均值和方差的,這真是大新聞了,還有均值和方差不都是統計量嗎,怎麼是用神經網絡來算的?

事實上,VAE從讓普通人望而生畏的變分和貝葉斯理論出發,最後落地到一個具體的模型中,雖然走了比較長的一段路,但最終的模型其實是很接地氣的:它本質上就是在我們常規的自編碼器的基礎上,對encoder的結果(在VAE中對應著計算均值的網絡)加上了「高斯噪聲」,使得結果decoder能夠對噪聲有 robustness;而那個額外的KL loss(目的是讓均值為0,方差為1),事實上就是相當於對encoder的一個正則項,希望encoder出來的東西均有零均值。

那另外一個encoder(對應著計算方差的網絡)的作用呢?它是用來動態調節噪聲的強度的。直覺上來想,當decoder還沒有訓練好時(重構誤差遠大於KL loss),就會適當降低噪聲(KL loss增加),使得擬合起來容易一些(重構誤差開始下降);反之,如果decoder訓練得還不錯時(重構誤差小於KL loss),這時候噪聲就會增加(KL loss減少),使得擬合更加困難了(重構誤差又開始增加),這時候decoder就要想辦法提高它的生成能力了。

說白了,重構的過程是希望沒噪聲的,而KL loss則希望有高斯噪聲的,兩者是對立的。所以,VAE跟GAN一樣,內部其實是包含了一個對抗的過程,只不過它們兩者是混合起來,共同進化的。從這個角度看,VAE的思想似乎還高明一些,因為在GAN中,造假者在進化時,鑒別者是安然不動的,反之亦然。當然,這只是一個側面,不能說明VAE就比GAN好。GAN真正高明的地方是:它連度量都直接訓練出來了,而且這個度量往往比我們人工想的要好(然而GAN本身也有各種問題)。

Appendix A: VAE Coding Example [@durrVAETutorial2016]

https://ithelp.ithome.com.tw/articles/10188453
Variational Autoencoder 直接從 Github 上找實作來試試看,並用 MNIST 的資料來重現。

Encoder

在 encoder 一開始的地方和 Autoencoder 一樣,循序的降維.這裡定義了維度從 784 維到 500 維到 200(501?) 維再到 2 維.

n_z = 2 #Dimension of the latent space
# Input
x = tf.placeholder("float", shape=[None, 28*28]) #Batchsize x Number of Pixels
y_ = tf.placeholder("float", shape=[None, 10])   #Batchsize x 10 (one hot encoded)

# First hidden layer
W_fc1 = weights([784, 500])
b_fc1 = bias([500])
h_1   = tf.nn.softplus(tf.matmul(x, W_fc1) + b_fc1)

# Second hidden layer 
W_fc2 = weights([500, 501]) #501 and not 500 to spot errors
b_fc2 = bias([501])
h_2   = tf.nn.softplus(tf.matmul(h_1, W_fc2) + b_fc2)

接下來就是有趣的地方了,再進入 2 維前它把前面經過低維權重輸出的向量複製兩份,來建立 Gaussian,而且一份做成 mean 一份做成 stddev …
再來把它轉成二維的 code layer

# Parameters for the Gaussian
z_mean = tf.add(tf.matmul(h_2, weights([501, n_z])), bias([n_z]))
z_log_sigma_sq = tf.add(tf.matmul(h_2, weights([501, n_z])), bias([n_z]))

Decoder

Samples from a Gaussian using the given mean and the std. The sampling is done by adding a random number ensuring that backpropagation works fine.

batch_size = 64
eps = tf.random_normal((batch_size, n_z), 0, 1, dtype=tf.float32) # Adding a random number
z = tf.add(z_mean, tf.mul(tf.sqrt(tf.exp(z_log_sigma_sq)), eps))  # The sampled z

W_fc1_g = weights([n_z, 500])
b_fc1_g = bias([500])
h_1_g   = tf.nn.softplus(tf.matmul(z, W_fc1_g) + b_fc1_g)

W_fc2_g = weights([500, 501])
b_fc2_g = bias([501])
h_2_g   = tf.nn.softplus(tf.matmul(h_1_g, W_fc2_g) + b_fc2_g)

x_reconstr_mean = tf.nn.sigmoid(tf.add(tf.matmul(h_2_g,  weights([501, 784])), bias([784])))

Loss function

reconstr_loss = -tf.reduce_sum(x * tf.log(1e-10 + x_reconstr_mean) + (1-x) * tf.log(1e-10 + 1 - x_reconstr_mean), 1)
latent_loss = -0.5 * tf.reduce_sum(1 + z_log_sigma_sq - tf.square(z_mean) - tf.exp(z_log_sigma_sq), 1)
cost = tf.reduce_mean(reconstr_loss + latent_loss)   # average over batch

# Use ADAM optimizer
optimizer =  tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost)

Appendix B: KL Divergence

由於我們考慮的是各分量獨立的多元正態分布,因此只需要推導一元正態分布的情形即可,根據定義我們可以寫出
$latex \begin{aligned}
& K L\left(N\left(\mu, \sigma^{2}\right) \| N(0,1)\right) \\
=& \int \frac{1}{\sqrt{2 \pi \sigma^{2}}} e^\frac{-(x-\mu)^{2}}{2 \sigma^{2}}\left(\log \frac{e^{-(x-\mu)^{2} / 2 \sigma^{2}} / \sqrt{2 \pi \sigma^{2}}}{e^{-x^{2} / 2} / \sqrt{2 \pi}}\right) d x\\
=& \int \frac{1}{\sqrt{2 \pi \sigma^{2}}} e^\frac{-(x-\mu)^{2}}{2 \sigma^{2}} \log \left\{\frac{1}{\sqrt{\sigma^{2}}} \exp \left\{\frac{1}{2}\left[x^{2}-(x-\mu)^{2} / \sigma^{2}\right]\right\}\right\} d x \\
=& \frac{1}{2} \int \frac{1}{\sqrt{2 \pi \sigma^{2}}} e^\frac{-(x-\mu)^{2}}{2 \sigma^{2}} \left[ -\log \sigma^{2}+x^{2}-(x-\mu)^{2} / \sigma^{2}\right] d x
\end{aligned} $

整個結果分為三項積分,第一項實際上就是-\log \sigma^2 乘以概率密度的積分(也就是1),所以結果是-\log \sigma^2 ;第二項實際是正態分布的二階矩,熟悉正態分布的朋友應該都清楚正態分布的二階矩為 \mu^2+\sigma^2 ;而根據定義,第三項實際上就是「-方差除以方差=-1」。所以總結果就是
K L\left(N\left(\mu, \sigma^{2}\right) \| N(0,1)\right)=\frac{1}{2}\left(-\log \sigma^{2}+\mu^{2}+\sigma^{2}-1\right)

Reference

Durr, Oliver. 2016. “VAE Tutorial.” GitHub. November 25, 2016. https://github.com/oduerr/dl_tutorial.

Hinton, G. E., and R. R. Salakhutdinov. 2006. “Reducing the Dimensionality of Data with Neural Networks.” Science 313 (5786):504–7. https://doi.org/10.1126/science.1127647.

Su, Jianlin. 2018. “Variational Autoencoder 1:原来是这么一回事 – 科学空间|Scientific Spaces.” March 18, 2018.
https://kexue.fm/archives/5253.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Design a site like this with WordPress.com
Get started