深度學(xué)習概述:從感知機到深度網(wǎng)絡(luò )
近些年來(lái),人工智能領(lǐng)域又活躍起來(lái),除了傳統了學(xué)術(shù)圈外,Google、Microsoft、facebook等工業(yè)界優(yōu)秀企業(yè)也紛紛成立相關(guān)研究團隊,并取得了很多令人矚目的成果。這要歸功于社交網(wǎng)絡(luò )用戶(hù)產(chǎn)生的大量數據,這些數據大都是原始數據,需要被進(jìn)一步分析處理;還要歸功于廉價(jià)而又強大的計算資源的出現,比如GPGPU的快速發(fā)展。
本文引用地址:http://dyxdggzs.com/article/201612/342184.htm除去這些因素,AI尤其是機器學(xué)習領(lǐng)域出現的一股新潮流很大程度上推動(dòng)了這次復興——深度學(xué)習。本文中我將介紹深度學(xué)習背后的關(guān)鍵概念及算法,從最簡(jiǎn)單的元素開(kāi)始并以此為基礎進(jìn)行下一步構建。
(本文作者也是Java deep learning library的作者,可以從此處獲得,本文中的例子就是使用這個(gè)庫實(shí)現的。如果你喜歡,可以在Github上給個(gè)星~。用法介紹也可以從此處獲得)
機器學(xué)習基礎
如果你不太熟悉相關(guān)知識,通常的機器學(xué)習過(guò)程如下:
1、機器學(xué)習算法需要輸入少量標記好的樣本,比如10張小狗的照片,其中1張標記為1(意為狗)其它的標記為0(意為不是狗)——本文主要使用監督式、二叉分類(lèi)。
2、這些算法“學(xué)習”怎么樣正確將狗的圖片分類(lèi),然后再輸入一個(gè)新的圖片時(shí),可以期望算法輸出正確的圖片標記(如輸入一張小狗圖片,輸出1;否則輸出0)。
這通常是難以置信的:你的數據可能是模糊的,標記也可能出錯;或者你的數據是手寫(xiě)字母的圖片,用其實(shí)際表示的字母來(lái)標記它。
感知機
感知機是最早的監督式訓練算法,是神經(jīng)網(wǎng)絡(luò )構建的基礎。
假如平面中存在 n 個(gè)點(diǎn),并被分別標記為“0”和“1”。此時(shí)加入一個(gè)新的點(diǎn),如果我們想知道這個(gè)點(diǎn)的標記是什么(和之前提到的小狗圖片的辨別同理),我們要怎么做呢?
一種很簡(jiǎn)單的方法是查找離這個(gè)點(diǎn)最近的點(diǎn)是什么,然后返回和這個(gè)點(diǎn)一樣的標記。而一種稍微“智能”的辦法則是去找出平面上的一條線(xiàn)來(lái)將不同標記的數據點(diǎn)分開(kāi),并用這條線(xiàn)作為“分類(lèi)器”來(lái)區分新數據點(diǎn)的標記。

在本例中,每一個(gè)輸入數據都可以表示為一個(gè)向量 x = (x_1, x_2) ,而我們的函數則是要實(shí)現“如果線(xiàn)以下,輸出0;線(xiàn)以上,輸出1”。
用數學(xué)方法表示,定義一個(gè)表示權重的向量 w 和一個(gè)垂直偏移量 b。然后,我們將輸入、權重和偏移結合可以得到如下傳遞函數:

這個(gè)傳遞函數的結果將被輸入到一個(gè)激活函數中以產(chǎn)生標記。在上面的例子中,我們的激活函數是一個(gè)門(mén)限截止函數(即大于某個(gè)閾值后輸出1):

訓練
感知機的訓練包括多訓練樣本的輸入及計算每個(gè)樣本的輸出。在每一次計算以后,權重 w 都要調整以最小化輸出誤差,這個(gè)誤差由輸入樣本的標記值與實(shí)際計算得出值的差得出。還有其它的誤差計算方法,如均方差等,但基本的原則是一樣的。
缺陷
這種簡(jiǎn)單的感知機有一個(gè)明顯缺陷:只能學(xué)習線(xiàn)性可分函數。這個(gè)缺陷重要嗎?比如 XOR,這么簡(jiǎn)單的函數,都不能被線(xiàn)性分類(lèi)器分類(lèi)(如下圖所示,分隔兩類(lèi)點(diǎn)失敗):

