Last active
February 1, 2017 15:27
-
-
Save cympfh/51be12760f9031ec20675e6fb03b49b2 to your computer and use it in GitHub Desktop.
ニューラルネットワークの実装
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Neural network | |
「パターン認識と機会学習」上巻 | |
p.246 | |
5.3.2 "単純な例" | |
を実装したもの | |
合ってるかそんな自信ないだけど | |
パラメータ初期値ゼロから始めるとゼロのまま動かない (そもそもその挙動は正しい?) | |
なので乱数を使ってるんだけど,その結果,たま〜にダメな結果出しちゃう | |
あと訓練だけど収束まで,とするのが面倒なので適当に1000回,訓練するだけ | |
function NN がそれ.その下に使い方の例を示します | |
*/ | |
// N-input, M-unit in 1-hidden-layer and 1-output | |
function NN(N, M, datum) { | |
this.w1 = []; | |
this.w2 = []; | |
this.b1 = []; | |
this.b2 = Math.random() - .5; | |
for (var i=0; i<M; ++i) { | |
this.w1[i] = []; | |
this.w2[i] = Math.random() - .5; | |
this.b1[i] = Math.random() - .5; | |
for (var j=0; j<N;+ ++j) { | |
this.w1[i][j] = Math.random() - .5; | |
} | |
} | |
this.iotaN = iota(N); | |
this.iotaM = iota(M); | |
var that = this; | |
for (var cx=0; cx<1000; ++cx) | |
for (var i=0, n=datum.length; i<n; ++i) | |
train(datum[i]); | |
function train(d) { | |
var xs = d.xs | |
, t = d.t; | |
const eps = .1; | |
var z = | |
that.iotaM.map(function(i){ | |
return tanh( that.iotaN.map(function(j){ return xs[j] * that.w1[i][j] }).reduce(add) + that.b1[i] ); | |
}); | |
var y = | |
sigm( that.iotaM.map(function(i){ return z[i] * that.w2[i] }).reduce(add) + that.b2 ); | |
var deltak = y - t; | |
for (var i=0; i<M; ++i) { | |
that.w2[i] -= eps * deltak * z[i]; | |
} | |
// that.b2 -= eps * deltak * that.b2; | |
that.b2 -= eps * deltak; | |
var delta = []; | |
for (var i=0; i<M; ++i) { | |
delta[i] = (1 - Math.pow(z[i], 2)) * that.w2[i] * deltak; | |
} | |
for (var i=0; i<M; ++i) { | |
for (var j=0; j<N; ++j) { | |
that.w1[i][j] -= eps * delta[i] * xs[j]; | |
} | |
// that.b1[i] -= eps * delta[i] * that.b1[i]; | |
that.b1[i] -= eps * delta[i]; | |
} | |
} | |
function iota(n) { | |
for (var i=0, ret=[]; i<n; ++i) ret[i] = i; | |
return ret; | |
} | |
function tanh(x) { return 1 - 2 / (1 + Math.exp(2*x)); } | |
function sigm(x) { return 1 / (1 + Math.exp(-x)) } | |
function add(x,y) { return x+y } | |
this.test = function(xs) { | |
var that = this; | |
var z = | |
this.iotaM.map(function(i){ | |
return tanh( that.iotaN.map(function(j){ return xs[j] * that.w1[i][j] }).reduce(add) + that.b1[i] ); | |
}); | |
var y = sigm( that.iotaM.map(function(i){ return z[i] * that.w2[i] }).reduce(add) + that.b2 ); | |
return y; | |
}; | |
} | |
// 2入力,隠れ層は試しに3ユニット,あと訓練データを4つ | |
// 一つの訓練データは 入力 xs, 答え t | |
var xor = | |
new NN(2, 3, | |
[ {xs : [0,0], t : 0} | |
, {xs : [1,0], t : 1} | |
, {xs : [0,1], t : 1} | |
, {xs : [1,1], t : 0} ]); | |
// 訓練したデータそのままだけど,さすがに2入力,訓練データ4つだけじゃ未知データにとてもとても対応できないからね | |
// tを実数値の範囲で答える | |
// 実際には Math.round(xor.test([0, 0])) などとして予測値とする | |
console.log( xor.test([0, 0]) ); | |
console.log( xor.test([0, 1]) ); | |
console.log( xor.test([1, 0]) ); | |
console.log( xor.test([1, 1]) ); | |
/* | |
:!node ./neuralNetwork.js | |
0.20426953217150673 | |
0.8139313401257358 | |
0.9135743890231167 | |
0.023482815195126294 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment