我将于周二向我的同学网络开发人员简要介绍神经网络。我希望将this code(在第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代码。我只是去了它,让它在我的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的文档,而不是混淆我的矩阵乘法和我的元素乘法,但有些东西非常破碎,每次输出都得到.5。我已经在调试器中逐步完成了我的程序,并在python临时文件中并排比较了值,使用JavaScript程序生成的syn0的值开始python out,看起来就像它在这里,反向传播线,他们略微分歧(并且可能在迭代中分歧更多):l1_delta = m.dotMultiply(l1_error, m.map(l1, sigmoid_prime))
。但我不明白为什么。
var y = m.matrix([ [0], [0], [1], [1]])
并稍微修改了问题,因为输出从全部转换为.5&# 39; s稍微离开.5。
第二次编辑:布伦特在评论中正确地指出我有一个错误,因为模仿我从sigmoid prime函数移植的代码只需要是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 }
答案 0 :(得分:0)
看起来你非常接近,这是一个不错的端口。
我认为这是nonlin
函数翻译中的一个小错误。在deriv
参数为真的情况下,等式为x * (1 - x)
。在您的版本中,您使用的是sigmoid(x) * (1 - sigmoid(x))
。我不认为您需要在sigmoid
内拨打sigmoid_prime
。
我希望有所帮助!