Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Neural network in Javascript not learning properly

I've tried to rewrite neural network found here to javascript. My javascript code looks like this.

function NeuralFactor(weight) {
    var self = this;
    this.weight = weight;
    this.delta =  0;
}

function Sigmoid(value) {
    return 1 / (1 + Math.exp(-value));
}

function Neuron(isInput) {
    var self = this;
    this.pulse = function() {
        self.output = 0;
        self.input.forEach(function(item) {
            self.output += item.signal.output * item.factor.weight;
        });

        self.output += self.bias.weight;
        self.output = Sigmoid(self.output);
    };

    this.bias = new NeuralFactor(isInput ? 0 : Math.random());
    this.error = 0;
    this.input = [];
    this.output = 0;

    this.findInput = function(signal) {
        var input = self.input.filter(function(input) {
            return signal == input.signal;
        })[0];
        return input;
    };
}

function NeuralLayer() {
    var self = this;
    this.pulse = function() {
        self.neurons.forEach(function(neuron) {
            neuron.pulse();
        });
    };
    this.neurons = [];
    this.train = function(learningRate) {
        self.neurons.forEach(function(neuron) {
            neuron.bias.weight += neuron.bias.delta * learningRate;
            neuron.bias.delta = 0;
            neuron.input.forEach(function(input) {
                input.factor.weight += input.factor.delta * learningRate;
                input.factor.delta = 0;
            })
        })
    }
}

function NeuralNet(inputCount, hiddenCount, outputCount) {
    var self = this;
    this.inputLayer = new NeuralLayer();
    this.hiddenLayer = new NeuralLayer();
    this.outputLayer = new NeuralLayer();
    this.learningRate = 0.5;

    for(var i = 0; i < inputCount; i++)
        self.inputLayer.neurons.push(new Neuron(true));

    for(var i = 0; i < hiddenCount; i++)
        self.hiddenLayer.neurons.push(new Neuron());

    for(var i = 0; i < outputCount; i++)
        self.outputLayer.neurons.push(new Neuron());

    for (var i = 0; i < hiddenCount; i++)
        for (var j = 0; j < inputCount; j++)
            self.hiddenLayer.neurons[i].input.push({
                signal: self.inputLayer.neurons[j],
                factor: new NeuralFactor(Math.random())
            });

    for (var i = 0; i < outputCount; i++)
        for (var j = 0; j < hiddenCount; j++)
            self.outputLayer.neurons[i].input.push({
                signal: self.hiddenLayer.neurons[j],
                factor: new NeuralFactor(Math.random())
            });

    this.pulse = function() {
        self.hiddenLayer.pulse();
        self.outputLayer.pulse();
    };

    this.backPropagation = function(desiredResults) {
        for(var i = 0; i < self.outputLayer.neurons.length; i++) {
            var outputNeuron = self.outputLayer.neurons[i];
            var output = outputNeuron.output;
            outputNeuron.error = (desiredResults[i] - output) * output * (1.0 - output);
        }
        for(var i = 0; i < self.hiddenLayer.neurons.length; i++) {
            var hiddenNeuron = self.hiddenLayer.neurons[i];
            var error = 0;
            for(var j = 0; j < self.outputLayer.neurons.length; j++) {
                var outputNeuron = self.outputLayer.neurons[j];
                error += outputNeuron.error * outputNeuron.findInput(hiddenNeuron).factor.weight * hiddenNeuron.output * (1.0 - hiddenNeuron.output);
            }
            hiddenNeuron.error = error;
        }
        for(var j = 0; j < self.outputLayer.neurons.length; j++) {
            var outputNeuron = self.outputLayer.neurons[j];
            for(var i = 0; i < self.hiddenLayer.neurons.length; i++) {
                var hiddenNeuron = self.hiddenLayer.neurons[i];
                outputNeuron.findInput(hiddenNeuron).factor.delta += outputNeuron.error * hiddenNeuron.output;
            }
            outputNeuron.bias.delta += outputNeuron.error * outputNeuron.bias.weight;
        }
        for(var j = 0; j < self.hiddenLayer.neurons.length; j++) {
            var hiddenNeuron = self.hiddenLayer.neurons[j];
            for(var i = 0; i < self.inputLayer.neurons.length; i++) {
                var inputNeuron = self.inputLayer.neurons[i];
                hiddenNeuron.findInput(inputNeuron).factor.delta += hiddenNeuron.error * inputNeuron.output;
            }
            hiddenNeuron.bias.delta += hiddenNeuron.error * hiddenNeuron.bias.weight;
        }
    };
    this.train = function(input, desiredResults) {
        for(var i = 0; i < self.inputLayer.neurons.length; i++) {
            var neuron = self.inputLayer.neurons[i];
            neuron.output = input[i];
        }

        self.pulse();
        self.backPropagation(desiredResults);

        self.hiddenLayer.train(self.learningRate);
        self.outputLayer.train(self.learningRate);
    };

}

