精讀《30行js代碼創建神經網路》
本期精讀的文章是:30行js代碼創建神經網路。
懶得看文章?沒關係,稍後會附上文章內容概述,同時,更希望能通過閱讀這一期的精讀,穿插著深入閱讀原文。
1 引言
自從Alpha Go 打敗了李世石,大家對深度學習的體感更加的強烈,人工智慧也越來越多的出現在大家的生活之中。很多人也會談論,程序員什麼時候會被人工智慧給替代?與其慌張,在人工智慧的潮流下,不斷學習新的人工智慧相關技術,武裝自己,才是硬道理。 本文介紹了如何使用Synaptic.js 創建簡單的神經網路,解決異或運算的問題。
2 內容概要
神經網路中的神經元和突觸
對神經網路有所了解的人都知道,神經網路就是構建類似人腦的神經系統,在人腦的神經系統中,存在一種非常重要的細胞,叫神經元。在神經網路中,你可以把神經元理解為一個函數,它接受一些輸入返回一些輸出結果,其中Sigmoid神經元是一種非常常用的神經元,這種神經元以 Sigmoid 函數 作為激活函數。Sigmoid 函數接受任意的數值,輸出 0
到 1
之間的值,大家可以看看常見的幾種 Sigmoid 函數的函數曲線。
知道了 Sigmoid 函數了,我們可以看一個具體的 Sigmoid神經元 例子。
在這個例子中 7
和 3
是權重參數,-2
是偏差,最左邊的 1
和 0
是 輸入層 中的兩個節點,通過如下的計算,得到了一個 隱藏層 節點 5
。
然後將節點 5
輸入到一個 Sigmoid 函數,得到一個 輸出層 節點 1
。
如何構建神經網路
有了神經元,將所有的神經元連接起來,就構建了一個 神經網路。如下圖,神經元間的箭頭,可以理解為是一種 "突觸"。
完成神經網路的構建了,你可以用來識別手寫數字、垃圾郵件判斷等眾多領域。當然就像上面的例子,好的模型依賴於正確的權重 和 偏差的選擇。在實際工作中,每次完成神經網路的訓練,我們都會拿訓練的結果來對測試樣式進行預測,得到演算法的準確率,然後嘗試選擇更好的權重和偏差,期望達到更好的準確度,這個學習的過程稱為反向傳播。通過大量的學習後,最終才會得到更好的預測準確率。
代碼實現
下面附上代碼的實現。
const { Layer, Network } = window.synaptic;var inputLayer = new Layer(2);var hiddenLayer = new Layer(3);var outputLayer = new Layer(1);inputLayer.project(hiddenLayer);hiddenLayer.project(outputLayer);var myNetwork = new Network({ input: inputLayer, hidden: [hiddenLayer], output: outputLayer});// train the network - learn XORvar learningRate = .3;for (var i = 0; i < 20000; i++) { // 0,0 => 0 myNetwork.activate([0,0]); myNetwork.propagate(learningRate, [0]); // 0,1 => 1 myNetwork.activate([0,1]); myNetwork.propagate(learningRate, [1]); // 1,0 => 1 myNetwork.activate([1,0]); myNetwork.propagate(learningRate, [1]); // 1,1 => 0 myNetwork.activate([1,1]); myNetwork.propagate(learningRate, [0]);}
簡單而言,運行 myNetwork.activate([0,0])
時,[0, 0]
是輸入值,它對應的異或運算的結果是false, 也就是 0
。 這個是前向的傳播,所以稱為 激活 網路,每次前向傳播之後,我們需要做一次反向傳播來更新權重和偏差。
反向傳播就是通過這行代碼來做的: myNetwork.propagate(learningRate, [0])
,其中 learningRate
是告訴神經網路如何調整權重的常量,第二個參數 [0]
是異或運算的結果。
經過20000次學習,我們得到如下的結果:
console.log(myNetwork.activate([0,0])); -> [0.015020775950893527]console.log(myNetwork.activate([0,1]));->[0.9815816381088985]console.log(myNetwork.activate([1,0]));-> [0.9871822457132193]console.log(myNetwork.activate([1,1]));-> [0.012950087641929467]
對運算結果取最近的整數,我們就可以得到正確異或運算的結果。
3 精讀
讀原文的時候,大家可能主要對反向傳播如何修正權重和偏差會有所疑問,作者給出的引文A Step by Step Backpropagation Example?—?by Matt Mazur 很詳細的解釋了整個過程。
方便大家理解,我以上面的異或運算的例子,簡單的分析一下整個過程。其中我們選取的激活函數是:Logistic 函數。
當我們輸[0, 0]
時,我們選取一些任意的權重和偏差,計算過程如下:
為了方便後續的推導,我們可以通過一些符號來簡單的描述一下h1
和最終結果output
計算的過程:
計算得到結果 o
後,我們可以通過平方誤差函數
來計算誤差。我們在上面的運算中得到的 output = 0.73673
, 目標值是對 [0,0]
取異或運算的值,也就是: target = 0
,帶入上面的公式得到的誤差值為: 0.271385
。
到這裡我們進行反向傳播的過程,也就是說我們需要確認新的參數: w1
, w2
, w3
, w4
, w5
, w6
, b1
, b2
.
我們先計算新的 w5
,這裡是通過計算誤差函數相對於w5
的偏導來得到新的參數的,我們可以通過下面的鏈式求導來計算偏導。
得到 w5
對應的偏導後,我們通過下面的公式來計算新的w5
參數:
其中, 0.3
就是我們在代碼中設置的 learningRate
的值。 重複上面相似的過程,我們可以計算其他參數的值,這裡就不再累述。
4. 總結
本文介紹了使用Synaptic.js 創建簡單的神經網路,解決異或運算的問題過程,也對反向傳播的過程進行了簡單的解釋。文中實現神經網路的代碼非常簡單,包行注釋也不超過30行,但是只會代碼會有點囫圇吞棗的感覺,大家可以參考文章中給的引文,了解更多的演算法原理。
相關資料
1. A Step by Step Backpropagation Example?—?by Matt Mazur
2. Hackers Guide to Neural Nets?—?by Andrej Karpathy
3. NeuralNetworksAndDeepLarning?—?by Michael Nielsen
4. Synaptic.js
更多討論
討論地址是:精讀《30行js代碼創建神經網路》 · Issue #45 · dt-fe/weekly
如果你想參與討論,請點擊這裡,每周都有新的主題,每周五發布。
推薦閱讀:
※做出Uber移動網頁版還不夠 極致性能打造才見真章
※前端學習路徑
※寫在 2016 年的最後
TAG:前端开发 | 深度学习DeepLearning | 神经网络 |