為了解決這個(gè)問(wèn)題,我們要使用一種多層感知機,也就是——前饋神經(jīng)網(wǎng)絡(luò ):事實(shí)上,我們將要組合一群這樣的感知機來(lái)創(chuàng )建出一個(gè)更強大的學(xué)習機器。
前饋神經(jīng)網(wǎng)絡(luò )
神經(jīng)網(wǎng)絡(luò )實(shí)際上就是將大量之前講到的感知機進(jìn)行組合,用不同的方法進(jìn)行連接并作用在不同的激活函數上。

我們簡(jiǎn)單介紹下前向神經(jīng)網(wǎng)絡(luò ),其具有以下屬性:
一個(gè)輸入層,一個(gè)輸出層,一個(gè)或多個(gè)隱含層。上圖所示的神經(jīng)網(wǎng)絡(luò )中有一個(gè)三神經(jīng)元的輸入層、一個(gè)四神經(jīng)元的隱含層、一個(gè)二神經(jīng)元的輸出層。
每一個(gè)神經(jīng)元都是一個(gè)上文提到的感知機。
輸入層的神經(jīng)元作為隱含層的輸入,同時(shí)隱含層的神經(jīng)元也是輸出層神經(jīng)元的輸入。
每條建立在神經(jīng)元之間的連接都有一個(gè)權重 w (與感知機中提到的權重類(lèi)似)。
在 t 層的每個(gè)神經(jīng)元通常與前一層( t - 1層)中的每個(gè)神經(jīng)元都有連接(但你可以通過(guò)將這條連接的權重設為0來(lái)斷開(kāi)這條連接)。
為了處理輸入數據,將輸入向量賦到輸入層中。在上例中,這個(gè)網(wǎng)絡(luò )可以計算一個(gè)3維輸入向量(由于只有3個(gè)輸入層神經(jīng)元)。假如輸入向量是 [7, 1, 2],你將第一個(gè)輸入神經(jīng)元輸入7,中間的輸入1,第三個(gè)輸入2。這些值將被傳播到隱含層,通過(guò)加權傳遞函數傳給每一個(gè)隱含層神經(jīng)元(這就是前向傳播),隱含層神經(jīng)元再計算輸出(激活函數)。
輸出層和隱含層一樣進(jìn)行計算,輸出層的計算結果就是整個(gè)神經(jīng)網(wǎng)絡(luò )的輸出。
超線(xiàn)性
如果每一個(gè)感知機都只能使用一個(gè)線(xiàn)性激活函數會(huì )怎么樣?整個(gè)網(wǎng)絡(luò )的最終輸出也仍然是將輸入數據通過(guò)一些線(xiàn)性函數計算過(guò)一遍,只是用一些在網(wǎng)絡(luò )中收集的不同權值調整了一下。換名話(huà)說(shuō),再多線(xiàn)性函數的組合還是線(xiàn)性函數。如果我們限定只能使用線(xiàn)性激活函數的話(huà),前饋神經(jīng)網(wǎng)絡(luò )其實(shí)比一個(gè)感知機強大不到哪里去,無(wú)論網(wǎng)絡(luò )有多少層。
正是這個(gè)原因,大多數神經(jīng)網(wǎng)絡(luò )都是使用的非線(xiàn)性激活函數,如對數函數、雙曲正切函數、階躍函數、整流函數等。不用這些非線(xiàn)性函數的神經(jīng)網(wǎng)絡(luò )只能學(xué)習輸入數據的線(xiàn)性組合。
訓練
大多數常見(jiàn)的應用在多層感知機的監督式訓練的算法都是反向傳播算法?;镜牧鞒倘缦拢?/p>
1、將訓練樣本通過(guò)神經(jīng)網(wǎng)絡(luò )進(jìn)行前向傳播計算。
2、計算輸出誤差,常用均方差:

其中 t 是目標值, y 是實(shí)際的神經(jīng)網(wǎng)絡(luò )計算輸出。其它的誤差計算方法也可以,但MSE(均方差)通常是一種較好的選擇。

