为什么稀疏自编码器很少见到多层的?
Andrew Ng 的視頻和資料也好,還是網上的資料和代碼,以及書上的內容,我很少見到稀疏自編碼器是多層的結構一般都是{N,m,N}的三層結構(一層是隱層,輸入輸出各一層)為什么很少見到例如{N,m,k,m,N}這種5層的結構的Auto Encoder?是沒有必要嗎?還是有別的原因(比如破壞稀疏性)?
科研君?,每周六提供一份高質量回答。 張逸萌?等?147?人贊同 自編碼器
自從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<p,即隱層維度大于輸入數據維度。這又有什么用呢?其實不好說,但比如我們同時約束h的表達盡量稀疏(有大量維度為0,未被激活),此時的編碼器便是大名鼎鼎的“稀疏自編碼器”。可為什么稀疏的表達就是好的?這就說來話長了,有人試圖從人腦機理對比,即人類神經系統在某一刺激下,大部分神經元是被抑制的。個人覺得,從特征的角度來看更直觀些,稀疏的表達意味著系統在嘗試去特征選擇,找出大量維度中真正重要的若干維。
堆疊自編碼器
有過深度學習基礎的童鞋想必了解,深層網絡的威力在于其能夠逐層地學習原始數據的多種表達。每一層的都以底一層的表達為基礎,但往往更抽象,更加適合復雜的分類等任務。
堆疊自編碼器實際上就在做這樣的事情,如前所述,單個自編碼器通過虛構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,供閱讀上圖時參考。
相關學習資料推薦
- 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,也會定期更新我們的文章,如果您不想錯過我們的每篇回答,歡迎掃碼關注~ 】
http://weixin.qq.com/r/5zsuNoHEZdwarcVV9271?(二維碼自動識別)
編輯于 2016-05-31?22 條評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 5贊同 反對,不會顯示你的姓名 水滴 5?人贊同 Ivan Goodfellow, Yoshua Bengio, Aaron Courville的Deep Learning中14.3節描述了深度自編碼器像其他深度神經網絡一樣能夠指數級減少訓練數據和計算資源需求。在實踐中,深度自編碼器比淺層自編碼器有更好的壓縮性能。我們之所以很少看到深度自編碼器,是因為一般訓練深度自編碼器的方法是采取貪心策略,逐層訓練淺層自編碼器。
from:?https://www.zhihu.com/question/41490383#answer-36659160
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的为什么稀疏自编码器很少见到多层的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: github上可供新手阅读和玩耍的jav
- 下一篇: 简单提升编译速度的一个方法