- 神經網絡與深度學習
- 吳岸城
- 2504字
- 2019-01-04 14:25:26
2.5 構造一個神經網絡
我們談生物學上的神經網絡時曾提到過,單個生物神經元有不同的作用,當這些不同種類的神經元依據某種結構聯系起來時,就成為神經網絡。人類靠這樣的神經網絡分析、判斷、思考并指導肢體進行反應,其中聯系或連接非常重要,我們模仿人類大腦,把人工神經網絡看成是一種運算模型,由大量的節點(或稱神經元)相互連接構成。每個節點代表一種特定的輸出函數。每兩個節點間的連接都代表一個通過該連接信號的加權值,稱之為權重,這相當于人工神經網絡的記憶。網絡的輸出根據網絡的連接方式,權重值和激勵函數的不同而不同。
先看看單層神經網絡,如圖2-9所示。

圖2-9 單層神經網絡
在實際運用中,我們很少用單層神經網絡直接解決問題,但它是學習多層神經元網絡的基礎。
2.5.1 線性不可分
我們已經學習了單個神經元、感知機和單層神經網絡(又被稱為單層前饋型神經網絡)的知識。
我們已經可以讓模型正確地學習AND邏輯運算和OR邏輯運算,如果你愿意,你甚至可以將之前說的香蕉和蘋果分類,再回頭看看表2-1,你會發現這就是個邏輯運算。
將香蕉的-1更換成0,得到表2-4。
表2-4 邏輯運算

利用AND運算規則:
0 and 0=0 香蕉
1 and 1=1 蘋果
等等,如果輸入是以下組合怎么辦?
0 and 1=0 香蕉?
1 and 0=0 香蕉?
這個計算式表示了無論{顏色紅色、形狀彎形}或{形狀圓形、顏色黃色}都輸出香蕉了!這明顯和我們的期望不符。
怎么辦,這就要先引入一個概念:線性不可分。
還是以上面的蘋果和香蕉為例,如圖2-10所示。

圖2-10 線性可分展示
我設計了一個能直觀顯示的圖,大家一眼就可以看出方形的接近蘋果的特征,菱形的接近香蕉的特征,這兩種水果的特征如此鮮明,我們可以用一條直線分割這兩類水果,如圖2-11所示。

圖2-11 線性可分展示
這條直線變成了分割蘋果和香蕉的最優直線,先不去探討如何最優化得到這條直線。我們能夠用直線清晰地分類這兩類水果,這就是線性可分。
我們知道現實中很多東西都是線性不可分的,比如你去分類兩類以上的水果,大多數情況下,我們不能用一條直線把多種水果分開,如圖2-12所示。

圖2-12 線性不可分
完全傻眼,無法用一條直線分類。
再來看看之前我們用程序實現的感知機無法解決的XOR問題,XOR問題就是無法用一條直線區分兩類事物,這就是線性不可分問題,如圖2-13所示。最右邊的圖要想把淺色和深色分開需要兩條線。

圖2-13 XOR線性不可分
好的,在機器學習領域,有多種方法可以解決這類問題,本書講的是神經網絡和深度學習,所以我們需要用以下知識體系了解如何解決線性不可分問題。
1.多層神經網絡
還記得是誰提出的XOR解決方法嗎?請回顧一下:1974年,哈佛大學的一篇博士論文證明了在神經網絡多加一層,并且利用“后向傳播”(Back-propagation)學習方法,可以解決XOR問題。
我們先講講神經網絡分層的概念。
(1)感知器:感知器是一種雙層神經網絡模型,一層為輸入層(以上我們簡化為輸入刺激,也就是輸入節點不參與計算),另一層具有計算單元,可以通過監督學習建立模式判別的能力。
(2)多層神經網絡(也叫前饋神經網絡)。
特點:前饋網絡的各神經元接受前一級輸入,并輸出到下一級,無反饋。
節點:輸入節點,輸出節點。
(3)計算單元:可有任意一個輸入,但只有一個輸出,輸出可耦合到任意多個其他節點的輸入。
(4)層:可見層——輸入和輸出節點;隱層——中間層。
三層(一般我們只畫出兩層計算單元,輸入層不參與計算不畫出)前饋網絡可以實現任何邏輯函數,如圖2-14所示。

圖2-14 前饋神經網絡
我們把中間單層神經元擴展成兩個神經元層,并且賦予了新的名字。第一層神經元叫第一隱層,第二層神經元叫第二隱層,我們把由輸入的信號源、隱層及輸出組成的層叫作多層神經網絡,多層神經網絡里一個重要的特征是上一層輸出只能是下一層輸入,不可跨層鏈接。
2.5.2 解決XOR問題(解決線性不可分)
利用多層感知機結構,連接多個神經元就可以處理異或問題。使用一個兩層神經網絡就可以記憶異或運算。一個可行的方案如圖2-15所示,f1使用Step函數。
網絡接收兩個輸入p1和p2,第一層上側的神經元有凈輸入:
2p1+2p2-1