3、網(wǎng)絡(luò )誤差通過(guò)隨機梯度下降的方法來(lái)最小化。
梯度下降很常用,但在神經(jīng)網(wǎng)絡(luò )中,輸入參數是一個(gè)訓練誤差的曲線(xiàn)。每個(gè)權重的最佳值應該是誤差曲線(xiàn)中的全局最小值(上圖中的 global minimum)。在訓練過(guò)程中,權重以非常小的步幅改變(在每個(gè)樣本或每小組樣本訓練完成后)以找到全局最小值,但這可不容易,訓練通常會(huì )結束在局部最小值上(上圖中的local minima)。如例子中的,如果當前權重值為0.6,那么要向0.4方向移動(dòng)。
這個(gè)圖表示的是最簡(jiǎn)單的情況,誤差只依賴(lài)于單個(gè)參數。但是,網(wǎng)絡(luò )誤差依賴(lài)于每一個(gè)網(wǎng)絡(luò )權重,誤差函數非常、非常復雜。
好消息是反向傳播算法提供了一種通過(guò)利用輸出誤差來(lái)修正兩個(gè)神經(jīng)元之間權重的方法。關(guān)系本身十分復雜,但對于一個(gè)給定結點(diǎn)的權重修正按如下方法(簡(jiǎn)單):

其中 E 是輸出誤差, w_i 是輸入 i 的權重。
實(shí)質(zhì)上這么做的目的是利用權重 i 來(lái)修正梯度的方向。關(guān)鍵的地方在于誤差的導數的使用,這可不一定好計算:你怎么樣能給一個(gè)大型網(wǎng)絡(luò )中隨機一個(gè)結點(diǎn)中的隨機一個(gè)權重求導數呢?
答案是:通過(guò)反向傳播。誤差的首次計算很簡(jiǎn)單(只要對預期值和實(shí)際值做差即可),然后通過(guò)一種巧妙的方法反向傳回網(wǎng)絡(luò ),讓我們有效的在訓練過(guò)程中修正權重并(期望)達到一個(gè)最小值。
隱含層
隱含層十分有趣。根據普適逼近原理,一個(gè)具有有限數目神經(jīng)元的隱含層可以被訓練成可逼近任意隨機函數。換句話(huà)說(shuō),一層隱含層就強大到可以學(xué)習任何函數了。這說(shuō)明我們在多隱含層(如深度網(wǎng)絡(luò ))的實(shí)踐中可以得到更好的結果。
隱含層存儲了訓練數據的內在抽象表示,和人類(lèi)大腦(簡(jiǎn)化的類(lèi)比)保存有對真實(shí)世界的抽象一樣。接下來(lái),我們將用各種方法來(lái)搞一下這個(gè)隱含層。
一個(gè)網(wǎng)絡(luò )的例子
可以看一下這個(gè)通過(guò) testMLPSigmoidBP 方法用Java實(shí)現的簡(jiǎn)單(4-2-3)前饋神經(jīng)網(wǎng)絡(luò ),它將 IRIS 數據集進(jìn)行了分類(lèi)。這個(gè)數據集中包含了三類(lèi)鳶尾屬植物,特征包括花萼長(cháng)度,花瓣長(cháng)度等等。每一類(lèi)提供50個(gè)樣本給這個(gè)神經(jīng)網(wǎng)絡(luò )訓練。特征被賦給輸入神經(jīng)元,每一個(gè)輸出神經(jīng)元代表一類(lèi)數據集(“1/0/0” 表示這個(gè)植物是Setosa,“0/1/0”表示 Versicolour,而“0/0/1”表示 Virginica)。分類(lèi)的錯誤率是2/150(即每分類(lèi)150個(gè),錯2個(gè))。
大規模網(wǎng)絡(luò )中的難題
神經(jīng)網(wǎng)絡(luò )中可以有多個(gè)隱含層:這樣,在更高的隱含層里可以對其之前的隱含層構建新的抽象。而且像之前也提到的,這樣可以更好的學(xué)習大規模網(wǎng)絡(luò )。增加隱含層的層數通常會(huì )導致兩個(gè)問(wèn)題:
1、梯度消失:隨著(zhù)我們添加越來(lái)越多的隱含層,反向傳播傳遞給較低層的信息會(huì )越來(lái)越少。實(shí)際上,由于信息向前反饋,不同層次間的梯度開(kāi)始消失,對網(wǎng)絡(luò )中權重的影響也會(huì )變小。
2、過(guò)度擬合:也許這是機器學(xué)習的核心難題。簡(jiǎn)要來(lái)說(shuō),過(guò)度擬合指的是對訓練數據有著(zhù)過(guò)于好的識別效果,這時(shí)導至模型非常復雜。這樣的結果會(huì )導致對訓練數據有非常好的識別較果,而對真實(shí)樣本的識別效果非常差。
下面我們來(lái)看看一些深度學(xué)習的算法是如何面對這些難題的。
自編碼器
大多數的機器學(xué)習入門(mén)課程都會(huì )讓你放棄前饋神經(jīng)網(wǎng)絡(luò )。但是實(shí)際上這里面大有可為——請接著(zhù)看。
自編碼器就是一個(gè)典型的前饋神經(jīng)網(wǎng)絡(luò ),它的目標就是學(xué)習一種對數據集的壓縮且分布式的表示方法(編碼思想)。

