1 |
|
2 |
|
3 |
|
4 | var math = require('./utils').math;
|
5 |
|
6 | MLP = module.exports = function (settings) {
|
7 | var self = this;
|
8 | self.x = settings['input'];
|
9 | self.y = settings['label'];
|
10 | self.sigmoidLayers = [];
|
11 | self.nLayers = settings['hidden_layer_sizes'].length;
|
12 | self.settings = {
|
13 | 'log level' : 1
|
14 | };
|
15 | var i;
|
16 | for(i=0 ; i<self.nLayers+1 ; i++) {
|
17 | var inputSize, layerInput;
|
18 | if(i == 0)
|
19 | inputSize = settings['n_ins'];
|
20 | else
|
21 | inputSize = settings['hidden_layer_sizes'][i-1];
|
22 |
|
23 | if(i == 0)
|
24 | layerInput = self.x;
|
25 | else
|
26 | layerInput = self.sigmoidLayers[self.sigmoidLayers.length-1].sampleHgivenV();
|
27 |
|
28 | var sigmoidLayer;
|
29 | if(i == self.nLayers) {
|
30 | sigmoidLayer = new HiddenLayer({
|
31 | 'input' : layerInput,
|
32 | 'n_in' : inputSize,
|
33 | 'n_out' : settings['n_outs'],
|
34 | 'activation' : math.sigmoid,
|
35 | 'W' : (typeof settings['w_array'] === 'undefined')? undefined : settings['w_array'][i],
|
36 | 'b' : (typeof settings['b_array'] === 'undefined')? undefined : settings['b_array'][i]
|
37 | });
|
38 | } else {
|
39 | sigmoidLayer = new HiddenLayer({
|
40 | 'input' : layerInput,
|
41 | 'n_in' : inputSize,
|
42 | 'n_out' : settings['hidden_layer_sizes'][i],
|
43 | 'activation' : math.sigmoid,
|
44 | 'W' : (typeof settings['w_array'] === 'undefined')? undefined : settings['w_array'][i],
|
45 | 'b' : (typeof settings['b_array'] === 'undefined')? undefined : settings['b_array'][i]
|
46 | });
|
47 | }
|
48 | self.sigmoidLayers.push(sigmoidLayer);
|
49 | }
|
50 | };
|
51 |
|
52 | MLP.prototype.train = function(settings) {
|
53 | var self = this;
|
54 | var lr = 0.6, epochs = 1000;
|
55 | if(typeof settings['lr'] !== 'undefined')
|
56 | lr = settings['lr'];
|
57 | if(typeof settings['epochs'] !== 'undefined')
|
58 | epochs = settings['epochs'];
|
59 |
|
60 |
|
61 | var epoch;
|
62 | var currentProgress = 1;
|
63 | for(epoch=0 ; epoch < epochs ; epoch++) {
|
64 |
|
65 |
|
66 | var i;
|
67 | var layerInput = [];
|
68 | layerInput.push(self.x);
|
69 | for(i=0; i<self.nLayers+1 ; i++) {
|
70 | layerInput.push(self.sigmoidLayers[i].output(layerInput[i]));
|
71 | }
|
72 | var output = layerInput[self.nLayers+1];
|
73 |
|
74 | var delta = new Array(self.nLayers + 1);
|
75 | delta[self.nLayers] = m.mulMatElementWise(m.minusMat(self.y, output),
|
76 | m.activateMat(self.sigmoidLayers[self.nLayers].linearOutput(layerInput[self.nLayers]), m.dSigmoid));
|
77 |
|
78 | |
79 |
|
80 |
|
81 |
|
82 |
|
83 | for(i = self.nLayers - 1; i>=0 ; i--) {
|
84 | delta[i] = m.mulMatElementWise(self.sigmoidLayers[i+1].backPropagate(delta[i+1]),
|
85 | m.activateMat(self.sigmoidLayers[i].linearOutput(layerInput[i]), m.dSigmoid));
|
86 | }
|
87 |
|
88 | for(var i=0; i<self.nLayers+1 ; i++) {
|
89 | var deltaW = m.activateMat(m.mulMat(m.transpose(layerInput[i]),delta[i]),function(x){return 1. * x / self.x.length;})
|
90 | var deltaB = m.meanMatAxis(delta[i],0);
|
91 | self.sigmoidLayers[i].W = m.addMat(self.sigmoidLayers[i].W,deltaW);
|
92 | self.sigmoidLayers[i].b = m.addVec(self.sigmoidLayers[i].b,deltaB);
|
93 | }
|
94 |
|
95 | if(self.settings['log level'] > 0) {
|
96 | var progress = (1.*epoch/epochs)*100;
|
97 | if(progress > currentProgress) {
|
98 | console.log("MLP",progress.toFixed(0),"% Completed.");
|
99 | currentProgress+=8;
|
100 | }
|
101 | }
|
102 | }
|
103 | if(self.settings['log level'] > 0)
|
104 | console.log("MLP Final Cross Entropy : ",self.getReconstructionCrossEntropy());
|
105 | };
|
106 |
|
107 | MLP.prototype.getReconstructionCrossEntropy = function() {
|
108 | var self = this;
|
109 | var reconstructedOutput = self.predict(self.x);
|
110 | var a = math.activateTwoMat(self.y,reconstructedOutput,function(x,y){
|
111 | return x*Math.log(y);
|
112 | });
|
113 |
|
114 | var b = math.activateTwoMat(self.y,reconstructedOutput,function(x,y){
|
115 | return (1-x)*Math.log(1-y);
|
116 | });
|
117 |
|
118 | var crossEntropy = -math.meanVec(math.sumMatAxis(math.addMat(a,b),1));
|
119 | return crossEntropy
|
120 | }
|
121 |
|
122 | MLP.prototype.predict = function(x) {
|
123 | var self = this;
|
124 | var output = x;
|
125 | for(i=0; i<self.nLayers+1 ; i++) {
|
126 | output = self.sigmoidLayers[i].output(output);
|
127 | }
|
128 | return output;
|
129 | };
|
130 |
|
131 | MLP.prototype.set = function(property,value) {
|
132 | var self = this;
|
133 | self.settings[property] = value;
|
134 | } |
\ | No newline at end of file |