精讀《30行js代碼創建神經網路》

本期精讀的文章是:30行js代碼創建神經網路。

懶得看文章?沒關係,稍後會附上文章內容概述,同時,更希望能通過閱讀這一期的精讀,穿插著深入閱讀原文。

1 引言

自從Alpha Go 打敗了李世石,大家對深度學習的體感更加的強烈,人工智慧也越來越多的出現在大家的生活之中。很多人也會談論,程序員什麼時候會被人工智慧給替代?與其慌張,在人工智慧的潮流下,不斷學習新的人工智慧相關技術,武裝自己,才是硬道理。 本文介紹了如何使用Synaptic.js 創建簡單的神經網路,解決異或運算的問題。

2 內容概要

神經網路中的神經元和突觸

對神經網路有所了解的人都知道,神經網路就是構建類似人腦的神經系統,在人腦的神經系統中,存在一種非常重要的細胞,叫神經元。在神經網路中,你可以把神經元理解為一個函數,它接受一些輸入返回一些輸出結果,其中Sigmoid神經元是一種非常常用的神經元,這種神經元以 Sigmoid 函數 作為激活函數。Sigmoid 函數接受任意的數值,輸出 01 之間的值,大家可以看看常見的幾種 Sigmoid 函數的函數曲線。

知道了 Sigmoid 函數了,我們可以看一個具體的 Sigmoid神經元 例子。

在這個例子中 73權重參數,-2偏差,最左邊的 10輸入層 中的兩個節點,通過如下的計算,得到了一個 隱藏層 節點 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 | 神经网络 |