從概念上講,神經(jīng)網(wǎng)絡(luò )的目的是要訓練去“重新建立”輸入數據,好像輸入和目標輸出數據是一樣的。換句話(huà)說(shuō):你正在讓神經(jīng)網(wǎng)絡(luò )的輸出與輸入是同一樣東西,只是經(jīng)過(guò)了壓縮。這還是不好理解,先來(lái)看一個(gè)例子。
壓縮輸入數據:灰度圖像
這里有一個(gè)由28x28像素的灰度圖像組成的訓練集,且每一個(gè)像素的值都作為一個(gè)輸入層神經(jīng)元的輸入(這時(shí)輸入層就會(huì )有784個(gè)神經(jīng)元)。輸出層神經(jīng)元要有相同的數目(784),且每一個(gè)輸出神經(jīng)元的輸出值和輸入圖像的對應像素灰度值相同。
在這樣的算法架構背后,神經(jīng)網(wǎng)絡(luò )學(xué)習到的實(shí)際上并不是一個(gè)訓練數據到標記的“映射”,而是去學(xué)習數據本身的內在結構和特征(也正是因為這,隱含層也被稱(chēng)作特征探測器(feature detector))。通常隱含層中的神經(jīng)元數目要比輸入/輸入層的少,這是為了使神經(jīng)網(wǎng)絡(luò )只去學(xué)習最重要的特征并實(shí)現特征的降維。
我們想在中間層用很少的結點(diǎn)去在概念層上學(xué)習數據、產(chǎn)生一個(gè)緊致的表示方法。
流行感冒
為了更好的描述自編碼器,再看一個(gè)應用。
這次我們使用一個(gè)簡(jiǎn)單的數據集,其中包括一些感冒的癥狀。如果感興趣,這個(gè)例子的源碼發(fā)布在這里。
數據結構如下:
輸入數據一共六個(gè)二進(jìn)制位
前三位是病的證狀。例如,1 0 0 0 0 0 代表病人發(fā)燒;0 1 0 0 0 0 代表咳嗽;1 1 0 0 0 0 代表即咳嗽又發(fā)燒等等。
后三位表示抵抗能力,如果一個(gè)病人有這個(gè),代表他/她不太可能患此病。例如,0 0 0 1 0 0 代表病人接種過(guò)流感疫苗。一個(gè)可能的組合是:0 1 0 1 0 0 ,這代表著(zhù)一個(gè)接種過(guò)流感疫苗的咳嗽病人,等等。
當一個(gè)病人同時(shí)擁用前三位中的兩位時(shí),我們認為他生病了;如果至少擁用后三位中的兩位,那么他是健康的,如:
111000, 101000, 110000, 011000, 011100 = 生病
000111, 001110, 000101, 000011, 000110 = 健康
我們來(lái)訓練一個(gè)自編碼器(使用反向傳播),六個(gè)輸入、六個(gè)輸出神經(jīng)元,而只有兩個(gè)隱含神經(jīng)元。
在經(jīng)過(guò)幾百次迭代以后,我們發(fā)現,每當一個(gè)“生病”的樣本輸入時(shí),兩個(gè)隱含層神經(jīng)元中的一個(gè)(對于生病的樣本總是這個(gè))總是顯示出更高的激活值。而如果輸入一個(gè)“健康”樣本時(shí),另一個(gè)隱含層則會(huì )顯示更高的激活值。
再看學(xué)習
本質(zhì)上來(lái)說(shuō),這兩個(gè)隱含神經(jīng)元從數據集中學(xué)習到了流感癥狀的一種緊致表示方法。為了檢驗它是不是真的實(shí)現了學(xué)習,我們再看下過(guò)度擬合的問(wèn)題。通過(guò)訓練我們的神經(jīng)網(wǎng)絡(luò )學(xué)習到的是一個(gè)緊致的簡(jiǎn)單的,而不是一個(gè)高度復雜且對數據集過(guò)度擬合的表示方法。
某種程度上來(lái)講,與其說(shuō)在找一種簡(jiǎn)單的表示方法,我們更是在嘗試從“感覺(jué)”上去學(xué)習數據。
受限波爾茲曼機
下一步來(lái)看下受限波爾茲曼機(Restricted Boltzmann machines RBM),一種可以在輸入數據集上學(xué)習概率分布的生成隨機神經(jīng)網(wǎng)絡(luò )。

