【问题标题】:trouble translating 11-line toy neural network code to JavaScript将 11 行玩具神经网络代码翻译成 JavaScript 时遇到问题
【发布时间】:2017-06-18 23:28:51
【问题描述】:

周二我将向我的 Web 开发同学同学做一个关于神经网络的简短演讲。我希望将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 代码。我只是去 ES6ified 让它在我的 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 临时文件中并排比较了值,从 JavaScript 程序生成的 syn0 的值开始 python,看起来它就在这里,反向传播线,它们略有不同(并且可能在迭代中出现更多分歧):l1_delta = m.dotMultiply(l1_error, m.map(l1, sigmoid_prime))。但我不明白为什么。

编辑:我应该在发布之前更新我的代码以反映在上一个版本中我将 y 定义更改为 var y = m.matrix([ [0], [0], [1], [1]]) 并稍微修改了问题,因为输出从全 0.5 切换到稍微浮动关闭 0.5。

第二次编辑:Brent 在 cmets 中正确地指出我有一个错误,即模仿我从我的 sigmoid 素数函数移植的代码只需要 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 }

【问题讨论】:

  • 我要在这里猜测一下 - 您的权重是否正确输入为浮点数/双精度数而不是整数等?
  • 如果我在syn0 = m.multiply(m.transpose(l0),l1_delta) 之后添加此行m.map(syn0, function(w) {console.log(typeof w)}),控制台会记录“数字”。我不认为它们可以是整数,它们有很多小数位(除非我无意中对数据类型说了一些简单的话,我不知道)。

标签: javascript python numpy neural-network mathjs


【解决方案1】:

看起来你已经很近了,这是一个不错的港口。

认为这是您对nonlin 函数的翻译中的一个小错误。在deriv 参数为真的情况下,等式为x * (1 - x)。在您的版本中,您使用的是sigmoid(x) * (1 - sigmoid(x))。我认为您不需要在 sigmoid_prime 内拨打 sigmoid

希望对你有帮助!

【讨论】:

  • 您是对的,感谢您指出这一点,但实际上似乎并没有什么不同。对于为什么会这样,我没有数学直觉,但似乎是这样。我将在问题的编辑中放置一些显示此内容的控制台日志;评论有点太复杂了。我还应该注意,原始问题中的“权重收敛到零”是错误的,也许思考这个错误会帮助我弄清楚发生了什么。最后两个收敛到零,但第一个大于最后两个,应该是这样,但仍然太小。
猜你喜欢
  • 2012-08-05
  • 2017-05-24
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 2017-05-27
  • 2013-10-09
相关资源
最近更新 更多