自編碼器應用
自編碼器(autoencoder, AE)已在機器學習和人工神經網絡引起了許多人的關注,事實上,自編碼器已在醫療醫藥、圖像去噪、神經機器翻譯等領域產生了很可觀的成績。
自編碼器的組成
與大多數神經網絡一樣,自編碼器通過向后傳播梯度以優化一組數據的權重進行學習,但自編碼器的體系結構與大多數神經網絡間最顯著差異在于瓶頸層[編者注:bottleneck,簡單翻譯就是瓶頸層,一般在深度較高的網絡(如resnet101)中使用]。自編碼器的瓶頸層是將數據壓縮為小尺寸表示的一種方法。
而自編碼器的另外兩個重要部分是編碼器和解碼器。這三個組件融合在一起,便可形成“原始”自編碼器,當然更復雜的自編碼器可能還具有一些其他組件。
接下來,讓我們單獨看一下這些組件。
1、編碼器
是將數據壓縮和重建的第一階段,編碼器負責了數據壓縮階段。編碼器是一個前饋神經網絡,它將接收數據特征(例如在圖像壓縮的情況下為像素),并輸出小于數據特征大小的潛向量。
為了使數據重建更強有力,編碼器在訓練過程中優化了權重,以保證將輸入數據最重要的特征壓縮到小尺寸的潛在向量中。這確保了解碼器具足夠的輸入數據的相關信息,可以在最小的損失下重建數據。
2、潛在向量(瓶頸層)
自編碼器的潛在向量組件(瓶頸層)是最關鍵的部分,當需要選擇潛在向量的大小時,它就會變得更加關鍵。
編碼器的輸出為我們提供了潛在向量,而這個向量則是輸入數據最重要的特征,最終將被解碼器解碼,并將有效信息傳播到解碼器以進行重建。
選擇較小的潛在向量意味著可以用較少的數據數據信息來表示數據特征,選擇較大的潛在向量則與自編碼器壓縮的思路相違背,還會增加計算成本。
3、解碼器
總結一下數據壓縮和重建的過程,就如同編碼器一樣,這個組件也是前饋神經網絡,但在結構上和編碼器略有不同。差異主要來自于解碼器會將比解碼器輸出小的潛在向量作為輸入。
解碼器的功能是從潛在向量生成一個非常接近輸入的輸出。
訓練自編碼器
在訓練自編碼器時,通常會將組件組合在一起,并不是單獨構建的,最終使用諸如梯度下降或ADAM優化器之類的優化算法對它們進行端到端訓練。
1、損失函數
自編碼器訓練過程中最值得討論的一部分就是損失函數。數據重構是一項生成數據的任務,與其他機器學習任務不同(目標是最大程度預測正確類別的可能性),這會驅動網絡產生接近輸入的輸出。
可通過幾個損失函數(例如l1、l2、均方誤差等)來實現該目標,這些損失函數的共同之處在于可以測量輸入和輸出之間的差異,因此使用任何一個函數都是可以的。
2、自編碼器網絡
一直以來,大都使用多層感知器來設計編碼器和解碼器,但事實證明,仍然還有更加專業的框架,例如卷積神經網絡(CNN)來捕獲有關輸入數據的更多空間信息來進行圖像數據壓縮。
令人驚訝的是,研究表明,用作文本數據的自編碼器的遞歸網絡效果非常好,但這并不在本文的范圍內,不再一一贅述。多層感知器中使用的編碼器的潛在向量解碼器的概念仍然適用于卷積自編碼器。唯一的區別就是卷積層需要設計專用的解碼器和編碼器。
所有這些自編碼器網絡都可以很好地完成壓縮任務,但是存在一個問題,就是這些網絡的并不具備什么創造力。這里所指的創造力是這些自編碼器只能產生見過或訓練過的東西。
不過,通過稍微調整一下整體架構的設計,就可以引出一定水平的創造力,這種調整過的東西被稱之為可變自編碼器。
可變自編碼器
可變自編碼器引入了兩個主要的設計更改:
1、不再將輸入轉換為潛在向量,而是輸出兩個向量參數:均值和方差。
2、KL散度損失的附加損失項會添加到初始損失函數中。
可變自編碼器背后的思想是,希望解碼器使用由編碼器生成的均值向量和方差向量兩個參數化的分布中,采樣出潛在向量來重構數據。
這種采樣特征,賦予了編碼器一個受控空間。而當可變自編碼器被訓練后,每當對輸入數據執行前向傳遞時,編碼器都會生成均值和方差向量,該均值和方差向量負責確定從中采樣潛在向量的分布。
均值向量確定了輸入數據編碼的中心位置,方差向量確定了要從中選擇編碼以生成真實輸出的徑向空間或圓。這意味著,對于具有相同輸入數據的前向傳遞,可變自編碼器可以生成以均值向量為中心,以方差向量空間內為中心的輸出的不同變體。
為了進行比較,在查看標準自編碼器時,當嘗試生成尚未經過網絡訓練的輸出時,由于編碼器產生的潛在向量空間的不連續性,它會生成一些并不真實的輸出。
現在我們對可變自編碼器有了直觀的了解,讓我們看看如何在TensorFlow中構建一個。
計算梯度的重新參數化
在上面的過程中,我們并未提及重參數化功能,但是它解決了可變自編碼器中一個非常關鍵的問題。
回想一下,在解碼階段,由編碼器生成的均值和方差向量控制的分布采樣潛在向量編碼,當通過的網絡前向數據傳播時,這不會產生任何問題,但是假若解碼器到編碼器反向傳播時,由于采樣操作是不可逆的,會引起很大的問題。
簡而言之,就是無法通過采樣操作來計算梯度。
應用重參數化技巧是解決這個問題的一個不錯的方法,首先通過生成均值0和方差1的標準高斯分布,再使用編碼器生成的均值和方差對該分布執行微分加法和乘法運算,就可完成這項工作。
注意,在將方差轉換為代碼中的對數空間,是為了確保數值的穩定性。引入額外的損失項,即Kullback-Leibler散度損失,以確保生成的分布盡可能接近均值0和方差1的標準高斯分布。
將分布的均值驅動為0,可以確保生成的分布彼此非常接近,防止分布之間的不連續性。接近1的方差意味著我們有一個更適度(既不是很大也不是很小)的空間來生成編碼。
在執行重參數化之后,通過將方差向量與標準高斯分布相乘,并將結果添加到均值向量而獲得的分布,與由均值和方差向量立即控制的分布非常相似。
構建可變自編碼器的簡單步驟
最后,進行一下技術總結:
1、建立編碼器和解碼器網絡。
2、在編碼器和解碼器之間應用重參數化技巧,以允許反向傳播。
3、端到端訓練兩個網絡。
上文所使用的的完整代碼可在TensorFlow官方網站上找到。