簡評:本文中身堡,原文作者 Scrimba 的創(chuàng)始人 Per Harald Borgen 將會展示如何利用 Synaptic.js 來創(chuàng)建和訓(xùn)練神經(jīng)網(wǎng)絡(luò)昌屉,從而使我們可以在 Node.js 和瀏覽器中進(jìn)行深度學(xué)習(xí)。
題圖:一幅由 Google Dream 神經(jīng)網(wǎng)絡(luò)創(chuàng)建的光怪陸離
我們將嘗試搭建最簡單的神經(jīng)網(wǎng)絡(luò)之一 —— 一個用于解決 XOR方程 的神經(jīng)網(wǎng)絡(luò)句占。
看代碼之前呢,我們先溫習(xí)一下神經(jīng)網(wǎng)絡(luò)的基礎(chǔ)知識:
神經(jīng)元和突觸
構(gòu)建神經(jīng)網(wǎng)絡(luò)的第一個塊是神經(jīng)元。神經(jīng)元就像一個函數(shù)冗尤,它需要輸入,然后返回輸出胀溺。
有許多不同類型的神經(jīng)元裂七。我們的網(wǎng)絡(luò)將使用 sigmoid 神經(jīng)元,不管給定任何輸入仓坞,都會輸出 0 或者 1背零。
下圖是一個 Sigmoid 函數(shù),輸入 5 輸出 1无埃。箭頭稱為突觸徙瓶,將神經(jīng)元連接到網(wǎng)絡(luò)中的其他層。
那么嫉称,會什么左邊的輸入是 5 呢侦镇?因?yàn)樗沁B接到到神經(jīng)元的三個突觸的總和。
輸入乘以它們的權(quán)重就是人造神經(jīng)元的總輸入织阅。
由于這是一個 Sigmoid 神經(jīng)元壳繁,它能將任何值壓縮在 0 和 1 之間。
如果將這些神經(jīng)元的網(wǎng)絡(luò)連接在一起,那么一個神經(jīng)網(wǎng)絡(luò)就誕生了闹炉。神經(jīng)元通過突觸相互連接蒿赢,從輸入到輸出:
這個神經(jīng)網(wǎng)絡(luò)的目標(biāo)是訓(xùn)練它來進(jìn)行事件概括,例如識別手寫數(shù)字或垃圾郵件渣触。你只需要用大量例子來訓(xùn)練網(wǎng)絡(luò)羡棵,之后就能讓網(wǎng)絡(luò)預(yù)測正確的答案。
在每次預(yù)測之后昵观,根據(jù)預(yù)測的錯誤晾腔,調(diào)整權(quán)重和偏差值,以便網(wǎng)絡(luò)在下一次會更準(zhǔn)確地猜測啊犬。這種學(xué)習(xí)過程稱為 backpropagation(反向傳播)灼擂,做幾千次就差不多了。
backpropagation 技術(shù)就不展開了觉至,感興趣的話可以查看以下資料:
- A Step by Step Backpropagation Example?—?by Matt Mazur
- Hackers Guide to Neural Nets?—?by Andrej Karpathy
- NeuralNetworks And DeepLarning?—?by Michael Nielsen
代碼
有了基本概念后剔应,現(xiàn)在我們開始 coding。
第一件事就是創(chuàng)建圖層语御。我們使用 new Layer() 來實(shí)現(xiàn)峻贮。傳遞給函數(shù)的數(shù)字決定了每層應(yīng)該有多少個神經(jīng)元:
const { Layer, Network } = window.synaptic;
var inputLayer = new Layer(2);
var hiddenLayer = new Layer(3);
var outputLayer = new Layer(1);
接下來,我們將這些層連接在一起并實(shí)例化一個新的網(wǎng)絡(luò)应闯,如下所示:
inputLayer.project(hiddenLayer);
hiddenLayer.project(outputLayer);
var myNetwork = new Network({
input: inputLayer,
hidden: [hiddenLayer],
output: outputLayer
});
這是一個 2-3-1 網(wǎng)絡(luò)纤控,可以像這樣可視化:
現(xiàn)在我們來訓(xùn)練網(wǎng)絡(luò):
// train the network - learn XOR
var 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]);
}
這里我們運(yùn)行 20000 次,每次我們都向前和向后四次碉纺,傳遞可能的四個輸入:[0,0] [0,1] [1,0] [1,1] 船万。
我們從 myNetwork.activate([0,0]) 開始。數(shù)據(jù) [0,0] 是正向傳播骨田,也稱為激活網(wǎng)絡(luò)耿导。在每次向前傳播之后,我們需要進(jìn)行反向傳播态贤,網(wǎng)絡(luò)會更新權(quán)重和偏差舱呻。
反向傳播是用這一行代碼完成的:
myNetwork.propagate(learningRate, [0])
learningRate 是一個常數(shù),告訴網(wǎng)絡(luò)每次應(yīng)該調(diào)整多少權(quán)重悠汽。參數(shù) 0 表示當(dāng)輸入 [0,0] 時正確的輸出箱吕。
之后網(wǎng)絡(luò)將自己的預(yù)測與正確的標(biāo)簽進(jìn)行比較,然后就知道什么是對的了柿冲。
這個比較將作為校正權(quán)重和偏差值的基礎(chǔ)殖氏,以便下次猜測會更準(zhǔn)確一些。
完成 20000 次學(xué)習(xí)后姻采,我們就可以檢查下網(wǎng)絡(luò)的學(xué)習(xí)情況:
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]
如果我們將這些輸入值四舍五入到最接近的整數(shù)雅采,我們將得到 XOR 方程的正確答案爵憎。
這是個很初級的神經(jīng)網(wǎng)絡(luò),不過也足夠自己開始玩 Synaptic 了婚瓜,感興趣的話還可以看這個 wiki宝鼓,里面有很多很好的教程。
原文鏈接:How to create a Neural Network in JavaScript in only 30 lines of code
推薦閱讀: