深度學(xué)習(xí)概述:從感知機到深度網(wǎng)絡(luò)
近些年來,人工智能領(lǐng)域又活躍起來,除了傳統(tǒng)了學(xué)術(shù)圈外,Google、Microsoft、facebook等工業(yè)界優(yōu)秀企業(yè)也紛紛成立相關(guān)研究團隊,并取得了很多令人矚目的成果。這要歸功于社交網(wǎng)絡(luò)用戶產(chǎn)生的大量數(shù)據(jù),這些數(shù)據(jù)大都是原始數(shù)據(jù),需要被進一步分析處理;還要歸功于廉價而又強大的計算資源的出現(xiàn),比如GPGPU的快速發(fā)展。
本文引用地址:http://www.ex-cimer.com/article/201612/342184.htm除去這些因素,AI尤其是機器學(xué)習(xí)領(lǐng)域出現(xiàn)的一股新潮流很大程度上推動了這次復(fù)興——深度學(xué)習(xí)。本文中我將介紹深度學(xué)習(xí)背后的關(guān)鍵概念及算法,從最簡單的元素開始并以此為基礎(chǔ)進行下一步構(gòu)建。
(本文作者也是Java deep learning library的作者,可以從此處獲得,本文中的例子就是使用這個庫實現(xiàn)的。如果你喜歡,可以在Github上給個星~。用法介紹也可以從此處獲得)
機器學(xué)習(xí)基礎(chǔ)
如果你不太熟悉相關(guān)知識,通常的機器學(xué)習(xí)過程如下:
1、機器學(xué)習(xí)算法需要輸入少量標(biāo)記好的樣本,比如10張小狗的照片,其中1張標(biāo)記為1(意為狗)其它的標(biāo)記為0(意為不是狗)——本文主要使用監(jiān)督式、二叉分類。
2、這些算法“學(xué)習(xí)”怎么樣正確將狗的圖片分類,然后再輸入一個新的圖片時,可以期望算法輸出正確的圖片標(biāo)記(如輸入一張小狗圖片,輸出1;否則輸出0)。
這通常是難以置信的:你的數(shù)據(jù)可能是模糊的,標(biāo)記也可能出錯;或者你的數(shù)據(jù)是手寫字母的圖片,用其實際表示的字母來標(biāo)記它。
感知機
感知機是最早的監(jiān)督式訓(xùn)練算法,是神經(jīng)網(wǎng)絡(luò)構(gòu)建的基礎(chǔ)。
假如平面中存在 n 個點,并被分別標(biāo)記為“0”和“1”。此時加入一個新的點,如果我們想知道這個點的標(biāo)記是什么(和之前提到的小狗圖片的辨別同理),我們要怎么做呢?
一種很簡單的方法是查找離這個點最近的點是什么,然后返回和這個點一樣的標(biāo)記。而一種稍微“智能”的辦法則是去找出平面上的一條線來將不同標(biāo)記的數(shù)據(jù)點分開,并用這條線作為“分類器”來區(qū)分新數(shù)據(jù)點的標(biāo)記。
在本例中,每一個輸入數(shù)據(jù)都可以表示為一個向量 x = (x_1, x_2) ,而我們的函數(shù)則是要實現(xiàn)“如果線以下,輸出0;線以上,輸出1”。
用數(shù)學(xué)方法表示,定義一個表示權(quán)重的向量 w 和一個垂直偏移量 b。然后,我們將輸入、權(quán)重和偏移結(jié)合可以得到如下傳遞函數(shù):
這個傳遞函數(shù)的結(jié)果將被輸入到一個激活函數(shù)中以產(chǎn)生標(biāo)記。在上面的例子中,我們的激活函數(shù)是一個門限截止函數(shù)(即大于某個閾值后輸出1):
訓(xùn)練
感知機的訓(xùn)練包括多訓(xùn)練樣本的輸入及計算每個樣本的輸出。在每一次計算以后,權(quán)重 w 都要調(diào)整以最小化輸出誤差,這個誤差由輸入樣本的標(biāo)記值與實際計算得出值的差得出。還有其它的誤差計算方法,如均方差等,但基本的原則是一樣的。
缺陷
這種簡單的感知機有一個明顯缺陷:只能學(xué)習(xí)線性可分函數(shù)。這個缺陷重要嗎?比如 XOR,這么簡單的函數(shù),都不能被線性分類器分類(如下圖所示,分隔兩類點失敗):
為了解決這個問題,我們要使用一種多層感知機,也就是——前饋神經(jīng)網(wǎng)絡(luò):事實上,我們將要組合一群這樣的感知機來創(chuàng)建出一個更強大的學(xué)習(xí)機器。
前饋神經(jīng)網(wǎng)絡(luò)
神經(jīng)網(wǎng)絡(luò)實際上就是將大量之前講到的感知機進行組合,用不同的方法進行連接并作用在不同的激活函數(shù)上。
我們簡單介紹下前向神經(jīng)網(wǎng)絡(luò),其具有以下屬性:
一個輸入層,一個輸出層,一個或多個隱含層。上圖所示的神經(jīng)網(wǎng)絡(luò)中有一個三神經(jīng)元的輸入層、一個四神經(jīng)元的隱含層、一個二神經(jīng)元的輸出層。
每一個神經(jīng)元都是一個上文提到的感知機。
輸入層的神經(jīng)元作為隱含層的輸入,同時隱含層的神經(jīng)元也是輸出層神經(jīng)元的輸入。
每條建立在神經(jīng)元之間的連接都有一個權(quán)重 w (與感知機中提到的權(quán)重類似)。
在 t 層的每個神經(jīng)元通常與前一層( t - 1層)中的每個神經(jīng)元都有連接(但你可以通過將這條連接的權(quán)重設(shè)為0來斷開這條連接)。
為了處理輸入數(shù)據(jù),將輸入向量賦到輸入層中。在上例中,這個網(wǎng)絡(luò)可以計算一個3維輸入向量(由于只有3個輸入層神經(jīng)元)。假如輸入向量是 [7, 1, 2],你將第一個輸入神經(jīng)元輸入7,中間的輸入1,第三個輸入2。這些值將被傳播到隱含層,通過加權(quán)傳遞函數(shù)傳給每一個隱含層神經(jīng)元(這就是前向傳播),隱含層神經(jīng)元再計算輸出(激活函數(shù))。
輸出層和隱含層一樣進行計算,輸出層的計算結(jié)果就是整個神經(jīng)網(wǎng)絡(luò)的輸出。
超線性
如果每一個感知機都只能使用一個線性激活函數(shù)會怎么樣?整個網(wǎng)絡(luò)的最終輸出也仍然是將輸入數(shù)據(jù)通過一些線性函數(shù)計算過一遍,只是用一些在網(wǎng)絡(luò)中收集的不同權(quán)值調(diào)整了一下。換名話說,再多線性函數(shù)的組合還是線性函數(shù)。如果我們限定只能使用線性激活函數(shù)的話,前饋神經(jīng)網(wǎng)絡(luò)其實比一個感知機強大不到哪里去,無論網(wǎng)絡(luò)有多少層。
正是這個原因,大多數(shù)神經(jīng)網(wǎng)絡(luò)都是使用的非線性激活函數(shù),如對數(shù)函數(shù)、雙曲正切函數(shù)、階躍函數(shù)、整流函數(shù)等。不用這些非線性函數(shù)的神經(jīng)網(wǎng)絡(luò)只能學(xué)習(xí)輸入數(shù)據(jù)的線性組合。
訓(xùn)練
大多數(shù)常見的應(yīng)用在多層感知機的監(jiān)督式訓(xùn)練的算法都是反向傳播算法?;镜牧鞒倘缦拢?/p>
1、將訓(xùn)練樣本通過神經(jīng)網(wǎng)絡(luò)進行前向傳播計算。
2、計算輸出誤差,常用均方差:
其中 t 是目標(biāo)值, y 是實際的神經(jīng)網(wǎng)絡(luò)計算輸出。其它的誤差計算方法也可以,但MSE(均方差)通常是一種較好的選擇。
3、網(wǎng)絡(luò)誤差通過隨機梯度下降的方法來最小化。
梯度下降很常用,但在神經(jīng)網(wǎng)絡(luò)中,輸入?yún)?shù)是一個訓(xùn)練誤差的曲線。每個權(quán)重的最佳值應(yīng)該是誤差曲線中的全局最小值(上圖中的 global minimum)。在訓(xùn)練過程中,權(quán)重以非常小的步幅改變(在每個樣本或每小組樣本訓(xùn)練完成后)以找到全局最小值,但這可不容易,訓(xùn)練通常會結(jié)束在局部最小值上(上圖中的local minima)。如例子中的,如果當(dāng)前權(quán)重值為0.6,那么要向0.4方向移動。
這個圖表示的是最簡單的情況,誤差只依賴于單個參數(shù)。但是,網(wǎng)絡(luò)誤差依賴于每一個網(wǎng)絡(luò)權(quán)重,誤差函數(shù)非常、非常復(fù)雜。
好消息是反向傳播算法提供了一種通過利用輸出誤差來修正兩個神經(jīng)元之間權(quán)重的方法。關(guān)系本身十分復(fù)雜,但對于一個給定結(jié)點的權(quán)重修正按如下方法(簡單):
其中 E 是輸出誤差, w_i 是輸入 i 的權(quán)重。
實質(zhì)上這么做的目的是利用權(quán)重 i 來修正梯度的方向。關(guān)鍵的地方在于誤差的導(dǎo)數(shù)的使用,這可不一定好計算:你怎么樣能給一個大型網(wǎng)絡(luò)中隨機一個結(jié)點中的隨機一個權(quán)重求導(dǎo)數(shù)呢?
答案是:通過反向傳播。誤差的首次計算很簡單(只要對預(yù)期值和實際值做差即可),然后通過一種巧妙的方法反向傳回網(wǎng)絡(luò),讓我們有效的在訓(xùn)練過程中修正權(quán)重并(期望)達到一個最小值。
隱含層
隱含層十分有趣。根據(jù)普適逼近原理,一個具有有限數(shù)目神經(jīng)元的隱含層可以被訓(xùn)練成可逼近任意隨機函數(shù)。換句話說,一層隱含層就強大到可以學(xué)習(xí)任何函數(shù)了。這說明我們在多隱含層(如深度網(wǎng)絡(luò))的實踐中可以得到更好的結(jié)果。
隱含層存儲了訓(xùn)練數(shù)據(jù)的內(nèi)在抽象表示,和人類大腦(簡化的類比)保存有對真實世界的抽象一樣。接下來,我們將用各種方法來搞一下這個隱含層。
一個網(wǎng)絡(luò)的例子
可以看一下這個通過 testMLPSigmoidBP 方法用Java實現(xiàn)的簡單(4-2-3)前饋神經(jīng)網(wǎng)絡(luò),它將 IRIS 數(shù)據(jù)集進行了分類。這個數(shù)據(jù)集中包含了三類鳶尾屬植物,特征包括花萼長度,花瓣長度等等。每一類提供50個樣本給這個神經(jīng)網(wǎng)絡(luò)訓(xùn)練。特征被賦給輸入神經(jīng)元,每一個輸出神經(jīng)元代表一類數(shù)據(jù)集(“1/0/0” 表示這個植物是Setosa,“0/1/0”表示 Versicolour,而“0/0/1”表示 Virginica)。分類的錯誤率是2/150(即每分類150個,錯2個)。
大規(guī)模網(wǎng)絡(luò)中的難題
神經(jīng)網(wǎng)絡(luò)中可以有多個隱含層:這樣,在更高的隱含層里可以對其之前的隱含層構(gòu)建新的抽象。而且像之前也提到的,這樣可以更好的學(xué)習(xí)大規(guī)模網(wǎng)絡(luò)。增加隱含層的層數(shù)通常會導(dǎo)致兩個問題:
1、梯度消失:隨著我們添加越來越多的隱含層,反向傳播傳遞給較低層的信息會越來越少。實際上,由于信息向前反饋,不同層次間的梯度開始消失,對網(wǎng)絡(luò)中權(quán)重的影響也會變小。
2、過度擬合:也許這是機器學(xué)習(xí)的核心難題。簡要來說,過度擬合指的是對訓(xùn)練數(shù)據(jù)有著過于好的識別效果,這時導(dǎo)至模型非常復(fù)雜。這樣的結(jié)果會導(dǎo)致對訓(xùn)練數(shù)據(jù)有非常好的識別較果,而對真實樣本的識別效果非常差。
下面我們來看看一些深度學(xué)習(xí)的算法是如何面對這些難題的。
自編碼器
大多數(shù)的機器學(xué)習(xí)入門課程都會讓你放棄前饋神經(jīng)網(wǎng)絡(luò)。但是實際上這里面大有可為——請接著看。
自編碼器就是一個典型的前饋神經(jīng)網(wǎng)絡(luò),它的目標(biāo)就是學(xué)習(xí)一種對數(shù)據(jù)集的壓縮且分布式的表示方法(編碼思想)。
從概念上講,神經(jīng)網(wǎng)絡(luò)的目的是要訓(xùn)練去“重新建立”輸入數(shù)據(jù),好像輸入和目標(biāo)輸出數(shù)據(jù)是一樣的。換句話說:你正在讓神經(jīng)網(wǎng)絡(luò)的輸出與輸入是同一樣?xùn)|西,只是經(jīng)過了壓縮。這還是不好理解,先來看一個例子。
壓縮輸入數(shù)據(jù):灰度圖像
這里有一個由28x28像素的灰度圖像組成的訓(xùn)練集,且每一個像素的值都作為一個輸入層神經(jīng)元的輸入(這時輸入層就會有784個神經(jīng)元)。輸出層神經(jīng)元要有相同的數(shù)目(784),且每一個輸出神經(jīng)元的輸出值和輸入圖像的對應(yīng)像素灰度值相同。
在這樣的算法架構(gòu)背后,神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)到的實際上并不是一個訓(xùn)練數(shù)據(jù)到標(biāo)記的“映射”,而是去學(xué)習(xí)數(shù)據(jù)本身的內(nèi)在結(jié)構(gòu)和特征(也正是因為這,隱含層也被稱作特征探測器(feature detector))。通常隱含層中的神經(jīng)元數(shù)目要比輸入/輸入層的少,這是為了使神經(jīng)網(wǎng)絡(luò)只去學(xué)習(xí)最重要的特征并實現(xiàn)特征的降維。
我們想在中間層用很少的結(jié)點去在概念層上學(xué)習(xí)數(shù)據(jù)、產(chǎn)生一個緊致的表示方法。
流行感冒
為了更好的描述自編碼器,再看一個應(yīng)用。
這次我們使用一個簡單的數(shù)據(jù)集,其中包括一些感冒的癥狀。如果感興趣,這個例子的源碼發(fā)布在這里。
數(shù)據(jù)結(jié)構(gòu)如下:
輸入數(shù)據(jù)一共六個二進制位
前三位是病的證狀。例如,1 0 0 0 0 0 代表病人發(fā)燒;0 1 0 0 0 0 代表咳嗽;1 1 0 0 0 0 代表即咳嗽又發(fā)燒等等。
后三位表示抵抗能力,如果一個病人有這個,代表他/她不太可能患此病。例如,0 0 0 1 0 0 代表病人接種過流感疫苗。一個可能的組合是:0 1 0 1 0 0 ,這代表著一個接種過流感疫苗的咳嗽病人,等等。
當(dāng)一個病人同時擁用前三位中的兩位時,我們認(rèn)為他生病了;如果至少擁用后三位中的兩位,那么他是健康的,如:
111000, 101000, 110000, 011000, 011100 = 生病
000111, 001110, 000101, 000011, 000110 = 健康
我們來訓(xùn)練一個自編碼器(使用反向傳播),六個輸入、六個輸出神經(jīng)元,而只有兩個隱含神經(jīng)元。
在經(jīng)過幾百次迭代以后,我們發(fā)現(xiàn),每當(dāng)一個“生病”的樣本輸入時,兩個隱含層神經(jīng)元中的一個(對于生病的樣本總是這個)總是顯示出更高的激活值。而如果輸入一個“健康”樣本時,另一個隱含層則會顯示更高的激活值。
再看學(xué)習(xí)
本質(zhì)上來說,這兩個隱含神經(jīng)元從數(shù)據(jù)集中學(xué)習(xí)到了流感癥狀的一種緊致表示方法。為了檢驗它是不是真的實現(xiàn)了學(xué)習(xí),我們再看下過度擬合的問題。通過訓(xùn)練我們的神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)到的是一個緊致的簡單的,而不是一個高度復(fù)雜且對數(shù)據(jù)集過度擬合的表示方法。
某種程度上來講,與其說在找一種簡單的表示方法,我們更是在嘗試從“感覺”上去學(xué)習(xí)數(shù)據(jù)。
受限波爾茲曼機
下一步來看下受限波爾茲曼機(Restricted Boltzmann machines RBM),一種可以在輸入數(shù)據(jù)集上學(xué)習(xí)概率分布的生成隨機神經(jīng)網(wǎng)絡(luò)。
RBM由隱含層、可見層、偏置層組成。和前饋神經(jīng)網(wǎng)絡(luò)不同,可見層和隱含層之間的連接是無方向性(值可以從可見層->隱含層或隱含層->可見層任意傳輸)且全連接的(每一個當(dāng)前層的神經(jīng)元與下一層的每個神經(jīng)元都有連接——如果允許任意層的任意神經(jīng)元連接到任意層去,我們就得到了一個波爾茲曼機(非受限的))。
標(biāo)準(zhǔn)的RBM中,隱含和可見層的神經(jīng)元都是二態(tài)的(即神經(jīng)元的激活值只能是服從伯努力分布的0或1),不過也存在其它非線性的變種。
雖然學(xué)者們已經(jīng)研究RBM很長時間了,最近出現(xiàn)的對比差異無監(jiān)督訓(xùn)練算法使這個領(lǐng)域復(fù)興。
對比差異
單步對比差異算法原理:
1、正向過程:
輸入樣本 v 輸入至輸入層中。
v 通過一種與前饋網(wǎng)絡(luò)相似的方法傳播到隱含層中,隱含層的激活值為 h。
2、反向過程:
將 h 傳回可見層得到 v’ (可見層和隱含層的連接是無方向的,可以這樣傳)。
再將 v’ 傳到隱含層中,得到 h’。
3、權(quán)重更新:
其中 a 是學(xué)習(xí)速率, v, v’, h, h’ 和 w 都是向量。
算法的思想就是在正向過程中影響了網(wǎng)絡(luò)的內(nèi)部對于真實數(shù)據(jù)的表示。同時,反向過程中嘗試通過這個被影響過的表示方法重建數(shù)據(jù)。主要目的是可以使生成的數(shù)據(jù)與原數(shù)據(jù)盡可能相似,這個差異影響了權(quán)重更新。
換句話說,這樣的網(wǎng)絡(luò)具有了感知對輸入數(shù)據(jù)表示的程度的能力,而且嘗試通過這個感知能力重建數(shù)據(jù)。如果重建出來的數(shù)據(jù)與原數(shù)據(jù)差異很大,那么進行調(diào)整并再次重建。
再看流行感冒的例子
為了說明對比差異,我們使用與上例相同的流感癥狀的數(shù)據(jù)集。測試網(wǎng)絡(luò)是一個包含6個可見層神經(jīng)元、2個隱含層神經(jīng)元的RBM。我們用對比差異的方法對網(wǎng)絡(luò)進行訓(xùn)練,將癥狀 v 賦到可見層中。在測試中,這些癥狀值被重新傳到可見層;然后再被傳到隱含層。隱含層的神經(jīng)元表示健康/生病的狀態(tài),與自編碼器相似。
在進行過幾百次迭代后,我們得到了與自編碼器相同的結(jié)果:輸入一個生病樣本,其中一個隱含層神經(jīng)元具有更高激活值;輸入健康的樣本,則另一個神經(jīng)元更興奮。
例子的代碼在這里。
深度網(wǎng)絡(luò)
到現(xiàn)在為止,我們已經(jīng)學(xué)習(xí)了隱含層中強大的特征探測器——自編碼器和RBM,但現(xiàn)在還沒有辦法有效的去利用這些功能。實際上,上面所用到的這些數(shù)據(jù)集都是特定的。而我們要找到一些方法來間接的使用這些探測出的特征。
好消息是,已經(jīng)發(fā)現(xiàn)這些結(jié)構(gòu)可以通過棧式疊加來實現(xiàn)深度網(wǎng)絡(luò)。這些網(wǎng)絡(luò)可以通過貪心法的思想訓(xùn)練,每次訓(xùn)練一層,以克服之前提到在反向傳播中梯度消失及過度擬合的問題。
這樣的算法架構(gòu)十分強大,可以產(chǎn)生很好的結(jié)果。如Google著名的“貓”識別,在實驗中通過使用特定的深度自編碼器,在無標(biāo)記的圖片庫中學(xué)習(xí)到人和貓臉的識別。
下面我們將更深入。
棧式自編碼器
和名字一樣,這種網(wǎng)絡(luò)由多個棧式結(jié)合的自編碼器組成。
自編碼器的隱含層 t 會作為 t + 1 層的輸入層。第一個輸入層就是整個網(wǎng)絡(luò)的輸入層。利用貪心法訓(xùn)練每一層的步驟如下:
1、通過反向傳播的方法利用所有數(shù)據(jù)對第一層的自編碼器進行訓(xùn)練(t=1,上圖中的紅色連接部分)。
2、訓(xùn)練第二層的自編碼器 t=2 (綠色連接部分)。由于 t=2 的輸入層是 t=1 的隱含層,我們已經(jīng)不再關(guān)心 t=1 的輸入層,可以從整個網(wǎng)絡(luò)中移除。整個訓(xùn)練開始于將輸入樣本數(shù)據(jù)賦到 t=1 的輸入層,通過前向傳播至 t = 2 的輸出層。下面t = 2的權(quán)重(輸入->隱含和隱含->輸出)使用反向傳播的方法進行更新。t = 2的層和 t=1 的層一樣,都要通過所有樣本的訓(xùn)練。
3、對所有層重復(fù)步驟1-2(即移除前面自編碼器的輸出層,用另一個自編碼器替代,再用反向傳播進行訓(xùn)練)。
4、步驟1-3被稱為預(yù)訓(xùn)練,這將網(wǎng)絡(luò)里的權(quán)重值初始化至一個合適的位置。但是通過這個訓(xùn)練并沒有得到一個輸入數(shù)據(jù)到輸出標(biāo)記的映射。例如,一個網(wǎng)絡(luò)的目標(biāo)是被訓(xùn)練用來識別手寫數(shù)字,經(jīng)過這樣的訓(xùn)練后還不能將最后的特征探測器的輸出(即隱含層中最后的自編碼器)對應(yīng)到圖片的標(biāo)記上去。這樣,一個通常的辦法是在網(wǎng)絡(luò)的最后一層(即藍色連接部分)后面再加一個或多個全連接層。整個網(wǎng)絡(luò)可以被看作是一個多層的感知機,并使用反向傳播的方法進行訓(xùn)練(這步也被稱為微調(diào))。
棧式自編碼器,提供了一種有效的預(yù)訓(xùn)練方法來初始化網(wǎng)絡(luò)的權(quán)重,這樣你得到了一個可以用來訓(xùn)練的復(fù)雜、多層的感知機。
深度信度網(wǎng)絡(luò)
和自編碼器一樣,我也可以將波爾茲曼機進行棧式疊加來構(gòu)建深度信度網(wǎng)絡(luò)(DBN)。
在本例中,隱含層 RBM t 可以看作是 RBM t+1 的可見層。第一個RBM的輸入層即是整個網(wǎng)絡(luò)的輸入層,層間貪心式的預(yù)訓(xùn)練的工作模式如下:
1. 通過對比差異法對所有訓(xùn)練樣本訓(xùn)練第一個RBM t=1
2. 訓(xùn)練第二個RBM t=1。由于 t=2 的可見層是 t=1 的隱含層,訓(xùn)練開始于將數(shù)據(jù)賦至 t=1 的可見層,通過前向傳播的方法傳至 t=1 的隱含層。然后作為 t=2 的對比差異訓(xùn)練的初始數(shù)據(jù)。
3. 對所有層重復(fù)前面的過程。
4. 和棧式自編碼器一樣,通過預(yù)訓(xùn)練后,網(wǎng)絡(luò)可以通過連接到一個或多個層間全連接的 RBM 隱含層進行擴展。這構(gòu)成了一個可以通過反向傳僠進行微調(diào)的多層感知機。
本過程和棧式自編碼器很相似,只是用RBM將自編碼器進行替換,并用對比差異算法將反向傳播進行替換。
(注: 例中的源碼可以從 此處獲得.)
卷積網(wǎng)絡(luò)
這個是本文最后一個軟件架構(gòu)——卷積網(wǎng)絡(luò),一類特殊的對圖像識別非常有效的前饋網(wǎng)絡(luò)。
在我們深入看實際的卷積網(wǎng)絡(luò)之臆,我們先定義一個圖像濾波器,或者稱為一個賦有相關(guān)權(quán)重的方陣。一個濾波器可以應(yīng)用到整個圖片上,通??梢詰?yīng)用多個濾波器。比如,你可以應(yīng)用四個6x6的濾波器在一張圖片上。然后,輸出中坐標(biāo)(1,1)的像素值就是輸入圖像左上角一個6x6區(qū)域的加權(quán)和,其它像素也是如此。
有了上面的基礎(chǔ),我們來介紹定義出卷積網(wǎng)絡(luò)的屬性:
卷積層 對輸入數(shù)據(jù)應(yīng)用若干濾波器。比如圖像的第一卷積層使用4個6x6濾波器。對圖像應(yīng)用一個濾波器之后的得到的結(jié)果被稱為特征圖譜(feature map, FM),特征圖譜的數(shù)目和濾波器的數(shù)目相等。如果前驅(qū)層也是一個卷積層,那么濾波器應(yīng)用在FM上,相當(dāng)于輸入一個FM,輸出另外一個FM。從直覺上來講,如果將一個權(quán)重分布到整個圖像上后,那么這個特征就和位置無關(guān)了,同時多個濾波器可以分別探測出不同的特征。
下采樣層 縮減輸入數(shù)據(jù)的規(guī)模。例如輸入一個32x32的圖像,并且通過一個2x2的下采樣,那么可以得到一個16x16的輸出圖像,這意味著原圖像上的四個像素合并成為輸出圖像中的一個像素。實現(xiàn)下采樣的方法有很多種,最常見的是最大值合并、平均值合并以及隨機合并。
最后一個下采樣層(或卷積層)通常連接到一個或多個全連層,全連層的輸出就是最終的輸出。
訓(xùn)練過程通過改進的反向傳播實現(xiàn),將下采樣層作為考慮的因素并基于所有值來更新卷積濾波器的權(quán)重。
可以在這看幾個應(yīng)用在 MNIST 數(shù)據(jù)集上的卷積網(wǎng)絡(luò)的例子,在這還有一個用JavaScript實現(xiàn)的一個可視的類似網(wǎng)絡(luò)。
實現(xiàn)
目前為止,我們已經(jīng)學(xué)會了常見神經(jīng)網(wǎng)絡(luò)中最主要的元素了,但是我只寫了很少的在實現(xiàn)過程中所遇到的挑戰(zhàn)。
概括來講,我的目標(biāo)是實現(xiàn)一個深度學(xué)習(xí)的庫,即一個基于神經(jīng)網(wǎng)絡(luò)且滿足如下條件的框架:
一個可以表示多種模型的通用架構(gòu)(比如所有上文提到的神經(jīng)網(wǎng)絡(luò)中的元素)
可以使用多種訓(xùn)練算法(反向傳播,對比差異等等)。
體面的性能
為了滿足這些要求,我在軟件的設(shè)計中使用了分層的思想。
結(jié)構(gòu)
我們從如下的基礎(chǔ)部分開始:
NeuralNetworkImpl 是所有神經(jīng)網(wǎng)絡(luò)模型實現(xiàn)的基類。
每個網(wǎng)絡(luò)都包含有一個 layer 的集合。
每一層中有一個 connections 的鏈表, connection 指的是兩個層之間的連接,將整個網(wǎng)絡(luò)構(gòu)成一個有向無環(huán)圖。
這個結(jié)構(gòu)對于經(jīng)典的反饋網(wǎng)絡(luò)、RBM 及更復(fù)雜的如 ImageNet 都已經(jīng)足夠靈活。
這個結(jié)構(gòu)也允許一個 layer 成為多個網(wǎng)絡(luò)的元素。比如,在 Deep Belief Network(深度信度網(wǎng)絡(luò))中的layer也可以用在其 RBM 中。
另外,通過這個架構(gòu)可以將DBN的預(yù)訓(xùn)練階段顯示為一個棧式RBM的列表,微調(diào)階段顯示為一個前饋網(wǎng)絡(luò),這些都非常直觀而且程序?qū)崿F(xiàn)的很好。
數(shù)據(jù)流
下個部分介紹網(wǎng)絡(luò)中的數(shù)據(jù)流,一個兩步過程:
定義出層間的序列。例如,為了得到一個多層感知機的結(jié)果,輸入數(shù)據(jù)被賦到輸入層(因此,這也是首先被計算的層),然后再將數(shù)據(jù)通過不同的方法流向輸出層。為了在反向傳播中更新權(quán)重,輸出的誤差通過廣度優(yōu)先的方法從輸出層傳回每一層。這部分通過 LayerOrderStrategy 進行實現(xiàn),應(yīng)用到了網(wǎng)絡(luò)圖結(jié)構(gòu)的優(yōu)勢,使用了不同的圖遍歷方法。其中一些樣例包含了 廣度優(yōu)先策略 和 定位到一個指定的層。層的序列實際上由層間的連接進行決定,所以策略部分都是返回一個連接的有序列表。
計算激活值。每一層都有一個關(guān)聯(lián)的 ConnectionCalculator,包含有連接的列表(從上一步得來)和輸入值(從其它層得到)并計算得到結(jié)果的激活值。例如,在一個簡單的S形前饋網(wǎng)絡(luò)中,隱含層的 ConnectionCalculator 接受輸入層和偏置層的值(分別為輸入值和一個值全為1的數(shù)組)和神經(jīng)元之間的權(quán)重值(如果是全連接層,權(quán)重值實際上以一個矩陣的形式存儲在一個 FullyConnected 結(jié)構(gòu)中,計算加權(quán)和,然后將結(jié)果傳給S函數(shù)。ConnectionCalculator 中實現(xiàn)了一些轉(zhuǎn)移函數(shù)(如加權(quán)求和、卷積)和激活函數(shù)(如對應(yīng)多層感知機的對數(shù)函數(shù)和雙曲正切函數(shù),對應(yīng)RBM的二態(tài)函數(shù))。其中的大部分都可以通過 Aparapi 在GPU上進行計算,可以利用迷你批次訓(xùn)練。
通過 Aparapi 進行 GPU 計算
像我之前提到的,神經(jīng)網(wǎng)絡(luò)在近些年復(fù)興的一個重要原因是其訓(xùn)練的方法可以高度并行化,允許我們通過GPGPU高效的加速訓(xùn)練。本文中,我選擇 Aparapi 庫來進行GPU的支持。
Aparapi 在連接計算上強加了一些重要的限制:
只允許使用原始數(shù)據(jù)類型的一維數(shù)組(變量)。
在GPU上運行的程序只能調(diào)用 Aparapi Kernel 類本身的成員函數(shù)。
這樣,大部分的數(shù)據(jù)(權(quán)重、輸入和輸出數(shù)據(jù))都要保存在 Matrix 實例里面,其內(nèi)部是一個一維浮點數(shù)組。所有Aparapi 連接計算都是使用 AparapiWeightedSum (應(yīng)用在全連接層和加權(quán)求和函數(shù)上)、 AparapiSubsampling2D (應(yīng)用在下采樣層)或 AparapiConv2D (應(yīng)用在卷積層)。這些限制可以通過 Heterogeneous System Architecture 里介紹的內(nèi)容解決一些。而且Aparapi 允許相同的代碼運行在CPU和GPU上。
訓(xùn)練
training 的模塊實現(xiàn)了多種訓(xùn)練算法。這個模塊依賴于上文提到的兩個模塊。比如,BackPropagationTrainer (所有的訓(xùn)練算法都以 Trainer 為基類)在前饋階段使用前饋層計算,在誤差傳播和權(quán)重更新時使用特殊的廣度優(yōu)先層計算。
我最新的工作是在Java8環(huán)境下開發(fā),其它一些更新的功能可以在這個branch 下獲得,這部分的工作很快會merge到主干上。
結(jié)論
本文的目標(biāo)是提供一個深度學(xué)習(xí)算法領(lǐng)域的一個簡明介紹,由最基本的組成元素開始(感知機)并逐漸深入到多種當(dāng)前流行且有效的架構(gòu)上,比如受限波爾茲曼機。
神經(jīng)網(wǎng)絡(luò)的思想已經(jīng)出現(xiàn)了很長時間,但是今天,你如果身處機器學(xué)習(xí)領(lǐng)域而不知道深度學(xué)習(xí)或其它相關(guān)知識是不應(yīng)該的。不應(yīng)該過度宣傳,但不可否認(rèn)隨著GPGPU提供的計算能力、包括Geoffrey Hinton, Yoshua Bengio, Yann LeCun and Andrew Ng在內(nèi)的研究學(xué)者們提出的高效算法,這個領(lǐng)域已經(jīng)表現(xiàn)出了很大的希望?,F(xiàn)在正是最佳的時間深入這些方面的學(xué)習(xí)。
附錄:相關(guān)資源
如果你想更深入的學(xué)習(xí),下面的這些資源在我的工作當(dāng)中都起過重要的作用:
DeepLearning.net: 深度學(xué)習(xí)所有方面知識的一個門戶。里面有完善的手冊、軟件庫 和一個非常好的 閱讀列表。
活躍的 Google+ 社區(qū).
兩個很好的課程: Machine Learning and Neural Networks for Machine Learning, 都在Coursera上。
The Stanford neural networks tutorial,斯坦福神經(jīng)網(wǎng)絡(luò)指南。
評論