AI應用開發基礎傻瓜書系列1-神經網路的基本工作原理
第一篇:神經網路的基本工作原理
看過很多部落格、文章,東一榔頭西一棒子的,總覺得沒有一個系列的文章把問題從頭到尾說清楚,找東西很困難。有的部落格、文章的質量還不算很理想,似是而非,或者重點不明確,或者直接把別人的部落格抄襲過來......種種不靠譜,讓小白們學習起來很困難,增加了學習曲線的陡峭程度。當然也有很多博主非常非常負責任,文章質量很高,只是連續度不夠,正看得過癮的時候,沒有後續章節了。
從本文開始,我們試圖用一系列部落格,講解現代神經網路的基本知識,使大家能夠從真正的“零”開始,對神經網路、深度學習有基本的瞭解,並能動手實踐。這是本系列的第一篇,我們先從神經網路的基本工作原理開始講解。
神經元細胞的數學計算模型
神經網路由基本的神經元組成,下圖就是一個神經元的數學/計算模型,便於我們用程式來實現。
輸入
(x1,x2,x3) 是外界輸入訊號,一般是一個訓練資料樣本的多個屬性,比如,我們要識別手寫數字0~9,那麼在手寫圖片樣本中,x1可能代表了筆畫是直的還是有彎曲,x2可能代表筆畫所佔面積的寬度,x3可能代表筆畫上下兩部分的複雜度。
(W1,W2,W3) 是每個輸入訊號的權重值,以上面的 (x1,x2,x3) 的例子來說,x1的權重可能是0.5,x2的權重可能是0.2,x3的權重可能是0.3。當然權重值相加之後可以不是1。
還有個b是幹嗎的?一般的書或者部落格上會告訴你那是因為\(y=wx+b\)
\[w1*x1 + w2*x2 + w3*x3 >= t\]
時,該神經元細胞才會興奮。我們把t挪到等式左側來,變成\((-t)\),然後把它寫成b,變成了:
\[w1*x1 + w2*x2 + w3*x3 + b >= 0\]
於是b誕生了!
求和計算
\[Z = w1*x1 + w2*x2 + w3*x3 + b = \sum_{i=1}^m(w_i*x_i) + b\]
在上面的例子中m=3。我們把\(w_i*x_i\)變成矩陣運算的話,就變成了:
\[Z = W*X + b\]
啟用函式
求和之後,神經細胞已經處於興奮狀態了,已經決定要向下一個神經元傳遞訊號了,但是要傳遞多強烈的訊號,要由啟用函式來確定:
\[A=\sigma{(Z)}\]
如果啟用函式是一個階躍訊號的話,那受不了啊,你會覺得腦子裡總是一跳一跳的,像繼電器開合一樣咔咔亂響,所以一般啟用函式都是有一個漸變的過程,也就是說是個曲線。
啟用函式的更多描述在後續的部落格中。
至此,一個神經元的工作過程就在電光火石般的一瞬間結束了。
神經網路的基本訓練過程
單層神經網路模型
這是一個單層的神經網路,有m個輸入 (這裡m=3),有n個輸出 (這裡n=2)。在單個神經元裡,b是個值。但是在神經網路中,我們把b的值永遠設定為1,而用b到每個神經元的權值來表示實際的偏移值,亦即(b1,b2),這樣便於矩陣運算。也有些作者把b寫成x0,其實是同一個意思,只不過x0用於等於1。
- (x1,x2,x3)是一個樣本資料的三個特徵值
- (w11,w12,w13)是(x1,x2,x3)到n1的權重
- (w21,w22,w23)是(x1,x2,x3)到n2的權重
- b1是n1的偏移
- b2是n2的偏移
從這裡大家可以意識到,同一個特徵x1,對於n1、n2來說,權重是不相同的,因為n1、n2是兩個神經元,它們完成不同的任務(特徵識別)。這就如同老師講同樣的課,不同的學生有不同的理解。
而對於n1來說,x1,x2,x3輸入的權重也是不相同的,因為它要對不同特徵有選擇地接納。這就如同一個學生上三門課,但是側重點不同,第一門課花50%的精力,第二門課30%,第三門課20%。
訓練流程
從真正的“零”開始學習神經網路時,我沒有看到過一個流程圖來講述訓練過程,大神們寫書或者部落格時都忽略了這一點,我在這裡給大家畫一個簡單的流程圖:
損失函式和反向傳播的更多內容在後續的部落格中。
前提條件
- 首先是我們已經有了訓練資料,否則連目標都沒有,訓練個啥?
- 我們已經根據資料的規模、領域,建立了神經網路的基本結構,比如有幾層,每一層有幾個神經元
- 定義好損失函式來合理地計算誤差
步驟
假設我們有以下訓練資料樣本:
Id | x1 | x2 | x3 | Y |
---|---|---|---|---|
1 | 0.5 | 1.4 | 2.7 | 3 |
2 | 0.4 | 1.3 | 2.5 | 5 |
3 | 0.1 | 1.5 | 2.3 | 9 |
4 | 0.5 | 1.7 | 2.9 | 1 |
其中,x1,x2,x3是每一個樣本資料的三個特徵值,Y是樣本的真實結果值,
- 隨機初始化權重矩陣,可以根據高斯分佈或者正態分佈等來初始化。這一步可以叫做“蒙”,但不是瞎蒙。
- 拿一個或一批資料作為輸入,帶入權重矩陣中計算,再通過啟用函式傳入下一層,最終得到預測值。在本例中,我們先用Id-1的資料輸入到矩陣中,得到一個A值,假設A=5
- 拿到Id-1樣本的真實值Y=3
- 計算損失,假設用均方差函式 \(Loss = (A-Y)^2=(5-3)^2=4\)
- 根據一些神奇的數學公式(反向微分),把Loss=4這個值用大喇叭喊話,告訴在前面計算的步驟中,影響A=5這個值的每一個權重矩陣,然後對這些權重矩陣中的值做一個微小的修改(當然是向著好的方向修改,這一點可以用數學家的名譽來保證)
- 用Id-2樣本作為輸入再次訓練(goto 2)
- 這樣不斷地迭代下去,直到以下一個或幾個條件滿足就停止訓練:損失函式值非常小;迭代了指定的次數;計算機累吐血了......
訓練完成後,我們會把這個神經網路中的結構和權重矩陣的值匯出來,形成一個計算圖(就是矩陣運算加上啟用函式)模型,然後嵌入到任何可以識別/呼叫這個模型的應用程式中,根據輸入的值進行運算,輸出預測值。
神經網路中的矩陣運算
下面這個圖就是一個兩層的神經網路,包含隱藏層和輸出層:
其中,w1-m,n(應該寫作\(w^1_{1,1},w^1_{1,2},w^1_{1,3}\),上面的角標1表示第1層,但是visio裡不支援這種格式)表示第一層神經網路的權重矩陣,w2-m,n(應該寫作\(w^2_{1,1},w^2_{1,2},w^2_{1,3}\))表示第二層神經網路的權重矩陣。
\[Z^1_1 = w^1_{1,1}x_1+w^1_{1,2}x_2+w^1_{1,784}x_{784}+b_1^1\\ ......\\ Z^1_{10} = w^1_{10,1}x_1+w^1_{10,2}x_2+w^1_{10,784}x_{784}+b_{10}^{1}\]
變成矩陣運算:
\[ Z_1^1=\begin{pmatrix}w^1_{1,1}&w^1_{1,2}&...&w^1_{1,784}\end{pmatrix} \begin{pmatrix}x_1\\x_2\\...\\x_{784}\end{pmatrix} +b^1_1\\ .....\\ Z_{10}^1= \begin{pmatrix}w^1_{10,1}&w^1_{10,2}&...&w^1_{10,784}\end{pmatrix} \begin{pmatrix}x_1\\x_2\\...\\x_{784}\end{pmatrix} +b^1_{10} \]
再變成大矩陣:
\[Z_1 = \begin{pmatrix} w^1_{1,1}&w^1_{1,2}&...&w^1_{1,784} \\ w^1_{2,1}&w^1_{2,2}&...&w^1_{2,784}\\ ......\\ w^1_{10,1}&w^1_{10,2}&...&w^1_{10,784} \end{pmatrix} \begin{pmatrix}x_1\\x_2\\...\\x_{784}\end{pmatrix} +\begin{pmatrix}b^1_1\\b^1_2\\...\\ b^1_{10} \end{pmatrix}\]
最後變成矩陣符號:
\[Z_1 = W_1X + B_1\]
然後是啟用函式運算:
\[A_1=\sigma{(Z_1)}\]
同理可得:
\[Z_2 = W_2A_1 + B_2\]
\[A_2=\sigma{(Z_2)}\]
神經網路為什麼能普遍適用
單層的神經網路能夠模擬一條二維平面上的直線,從而可以完成線性分割任務。而理論證明,兩層神經網路可以無限逼近任意連續函式。
比如下面這張圖,二維平面中有兩類點,紅色的和藍色的,用一條直線肯定不能把兩者分開了。
我們使用一個兩層的神經網路可以得到一個非常近似的結果,使得分類誤差在滿意的範圍之內。而這個真實的連續函式的原型是:
\[y=0.4x^2 + 0.3xsin(15x) + 0.01cos(50x)-0.3\]
哦,my god(我靠)! 這麼複雜的函式,一個兩層的神經網路是如何做到的呢?其實從輸入層到隱藏層的矩陣計算,就是對輸入資料進行了空間變換,使其可以被線性可分,然後輸出層畫出了一個分界線。而訓練的過程,就是確定那個空間變換矩陣的過程。因此,多層神經網路的本質就是對複雜函式的擬合。我們可以在後面的試驗中來學習如何擬合上述的複雜函式的。
為什麼需要啟用函式
為什麼我們不能在沒有啟用輸入訊號的情況下完成神經網路的學習呢?
如果我們不運用啟用函式的話,則輸出訊號將僅僅是一個簡單的線性函式。線性函式一個一級多項式。現如今,線性方程是很容易解決的,但是它們的複雜性有限,並且從資料中學習複雜函式對映的能力更小。一個沒有啟用函式的神經網路將只不過是一個線性迴歸模型(Linear regression Model)罷了,它功率有限,並且大多數情況下執行得並不好。我們希望我們的神經網路不僅僅可以學習和計算線性函式,而且還要比這複雜得多。同樣是因為沒有啟用函式,我們的神經網路將無法學習和模擬其他複雜型別的資料,例如影象、視訊、音訊、語音等。這就是為什麼我們要使用人工神經網路技術,諸如深度學習(Deep learning),來理解一些複雜的事情,一些相互之間具有很多隱藏層的非線性問題,而這也可以幫助我們瞭解複雜的資料。
那麼為什麼我們需要非線性函式?
非線性函式是那些一級以上的函式,而且當繪製非線性函式時它們具有曲率。現在我們需要一個可以學習和表示幾乎任何東西的神經網路模型,以及可以將輸入對映到輸出的任意複雜函式。神經網路被認為是通用函式近似器(Universal Function Approximators)。這意味著他們可以計算和學習任何函式。幾乎我們可以想到的任何過程都可以表示為神經網路中的函式計算。
而這一切都歸結於這一點,我們需要應用啟用函式f(x),以便使網路更加強大,增加它的能力,使它可以學習複雜的事物,複雜的表單資料,以及表示輸入輸出之間非線性的複雜的任意函式對映。因此,使用非線性啟用函式,我們便能夠從輸入輸出之間生成非線性對映。
啟用函式的另一個重要特徵是:它應該是可以區分的。我們需要這樣做,以便在網路中向後推進以計算相對於權重的誤差(丟失)梯度時執行反向優化策略,然後相應地使用梯度下降或任何其他優化技術優化權重以減少誤差。
深度神經網路與深度學習
兩層的神經網路雖然強大,但可能只能完成二維空間上的一些曲線擬合的事情。如果對於圖片、語音、文字序列這些複雜的事情,就需要更復雜的網路來理解和處理。第一個方式是增加每一層中神經元的數量,但這是線性的,不夠有效。另外一個方式是增加層的數量,每一層都處理不同的事情。
淺神經網路雖然具備了反向傳播機制,但是仍存在問題:
- 梯度越來越疏,從後向前,誤差校正訊號越來越微弱
- 隨機初始化會導致訓練過程收斂到區域性最小值
- 需要資料帶標籤(人工label好的資料),但是大部分資料沒標籤
Deep Learning的訓練過程簡介
使用自下上升非監督學習(就是從底層開始,一層一層的往頂層訓練):
採用無標籤資料(有標籤資料也可)分層訓練各層引數,這一步可以看作是一個無監督訓練過程,是和傳統神經網路區別最大的部分(這個過程可以看作是feature learning過程)。
具體的,先用無標定資料訓練第一層,訓練時先學習第一層的引數(這一層可以看作是得到一個使得輸出和輸入差別最小的三層神經網路的隱層),由於模型capacity的限制以及稀疏性約束,使得得到的模型能夠學習到資料本身的結構,從而得到比輸入更具有表示能力的特徵;在學習得到第n-1層後,將n-1層的輸出作為第n層的輸入,訓練第n層,由此分別得到各層的引數;自頂向下的監督學習(就是通過帶標籤的資料去訓練,誤差自頂向下傳輸,對網路進行微調):
基於第一步得到的各層引數進一步fine-tune整個多層模型的引數,這一步是一個有監督訓練過程;第一步類似神經網路的隨機初始化初值過程,由於DL的第一步不是隨機初始化,而是通過學習輸入資料的結構得到的,因而這個初值更接近全域性最優,從而能夠取得更好的效果;所以deep learning效果好很大程度上歸功於第一步的feature learning過程。
本系列部落格連結: