简体   繁体   English

无法将11行玩具神经网络代码转换为JavaScript

[英]trouble translating 11-line toy neural network code to JavaScript

I am giving a short presentation on neural networks Tuesday to my fellow student web developers. 我将在星期二向我的同学Web开发人员做一个关于神经网络的简短演讲。 I was hoping to translate this code (under Part 1, a tiny toy neural network: 2 layer network) to JavaScript so it would be more recognizable to my audience. 我希望将这段代码 (在第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

Here's my JavaScript code as it stands now. 这是我现在的JavaScript代码。 I just de-ES6ified it to get it to run in my IDE: 我只是取消了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)

As you can see I'm using mathjs as a substitute for numpy. 如您所见,我正在使用mathjs代替numpy。 I have tried to look carefully at the documentation for mathjs and numpy and not mix up my matrix multiplication and my elementwise multiplication, but something is very broken and I get .5 for every output. 我试图仔细查看mathjs和numpy的文档,而不是将矩阵乘法和元素乘法相混淆,但是有些地方很破损,每个输出都得到0.5。 I have stepped through my program in the debugger and compared values side by side in a python scratch file, starting python out with the values for syn0 that the JavaScript program generated, and it seems like it's here, the backpropagation line, that they slightly diverge (and maybe diverge more over iterations): l1_delta = m.dotMultiply(l1_error, m.map(l1, sigmoid_prime)) . 我在调试器中逐步执行了程序,并在python暂存文件中并排比较了值,从python开始使用JavaScript程序生成的syn0值,似乎在这里,反向传播线,它们略有差异(并且在迭代中可能会更多): l1_delta = m.dotMultiply(l1_error, m.map(l1, sigmoid_prime)) But I can't see why. 但是我不明白为什么。

EDIT: I should have updated my code before I posted to reflect that in the last version I changed the y definition to var y = m.matrix([ [0], [0], [1], [1]]) and it slightly modified the problem, in that the output switched from being all .5's to floats slightly off of .5. 编辑:我应该在发布之前更新代码,以反映在上一版本中我将y定义更改为var y = m.matrix([ [0], [0], [1], [1]])和它稍微修改了问题,因为输出从所有的.5切换为从.5稍微浮动。

SECOND EDIT: Brent rightly points out in comments that I have a bug, in that to imitate the code I'm porting from my sigmoid prime function only needs to be z*(1-z). 第二次编辑:Brent在注释中正确地指出了我有一个错误,因为要模仿从S型素数素函数中移植的代码,只需要z *(1-z)。 I had missed that wrinkle. 我错过了那皱纹。 Sadly, this doesn't make a difference. 可悲的是,这没有什么区别。 Console logging the stringified function and the value of syn0 in the last iteration: 控制台在最后一次迭代中记录字符串化函数和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 }

Now changing the function: 现在更改功能:

sigmoid prime is function (z) { return z * (1 - (z)) }
syn0 is Matrix {
  _data: 
   [ [ 0.2235282818415481 ],
     [ -0.010714305064562765 ],
     [ -0.022890185954402634 ] ],
  _size: [ 3, 1 ],
  _datatype: undefined }

It looks like you're very close, this is a nice port. 看起来您非常接近,这是一个不错的港口。

I think this is a small bug in your translation of the nonlin function. 认为这是您翻译nonlin函数时的一个小错误。 In the case where the deriv parameter is true, the equation is x * (1 - x) . 在其中的情况下deriv参数为真时,方程是x * (1 - x) In your version you are using sigmoid(x) * (1 - sigmoid(x)) . 在您的版本中,您正在使用sigmoid(x) * (1 - sigmoid(x)) I don't think you need to be calling sigmoid from within sigmoid_prime . 我认为您不需要从sigmoid_prime内部调用sigmoid

I hope that helps! 希望对您有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM