2017-06-18 10 views
0

Ich bin eine kurze Präsentation über neuronale Netze Dienstag meinen Kommilitonen Web-Entwickler. Ich hatte gehofft, this code (unter Teil 1, ein kleines Spielzeug neuronales Netzwerk: 2-Schicht-Netzwerk) zu JavaScript zu übersetzen, so dass es für mein Publikum besser erkennbar wäre.Probleme Übersetzung 11-Linien-Spielzeug neuronalen Netzwerk-Code zu 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 

Hier ist mein JavaScript-Code, wie er jetzt steht. Ich habe gerade de-ES6ified es, um es in meiner IDE auszuführen:

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) 

Wie man sehen kann ich mathjs als Ersatz für numpy verwenden. Ich habe versucht, die Dokumentation für mathjs und numpy genau zu betrachten und meine Matrixmultiplikation und meine elementweise Multiplikation nicht zu verwechseln, aber etwas ist sehr kaputt und ich bekomme für jede Ausgabe .5. Ich habe mein Programm im Debugger durchgegangen und die Werte nebeneinander in einer Python-Scratch-Datei verglichen, Python mit den Werten für syn0, die das JavaScript-Programm erzeugt hat, gestartet und es scheint, als ob es hier ist, die backpropagation Linie, die sie leicht abweichen (und möglicherweise mehr über Iterationen divergieren): l1_delta = m.dotMultiply(l1_error, m.map(l1, sigmoid_prime)). Aber ich kann nicht sehen warum.

EDIT: Ich sollte meinen Code aktualisiert haben, bevor ich gepostet, um in der letzten Version zu reflektieren Ich änderte die y-Definition zu var y = m.matrix([ [0], [0], [1], [1]]) und es leicht modifiziert das Problem, in dem die Ausgabe von allen .5 zu schweben etwas aus von .5.

ZWEITE BEARBEITUNG: Brent weist zu Recht in Kommentaren darauf hin, dass ich einen Fehler habe, um den Code, den ich von meiner sigmoiden Primzahlfunktion portiere, nur z * (1-z) zu imitieren. Ich hatte diese Falte vermisst. Leider macht das keinen Unterschied. Console Protokollierung der Zeichenfolge Funktion und den Wert von syn0 in der letzten Iteration:

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 } 

nun die Änderung der Funktion:

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

Ich werde hier eine Vermutung einwerfen - sind Ihre Gewichte richtig getippt zu floats/doubles und nicht ints usw.? – Monza

+0

Wenn ich diese Zeile 'm.map (syn0, function (w) {console.log (typeof w)})' direkt nach 'syn0 = m.multiply (m.transpose (l0), l1_delta)' it console logs hinzufüge 'Nummer'. Ich glaube nicht, dass sie Ints sein können, sie haben viele Dezimalstellen (außer ich sage unwissentlich etwas Einfaches über Datentypen, ich weiß es nicht). – Katie

Antwort

0

Es sieht aus wie Sie ganz in der Nähe sind, ist dieses ein schöner Hafen ist.

I denken Dies ist ein kleiner Fehler in Ihrer Übersetzung der nonlin-Funktion. In dem Fall, in dem der Parameter deriv wahr ist, lautet die Gleichung x * (1 - x). In Ihrer Version verwenden Sie sigmoid(x) * (1 - sigmoid(x)). Ich glaube nicht, dass Sie aus sigmoid_primesigmoid aufrufen müssen.

Ich hoffe, dass hilft!

+0

Sie haben Recht, und danke, dass Sie darauf hingewiesen haben, aber es scheint tatsächlich keinen Unterschied zu machen. Ich habe keine mathematische Intuition dafür, warum das so ist, aber es scheint so zu sein. Ich werde ein paar Konsolenprotokolle einfügen, die das in einer Bearbeitung der Frage zeigen; es ist ein wenig zu kompliziert für einen Kommentar. Ich sollte auch anmerken, dass "die Gewichte in der ursprünglichen Frage auf Null konvergieren" falsch war, und vielleicht wird es mir helfen, herauszufinden, was vor sich geht. Die letzten beiden konvergieren zu Null, aber der erste ist größer als die letzten beiden, wie es sein sollte, ist aber immer noch zu klein. – Katie

+0

(Ich habe herausgeschnitten "die Gewichte konvergieren zu Null" Ich entschied, das am wenigsten verwirrende Ding war, es vollständig in der ursprünglichen Frage loszuwerden, aber es tut mir leid, wenn es irreführend war!) – Katie

Verwandte Themen