1. 程式人生 > >再談變分自編碼器VAE:從貝葉斯觀點出發

再談變分自編碼器VAE:從貝葉斯觀點出發

作者丨蘇劍林

單位丨廣州火焰資訊科技有限公司

研究方向丨NLP,神經網路

個人主頁丨kexue.fm

前幾天寫了文章變分自編碼器VAE:原來是這麼一回事,從一種比較通俗的觀點來理解變分自編碼器(VAE),在那篇文章的視角中,VAE 跟普通的自編碼器差別不大,無非是多加了噪聲並對噪聲做了約束。

然而,當初我想要弄懂 VAE 的初衷,是想看看究竟貝葉斯學派的概率圖模型究竟是如何與深度學習結合來發揮作用的,如果僅僅是得到一個通俗的理解,那顯然是不夠的。

所以我對 VAE 繼續思考了幾天,試圖用更一般的、概率化的語言來把 VAE 說清楚。事實上,這種思考也能回答通俗理解中無法解答的問題,比如重構損失用 MSE 好還是交叉熵好、重構損失和 KL 損失應該怎麼平衡,等等。

建議在閱讀變分自編碼器VAE:原來是這麼一回事後再對本文進行閱讀,本文在內容上儘量不與前文重複。

準備

在進入對 VAE 的描述之前,我覺得有必要把一些概念性的內容講一下。 

數值計算 vs 取樣計算

對於不是很熟悉概率統計的讀者,容易混淆的兩個概念應該是數值計算和取樣計算,也有讀者對三味Capsule:矩陣Capsule與EM路由出現過同樣的疑惑。比如已知概率密度函式 p(x),那麼 x 的期望也就定義為:

640

如果要對它進行數值計算,也就是數值積分,那麼可以選若干個有代表性的點 x0<x1<x2<⋯<xn,然後得到:

640

這裡不討論“有代表性”是什麼意思,也不討論提高數值計算精度的方法。這樣寫出來,是為了跟取樣計算對比。如果p

(x) 中取樣若干個點 x1,x2,…,xn,那麼我們有:

640

我們可以比較 (2) 跟 (3),它們的主要區別是 (2) 中包含了概率的計算而 (3) 中僅有 x 的計算,這是因為在 (3) 中 xi 是從 p(x) 中依概率取樣出來的,概率大的 xi 出現的次數也多,所以可以說取樣的結果已經包含了 p(x) 在裡邊,就不用再乘以 p(xi) 了

更一般地,我們可以寫出:

640

這就是蒙特卡洛模擬的基礎。

KL散度及變分

我們通常用 KL 散度來度量兩個概率分佈 p(x) 和 q(x) 之間的差異,定義為:

640

KL 散度的主要性質是非負性,如果固定 p(x),那麼 KL(p(x)‖‖‖q(x))=0⇔p(x)=q(

x);如果固定 q(x),同樣有 KL(p(x)‖‖‖q(x))=0⇔p(x)=q(x),也就是不管固定哪一個,最小化 KL 散度的結果都是兩者儘可能相等。

這一點的嚴格證明要用到變分法,而事實上 VAE 中的 V(變分)就是因為 VAE 的推導就是因為用到了 KL 散度(進而也包含了變分法)。 

當然,KL 散度有一個比較明顯的問題,就是當 q(x) 在某個區域等於 0,而 p(x在該區域不等於 0,那麼 KL 散度就出現無窮大。

這是 KL 散度的固有問題,我們只能想辦法規避它,比如隱變數的先驗分佈我們用高斯分佈而不是均勻分佈,原因便在此,這一點我們在前文變分自編碼器VAE:原來是這麼一回事中也提到過了。 

順便說點題外話,度量兩個概率分佈之間的差異只有 KL 散度嗎?

當然不是,我們可以看維基百科的 Statistical Distance 一節,裡邊介紹了不少分佈距離,比如有一個很漂亮的度量,我們稱之為巴氏距離(Bhattacharyya distance),定義為:

640

這個距離不僅對稱,還沒有 KL 散度的無窮大問題。然而我們還是選用 KL 散度,因為我們不僅要理論上的漂亮,還要實踐上的可行。KL 散度可以寫成期望的形式,這允許我們對其進行取樣計算,

相反,巴氏距離就沒那麼容易了,讀者要是想把下面計算過程中的 KL 散度替換成巴氏距離,就會發現寸步難行了。

本文的符號表

講解 VAE 免不了出現大量的公式和符號,這裡將部分式子的含義提前列舉如下:

640

框架

這裡通過直接對聯合分佈進行近似的方式,簡明快捷地給出了 VAE 的理論框架。 

直面聯合分佈

出發點依然沒變,這裡再重述一下。首先我們有一批資料樣本 {x1,…,xn},其整體用 x 來描述,我們希望藉助隱變數 z 描述 x 的分佈 p(x)

640

這樣(理論上)我們既描述了 p(x),又得到了生成模型 p(x|z),一舉兩得。 

接下來就是利用 KL 散度進行近似。但我一直搞不明白的是,為什麼從原作 Auto-Encoding Variational Bayes 開始,VAE 的教程就聚焦於後驗分佈 p(z|x) 的描述?

也許是受了 EM 演算法的影響,這個問題上不能應用 EM 演算法,就是因為後驗分佈 p(z|x) 難以計算,所以 VAE 的作者就聚焦於 p(z|x) 的推導。 

但事實上,直接來對 p(x,z) 進行近似是最為乾脆的。具體來說,我們設想用一個新的聯合概率分佈 q(x,z) 來逼近 p(x,z),那麼我們用 KL 散度來看它們的距離:

640

KL 散度是我們的終極目標,因為我們希望兩個分佈越接近越好,所以 KL 散度越小越好。由於我們手頭上只有 x 的樣本,因此利用 p(x,z)=p(x)p(z|x) 對上式進行改寫:

640

這樣一來利用 (4) 式,把各個 xi 代入就可以進行計算了,這個式子還可以進一步簡化,因為:

640

而:

640

注意這裡的 p(x) 是根據樣本 x1,x2,…,xn 確定的關於 x 的先驗分佈(更常見的寫法是 (x)),儘管我們不一定能準確寫出它的形式,但它是確定的、存在的,因此這一項只是一個常數,所以可以寫出:

640

目前最小化 KL(p(x,z)‖q(x,z)) 也就等價於最小化 L。注意減去的常數一般是負數(概率小於 1,取對數就小於 0),而 KL 散度本來就非負,非負數減去一個負數,結果會是一個正數,所以 恆大於一個某個正數。

你的VAE已經送達

到這裡,我們回顧初衷——為了得到生成模型,所以我們把 q(x,z) 寫成 q(x|z)q(z),於是就有:

640

再簡明一點,那就是:

640

看,括號內的不就是 VAE 的損失函式嗎?只不過我們換了個符號而已。我們就是要想辦法找到適當的 q(x|z)q(z) 使得 L 最小化。

再回顧一下整個過程,我們幾乎都沒做什麼“讓人難以想到”的形式變換,但 VAE 就出來了。所以,沒有必要去對後驗分佈進行分析,直面聯合分佈,我們能更快捷地到達終點。

不能搞分裂

鑑於 (13) 式的特點,我們也許會將 L 分開為兩部分看:?zp(z|x)[−lnq(x|z)] 的期望和 KL(p(z|x)‖q(z)) 的期望,並且認為問題變成了兩個 loss 的分別最小化。

然而這種看法是不妥的,我們前面已經分析了,L 會大於一個正數,這就意味著 ?zp(z|x)[−lnq(x|z)] KL(p(z|x)‖q(z)) 兩部分的 loss 不可能同時為零——儘管它們每一個都有可能為 0。這也表明這兩部分的 loss 其實是相互拮抗的。

所以,L 不能割裂來看,而是要整體來看,整個的 L 越小模型就越接近收斂,而不能只單獨觀察某一部分的 loss。

事實上,這正是 GAN 模型中夢寐以求的——有一個總指標能夠指示生成模型的訓練程序,在 VAE 模型中天然就具備了這種能力了,而 GAN 中要到 WGAN 才有這麼一個指標。

實驗

截止到上面的內容,其實我們已經完成了 VAE 整體的理論構建。但為了要將它付諸於實驗,還需要做一些工作。事實上原論文 Auto-Encoding Variational Bayes 也在這部分做了比較充分的展開,但遺憾的是,網上很多 VAE 教程都只是推導到 (13) 式就沒有細說了。

後驗分佈近似

現在 q(z),q(x|z),p(z|x) 全都是未知的,連形式都還沒確定,而為了實驗,就得把 (13) 式的每一項都明確寫出來。 

首先,為了便於取樣,我們假設 z∼N(0,I),即標準的多元正態分佈,這就解決了 q(z)。那 q(x|z)p(z|x) 呢?一股腦用神經網路擬合吧

注:本來如果已知 q(x|z)q(z),那麼 p(z|x)最合理的估計應該是:

640

這其實就是 EM 演算法中的後驗概率估計的步驟,具體可以參考從最大似然到EM演算法:一致的理解方式。但事實上,分母的積分幾乎不可能完成,因此這是行不通的。所以乾脆用一般的網路去近似它,這樣不一定能達到最優,但終究是一個可用的近似。

具體來說,我們假設 p(z|x) 也是(各分量獨立的)正態分佈,其均值和方差由 x 來決定,這個“決定”,就是一個神經網路:

640

這裡的 μ(x),σ^2(x) 是輸入為 x、輸出分別為均值和方差的神經網路,其中μ(x) 就起到了類似 encoder 的作用。既然假定了高斯分佈,那麼 (13) 式中的 KL 散度這一項就可以先算出來:

640

也就是我們所說的 KL loss,這在上一篇文章已經給出。

生成模型近似

現在只剩生成模型部分 q(x|z) 了,該選什麼分佈呢?論文 Auto-Encoding Variational Bayes 給出了兩種候選方案:伯努利分佈或正態分佈。 

什麼?又是正態分佈?是不是太過簡化了?然而並沒有辦法,因為我們要構造一個分佈,而不是任意一個函式,既然是分佈就得滿足歸一化的要求,而要滿足歸一化,又要容易算,我們還真沒多少選擇。 

伯努利分佈模型

首先來看伯努利分佈,眾所周知它其實就是一個二元分佈:

640

所以伯努利分佈只適用於 x 是一個多元的二值向量的情況,比如 x 是二值影象時(mnist 可以看成是這種情況)。這種情況下,我們用神經網路 ρ(z) 來算引數 ρ,從而得到:

640

這時候可以算出:

640

這表明 ρ(z) 要壓縮到 0~1 之間(比如用 sigmoid 啟用),然後用交叉熵作為損失函式,這裡 ρ(z) 就起到了類似 decoder 的作用。

正態分佈模型

然後是正態分佈,這跟 p(z|x) 是一樣的,只不過 xz 交換了位置:

640

這裡的 μ(z),σ^2(z) 是輸入為 z、輸出分別為均值和方差的神經網路,μ(z) 就起到了 decoder 的作用。於是:

640

很多時候我們會固定方差為一個常數 σ^2,這時候:

640

這就出現了 MSE 損失函式。

所以現在就清楚了,對於二值資料,我們可以對 decoder 用 sigmoid 函式啟用,然後用交叉熵作為損失函式,這對應於 q(x|z) 為伯努利分佈;而對於一般資料,我們用 MSE 作為損失函式,這對應於 q(x|z) 為固定方差的正態分佈

取樣計算技巧

前一節做了那麼多的事情,無非是希望能將 (13) 式明確地寫下來。當我們假設 p(z|x) 和 q(z) 都是正態分佈時,(13) 式的 KL 散度部分就已經算出來了,結果是 (16) 式;當我們假設 q(x|z) 是伯努利分佈或者高斯分佈時,−lnq(x|z) 也能算出來了。

現在缺什麼呢? 取樣!

p(z|x) 的作用分兩部分,一部分是用來算 KL(p(z|x)q(z)),另一部分是用來算 ?zp(z|x)[lnq(x|z)] 的,而 ?zp(z|x)[lnq(x|z)] 就意味著:

640

我們已經假定了 p(z|x) 是正態分佈,均值和方差由模型來算,這樣一來,藉助“重引數技巧”就可以完成取樣。

但是取樣多少個才適合呢?標準的 VAE 非常直接了當:一個!所以這時候 (13) 式就變得非常簡單了:

640

該式中的每一項,可以在把 (16),(19),(21),(22) 式找到。這因為標準的 VAE 只採樣了一個,所以這時候它就跟普通的 AE 對應起來了。

那麼最後的問題就是取樣一個究竟夠了嗎?事實上我們會執行多個 epoch,每次的隱變數都是隨機生成的,因此當 epoch 數足夠多時,事實上是可以保證取樣的充分性的。我也實驗過取樣多個的情形,感覺生成的樣本並沒有明顯變化。

致敬

這篇文章從貝葉斯理論的角度出發,對 VAE 的整體流程做了一個梳理。用這種角度考察的時候,我們心裡需要緊抓住兩個點:“分佈”和“取樣”——寫出分佈形式,並且通過取樣來簡化過程。

簡單來說,由於直接描述複雜分佈是難以做到的,所以我們通過引入隱變數來將它變成條件分佈的疊加。而這時候我們對隱變數的分佈和條件分佈都可以做適當的簡化(比如都假設為正態分佈),並且在條件分佈的引數可以跟深度學習模型結合起來(用深度學習來算隱變數的引數),至此,“深度概率圖模型”就可見一斑了。

讓我們一起致敬貝葉斯大神,以及眾多研究概率圖模型的大牛,他們都是真正的勇者。

640?

點選以下標題檢視相關內容: 

640?

640?

相關推薦

VAE----編碼Keras實現

這篇部落格用來記錄我自己用keras實現(抄寫)VAE過程中,掉進的一個坑。。。。。。 最近這幾天在網上看了很多VAE的介紹,並且看了一下keras中的實現。自我感覺良好,就想按著官方的程式碼自己也去寫一遍。不寫不知道,一寫嚇一跳!!我跳進了一個很大坑中(笑哭),我在把程式碼寫完以後,開始訓

零上手編碼VAE

閱讀更多,歡迎關注公眾號:論文收割機(paper_reader) Kingma D P, Welling M. Auto-encoding variational bayes[J]. arXiv preprint arXiv:1312.6114, 2013. Rez

【Learning Notes】編碼(Variational Auto-Encoder,VAE

近年,隨著有監督學習的低枝果實被採摘的所剩無幾,無監督學習成為了研究熱點。VAE(Variational Auto-Encoder,變分自編碼器)[1,2] 和 GAN(Generative Adversarial Networks) 等模型,受到越來越多的關注

Autoencorder理解(5):VAE(Variational Auto-Encoder,編碼

reference: http://blog.csdn.net/jackytintin/article/details/53641885 近年,隨著有監督學習的低枝果實被採摘的所剩無幾,無監督學習成為了研究熱點。VAE(Variational Auto-Encode

VAE編碼的一點理解

前言 網上很多關於VAE的教程都包含大量枯燥難懂的數學公式,如果有大佬特別喜歡推導這些公式,很高興能夠附上以下連結。然而,今天只是想簡單的談下自己的理解,只有圖片,沒有公式。 主要內容 如下圖所示,其實VAE的主要思想就是以均值方差計算模組來作為Enc

LearningNotes 編碼 VariationalAutoEncoder VAE

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

[深度學習]半監督學習、無監督學習之Variational Auto-Encoder編碼(附程式碼)

論文全稱:《Auto-Encoding Variational Bayes》 論文地址:https://arxiv.org/pdf/1312.6114.pdf 論文程式碼: keras 版本:https://github.com/bojone/vae pytorch 版本:https

白話Variational Autoencoder(編碼

本文將簡單介紹一下Variational Autoencoder。作者也在學習當中,如有不正確的地方,請大家指正,謝謝~原始的autoencoder一般分為兩個部分encoder part和decoder part。 encoder是將input轉化為encoding vec

沒有任何公式——直觀的理解自動編碼VAE

 autoencoders作為一種非常直觀的無監督的學習方法是很受歡迎的,最簡單的情況是三層的神經網路,第一層是資料輸入,第二層的節點數一般少於輸入層,並且第三層與輸入層類似,層與層之間互相全連線,這種網路被稱作自動編碼器,因為該網路將輸入“編碼”成一個隱藏程式碼,

【TensorFlow-windows】學習筆記六——編碼

前言 對理論沒興趣的直接看程式碼吧,理論一堆,而且還有點複雜,我自己的描述也不一定準確,但是程式碼就兩三句話搞定了。 國際慣例,參考博文 理論 基礎知識 似然函式(引自百度百科) 似然函式是關於統計模型中的引數的函式,

編碼VAE)及程式碼解讀

這幾天在看GAN模型的時候,順便關注了另外一種生成模型——VAE。其實這種生成模型在早幾年就有了,而且有了一些應用。著名黑客George Hotz在其開源的自主駕駛專案中就應用到了VAE模型。這其中的具體應用在我上一篇轉載的部落格comma.ai中有詳細介紹。在對VAE基本原

你瞭解編碼嗎? 請看這裡

10.9  變分自編碼器前面所描述的自編碼器可以降維重構樣本,在這基礎上我們來學習一個更強大的自編碼器。10.9.1  什麼是變分自編碼器變分自編碼器學習的不再是樣本的個體,而是要學習樣本的規律。這樣訓練出來的自編碼器不單單具有重構樣本的功能,還具有了仿照樣本的功能。聽起來這

關於FV(Fisher Vector)和編碼VAE(Variational Autoencoder)的原理簡介

1. FV(Fisher Vector)     FV的思想用一句話概括就是:用所有的聚類中心的線性組合去表示每個特徵點 簡單來說,假設樣本各特徵符合獨立同分布(i.i.d)則樣本的概率分佈可以由各個特徵維度的概率分佈的乘積得到。對該式取對數的話,就可以將乘法運算轉換為加

pytorch 實現自動編碼

本來以為自動編碼器是很簡單的東西,但是也是看了好多資料仍然不太懂它的原理。先把程式碼記錄下來,有時間好好研究。 這個例子是用MNIST資料集生成為例子。 # -*- coding: utf-8 -*- """ Created on Fri Oct 12 11:42:19 2018 @a

分貝編碼遷移

目錄 變分法簡介 變分推斷 變分貝葉斯 變分自編碼 變分與遷移 :heart: 一些資料 變分法簡介 變分法是研究依賴於某些未知函式的積分型泛函極值的一門科學。也就是求泛函極值的方法稱為變分法。 典型例子最速降線

編碼編碼大雜燴

1.變分自編碼          變分是數學上的概念,大致含義是尋求一箇中間的函式,通過改變中間函式來檢視目標函式的改變。變分推斷是變分自編碼的核心,那麼變分推斷是要解決的是什麼問題?? 問題描述如下,假如我們有一批樣本X,這個時候,我們想生成一批和它類似的樣本,且分佈相同,這個時候我們該怎麼辦呢? 1

編碼網路的實現

1、VAE跟Gan有點類似,都是可以通過一些輸入,生成一些樣本資料。不同點是VAE是假設在資料的分佈是服從正態分佈的,而GAN是沒有這個假設的,完全是由資料驅動,進行訓練得出規律的。 下面是變分自編碼網路的程式碼: import numpy as np import te