圖2-15 多層感知機處理異或
它的凈輸入/輸出與p1、p2的關系如表2-6所示。
表2-6 凈輸入/輸出與p1和p2的關系

實際上,這個神經元對輸出結果做了如圖2-16所示的劃分。

圖2-16 上側神經元的劃分
圖2-16所示為第一層下側的神經元,有凈輸入:
-2p1-2p2+3
它的凈輸入/輸出與p1、p2的關系如表2-7所示。
表2-7 凈輸入/輸出與p1和p2的關系

因此,下側神經元對數據進行了如圖2-17所示的劃分。

圖2-17 下側神經元的劃分
最后,由輸出神經元對兩個神經元的數據進行整合,這里使用邏輯與操作,得到圖2-18所示的正確的異或運算的劃分。

圖2-18 正確異或運算劃分
具體的工作過程如下。
上側神經元凈輸入:2p1+2p2-1
下側神經元凈輸入:-2p1-2p2+3
查表2-6和表2-7可知:
p1=0,p2=0
輸出:0 and 1=0
p1=0,p2=1
輸出:1 and 1=1
p1=1,p2=0
輸出:1 and 1=1
p1=1,p2=1
輸出:1 and 0=0
使用多層感知機成功解決了異或問題。
2.5.3 XOR問題的代碼實現
我們來看看如何用Neuroph實現多層感知機,也就是多層神經網絡。在Neuroph中使用多層感知機非常簡單,我們只要調用MultiLayerPerceptron類,并且設定好層數及每層的神經元數量就能實現一個多層神經網絡。
下面我們看看具體代碼:
DataSet trainingSet = new DataSet(2, 1); trainingSet.addRow(new DataSetRow(new double[]{0, 0}, new double[]{0})); trainingSet.addRow(new DataSetRow(new double[]{0, 1}, new double[]{1})); trainingSet.addRow(new DataSetRow(new double[]{1, 0}, new double[]{1})); trainingSet.addRow(new DataSetRow(new double[]{1, 1}, new double[]{0})); //創建多層感知機,輸入層2個神經元,隱含層3個神經元,最后輸出層為1個隱含神經元,我們 使用TANH傳輸函數用于最后格式化的輸出。 MultiLayerPerceptron myMlPerceptron = new MultiLayerPerceptron(TransferFunctionType.TANH, 2, 3, 1); //開始訓練 System.out.println("Training neural network..."); myMlPerceptron.learn(trainingSet);
看看輸出結果:
…… 231. iteration : 0.010857327129718937 232. iteration : 0.010643221657202485 233. iteration : 0.010435288982776427 234. iteration : 0.010233311250628364 235. iteration : 0.01003707920734522 236. iteration : 0.009846391849799534 [main] INFO org.neuroph.core.learning.LearningRule - Learning Stoped Testing trained neural network Input: [0.0, 0.0] Output: [0.03794371028454834] Input: [0.0, 1.0] Output: [0.8280251075783817] Input: [1.0, 0.0] Output: [0.8061029856179274] Input: [1.0, 1.0] Output: [0.0931520677705696]
經過236次計算,我們的程序學習完畢并輸出結果,Input:[0.0,0.0],輸出0.037經過TANH函數處理,得到最終結果0。
Input:[0.0, 1.0],輸出結果0.8,經過TANH得到1,依此類推,我們最后得到XOR異或學習的準確計算結果。
我們再來看看改變隱層的神經元個數會怎么樣?
new MultiLayerPerceptron(TransferFunctionType.TANH, 2, 3, 1); 改成new MultiLayerPerceptron(TransferFunctionType.TANH, 2, 2, 1);
計算結果:
…… 224. iteration : 0.010137332719035904 225. iteration : 0.009894060755430178 [main] INFO org.neuroph.core.learning.LearningRule - Learning Stoped Testing trained neural network Input: [0.0, 0.0] Output: [0.04957962733734304] Input: [0.0, 1.0] Output: [0.8184942278091288] Input: [1.0, 0.0] Output: [0.8006225511852936] Input: [1.0, 1.0] Output: [0.04613571126703119]
沒有太大變化,所有的變化都在正常的誤差內。
如果我們將中間層變成30,會發生什么變化呢?
2409. iteration : 0.002927935122956385 [main] INFO org.neuroph.core.learning.LearningRule - Learning Stoped Testing trained neural network Input: [0.0, 0.0] Output: [-0.022022339547133944] Input: [0.0, 1.0] Output: [0.9341172653775799] Input: [1.0, 0.0] Output: [0.9069350056674689] Input: [1.0, 1.0] Output: [0.009379875622236349]
計算了2409次才完成,太耗時了,看看得到的數字,-0.022、0.93、0.90、0.009,更趨向于1和0,換句話說就是更精確了。
好的,我們僅僅靠調整隱層的神經元個數就已經能優化一個較為精確的數字了。