UNPKG

rlab

Version:

Javascript scientific library like R

151 lines (135 loc) 5.67 kB
/** * Created by joonkukang on 2014. 1. 14.. */ var math = require('./utils').math; var M = R.M; MLP = module.exports = function (settings) { var self = this; self.x = settings['input']; self.y = settings['label']; self.sigmoidLayers = []; self.nLayers = settings['hidden_layer_sizes'].length; self.settings = { 'log level' : 1 // 0 : nothing, 1 : info, 2: warn }; var i; for(i=0 ; i<self.nLayers+1 ; i++) { var inputSize, layerInput; if(i == 0) inputSize = settings['n_ins']; else inputSize = settings['hidden_layer_sizes'][i-1]; if(i == 0) layerInput = self.x; else layerInput = self.sigmoidLayers[self.sigmoidLayers.length-1].sampleHgivenV(); var sigmoidLayer; if(i == self.nLayers) { sigmoidLayer = new HiddenLayer({ 'input' : layerInput, 'n_in' : inputSize, 'n_out' : settings['n_outs'], 'activation' : R.NN.sigmoid, // math.sigmoid, 'W' : (typeof settings['w_array'] === 'undefined')? undefined : settings['w_array'][i], 'b' : (typeof settings['b_array'] === 'undefined')? undefined : settings['b_array'][i] }); } else { sigmoidLayer = new HiddenLayer({ 'input' : layerInput, 'n_in' : inputSize, 'n_out' : settings['hidden_layer_sizes'][i], 'activation' : R.NN.sigmoid, // math.sigmoid, 'W' : (typeof settings['w_array'] === 'undefined')? undefined : settings['w_array'][i], 'b' : (typeof settings['b_array'] === 'undefined')? undefined : settings['b_array'][i] }); } self.sigmoidLayers.push(sigmoidLayer); } }; MLP.prototype.train = function(settings) { var self = this; var lr = 0.6, epochs = 1000; if(typeof settings['lr'] !== 'undefined') lr = settings['lr']; if(typeof settings['epochs'] !== 'undefined') epochs = settings['epochs']; var epoch; var currentProgress = 1; for(epoch=0 ; epoch < epochs ; epoch++) { // Feed Forward var i; var layerInput = []; layerInput.push(self.x); for(i=0; i<self.nLayers+1 ; i++) { layerInput.push(self.sigmoidLayers[i].output(layerInput[i])); } var output = layerInput[self.nLayers+1]; // Back Propagation var delta = new Array(self.nLayers + 1); delta[self.nLayers] = m.mulMatElementWise(m.minusMat(self.y, output), m.activateMat(self.sigmoidLayers[self.nLayers].linearOutput(layerInput[self.nLayers]), m.dSigmoid)); // var linearOutput=this.sigmoidLayers[this.nLayers].linearOutput(layerInput[this.nLayers]).map1(R.NN.dSigmoid); // delta[self.nLayers] = this.y.sub(output).mul(linearOutput); /* self.nLayers = 3 (3 hidden layers) delta[3] : ouput layer delta[2] : 3rd hidden layer, delta[0] : 1st hidden layer */ for(i = self.nLayers - 1; i>=0 ; i--) { // delta[i] = m.mulMatElementWise(self.sigmoidLayers[i+1].backPropagate(delta[i+1]), m.activateMat(self.sigmoidLayers[i].linearOutput(layerInput[i]), m.dSigmoid)); var o = this.sigmoidLayers[i].linearOutput(layerInput[i]).map1(R.NN.dSigmoid); delta[i] = this.sigmoidLayers[i+1].backPropagate(delta[i+1]).mul(o); } // Update Weight, Bias for(var i=0; i<self.nLayers+1 ; i++) { // var deltaW = m.activateMat(m.mulMat(m.transpose(layerInput[i]),delta[i]),function(x){return 1. * x / self.x.length;}) // var deltaB = m.meanMatAxis(delta[i],0); // self.sigmoidLayers[i].W = m.addMat(self.sigmoidLayers[i].W,deltaW); // self.sigmoidLayers[i].b = m.addVec(self.sigmoidLayers[i].b,deltaB); var deltaW = layerInput[i].tr().dot(delta[i]).map1((x)=>x/this.x.length); var deltaB = delta[i].colMean(); self.sigmoidLayers[i].W = this.sigmoidLayers[i].W.add(deltaW); self.sigmoidLayers[i].b = this.sigmoidLayers[i].b.add(deltaB); } if(self.settings['log level'] > 0) { var progress = (1.*epoch/epochs)*100; if(progress > currentProgress) { console.log("MLP",progress.toFixed(0),"% Completed."); currentProgress+=8; } } } if(self.settings['log level'] > 0) console.log("MLP Final Cross Entropy : ",self.getReconstructionCrossEntropy()); }; MLP.prototype.getReconstructionCrossEntropy = function() { var self = this; var reconstructedOutput = self.predict(self.x); var a = R.map2(self.y, reconstructedOutput, function(x,y) { return x*Math.log(y); }) // var a = math.activateTwoMat(self.y,reconstructedOutput,function(x,y){ // return x*Math.log(y); // }); var b = R.map2(self.y, reconstructedOutput, function(x,y) { return (1-x)*Math.log(1-y); }); // var b = math.activateTwoMat(self.y,reconstructedOutput,function(x,y){ // return (1-x)*Math.log(1-y); // }); // var crossEntropy = -math.meanVec(math.sumMatAxis(math.addMat(a,b),1)); var crossEntropy = a.add(b).colMean().neg(); // -(a+b).colMean() return crossEntropy } MLP.prototype.predict = function(x) { var self = this; var output = x; for(i=0; i<self.nLayers+1 ; i++) { output = self.sigmoidLayers[i].output(output); } return output; }; MLP.prototype.set = function(property,value) { var self = this; self.settings[property] = value; }