2
神經(jīng)元
先來認(rèn)識下真正的神經(jīng)元。
圖 1: 典型神經(jīng)元的結(jié)構(gòu)(來自維基百科 “樹突” 詞條)
神經(jīng)元大致可以分為樹突、突觸、細(xì)胞體和軸突。樹突為神經(jīng)元的輸入通道,其功能是將其他神經(jīng)元的動作電位傳遞至細(xì)胞體。其他神經(jīng)元的動作電位借由位于樹突分支上的多個突觸傳遞至樹突上。神經(jīng)細(xì)胞可以視為有兩種狀態(tài)的機器,激活時為 “是”,不激活時為 “否”。神經(jīng)細(xì)胞的狀態(tài)取決于從其他神經(jīng)細(xì)胞接收到的信號量,以及突觸的性質(zhì)(抑制或加強)。當(dāng)信號量超過某個閾值時,細(xì)胞體就會被激活,產(chǎn)生電脈沖。電脈沖沿著軸突并通過突觸傳遞到其它神經(jīng)元。(內(nèi)容來自維基百科 “感知機” 詞條,稍作整理)
我們的視覺系統(tǒng)非常復(fù)雜。大致來講,當(dāng)光線投射到視網(wǎng)膜后,視覺膜上的光感受細(xì)胞的突觸直接與雙極細(xì)胞相連,雙極細(xì)胞突觸則與最外層的節(jié)細(xì)胞相連,節(jié)細(xì)胞將動作電位傳遞到大腦。我們的視網(wǎng)膜有大約 1 億 3 千萬個光感受細(xì)胞接收光信號,然后通過大約 120 萬個節(jié)細(xì)胞軸突將信息從視網(wǎng)膜傳遞到大腦。(內(nèi)容來自維基百科 “視覺系統(tǒng)” 詞條)
視覺系統(tǒng)使我們有了視知覺能力,將外部世界的二維投射重構(gòu)為三維世界。
人類的視覺系統(tǒng)可以毫不費力的識別出下面圖片中的數(shù)字(當(dāng)然還有文字)。但如果讓計算機來識別,就會明顯感覺到視覺識別的困難。
圖 2: 街道地址(來源于維基百科 “Handwriting recognition” 詞條)
我們不能簡單地把 “數(shù)字 2 像一只水面上的天鵝,數(shù)字 7 像一把鋤頭” 這樣的規(guī)則教給計算機。因此,我們需要把手寫識別的問題表述成計算機可以理解的方式。
圖 3: 水面上的天鵝像極了數(shù)字 2
假設(shè)我們有 5x5 像素的圖片來顯示每個數(shù)字,例如數(shù)字 2 表示如下:
@@@@@
. . . . . @
@@@@@
@. . . . .
@@@@@
由于我們的神經(jīng)網(wǎng)絡(luò)是以數(shù)字組成向量作為輸入的,所以我們將每個圖片轉(zhuǎn)換成長度為 25 的向量,其元素的值是 1(“這個像素位于該圖像中”)或 0(“這個像素不在該圖像中”)
例如,數(shù)字 2 可以表示為:
two_digit=[1,1,1,1,1
0,0,0,0,1
1,1,1,1,1
1,0,0,0,0
1,1,1,1,1]
我們希望神經(jīng)網(wǎng)絡(luò)最終的輸出是一個具體的數(shù)字,因此我們需要 10 個不同的輸出結(jié)果。例如,對于數(shù)字 2,正確的輸出結(jié)果將是:
[0,0,1,0,0,0,0,0,0,0]
圖 4: 使用 python 列表解析式建立一個代表 0-9 不同數(shù)字的列表
其中 targets[2] 就是輸出結(jié)果數(shù)字 2。
那么,神經(jīng)網(wǎng)絡(luò)是如何把信息的輸入轉(zhuǎn)換成我們想要的輸出的呢?
感知器(Perceptron)
感知器是一種二元分類器,它是神經(jīng)網(wǎng)絡(luò)的基石。感知器是對神經(jīng)細(xì)胞的模擬,如權(quán)量(突觸)、偏置(閾值)及激活函數(shù)(細(xì)胞體)。
輸入以向量的形式表示 x=(x_0, x_1, x_2),你可以把它們理解為不同的特征維度,其中的 x_0 是偏置單元(bias unit), 相當(dāng)于線性回歸中的常數(shù)項。在經(jīng)過 “神經(jīng)元”(激活函數(shù))的計算后,感知器會輸出一個大于 0 或小于 0 的數(shù)。箭頭上的數(shù)字代表每個特征的權(quán)量(weights),相當(dāng)于線性回歸模型的參數(shù),是收集信息的神經(jīng)突觸。
例如,上圖列出了每個特征的權(quán)量,于是我們有這樣的模型:
hθ(x)=-3+2*x_1+2*x_2
當(dāng) x_1 和 x_2 同時為 1 時,輸出為 1,而不同時都將得到負(fù)數(shù)。這實際上就是邏輯與或稱為與門。
我們的感知器將根據(jù)輸出大于或小于 0 來對輸入進行分類:
這是一個單層的感知器。通過修改權(quán)量,我們也可以建立或門(weights=[2,2], bias=-1)、非門(weights=[-2],bias=1,只有一個輸入端)。但是,無論如何,你都無法通過一個單層的感知器來建立 “異或門”(XOR),即兩個輸入相同時輸出 1,否則輸出 0。這種情況下,我們就需要更復(fù)雜的神經(jīng)網(wǎng)絡(luò)了,即多層神經(jīng)網(wǎng)絡(luò),也被稱為前饋神經(jīng)網(wǎng)絡(luò)(feedforward neural network)。
前饋神經(jīng)網(wǎng)絡(luò)
前饋神經(jīng)網(wǎng)絡(luò)是多個感知器的組合,這些感知器以不同的方式產(chǎn)生連接,并由不同的激活函數(shù)控制激活。
圖 6: 前饋神經(jīng)網(wǎng)絡(luò)示意圖
我們來認(rèn)識下前饋神經(jīng)網(wǎng)絡(luò):
它包括輸入層(input layer)、輸出層(output layer)和一個或多個隱藏層(hidden layers)。上圖的神經(jīng)網(wǎng)絡(luò)由 3 個單元的輸入層,4 個單元的隱藏層和 2 個單元的輸出層組成。單元等于感知器。
輸入層的單元是隱藏層單元的輸入,隱藏層單元的輸出是輸出層單元的輸入。
兩個感知器之間的連接有一個權(quán)量。
第 t 層的每個感知器與第 t-1 層的每個感知器相互關(guān)聯(lián)。當(dāng)然,你也可以設(shè)置權(quán)量為 0,從而在實質(zhì)上取消連接。
在加工輸入數(shù)據(jù)時,你將輸入數(shù)據(jù)賦予輸入層的每個單元,而隱藏層的每個單元是輸入層每個單元的加權(quán)求和。也就是說,輸入層的數(shù)據(jù)會被前向傳播到隱藏層的每個單元。同理,隱藏層的輸出作為輸入會前向傳播到輸入層,計算得到最后的輸出,即神經(jīng)網(wǎng)絡(luò)的輸出。
多個隱藏層的神經(jīng)網(wǎng)絡(luò)同理。
超越線性
在 “感知器” 中我們談到,單層感知器雖然可以建立與門、或門、非門等,但無法建立更為復(fù)雜的異或門(XOR),即兩個輸入相同時輸出 1,否則輸出 0。
為了更為直觀地理解這個問題,我們可以看下圖:
圖 7: 雙輸入感知器的決策空間
模型有兩個輸入(input1 和 input2),我們可以線性地區(qū)分或門的兩類情況:即同時為 0 時在左下角,其它情況在右上角;與門的情況也可以線性地區(qū)分,即輸出同時為 1 時在右上角,其它情況在左下角。但異或門呢?這種情況是無法作出線性區(qū)分的,也就是說,單層感知器無法實現(xiàn)異或門。
多層感知器嗎?
先來分析輸入和輸出的情況。最左邊兩列列出了輸入的 4 種情況。異或門的輸出是最右邊一列的情況,即兩個輸入相同時輸出 1,否則為 0。我們在輸入層和輸出層之間加入兩個單元的隱藏層,那么,它給輸出層的輸入應(yīng)該是什么呢?答案如下圖。你可以發(fā)現(xiàn),對于隱藏層的 a_1 單元(上標(biāo) 2 代表這是第 2 層)來說,它實際上是且門(都為 1 時才輸出 1);對 a_2 單元來說,它的邏輯是 (not x_1) and (not x_2),即同時為 0 時才輸出 1。而從隱藏層到輸出層,是邏輯或。前饋神經(jīng)網(wǎng)絡(luò)可以實現(xiàn)異或門!
圖 8: 異或門輸入輸出下推導(dǎo)隱藏層
于是我們建立如下的神經(jīng)網(wǎng)絡(luò),但是其輸出并非我們想要。為什么?
圖 9: 線性激活函數(shù)下的前饋神經(jīng)網(wǎng)絡(luò)
這是因為上面感知器的激活函數(shù)是線性函數(shù)。這種情況下,神經(jīng)網(wǎng)絡(luò)的輸出也只是輸入的某種線性函數(shù),只不過是通過網(wǎng)絡(luò)的形式來進行加權(quán)。線性函數(shù)的線性組合仍然是線性函數(shù)。也就是說,即便是多層的感知器,激活函數(shù)為線性時也無法實現(xiàn)輸入 00 和輸入 11 時的輸出比輸入 01 和 10 時大,即非線性。
如果激活函數(shù)是線性函數(shù),前饋神經(jīng)網(wǎng)絡(luò)將不會比單層感知器強大多少,不管它有多少層。
我們需要 logistic 函數(shù)的幫助。大部分神經(jīng)網(wǎng)絡(luò)會使用非線性激活函數(shù),比如 logistic 函數(shù)(也被稱為 Sigmoid 函數(shù),這是就其形狀而言的)。此外,由于訓(xùn)練神經(jīng)網(wǎng)絡(luò)要使用微積分,而要使用微積分,就得使用光滑函數(shù)(在反向傳播時我們會詳細(xì)講解)。logistic 函數(shù)也滿足這一要求。
在 logistic 函數(shù)的作用下,線性函數(shù)的輸出值將被轉(zhuǎn)化到 0 到 1 之間。從下圖右上角的 logistc 曲線可以看到,輸入值越大,輸出越接近 1,輸入為 4 時輸出為 0.99;輸入值越小,輸出越接近 0,輸入值為 - 4 時,輸出為 0.01。
下圖是單層感知器的激活函數(shù)為 logitic 函數(shù)時與門的示例。
圖 10: 激活函數(shù)為 logitic 函數(shù)時的與門單層感知器
綜上,我們可以通過前饋神經(jīng)網(wǎng)絡(luò)和 logistic 函數(shù)解決異或門的問題:
圖 11: 非線性神經(jīng)網(wǎng)絡(luò)實現(xiàn)異或門
反向傳播(backpropagation):訓(xùn)練神經(jīng)網(wǎng)絡(luò)
反向傳播是使用數(shù)據(jù)來訓(xùn)練神經(jīng)網(wǎng)絡(luò)的算法,它是神經(jīng)網(wǎng)絡(luò)的梯度下降算法。
假設(shè)我們有一個訓(xùn)練集,其中含有輸入向量和相應(yīng)的目標(biāo)輸出向量。同時,假定我們的網(wǎng)絡(luò)已經(jīng)擁有一組權(quán)量(相當(dāng)于我們知道每個神經(jīng)元的激活函數(shù)),那么接下來,我們就需要使用以下算法來調(diào)整這些權(quán)量。
1、利用初始權(quán)量,在輸入向量上運行前向傳播,從而得到所有網(wǎng)絡(luò)所有神經(jīng)元的輸出。
2、這樣,每個輸出層神經(jīng)元都會得到一個誤差,即輸出值與實際值之差。
3、計算作為神經(jīng)元權(quán)量的函數(shù)的誤差的梯度,然后根據(jù)誤差降低最快的方向調(diào)整權(quán)量。
4、將這些輸出誤差反向傳播給隱藏層以便計算相應(yīng)誤差。
5、計算這些誤差的梯度,并利用同樣的方式調(diào)整隱藏層的權(quán)量。
不斷迭代,直到網(wǎng)絡(luò)收斂。
要理解上述過程,梯度下降算法是關(guān)鍵。
圖 12: 單個參數(shù)的損失函數(shù)示例
在梯度下降算法中,我們需要損失函數(shù)(即上面提到的作為神經(jīng)元權(quán)量的函數(shù)的誤差)。損失函數(shù)衡量了模型的誤差,即神經(jīng)網(wǎng)絡(luò)的輸出值與實際值之間的差異,它的參數(shù)是模型的參數(shù),即連接的權(quán)量。當(dāng)損失函數(shù)達到全局最低時,得到最優(yōu)的權(quán)權(quán)量。在訓(xùn)練階段,權(quán)量不斷被更新,慢慢接近全局最低值。例如,權(quán)量是 0.6 時,它就需要向 0.4 變化,這樣才能接近全局最低值。
上圖描述的是只有一個參數(shù)的情況,即模型的誤差取決于一個參數(shù)。然而,神經(jīng)網(wǎng)絡(luò)的誤差取決于每一個權(quán)量,它的損失函數(shù)也會復(fù)雜得多。
其中,i 代表第幾層,k 代表第 i 層的第幾個單元??梢?,損失函數(shù)把整個神經(jīng)網(wǎng)絡(luò)的誤差都加和了。后面的第二部分是正則化項,暫時不用理睬,不影響后面的理解。
有人可能會問,為什么神經(jīng)網(wǎng)絡(luò)的損失函數(shù)是上面的形式?這個問題等價于為什么 logistic 函數(shù)采用上面的形式?
在回歸模型中,損失函數(shù)是平方誤差函數(shù)(最小二乘法):
損失函數(shù)衡量了模型的輸出與實際值之間的誤差:
但對 logistic 函數(shù)而言,平方誤差函數(shù)是一個非凸函數(shù),利用梯度下降算法,它將無法保證找到損失函數(shù)的全局最優(yōu)解。
圖 13: 非凸函數(shù)
對 logistic 函數(shù),我們需要其他的損失函數(shù):
圖 14:
圖 15:
如果 y=1,而 h(x)=1 的話,則 cost=0,即圖 14 曲線上(1,0)的位置;如果 h(x)=0,則 cost 函數(shù)輸出值趨向于無窮大,這意味著當(dāng)我們認(rèn)為某種情況不會發(fā)生,例如用戶不會成為付費用戶,而事實上是可能的時,這種損失是不可估量的。同理,如果 y=0,而 h(x)=0 的話,則 cost=0,即圖 15 曲線上(0,0)的位置;如果 h(x)=1,則 cost 趨向于無窮大。
可以把兩種情況寫在一個表達式中:
也即:
神經(jīng)網(wǎng)絡(luò)衡量整個網(wǎng)絡(luò)的誤差,所以在形式上看起來會復(fù)雜些,但實質(zhì)是一樣的。
那么,接下來我們要如何更新權(quán)量才能使得損失函數(shù)接近全局最低值呢?
在神經(jīng)網(wǎng)絡(luò)中,我們使用反向傳播算法來更新神經(jīng)元之間連接的權(quán)量。反向傳播的意思是指,我們從輸出層開始計算,計算輸出層與實際值的誤差,然后返回到前面的隱藏層計算其誤差,以此類推,不斷迭代,直到網(wǎng)絡(luò)收斂。
在完成第一步的前向傳播后,我們會得到神經(jīng)網(wǎng)絡(luò)的輸出值,利用損失函數(shù)可以計算出輸出值與實際值之間的誤差。損失函數(shù)的偏導(dǎo)數(shù)可以告訴我們參數(shù)往哪個方向更新可以得到更小的損失函數(shù)值。導(dǎo)數(shù)的幾何意義為曲線的斜率,例如,對于圖 12 簡單的損失函數(shù)而言,參數(shù)在 0.5 時斜率為正,參數(shù)值需要減少才能得到更小的損失函數(shù)值;而如果參數(shù)值為 0.1,斜率為負(fù),參數(shù)值需要增加才能得到更小的損失函數(shù)值。導(dǎo)數(shù)可以告訴我們?nèi)肿畹偷姆较颍?/p>
為了得到最小的 J(θ),我們需要不斷更新參數(shù)θ,即神經(jīng)網(wǎng)絡(luò)連接的權(quán)量。每次更新的變化值由下面的公式?jīng)Q定:
其中, 為損失函數(shù)的偏導(dǎo)數(shù),前面為負(fù)是因為斜率為正時,我們需要減少參數(shù)的值才能 “下山”,而斜率為負(fù)時,我們需要增加參數(shù)的值才能 “下山”, 代表學(xué)習(xí)速率,代表下山的步子有多大,如果步子太小,要走很遠才能走到山底,如果步子太大,容易越過谷底,導(dǎo)致無法收斂;J(θ) 為神經(jīng)元輸出的誤差。
從隱藏層到輸出層的兩個神經(jīng)元之間的權(quán)量一旦更新,就可以更新隱藏層神經(jīng)元的輸出,從而得到隱藏層神經(jīng)元新的誤差值(更新后的輸出值和之前前向傳播時得到的輸出值),進而根據(jù)上述公式更新隱藏層和上一層兩個神經(jīng)元之間的權(quán)量。依此類推,直到更新完整個神經(jīng)網(wǎng)絡(luò)的權(quán)量。
利用損失函數(shù)繼續(xù)更新整個網(wǎng)絡(luò)的權(quán)量,直到神經(jīng)網(wǎng)絡(luò)輸出值的誤差達到最小。
所有神經(jīng)元之間的權(quán)量確定后,神經(jīng)網(wǎng)絡(luò)就完成訓(xùn)練了。
綜上,讓機器人看到 2 絕非易事。
參考資料:
Machine Learning from Coursera by Andrew Ng.
Data Science from Scratch by Joel Grus.
A Deep Learning Tutorial: From Perceptrons to Deep Networks BY IVAN VASILEV.
維基百科
雷鋒網(wǎng)按:本文原作者舒小曼,本文源自作者在知乎問題“如何簡單形象又有趣地講解神經(jīng)網(wǎng)絡(luò)是什么?”的回答。
深度學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)特訓(xùn)班
20年清華大學(xué)神經(jīng)網(wǎng)絡(luò)授課導(dǎo)師鄧志東教授,帶你系統(tǒng)學(xué)習(xí)人工智能之神經(jīng)網(wǎng)絡(luò)理論及應(yīng)用!
課程鏈接:http://www.mooc.ai/course/65
加入AI慕課學(xué)院人工智能學(xué)習(xí)交流QQ群:624413030,與AI同行一起交流成長
雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。