為什麼稀疏自編碼器很少見到多層的?
Andrew Ng 的視頻和資料也好,還是網上的資料和代碼,以及書上的內容,我很少見到稀疏自編碼器是多層的結構一般都是{N,m,N}的三層結構(一層是隱層,輸入輸出各一層)為什麼很少見到例如{N,m,k,m,N}這種5層的結構的Auto Encoder?是沒有必要嗎?還是有別的原因(比如破壞稀疏性)?
自編碼器
自從Hinton 2006年的工作之後,越來越多的研究者開始關注各種自編碼器模型相應的堆疊模型。實際上,自編碼器(Auto-Encoder)是一個較早的概念了,比如Hinton等人在1986, 1989年的工作。(說來說去都是這些人吶。。。)
自編碼器簡介
先暫且不談神經網路、深度學習,僅是自編碼器的話,其原理很簡單。自編碼器可以理解為一個試圖去還原其原始輸入的系統。如下圖所示。
圖中,虛線藍色框內就是一個自編碼器模型,它由編碼器(Encoder)和解碼器(Decoder)兩部分組成,本質上都是對輸入信號做某種變換。編碼器將輸入信號x變換成編碼信號y,而解碼器將編碼y轉換成輸出信號。即
y=f(x)
=g(y)=g(f(x))
而自編碼器的目的是,讓輸出儘可能復現輸入x,即tries to copy its input to its output。但是,這樣問題就來了——如果f和g都是恆等映射,那不就恆有=x了?不錯,確實如此,但這樣的變換——沒有任何卵用啊!因此,我們經常對中間信號y(也叫作「編碼」)做一定的約束,這樣,系統往往能學出很有趣的編碼變換f和編碼y。
這裡強調一點,對於自編碼器,我們往往並不關係輸出是啥(反正只是復現輸入),我們真正關心的是中間層的編碼,或者說是從輸入到編碼的映射。可以這麼想,在我們強迫編碼y和輸入x不同的情況下,系統還能夠去復原原始信號x,那麼說明編碼y已經承載了原始數據的所有信息,但以一種不同的形式!這就是特徵提取啊,而且是自動學出來的!實際上,自動學習原始數據的特徵表達也是神經網路和深度學習的核心目的之一。
為了更好的理解自編碼器,下面結合神經網路加以介紹。
自編碼器與神經網路
神經網路的知識不再詳細介紹,相信了解自編碼器的讀者或多或少會了解一些。簡單來講,神經網路就是在對原始信號逐層地做非線性變換,如下圖所示。
該網路把輸入層數據x∈Rn轉換到中間層(隱層)h∈Rp,再轉換到輸出層y∈Rm。圖中的每個節點代表數據的一個維度(偏置項圖中未標出)。每兩層之間的變換都是「線性變化」+「非線性激活」,用公式表示即為
h=f(W(1)x+b(1))
y=f(W(2)h+b(2))
神經網路往往用於分類,其目的是去逼近從輸入層到輸出層的變換函數。因此,我們會定義一個目標函數來衡量當前的輸出和真實結果的差異,利用該函數去逐步調整(如梯度下降)系統的參數(W(1),b(1),W(2),b(2)),以使得整個網路儘可能去擬合訓練數據。如果有正則約束的話,還同時要求模型盡量簡單(防止過擬合)。
那麼,自編碼器怎麼表示呢?前面已說過,自編碼器試圖復現其原始輸入,因此,在訓練中,網路中的輸出應與輸入相同,即y=x,因此,一個自編碼器的輸入、輸出應有相同的結構,即
我們利用訓練數據訓練這個網路,等訓練結束後,這個網路即學習出了x→h→x的能力。對我們來說,此時的h是至關重要的,因為它是在盡量不損失信息量的情況下,對原始數據的另一種表達。結合神經網路的慣例,我們再將自編碼器的公式表示如下:(假設激活函數是sigmoid,用s表示)
y=fθ(x)=s(Wx+b)
=gθ′(y)=s(W′y+b′)
L(x,)=L(x,g(f(x)))
其中,L表示損失函數,結合數據的不同形式,可以是二次誤差(squared error loss)或交叉熵誤差(cross entropy loss)。如果,一般稱為tied weights。
為了盡量學到有意義的表達,我們會給隱層加入一定的約束。從數據維度來看,常見以下兩種情況:
- n&>p,即隱層維度小於輸入數據維度。也就是說從x→h的變換是一種降維的操作,網路試圖以更小的維度去描述原始數據而盡量不損失數據信息。實際上,當每兩層之間的變換均為線性,且監督訓練的誤差是二次型誤差時,該網路等價於PCA!沒反應過來的童鞋可以反思下PCA是在做什麼事情。
- n&
堆疊自編碼器
有過深度學習基礎的童鞋想必了解,深層網路的威力在於其能夠逐層地學習原始數據的多種表達。每一層的都以底一層的表達為基礎,但往往更抽象,更加適合複雜的分類等任務。
堆疊自編碼器實際上就在做這樣的事情,如前所述,單個自編碼器通過虛構x→h→x的三層網路,能夠學習出一種特徵變化h=fθ(x)(這裡用θ表示變換的參數,包括W,b和激活函數)。實際上,當訓練結束後,輸出層已經沒什麼意義了,我們一般將其去掉,即將自編碼器表示為
之前之所以將自編碼器模型表示為3層的神經網路,那是因為訓練的需要,我們將原始數據作為假想的目標輸出,以此構建監督誤差來訓練整個網路。等訓練結束後,輸出層就可以去掉了,我們關心的只是從x到h的變換。
接下來的思路就很自然了——我們已經得到特徵表達h,那麼我們可不可以將
h再當做原始信息,訓練一個新的自編碼器,得到新的特徵表達呢?當然可以!這就是所謂的堆疊自編碼器(Stacked Auto-Encoder, SAE)。Stacked就是逐層壘疊的意思,跟「棧」有點像。UFLDL教程將其翻譯為「棧式自編碼」,anyway,不管怎麼稱呼,都是這個東東,別被花里胡哨的專業術語嚇到就行。當把多個自編碼器Stack起來之後,這個系統看起來就像這樣:
亦可賽艇!這個系統實際上已經有點深度學習的味道了,即learning multiple levels of representation and abstraction(Hinton, Bengio, LeCun, 2015)。需要注意的是,整個網路的訓練不是一蹴而就的,而是逐層進行。按題主提到的結構n,m,k結構,實際上我們是先訓練網路n→m→n,得到n→m的變換,然後再訓練m→k→m,得到m→k的變換。最終堆疊成SAE,即為n→m→k的結果,整個過程就像一層層往上蓋房子,這便是大名鼎鼎的layer-wise unsuperwised pre-training(逐層非監督預訓練),正是導致深度學習(神經網路)在2006年第3次興起的核心技術。
關於逐層預訓練與深度學習,將在本文最後探討。
自編碼器的變種形式
上述介紹的自編碼器是最基本的形式。善於思考的童鞋可能已經意識到了這個問題:隱層的維度到底怎麼確定?為什麼稀疏的特徵比較好?或者更準確的說,怎麼才能稱得上是一個好的表達(What defines a good representation)?
事實上,這個問題回答並不唯一,也正是從不同的角度去思考這個問題,導致了自編碼器的各種變種形式出現。目前常見的幾種模型總結如下(有些術語實在不好翻譯,看英文就好。。。)
下面簡介下其中兩種模型,以對這些變種模型有個直觀感受。
稀疏自編碼器
UFLDL-自編碼演算法與稀疏性對該模型有著比較詳細的介紹。如前所示,這種模型背後的思想是,高維而稀疏的表達是好的。一般而言,我們不會指定隱層表達h中哪些節點是被抑制的(對於sigmoid單元即輸出為0),而是指定一個稀疏性參數ρ,代表隱藏神經元的平均活躍程度(在訓練集上取平均)。比如,當ρ=0.05時,可以認為隱層節點在95%的時間裡都是被一直的,只有5%的機會被激活。實際上,為了滿足這一條件,隱層神經元的活躍度需要接近於0。
那麼,怎麼從數學模型上做到這點呢?思路也不複雜,既然要求平均激活度為ρ,那麼只要引入一個度量,來衡量神經元ii的實際激活度與期望激活度ρ之間的差異即可,然後將這個度量添加到目標函數作為正則,訓練整個網路即可。那麼,什麼樣的度量適合這個任務呢?有過概率論、資訊理論基礎的同學應該很容易想到它——相對熵,也就是KL散度(KL divergence)。因此,整個網路所添加的懲罰項即為
具體的公式不再展開,可以從下圖(摘自UFLDL)中直觀理解KL散度作為懲罰項的含義。圖中假設平均激活度ρ=0.2。
可以看出,當^ρiρ^i一旦偏離期望激活度ρρ,這種誤差便急劇增大,從而作為懲罰項添加到目標函數,指導整個網路學習出稀疏的特徵表達。
降噪自編碼器
關於降噪自編碼器,強烈推薦其作者Pascal Vincent的論文Stacked Denoising Autoencoders: Learning Useful Representations in a Deep Network with a Local Denoising Criterion。DAE的核心思想是,一個能夠從中恢復出原始信號的表達未必是最好的,能夠對「被污染/破壞」的原始數據編碼、解碼,然後還能恢復真正的原始數據,這樣的特徵才是好的。
稍微數學一點,假設原始數據x被我們「故意破壞」,比如加入高斯白噪,或者把某些維度數據抹掉,變成了,然後再對編碼、解碼,得到恢複信號,該恢複信號儘可能逼近未被污染的數據xx。此時,監督訓練的誤差從L(x,g(f(x)))變成了L(x,g(f()))。
直觀上理解,DAE希望學到的特徵變換儘可能魯棒,能夠在一定程度上對抗原始數據的污染、缺失。Vincent論文里也對DAE提出了基於流行的解釋,並且在圖像數據上進行測試,發現DAE能夠學出類似Gabor邊緣提取的特徵變換。注意,這一切都是在我們定義好規則、誤差後,系統自動學出來的!從而避免了領域專家費盡心力去設計這些性能良好的特徵。
DAE的系統結構如下圖(摘自Vincent論文)所示。
現在使用比較多的noise主要是mask noise,即原始數據中部分數據缺失,這是有著很強的實際意義的,比如圖像部分像素被遮擋、文本因記錄原因漏掉了一些單詞等等。
其他的模型就不再展開了,總之,每遇到一個自編碼器的一個變種模型時,搞清楚其背後的思想(什麼樣的表達才是好的),就很容易掌握了。套用V的」Behind this mask is a man, and behind this man is an idea, and ideas are bulletproof」,我們可以說,」Behind this auto-encoder is a model, and behind this model is an idea, and ideas are bulletproof」。
關於預訓練與深度學習
深度學習第3次興起正式因為逐層預訓練方法的提出,使得深度網路的訓練成為可能。對於一個深度網路,這種逐層預訓練的方法,正是前面介紹的這種Stacked Auto-Encoder。對於常見的分類任務,一般分為以下兩個階段:
- layer-wise pre-training (逐層預訓練)
- fune-tuning (微調)
注意到,前述的各種SAE,本質上都是非監督學習,SAE各層的輸出都是原始數據的不同表達。對於分類任務,往往在SAE頂端再添加一分類層(如Softmax層),並結合有標註的訓練數據,在誤差函數的指導下,對系統的參數進行微調,以使得整個網路能夠完成所需的分類任務。
對於微調過程,即可以只調整分類層的參數(此時相當於把整個SAE當做一個feature extractor),也可以調整整個網路的參數(適合訓練數據量比較大的情況)。
題主提到,為什麼訓練稀疏自編碼器為什麼一般都是3層的結構,實際上這裡的3層是指訓練單個自編碼器所假想的3層神經網路,這對任何基於神經網路的編碼器都是如此。多層的稀疏自編碼器自然是有的,只不過是通過layer-wise pre-training這種方式逐層壘疊起來的,而不是直接去訓練一個5層或是更多層的網路。
為什麼要這樣?實際上,這正是在訓練深層神經網路中遇到的問題。直接去訓練一個深層的自編碼器,其實本質上就是在做深度網路的訓練,由於梯度擴散等問題,這樣的網路往往根本無法訓練。這倒不是因為會破壞稀疏性等原因,只要網路能夠訓練,對模型施加的約束總能得到相應的結果。
但為什麼逐層預訓練就可以使得深度網路的訓練成為可能了呢?有不少文章也做過這方面的研究。一個直觀的解釋是,預訓練好的網路在一定程度上擬合了訓練數據的結構,這使得整個網路的初始值是在一個合適的狀態,便於有監督階段加快迭代收斂。
筆者曾經基於 MNIST數據集,嘗試了一個9層的網路完成分類任務。當隨機初始化時,誤差傳到底層幾乎全為0,根本無法訓練。但採用逐層預訓練的方法,訓練好每兩層之間的自編碼變換,將其參數作為系統初始值,然後網路在有監督階段就能比較穩定的迭代了。
當然,有不少研究提出了很好的初始化策略,再加上現在常用的dropout、ReLU,直接去訓練一個深層網路已經不是問題。這是否意味著這種逐層預訓練的方式已經過時了呢?這裡,我想採用下Bengio先生2015年的一段話作為回答:
Stacks of unsupervised feature learning layers are STILL useful when you are in a regime with insufficient labeled examples, for transfer learning or domain adaptation. It is a regularizer. But when the number of labeled examples becomes large enough, the advantage of that regularizer becomes much less. I suspect however that this story is far from ended! There are other ways besides pre-training of combining supervised and unsupervised learning, and I believe that we still have a lot to improve in terms of our unsupervised learning algorithms.
最後,多說一句,除了AE和SAE這種逐層預訓練的方式外,還有另外一條類似的主線,即限制玻爾茲曼機(RBM)與深度信念網路(DBN)。這些模型在神經網路/深度學習框架中的位置,可以簡要總結為下圖。
訂正:感謝@Detective 夏恩指正,RBM堆疊起來是Deep Boltzmann Machines, 再加一個分類器才是DBN,供閱讀上圖時參考。
相關學習資料推薦
- Sranford UFLDL教程 舊版有中文版作為參考
- Deep Learning Tutorial (Theano) 其中有關於AE、DAE、SDAE基於Theano的實現
- DeepLearnToolbox 該Toolbox基於Matlab實現,其中有SAE、CAE的實現
- 相關論文
- Hinton, G.E. and R.R. Salakhutdinov, Reducing the dimensionality of data with neural networks. Science, 2006. 313(5786): p. 504-507.
- Learning multiple layers of representation. Trends in cognitive sciences, 2007. 11(10): p. 428-434.
- Vincent, P., et al. Extracting and composing robust features with denoising autoencoders. in Proceedings of the 25th international conference on Machine learning. 2008.
- Bengio, Y., Learning deep architectures for AI. Foundations and trends? in Machine Learning, 2009. 2(1): p. 1-127.
- Vincent, P., et al., Stacked Denoising Autoencoders: Learning Useful Representations in a Deep Network with a Local Denoising Criterion. Journal of Machine Learning Research, 2010. 11(6): p. 3371-3408.
- Rifai, S., et al., Contractive Auto-Encoders: Explicit Invariance During Feature Extraction. Icml, 2011.
- Chen, M., et al., Marginalized denoising autoencoders for domain adaptation. arXiv preprint arXiv:1206.4683, 2012.
- Bengio, Y., A. Courville and P. Vincent, Representation learning: A review and new perspectives. Pattern Analysis and Machine Intelligence, IEEE Transactions on, 2013. 35(8): p. 1798-1828.
- LeCun, Y., Y. Bengio and G. Hinton, Deep learning. Nature, 2015. 521(7553): p. 436-444.
【非常高興看到大家喜歡並贊同我們的回答。應許多知友的建議,最近我們開通了同名公眾號:PhDer,也會定期更新我們的文章,如果您不想錯過我們的每篇回答,歡迎掃碼關注~ 】
【「科研君」公眾號初衷始終是希望聚集各專業一線科研人員和工作者,在進行科學研究的同時也作為知識的傳播者,利用自己的專業知識解釋和普及生活中的 一些現象和原理,展現科學有趣生動的一面。該公眾號由清華大學一群在校博士生髮起,目前參與的作者人數有10人,但我們感覺這遠遠不能覆蓋所以想科普的領域,並且由於空閑時間有限,導致我們只能每周發布一篇文章。我們期待更多的戰友加入,認識更多志同道合的人,每個人都是科研君,每個人都是知識的傳播者。我們期待大家的參與,想加入我們,進QQ群吧~:108141238】
Ivan Goodfellow, Yoshua Bengio, Aaron Courville的Deep Learning中14.3節描述了深度自編碼器像其他深度神經網路一樣能夠指數級減少訓練數據和計算資源需求。在實踐中,深度自編碼器比淺層自編碼器有更好的壓縮性能。
我們之所以很少看到深度自編碼器,是因為一般訓練深度自編碼器的方法是採取貪心策略,逐層訓練淺層自編碼器。感謝 @科研君的精彩回答,其中神經網路/深度學習框架圖尤贊。
最近在看自動編碼器相關的知識,搭樓回答一下新手學習路線吧
1. UFLDL中文教程,先對自編碼器,稀疏自編碼器,棧式自編碼器建立初步概念;英文版 UFLDL Tutorial (Unsupervised Feature Learning and Deep Learning Tutorial)。
2. 深度學習:從感知機到深度神經網路(中文版,英文版Deep Learning Tutorial: Perceptrons to Machine Learning Algorithms),綜述文章,言簡意賅,其中的選例都很到位。
3. Google貓臉人臉識別項目,基於棧式自編碼器提取特徵,無監督學習。在1000台機器上都跑了三天,個人的話很難搞。
4. 基於Theano的降噪自動編碼器,棧式自動編碼器,RBM,DBN的實現。
不stack起來,還能叫deep嗎
有多層的,實際中也一般是多層的。我懷疑問題提出這位朋友應該是對什麼有了誤解。訓練的時候一般是按照你說的預訓練
近來在複習這方面,正好看到資料說Auto Encoder本身就易於Overfit,直覺來說,似乎多層之後Generalize會更差。而Stacked之後的對大型網路比較適合,在小型網路上性能較差(我的理解是規模不夠強行深度的話會扯到蛋XD),對於Andrew Ng做教學時候可能就不適用了
我想問一下,一般如果用Autoencoder訓練3D的數據,那麼他的cost應該是多少?或者說一般認為cost是多少就代表訓練好了?
最近在研究這幾個自編碼器~
推薦閱讀: