diff --git a/lib/neuralnetwork.js b/lib/neuralnetwork.js index f147f9a..f633822 100644 --- a/lib/neuralnetwork.js +++ b/lib/neuralnetwork.js @@ -370,27 +370,42 @@ NeuralNetwork.prototype = { return this; }, - toFunction: function() { - var json = this.toJSON(); + toFunction: function() { // return standalone function that mimics run() - return new Function("input", -' var net = ' + JSON.stringify(json) + ';\n\n\ - for (var i = 1; i < net.layers.length; i++) {\n\ - var layer = net.layers[i];\n\ - var output = {};\n\ - \n\ - for (var id in layer) {\n\ - var node = layer[id];\n\ - var sum = node.bias;\n\ - \n\ - for (var iid in node.weights) {\n\ - sum += node.weights[iid] * input[iid];\n\ - }\n\ - output[id] = (1 / (1 + Math.exp(-sum)));\n\ - }\n\ - input = output;\n\ - }\n\ - return output;'); + + var layers = this.toJSON().layers; + // we start with 'input', but will use each layer as the next input + var input = 'input'; + + // NOTE: keys are sorted so as to guarantee a consistent order and matching + // key-to-index, as indexes are used to generate variable names + return new Function(input, [].concat( + _.map(_.keys(layers[0]).sort(), function(iid, i) { + // collect our inputs as variables + // e.g. var input_0 = input['x']; + return 'var ' + input + '_' + i + ' = ' + input + '[' + JSON.stringify(iid) + '];'; + }), + _.map(layers.slice(1), function(layer, i) { + var output = 'output' + i; + var result = _.map(_.keys(layer).sort(), function(id, j) { + var node = layer[id]; + // e.g. bias + (weight_0 * inputX_0) + (weight_1 * inputX_1) + ... + var sum = [ + JSON.stringify(node.bias) + ].concat(_.map(_.keys(node.weights).sort(), function(iid, k) { + return JSON.stringify(node.weights[iid]) + ' * ' + input + '_' + k; + })).join(' + '); + return 'var ' + output + '_' + j + ' = (1 / (1 + Math.exp(-(' + sum + '))));'; + }).join('\n'); + input = output; + return result; + }), [ + // finally, return the resultant object, which consists of the values of our last layer + // e.g. return {a: outputX_0, b: outputX_1, c: outputX_2}; + 'return {' + _.map(_.keys(layers[layers.length - 1]).sort(), function(id, j) { + return JSON.stringify(id) + ': ' + input + '_' + j; + }).join(', ') + '};' + ]).join('\n')); }, // This will create a TrainStream (WriteStream)