2017-06-18 9 views
0

私は、同僚の生徒ウェブ開発者に、火曜日のニューラルネットワークに関する短いプレゼンテーションを行います。私はthis code(パート1、小さなおもちゃのニューラルネットワーク:2層のネットワークの下)をJavaScriptに変換して、私の聴衆がより認識できるようにしたいと考えていました。11行目のおもちゃニューラルネットワークコードを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で実行するために取得するために、脱ES6ified:

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) 

あなたは私がnumpyのための代替としてmathjsを使用しています見ることができるように。私はmathjsとnumpyのドキュメントを慎重に見ようとしましたが、行列の乗算と要素の乗算を混在させませんでしたが、何かが非常に壊れていて、すべての出力に対して.5が得られます。私はデバッガで自分のプログラムを踏んで、Pythonのスクラッチファイルで値を並べて比較しました。JavaScriptプログラムが生成したsyn0の値でpythonを開始しました。そして、ここではバックプロジェクションラインのように少し拡散しているようです(そして、おそらく反復よりも分岐する):l1_delta = m.dotMultiply(l1_error, m.map(l1, sigmoid_prime))。しかし、なぜ私は見ることができません。

EDIT:前回のバージョンでyの定義をvar y = m.matrix([ [0], [0], [1], [1]])に変更したことを反映するために私のコードを更新しておき、出力がすべて.5から少し浮かれる.5の。

SECOND EDIT:Brentはコメントに、バグがあることを指摘します。私のシグモイドプライム関数から移植しているコードを真似するには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

私はここで推測をスローするつもりです - あなたの体重は浮動小数点型/倍精度型に正しく型付けされていますか? – Monza

+0

syn0 = m.multiply(m.transpose(l0)、l1_delta) 'の直後に' m.map(syn0、function(w){console.log(typeof w)}) 'という行を追加するとコンソールログ'数'。私は彼らがintであるとは思えません。小数点以下の桁がたくさんあります(私は知らないうちにデータ型について簡単なことを言っているのですが、わかりません)。 – Katie

答えて

0

あなたは非常に接近しているように見え、これは素敵なポートです。

I これはnonlinの翻訳での小さなバグです。 derivパラメータがtrueの場合、式はx * (1 - x)です。あなたのバージョンではsigmoid(x) * (1 - sigmoid(x))を使用しています。 sigmoid_primeからsigmoidを呼び出す必要はないと思います。

私はそれが助けてくれることを願っています!

+0

あなたは正しいですが、それを指摘してくれてありがとうが、実際には違いが生じていないようです。私はなぜそれがあるのか​​についての数学的な直感は持っていませんが、そうであるようです。私はいくつかのコンソールログにこの問題を編集して表示します。それは少しのコメントに関与している。また、元の質問の「重みが0に収束する」ことは間違っていて、それが間違っていると考えていると、何が起こっているのかがわかります。最後の2つは0に収束しますが、最初のものは最後の2つより大きくなりますが、まだ小さすぎます。 – Katie

+0

(私は「重みがゼロに収束する」を編集しました)私は、混乱を最小限に抑えることは元の質問で完全に取り除くことを決めたものですが、誤解を招いて申し訳ありません! – Katie

関連する問題