系列博客,原文在筆者所維護的github上:https://aka.ms/beginnerAI,
點擊star加星不要吝嗇,星越多筆者越努力。git
For things I don't know how to build, I don't understand.程序員
若是我不能親手搭建起來一個東西,那麼我就不能理解它。 -- 美國物理學家理查德·費曼github
在互聯網發達的今天,不少知識均可以從網絡上找到,可是網絡上的博客、文章的質量良莠不齊,或者重點不明確,或者直接把別人的博客抄襲過來。這種情況使得廣大的初學者們學習起來很困難,甚至誤入歧途,增長了學習曲線的陡峭程度。固然也有不少博主很是很是負責任,文章質量很高,只是連續度不夠,正看得過癮的時候,沒有後續章節了,沒法造成知識體系。編程
初學者也能夠選擇看一些教材或者理論書籍,可是,一個雞生蛋蛋生雞的問題出現了:若是你不懂,那麼看完了理論你仍是不會懂;若是你懂了,那麼你就不必看理論。這也是不少教材或者理論書籍的缺憾。數組
筆者也看過吳恩達老師的課,理論知識講得由淺入深,仍是很是清楚的,雖然代碼示例基本沒有,但仍然強烈建議你們去看。筆者的心得是:視頻能夠事先緩存在手機中,利用一些時間片斷就能夠學習了。緩存
社會上還有一些網課,在線講解深度學習的知識,筆者也參加了幾個團購,老師和助教通常都很負責任,最後能夠回看錄像,下載PPT課件。這些課程通常偏重於工程項目,講解深度學習框架和工具的使用,即教你們如何使用工具建模、訓練等等,也是頗有幫助的。但對於初學者來講,理解一個新概念可能須要前面不少個已有知識點的支撐,門檻太高,一會兒就變得很沮喪。或者是知其然而不知其因此然,最後淪爲調參工程師,職業發展受到了限制。網絡
仍是應了那句古話:授人以魚不如授人以漁。經歷了以上那些學習經歷,程序員出身的筆者迫切感受到應該有一種新的學習體驗,在「作中學」,用寫代碼的方式把一些基礎的理論復現一遍,能夠深入理解其內涵,並能擴充其外延,使讀者獲得觸類旁通的泛化能力。框架
筆者總結了自身的學習經歷後,把深度學習的入門知識概括成了9個步驟,簡稱爲9步學習法:機器學習
筆者看到過的不少書籍是直接從第7步起步的,其基本假設是讀者已經掌握了前面的知識。可是對於從零開始的初學者們,這種假設並不正確。函數
在後面的講解中,咱們通常會使用以下方式進行:
原理分析和可視化理解也是本書的一個特色,試圖讓神經網絡是能夠解釋的,而不是盲目地使用。
還有一個很是重要的地方,咱們還有配套的Python代碼,除了一些必要的科學計算庫和繪圖庫,如NumPy和Matplotlib等,咱們沒有使用任何已有的深度學習框架,而是帶領你們從零開始搭建本身的知識體系,從簡單到複雜,一步步理解深度學習中的衆多知識點。
對於沒有Python經驗的朋友來講,經過閱讀示例代碼,也能夠起到幫助你們學習Python的做用,一箭雙鵰。隨着問題的難度加深,代碼也會增多,可是先後都有繼承關係的,最後的代碼會造成一個小的框架,筆者稱之爲Mini-Framework,能夠用搭積木的方式調用其中的函數來搭建深度學習的組件。
這些代碼都是由筆者親自編寫調試的,每章節均可以獨立運行,獲得相關章節內所描述的結果,包括打印輸出和圖形輸出。
另外,爲了便於理解,筆者繪製了大量的示意圖,數量是同類書籍的10倍以上。一圖頂萬字,相信你們會經過這些示意圖快速而深入地理解筆者想要分享的知識點,使你們可以從真正的「零」開始,對神經網絡、深度學習有基本的瞭解,並能動手實踐。
對於讀者的要求:
能夠幫助讀者達到的水平:
符號 | 含義 |
---|---|
\(x\) | 訓練用樣本值 |
\(x_1\) | 第一個樣本或樣本的第一個特徵值,在上下文中會有說明 |
\(x_{12},x_{1,2}\) | 第1個樣本的第2個特徵值 |
\(X\) | 訓練用多樣本矩陣 |
\(y\) | 訓練用樣本標籤值 |
\(y_1\) | 第一個樣本的標籤值 |
\(Y\) | 訓練用多樣本標籤矩陣 |
\(z\) | 線性運算的結果值 |
\(Z\) | 線性運算的結果矩陣 |
\(Z1\) | 第一層網絡的線性運算結果矩陣 |
\(\sigma\) | 激活函數 |
\(a\) | 激活函數結果值 |
\(A\) | 激活函數結果矩陣 |
\(A1\) | 第一層網絡的激活函數結果矩陣 |
\(w\) | 權重參數值 |
\(w_{12},w_{1,2}\) | 權重參數矩陣中的第1行第2列的權重值 |
\(w1_{12},w1_{1,2}\) | 第一層網絡的權重參數矩陣中的第1行第2列的權重值 |
\(W\) | 權重參數矩陣 |
\(W1\) | 第一層網絡的權重參數矩陣 |
\(b\) | 偏移參數值 |
\(b_1\) | 偏移參數矩陣中的第1個偏移值 |
\(b2_1\) | 第二層網絡的偏移參數矩陣中的第1個偏移值 |
\(B\) | 偏移參數矩陣(向量) |
\(B1\) | 第一層網絡的偏移參數矩陣(向量) |
\(X^T\) | X的轉置矩陣 |
\(X^{-1}\) | X的逆矩陣 |
\(loss,loss(w,b)\) | 單樣本偏差函數 |
\(J, J(w,b)\) | 多樣本損失函數 |
神經網絡由基本的神經元組成,圖1-13就是一個神經元的數學/計算模型,便於咱們用程序來實現。
圖1-13 神經元計算模型
(x1,x2,x3) 是外界輸入信號,通常是一個訓練數據樣本的多個屬性,好比,咱們要預測一套房子的價格,那麼在房屋價格數據樣本中,x1可能表明了面積,x2可能表明地理位置,x3可能朝向。另一個例子是,假設(x1,x2,x3)分別表明了(紅,綠,藍)三種顏色,而此神經元用於識別輸入的信號是暖色仍是冷色。
(w1,w2,w3) 是每一個輸入信號的權重值,以上面的 (x1,x2,x3) 的例子來講,x1的權重多是0.92,x2的權重多是0.2,x3的權重多是0.03。固然權重值相加以後能夠不是1。
還有個b是怎麼來的?通常的書或者博客上會告訴你那是由於\(y=wx+b\),b是偏移值,使得直線可以沿Y軸上下移動。這是用結果來解釋緣由,並不是b存在的真實緣由。從生物學上解釋,在腦神經細胞中,必定是輸入信號的電平/電流大於某個臨界值時,神經元細胞纔會處於興奮狀態,這個b實際就是那個臨界值。亦即當:
\[w_1 \cdot x_1 + w_2 \cdot x_2 + w_3 \cdot x_3 >= t\]
時,該神經元細胞纔會興奮。咱們把t挪到等式左側來,變成\((-t)\),而後把它寫成b,變成了:
\[w_1 \cdot x_1 + w_2 \cdot x_2 + w_3 \cdot x_3 + b >= 0\]
因而b誕生了!
\[ \begin{aligned} Z &= w_1 \cdot x_1 + w_2 \cdot x_2 + w_3 \cdot x_3 + b \\ &= \sum_{i=1}^m(w_i \cdot x_i) + b \end{aligned} \]
在上面的例子中m=3。咱們把\(w_i \cdot x_i\)變成矩陣運算的話,就變成了:
\[Z = W \cdot X + b\]
求和以後,神經細胞已經處於興奮狀態了,已經決定要向下一個神經元傳遞信號了,可是要傳遞多強烈的信號,要由激活函數來肯定:
\[A=\sigma{(Z)}\]
若是激活函數是一個階躍信號的話,會像繼電器開合同樣咔咔的開啓和閉合,在生物體中是不可能有這種裝置的,而是一個漸漸變化的過程。因此通常激活函數都是有一個漸變的過程,也就是說是個曲線,如圖1-14所示。
圖1-14 激活函數圖像
至此,一個神經元的工做過程就在電光火石般的一瞬間結束了。
這是一個單層的神經網絡,有m個輸入 (這裏m=3),有n個輸出 (這裏n=2)。在神經網絡中,\(b\) 到每一個神經元的權值來表示實際的偏移值,亦即\((b_1,b_2)\),這樣便於矩陣運算。也有些人把 \(b\) 寫成\(x_0\),實際上是同一個效果,即把偏移值看作是神經元的一個輸入。
圖1-15 單層神經網絡模型
從圖1-15你們能夠看到,同一個特徵 \(x_1\),對於\(n一、n2\)來講,權重是不相同的,由於\(n一、n2\)是兩個神經元,它們完成不一樣的任務(特徵識別)。咱們假設\(x_1,x_2,x_3\)分別表明紅綠藍三種顏色,而 \(n1,n2\) 分別用於識別暖色和冷色,那麼 \(x_1\) 到 \(n1\) 的權重,確定要大於 \(x_1\) 到 \(n2\) 的權重,由於\(x_1\)表明紅色,是暖色。
而對於\(n1\)來講,\(x_1,x_2,x_3\)輸入的權重也是不相同的,由於它要對不一樣特徵有選擇地接納。如同上面的例子,\(n1\) 對於表明紅色的 \(x_1\),確定是特別重視,權重值較高;而對於表明藍色的 \(x_3\),儘可能把權重值下降,纔能有正確的輸出。
從真正的「零」開始學習神經網絡時,我沒有看到過任何一個流程圖來說述訓練過程,大神們寫書或者博客時都忽略了這一點,圖1-16是一個簡單的流程圖。
圖1-16 神經網絡訓練流程圖
假設咱們有表1-1所示的訓練數據樣本。
表1-1 訓練樣本示例
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是樣本的真實結果值:
訓練完成後,咱們會把這個神經網絡中的結構和權重矩陣的值導出來,造成一個計算圖(就是矩陣運算加上激活函數)模型,而後嵌入到任何能夠識別/調用這個模型的應用程序中,根據輸入的值進行運算,輸出預測值。
圖1-17是一個兩層的神經網絡,包含隱藏層和輸出層,輸入層不算作一層。
圖1-17 神經網絡中的各類符號約定
\[ z1_1 = x_1 \cdot w1_{1,1}+ x_2 \cdot w1_{2,1}+b1_1 \]
\[ z1_2 = x_1 \cdot w1_{1,2}+ x_2 \cdot w1_{2,2}+b1_2 \]
\[ z1_3 = x_1 \cdot w1_{1,3}+ x_2 \cdot w1_{2,3}+b1_3 \]
變成矩陣運算:
\[ z1_1= \begin{pmatrix} x_1 & x_2 \end{pmatrix} \begin{pmatrix} w1_{1,1} \\ w1_{2,1} \end{pmatrix} +b1_1 \]
\[ z1_2= \begin{pmatrix} x_1 & x_2 \end{pmatrix} \begin{pmatrix} w1_{1,2} \\ w1_{2,2} \end{pmatrix} +b1_2 \]
\[ z1_3= \begin{pmatrix} x_1 & x_2 \end{pmatrix} \begin{pmatrix} w1_{1,3} \\ w1_{2,3} \end{pmatrix} +b1_3 \]
再變成大矩陣:
\[ Z1 = \begin{pmatrix} x_1 & x_2 \end{pmatrix} \begin{pmatrix} w1_{1,1}&w1_{1,2}&w1_{1,3} \\ w1_{2,1}&w1_{2,2}&w1_{2,3} \\ \end{pmatrix} +\begin{pmatrix} b1_1 & b1_2 & b1_3 \end{pmatrix} \]
最後變成矩陣符號:
\[Z1 = X \cdot W1 + B1\]
而後是激活函數運算:
\[A1=a(Z1)\]
同理可得:
\[Z2 = A1 \cdot W2 + B2\]
注意:損失函數不是前向計算的一部分。
單層的神經網絡可以模擬一條二維平面上的直線,從而能夠完成線性分割任務。而理論證實,兩層神經網絡能夠無限逼近任意連續函數。圖1-18所示就是一個兩層神經網絡擬合複雜曲線的實例。
圖1-18 迴歸/擬合示意圖
所謂迴歸或者擬合,其實就是給出x值輸出y值的過程,而且讓y值與樣本數據造成的曲線的距離儘可能小,能夠理解爲是對樣本數據的一種骨架式的抽象。
以圖1-18爲例,藍色的點是樣本點,從中能夠大體地看出一個輪廓或骨架,而紅色的點所連成的線就是神經網絡的學習結果,它能夠「穿過」樣本點羣造成中心線,儘可能讓全部的樣本點到中心線的距離的和最近。
如圖1-19,二維平面中有兩類點,紅色的和藍色的,用一條直線確定不能把二者分開了。
圖1-19 分類示意圖
咱們使用一個兩層的神經網絡能夠獲得一個很是近似的結果,使得分類偏差在滿意的範圍以內。圖1-19中那條淡藍色的曲線,原本並不存在,是經過神經網絡訓練出來的分界線,能夠比較完美地把兩類樣本分開,因此分類能夠理解爲是對兩類或多類樣本數據的邊界的抽象。
圖1-18和圖1-19的曲線形態其實是一個真實的函數在[0,1]區間內的形狀,其原型是:
\[y=0.4x^2 + 0.3xsin(15x) + 0.01cos(50x)-0.3\]
這麼複雜的函數,一個兩層的神經網絡是如何作到的呢?其實從輸入層到隱藏層的矩陣計算,就是對輸入數據進行了空間變換,使其能夠被線性可分,而後在輸出層畫出一個分界線。而訓練的過程,就是肯定那個空間變換矩陣的過程。所以,多層神經網絡的本質就是對複雜函數的擬合。咱們能夠在後面的試驗中來學習如何擬合上述的複雜函數的。
神經網絡的訓練結果,是一大堆的權重組成的數組(近似解),並不能獲得上面那種精確的數學表達式(數學解析解)。
人體骨關節是動物界裏最複雜的生理結構,一共有8個重要的大關節:肩關節、
肘關節、腕關節、髖關節、膝關節、踝關節、頸關節、腰關節。
人的臂骨,腿骨等,都是一根直線,人體直立時,也是一根直線。可是人在骨關節和肌肉組織的配合下,能夠作不少複雜的動做,緣由就是關節自己不是線性結構,而是一個在有限範圍內能夠任意活動的結構,有必定的柔韌性。
好比肘關節,能夠完成小臂在一個二維平面上的活動。加上肩關節,就能夠完成胳膊在三維空間的活動。再加上其它關節,就能夠擴展胳膊活動的三維空間的範圍。
用表1-2來對比人體運動組織和神經網絡組織。
表1-2 人體運動組織和神經網絡組織的對比
人體運動組織 | 神經網絡組織 |
---|---|
支撐骨骼 | 網絡層次 |
關節 | 激活函數 |
肌肉韌帶 | 權重參數 |
學習各類運動的動做 | 前向+反向訓練過程 |
激活函數就至關於關節。
看如下的例子:
\[Z1=X \cdot W1 + B1\]
\[Z2 = Z1 \cdot W2 + B2\]
\[Z3 = Z2 \cdot W3 + B3\]
展開:
\[ \begin{aligned} Z3&=Z2 \cdot W3 + B3 \\ &=(Z1 \cdot W2 + B2) \cdot W3 + B3 \\ &=((X \cdot W1 + B1) \cdot W2 + B2) \cdot W3 + B3 \\ &=X \cdot (W1\cdot W2 \cdot W3) + (B1 \cdot W2 \cdot W3+B2 \cdot W2+B3) \\ &=X \cdot W+B \end{aligned} \]
\(Z1,Z2,Z3\)分別表明三層神經網絡的計算結果。最後能夠看到,無論有多少層,總能夠歸結到\(XW+B\)的形式,這和單層神經網絡沒有區別。
若是咱們不運用激活函數的話,則輸出信號將僅僅是一個簡單的線性函數。線性函數一個一級多項式。線性方程是很容易解決的,可是它們的複雜性有限,而且從數據中學習複雜函數映射的能力更小。一個沒有激活函數的神經網絡將只不過是一個線性迴歸模型罷了,不能解決現實世界中的大多數非線性問題。
沒有激活函數,咱們的神經網絡將沒法學習和模擬其餘複雜類型的數據,例如圖像、視頻、音頻、語音等。這就是爲何咱們要使用人工神經網絡技術,諸如深度學習,來理解一些複雜的事情,一些相互之間具備不少隱藏層的非線性問題。
圖1-20 從簡單到複雜的擬合
圖1-20展現了幾種擬合方式,最左側的是線性擬合,中間的是分段線性擬合,右側的是曲線擬合,只有當使用激活函數時,才能作到完美的曲線擬合。