RBM由隱含層、可見(jiàn)層、偏置層組成。和前饋神經(jīng)網(wǎng)絡(luò )不同,可見(jiàn)層和隱含層之間的連接是無(wú)方向性(值可以從可見(jiàn)層->隱含層或隱含層->可見(jiàn)層任意傳輸)且全連接的(每一個(gè)當前層的神經(jīng)元與下一層的每個(gè)神經(jīng)元都有連接——如果允許任意層的任意神經(jīng)元連接到任意層去,我們就得到了一個(gè)波爾茲曼機(非受限的))。
標準的RBM中,隱含和可見(jiàn)層的神經(jīng)元都是二態(tài)的(即神經(jīng)元的激活值只能是服從伯努力分布的0或1),不過(guò)也存在其它非線(xiàn)性的變種。
雖然學(xué)者們已經(jīng)研究RBM很長(cháng)時(shí)間了,最近出現的對比差異無(wú)監督訓練算法使這個(gè)領(lǐng)域復興。
對比差異
單步對比差異算法原理:
1、正向過(guò)程:
輸入樣本 v 輸入至輸入層中。
v 通過(guò)一種與前饋網(wǎng)絡(luò )相似的方法傳播到隱含層中,隱含層的激活值為 h。
2、反向過(guò)程:
將 h 傳回可見(jiàn)層得到 v’ (可見(jiàn)層和隱含層的連接是無(wú)方向的,可以這樣傳)。
再將 v’ 傳到隱含層中,得到 h’。
3、權重更新:

其中 a 是學(xué)習速率, v, v’, h, h’ 和 w 都是向量。
算法的思想就是在正向過(guò)程中影響了網(wǎng)絡(luò )的內部對于真實(shí)數據的表示。同時(shí),反向過(guò)程中嘗試通過(guò)這個(gè)被影響過(guò)的表示方法重建數據。主要目的是可以使生成的數據與原數據盡可能相似,這個(gè)差異影響了權重更新。
換句話(huà)說(shuō),這樣的網(wǎng)絡(luò )具有了感知對輸入數據表示的程度的能力,而且嘗試通過(guò)這個(gè)感知能力重建數據。如果重建出來(lái)的數據與原數據差異很大,那么進(jìn)行調整并再次重建。
再看流行感冒的例子
為了說(shuō)明對比差異,我們使用與上例相同的流感癥狀的數據集。測試網(wǎng)絡(luò )是一個(gè)包含6個(gè)可見(jiàn)層神經(jīng)元、2個(gè)隱含層神經(jīng)元的RBM。我們用對比差異的方法對網(wǎng)絡(luò )進(jìn)行訓練,將癥狀 v 賦到可見(jiàn)層中。在測試中,這些癥狀值被重新傳到可見(jiàn)層;然后再被傳到隱含層。隱含層的神經(jīng)元表示健康/生病的狀態(tài),與自編碼器相似。
在進(jìn)行過(guò)幾百次迭代后,我們得到了與自編碼器相同的結果:輸入一個(gè)生病樣本,其中一個(gè)隱含層神經(jīng)元具有更高激活值;輸入健康的樣本,則另一個(gè)神經(jīng)元更興奮。
例子的代碼在這里。
深度網(wǎng)絡(luò )
到現在為止,我們已經(jīng)學(xué)習了隱含層中強大的特征探測器——自編碼器和RBM,但現在還沒(méi)有辦法有效的去利用這些功能。實(shí)際上,上面所用到的這些數據集都是特定的。而我們要找到一些方法來(lái)間接的使用這些探測出的特征。
好消息是,已經(jīng)發(fā)現這些結構可以通過(guò)棧式疊加來(lái)實(shí)現深度網(wǎng)絡(luò )。這些網(wǎng)絡(luò )可以通過(guò)貪心法的思想訓練,每次訓練一層,以克服之前提到在反向傳播中梯度消失及過(guò)度擬合的問(wèn)題。
這樣的算法架構十分強大,可以產(chǎn)生很好的結果。如Google著(zhù)名的“貓”識別,在實(shí)驗中通過(guò)使用特定的深度自編碼器,在無(wú)標記的圖片庫中學(xué)習到人和貓臉的識別。
下面我們將更深入。
棧式自編碼器
和名字一樣,這種網(wǎng)絡(luò )由多個(gè)棧式結合的自編碼器組成。