Now I'm trying to learn it how to resolve XOR problem. I'm teaching it like this:

var net = new NeuralNet(2,2,1);

var testInputs = [[0,0], [0,1], [1,0], [1,1]];
var testOutputs = [[1],[0],[0],[1]];

for (var i = 0; i < 1000; i++)
    for(var j = 0; j < 4; j++)
        net.train(testInputs[j], testOutputs[j]);

function UseNet(a, b) {
    net.inputLayer.neurons[0].output = a;
    net.inputLayer.neurons[1].output = b;
    net.pulse();

    return net.outputLayer.neurons[0].output;
}

The problem is that all results that I get is close to 0.5 and pretty random, no matter what arguments I use. For example:

UseNet(0,0) => 0.5107701166677714
UseNet(0,1) => 0.4801498747476413
UseNet(1,0) => 0.5142463167153447
UseNet(1,1) => 0.4881829364416052

What can be wrong with my code?

like image 200
Łukasz W. Avatar asked Mar 18 '14 22:03

Łukasz W.


People also ask

Why a neural network may fail to learn a function?

Neural networks CAN fail to learn a function; this is most often caused by employing a network topology which is too simple to model the necessary function.

Can you build a neural network in JavaScript?

It really does not have to be Python to get started with deep learning. JavaScript equips you with everything you need to create your own neural network from the scratch.

Can a neural network learn anything?

Just like every other supervised machine learning model, neural networks learn relationships between input variables and output variables. In fact, we can even see how it's related to the most iconic model of all, linear regression.


2 Answers

This network is big enough for the XOR problem and I can't see any obvious mistakes, so I suspect it's getting stuck in a local minimum.

Try going through the training set 10,000 times instead of 1000; this gives it a better chance of breaking out of any minima and converging. You can also increase convergence a lot by upping the number of hidden neurons, tweaking η (the learning rate) or adding momentum. To implement the latter, try using this as your training function:

this.train = function(learningRate) {
    var momentum = 0 /* Some value, probably fairly small. */;
    self.neurons.forEach(function(neuron) {
        neuron.bias.weight += neuron.bias.delta * learningRate;
        neuron.bias.delta = 0;
        neuron.input.forEach(function(input) {
            input.factor.weight += (input.factor.delta * learningRate) + (input.factor.weight * momentum);
            input.factor.delta = 0;
        })
    })
}

I've had good results changing the learning rate to 1.5 (which is pretty high) and momentum to 0.000001 (which is pretty small).

(Incidentally, have you tried running the .NET implementation with a few different seeds? It can take quite a while to converge too!)

like image 74
Jordan Gray Avatar answered Sep 24 '22 00:09

Jordan Gray


This system uses fuzzy logic. As it says in the article don't use integers instead use "close" real numbers as the article suggests -- try

UseNet(0.1,0.1) => 
UseNet(0.1,0.9) => 
UseNet(0.9,0.1) => 
UseNet(0.9,0.9) => 

For the results anything above 0.5 is a 1 and below is 0

like image 43
Hogan Avatar answered Sep 23 '22 00:09

Hogan