[英]trouble translating 11-line toy neural network code to JavaScript
我將在星期二向我的同學Web開發人員做一個關於神經網絡的簡短演講。 我希望將這段代碼 (在第1部分中,一個很小的玩具神經網絡:2層網絡)轉換為JavaScript,以使我的讀者更容易理解。
import numpy as np
# sigmoid function
def nonlin(x,deriv=False):
if(deriv==True):
return x*(1-x)
return 1/(1+np.exp(-x))
# input dataset
X = np.array([ [0,0,1],
[0,1,1],
[1,0,1],
[1,1,1] ])
# output dataset
y = np.array([[0,0,1,1]]).T
# seed random numbers to make calculation
# deterministic (just a good practice)
np.random.seed(1)
# initialize weights randomly with mean 0
syn0 = 2*np.random.random((3,1)) - 1
for iter in xrange(10000):
# forward propagation
l0 = X
l1 = nonlin(np.dot(l0,syn0))
# how much did we miss?
l1_error = y - l1
# multiply how much we missed by the
# slope of the sigmoid at the values in l1
l1_delta = l1_error * nonlin(l1,True)
# update weights
syn0 += np.dot(l0.T,l1_delta)
print "Output After Training:"
print l1
這是我現在的JavaScript代碼。 我只是取消了ES6的版本使其可以在我的IDE中運行:
const _ = require('lodash')
const m = require('mathjs')
const sigmoid = function(z) { return 1.0 / (1.0 + Math.exp(-z)) }
const sigmoid_prime = function(z) { return sigmoid(z) * (1 - sigmoid(z)) }
var X = m.matrix([ [0,0,1],[0,1,1],[1,0,1],[1,1,1] ])
var y = m.transpose(m.matrix(([[0,1,1,0]])))
var syn0 = m.random([3, 1], -1, 1)
var l0, l1, l1_delta, l1_error
_.range(10000).forEach(function() {
l0 = X;
l1 = m.map(m.multiply(l0, syn0), sigmoid)
l1_error = m.subtract(y, l1)
l1_delta = m.dotMultiply(l1_error, m.map(l1, sigmoid_prime))
syn0 = m.multiply(m.transpose(l0),l1_delta)
})
console.log("Output After Training:")
console.log(l1)
如您所見,我正在使用mathjs代替numpy。 我試圖仔細查看mathjs和numpy的文檔,而不是將矩陣乘法和元素乘法相混淆,但是有些地方很破損,每個輸出都得到0.5。 我在調試器中逐步執行了程序,並在python暫存文件中並排比較了值,從python開始使用JavaScript程序生成的syn0值,似乎在這里,反向傳播線,它們略有差異(並且在迭代中可能會更多): l1_delta = m.dotMultiply(l1_error, m.map(l1, sigmoid_prime))
。 但是我不明白為什么。
編輯:我應該在發布之前更新代碼,以反映在上一版本中我將y定義更改為var y = m.matrix([ [0], [0], [1], [1]])
和它稍微修改了問題,因為輸出從所有的.5切換為從.5稍微浮動。
第二次編輯:Brent在注釋中正確地指出了我有一個錯誤,因為要模仿從S型素數素函數中移植的代碼,只需要z *(1-z)。 我錯過了那皺紋。 可悲的是,這沒有什么區別。 控制台在最后一次迭代中記錄字符串化函數和syn0的值:
sigmoid prime is function (z) {return sigmoid(z) * (1 - sigmoid(z))}
syn0 is Matrix {
_data:
[ [ 0.21089543115482337 ],
[ -0.010100491415226356 ],
[ -0.021376195229226028 ] ],
_size: [ 3, 1 ],
_datatype: undefined }
現在更改功能:
sigmoid prime is function (z) { return z * (1 - (z)) }
syn0 is Matrix {
_data:
[ [ 0.2235282818415481 ],
[ -0.010714305064562765 ],
[ -0.022890185954402634 ] ],
_size: [ 3, 1 ],
_datatype: undefined }
看起來您非常接近,這是一個不錯的港口。
我認為這是您翻譯nonlin
函數時的一個小錯誤。 在其中的情況下deriv
參數為真時,方程是x * (1 - x)
在您的版本中,您正在使用sigmoid(x) * (1 - sigmoid(x))
。 我認為您不需要從sigmoid_prime
內部調用sigmoid
。
希望對您有所幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.