自編碼器的隱含層 t 會(huì )作為 t + 1 層的輸入層。第一個(gè)輸入層就是整個(gè)網(wǎng)絡(luò )的輸入層。利用貪心法訓練每一層的步驟如下:
1、通過(guò)反向傳播的方法利用所有數據對第一層的自編碼器進(jìn)行訓練(t=1,上圖中的紅色連接部分)。
2、訓練第二層的自編碼器 t=2 (綠色連接部分)。由于 t=2 的輸入層是 t=1 的隱含層,我們已經(jīng)不再關(guān)心 t=1 的輸入層,可以從整個(gè)網(wǎng)絡(luò )中移除。整個(gè)訓練開(kāi)始于將輸入樣本數據賦到 t=1 的輸入層,通過(guò)前向傳播至 t = 2 的輸出層。下面t = 2的權重(輸入->隱含和隱含->輸出)使用反向傳播的方法進(jìn)行更新。t = 2的層和 t=1 的層一樣,都要通過(guò)所有樣本的訓練。
3、對所有層重復步驟1-2(即移除前面自編碼器的輸出層,用另一個(gè)自編碼器替代,再用反向傳播進(jìn)行訓練)。
4、步驟1-3被稱(chēng)為預訓練,這將網(wǎng)絡(luò )里的權重值初始化至一個(gè)合適的位置。但是通過(guò)這個(gè)訓練并沒(méi)有得到一個(gè)輸入數據到輸出標記的映射。例如,一個(gè)網(wǎng)絡(luò )的目標是被訓練用來(lái)識別手寫(xiě)數字,經(jīng)過(guò)這樣的訓練后還不能將最后的特征探測器的輸出(即隱含層中最后的自編碼器)對應到圖片的標記上去。這樣,一個(gè)通常的辦法是在網(wǎng)絡(luò )的最后一層(即藍色連接部分)后面再加一個(gè)或多個(gè)全連接層。整個(gè)網(wǎng)絡(luò )可以被看作是一個(gè)多層的感知機,并使用反向傳播的方法進(jìn)行訓練(這步也被稱(chēng)為微調)。
棧式自編碼器,提供了一種有效的預訓練方法來(lái)初始化網(wǎng)絡(luò )的權重,這樣你得到了一個(gè)可以用來(lái)訓練的復雜、多層的感知機。
深度信度網(wǎng)絡(luò )
和自編碼器一樣,我也可以將波爾茲曼機進(jìn)行棧式疊加來(lái)構建深度信度網(wǎng)絡(luò )(DBN)。

在本例中,隱含層 RBM t 可以看作是 RBM t+1 的可見(jiàn)層。第一個(gè)RBM的輸入層即是整個(gè)網(wǎng)絡(luò )的輸入層,層間貪心式的預訓練的工作模式如下:
1. 通過(guò)對比差異法對所有訓練樣本訓練第一個(gè)RBM t=1
2. 訓練第二個(gè)RBM t=1。由于 t=2 的可見(jiàn)層是 t=1 的隱含層,訓練開(kāi)始于將數據賦至 t=1 的可見(jiàn)層,通過(guò)前向傳播的方法傳至 t=1 的隱含層。然后作為 t=2 的對比差異訓練的初始數據。
3. 對所有層重復前面的過(guò)程。
4. 和棧式自編碼器一樣,通過(guò)預訓練后,網(wǎng)絡(luò )可以通過(guò)連接到一個(gè)或多個(gè)層間全連接的 RBM 隱含層進(jìn)行擴展。這構成了一個(gè)可以通過(guò)反向傳僠進(jìn)行微調的多層感知機。
本過(guò)程和棧式自編碼器很相似,只是用RBM將自編碼器進(jìn)行替換,并用對比差異算法將反向傳播進(jìn)行替換。
(注: 例中的源碼可以從 此處獲得.)
卷積網(wǎng)絡(luò )
這個(gè)是本文最后一個(gè)軟件架構——卷積網(wǎng)絡(luò ),一類(lèi)特殊的對圖像識別非常有效的前饋網(wǎng)絡(luò )。

在我們深入看實(shí)際的卷積網(wǎng)絡(luò )之臆,我們先定義一個(gè)圖像濾波器,或者稱(chēng)為一個(gè)賦有相關(guān)權重的方陣。一個(gè)濾波器可以應用到整個(gè)圖片上,通??梢詰枚鄠€(gè)濾波器。比如,你可以應用四個(gè)6x6的濾波器在一張圖片上。然后,輸出中坐標(1,1)的像素值就是輸入圖像左上角一個(gè)6x6區域的加權和,其它像素也是如此。
有了上面的基礎,我們來(lái)介紹定義出卷積網(wǎng)絡(luò )的屬性:
卷積層 對輸入數據應用若干濾波器。比如圖像的第一卷積層使用4個(gè)6x6濾波器。對圖像應用一個(gè)濾波器之后的得到的結果被稱(chēng)為特征圖譜(feature map, FM),特征圖譜的數目和濾波器的數目相等。如果前驅層也是一個(gè)卷積層,那么濾波器應用在FM上,相當于輸入一個(gè)FM,輸出另外一個(gè)FM。從直覺(jué)上來(lái)講,如果將一個(gè)權重分布到整個(gè)圖像上后,那么這個(gè)特征就和位置無(wú)關(guān)了,同時(shí)多個(gè)濾波器可以分別探測出不同的特征。
下采樣層 縮減輸入數據的規模。例如輸入一個(gè)32x32的圖像,并且通過(guò)一個(gè)2x2的下采樣,那么可以得到一個(gè)16x16的輸出圖像,這意味著(zhù)原圖像上的四個(gè)像素合并成為輸出圖像中的一個(gè)像素。實(shí)現下采樣的方法有很多種,最常見(jiàn)的是最大值合并、平均值合并以及隨機合并。
最后一個(gè)下采樣層(或卷積層)通常連接到一個(gè)或多個(gè)全連層,全連層的輸出就是最終的輸出。
訓練過(guò)程通過(guò)改進(jìn)的反向傳播實(shí)現,將下采樣層作為考慮的因素并基于所有值來(lái)更新卷積濾波器的權重。
可以在這看幾個(gè)應用在 MNIST 數據集上的卷積網(wǎng)絡(luò )的例子,在這還有一個(gè)用JavaScript實(shí)現的一個(gè)可視的類(lèi)似網(wǎng)絡(luò )。
實(shí)現
目前為止,我們已經(jīng)學(xué)會(huì )了常見(jiàn)神經(jīng)網(wǎng)絡(luò )中最主要的元素了,但是我只寫(xiě)了很少的在實(shí)現過(guò)程中所遇到的挑戰。
概括來(lái)講,我的目標是實(shí)現一個(gè)深度學(xué)習的庫,即一個(gè)基于神經(jīng)網(wǎng)絡(luò )且滿(mǎn)足如下條件的框架:
一個(gè)可以表示多種模型的通用架構(比如所有上文提到的神經(jīng)網(wǎng)絡(luò )中的元素)
可以使用多種訓練算法(反向傳播,對比差異等等)。
體面的性能
為了滿(mǎn)足這些要求,我在軟件的設計中使用了分層的思想。
結構
我們從如下的基礎部分開(kāi)始:
NeuralNetworkImpl 是所有神經(jīng)網(wǎng)絡(luò )模型實(shí)現的基類(lèi)。
每個(gè)網(wǎng)絡(luò )都包含有一個(gè) layer 的集合。
每一層中有一個(gè) connections 的鏈表, connection 指的是兩個(gè)層之間的連接,將整個(gè)網(wǎng)絡(luò )構成一個(gè)有向無(wú)環(huán)圖。
這個(gè)結構對于經(jīng)典的反饋網(wǎng)絡(luò )、RBM 及更復雜的如 ImageNet 都已經(jīng)足夠靈活。
這個(gè)結構也允許一個(gè) layer 成為多個(gè)網(wǎng)絡(luò )的元素。比如,在 Deep Belief Network(深度信度網(wǎng)絡(luò ))中的layer也可以用在其 RBM 中。
另外,通過(guò)這個(gè)架構可以將DBN的預訓練階段顯示為一個(gè)棧式RBM的列表,微調階段顯示為一個(gè)前饋網(wǎng)絡(luò ),這些都非常直觀(guān)而且程序實(shí)現的很好。
數據流
下個(gè)部分介紹網(wǎng)絡(luò )中的數據流,一個(gè)兩步過(guò)程:
定義出層間的序列。例如,為了得到一個(gè)多層感知機的結果,輸入數據被賦到輸入層(因此,這也是首先被計算的層),然后再將數據通過(guò)不同的方法流向輸出層。為了在反向傳播中更新權重,輸出的誤差通過(guò)廣度優(yōu)先的方法從輸出層傳回每一層。這部分通過(guò) LayerOrderStrategy 進(jìn)行實(shí)現,應用到了網(wǎng)絡(luò )圖結構的優(yōu)勢,使用了不同的圖遍歷方法。其中一些樣例包含了 廣度優(yōu)先策略 和 定位到一個(gè)指定的層。層的序列實(shí)際上由層間的連接進(jìn)行決定,所以策略部分都是返回一個(gè)連接的有序列表。
計算激活值。每一層都有一個(gè)關(guān)聯(lián)的 ConnectionCalculator,包含有連接的列表(從上一步得來(lái))和輸入值(從其它層得到)并計算得到結果的激活值。例如,在一個(gè)簡(jiǎn)單的S形前饋網(wǎng)絡(luò )中,隱含層的 ConnectionCalculator 接受輸入層和偏置層的值(分別為輸入值和一個(gè)值全為1的數組)和神經(jīng)元之間的權重值(如果是全連接層,權重值實(shí)際上以一個(gè)矩陣的形式存儲在一個(gè) FullyConnected 結構中,計算加權和,然后將結果傳給S函數。ConnectionCalculator 中實(shí)現了一些轉移函數(如加權求和、卷積)和激活函數(如對應多層感知機的對數函數和雙曲正切函數,對應RBM的二態(tài)函數)。其中的大部分都可以通過(guò) Aparapi 在GPU上進(jìn)行計算,可以利用迷你批次訓練。
通過(guò) Aparapi 進(jìn)行 GPU 計算
像我之前提到的,神經(jīng)網(wǎng)絡(luò )在近些年復興的一個(gè)重要原因是其訓練的方法可以高度并行化,允許我們通過(guò)GPGPU高效的加速訓練。本文中,我選擇 Aparapi 庫來(lái)進(jìn)行GPU的支持。
Aparapi 在連接計算上強加了一些重要的限制:
只允許使用原始數據類(lèi)型的一維數組(變量)。
在GPU上運行的程序只能調用 Aparapi Kernel 類(lèi)本身的成員函數。
這樣,大部分的數據(權重、輸入和輸出數據)都要保存在 Matrix 實(shí)例里面,其內部是一個(gè)一維浮點(diǎn)數組。所有Aparapi 連接計算都是使用 AparapiWeightedSum (應用在全連接層和加權求和函數上)、 AparapiSubsampling2D (應用在下采樣層)或 AparapiConv2D (應用在卷積層)。這些限制可以通過(guò) Heterogeneous System Architecture 里介紹的內容解決一些。而且Aparapi 允許相同的代碼運行在CPU和GPU上。
訓練
training 的模塊實(shí)現了多種訓練算法。這個(gè)模塊依賴(lài)于上文提到的兩個(gè)模塊。比如,BackPropagationTrainer (所有的訓練算法都以 Trainer 為基類(lèi))在前饋階段使用前饋層計算,在誤差傳播和權重更新時(shí)使用特殊的廣度優(yōu)先層計算。
我最新的工作是在Java8環(huán)境下開(kāi)發(fā),其它一些更新的功能可以在這個(gè)branch 下獲得,這部分的工作很快會(huì )merge到主干上。
結論
本文的目標是提供一個(gè)深度學(xué)習算法領(lǐng)域的一個(gè)簡(jiǎn)明介紹,由最基本的組成元素開(kāi)始(感知機)并逐漸深入到多種當前流行且有效的架構上,比如受限波爾茲曼機。
神經(jīng)網(wǎng)絡(luò )的思想已經(jīng)出現了很長(cháng)時(shí)間,但是今天,你如果身處機器學(xué)習領(lǐng)域而不知道深度學(xué)習或其它相關(guān)知識是不應該的。不應該過(guò)度宣傳,但不可否認隨著(zhù)GPGPU提供的計算能力、包括Geoffrey Hinton, Yoshua Bengio, Yann LeCun and Andrew Ng在內的研究學(xué)者們提出的高效算法,這個(gè)領(lǐng)域已經(jīng)表現出了很大的希望?,F在正是最佳的時(shí)間深入這些方面的學(xué)習。
附錄:相關(guān)資源
如果你想更深入的學(xué)習,下面的這些資源在我的工作當中都起過(guò)重要的作用:
DeepLearning.net: 深度學(xué)習所有方面知識的一個(gè)門(mén)戶(hù)。里面有完善的手冊、軟件庫 和一個(gè)非常好的 閱讀列表。
活躍的 Google+ 社區.
兩個(gè)很好的課程: Machine Learning and Neural Networks for Machine Learning, 都在Coursera上。
The Stanford neural networks tutorial,斯坦福神經(jīng)網(wǎng)絡(luò )指南。
評論