简体   繁体   English

Javascript神经网络不收敛

[英]Javascript neural network not converging

I've been trying to evolve a neural network that prints values converging to one, using a genetic algorithm. 我一直在尝试开发一种使用遗传算法来打印收敛到一个值的神经网络。

I've tried debugging the code but don't know what I've messed up. 我已经尝试调试代码,但不知道自己搞砸了什么。

I'm using fitness to chose the best "brains" and then cross them over (reproduce). 我正在使用健身方法来选择最佳的“大脑”,然后将它们交叉(复制)。

At the moment it is only trying to evolve "brains" that return the number. 目前,它只是试图演化出返回数字的“大脑”。 the fitness is a function of the difference between returned number and original number. 适应度是返回数字和原始数字之间差异的函数。

"use strict";



function sigmoid(x) {

    return 1 / (1 + Math.E ** -x);

}



function random(min, max) {

    return (max - min) * Math.random() + min

}



function toss() {

    return random(-1, 1)

}



function Brain(inputs, hiddens, outputs) {

    this.structure = [...arguments];

    if (this.structure.length < 3) throw "Invalid layer count";

    this.layers = [];

    this.layers[this.structure.length - 1] = {

        nodes: []

    };

    for (var i = this.structure.length - 1; i--;) this.layers[i] = {

        bias: toss(),

        nodes: []

    };

    for (var i = 1; i < this.structure.length; i++) {

        var nodes = this.layers[i].nodes;;

        for (var j = this.structure[i]; j--;) {

            var node = nodes[j] = {

                weights: []

            };

            for (var k = this.structure[i - 1]; k--;) node.weights[k] = toss();

        }

    };

}



Brain.prototype.compute = function() {

    if (arguments[0] !== this.structure[0]) throw "Invalid input count";

    for (var i = arguments.length; i--;) this.layers[0].nodes[i] = {

        value: arguments[i]

    };

    for (var i = 1; i < this.layers.length - 1; i++) {

        var layer = this.layers[i];

        var feeder = this.layers[i - 1];

        for (var j = layer.nodes.length; j--;) {

            var node = layer.nodes[j];

            var dot = 0;

            for (var k = node.weights.length; k--;) dot += node.weights[k] * feeder.nodes[k].value;

            node.value = sigmoid(dot + feeder.bias);

        }

    }

    var result = [];

    var layer = this.layers[this.layers.length - 1];

    var feeder = this.layers[this.layers.length - 2];

    for (var j = layer.nodes.length; j--;) {

        var node = layer.nodes[j];

        var dot = 0;

        for (var k = node.weights.length; k--;) dot += node.weights[k] * feeder.nodes[k].value;

        result[j] = sigmoid(dot + feeder.bias);

    }

    return result;

}

Brain.prototype.cross = function() {

    var newBrain = new Brain(...this.structure);

    var brains = [this, ...arguments];

    for (var i = 1; i < newBrain.layers.length; i++) {

        var layer = newBrain.layers[i];

        for (var j = layer.nodes.length; j--;) {

            var node = layer.nodes[j];

            for (var k = node.weights.length; k--;) node.weights[k] = mutate() ||

                brains[Math.floor(Math.random() * brains.length)]

                .layers[i].nodes[j].weights[k];

        }

    }

    for (var i = newBrain.layers.length - 1; i--;) newBrain.layers[i].bias = mutate() ||

        brains[Math.floor(Math.random() * brains.length)]

        .layers[i].bias;

    return newBrain;

}



function mutate(key, nodes) {

    if (Math.random() > 0.05) return toss();

}



var brain = new Brain(1, 5, 1);

var newBrain = new Brain(1, 5, 1)

var result = brain.compute(1);

var cross = brain.cross(newBrain);



var brains = [];

for (var node = 45; node--;) brains.push({

    brain: new Brain(1, 5, 4, 3, 2, 1)

});

for (var count = 1000000; count--;) {

    brains.push({

        brain: new Brain(1, 5, 4, 3, 2, 1)

    });

    for (var node = brains.length; node--;) {

        var brain = brains[node];

        var number = 1;

        var target = number;

        brain.fitness = 1 / Math.abs(number - brain.brain.compute(number));

    }

    brains.sort((a, b) => a.fitness < b.fitness);

    if (count % 10000 === 0) console.log(brains.length, brains[0].fitness);



    var newBrains = [];

    for (var node = 10; node--;)

        for (var j = node; j--;) newBrains.push({

            brain: brains[node].brain.cross(brains[j].brain)

        });

    brains = newBrains;

}

console.log(brains);

What will I need to improve/change? 我需要改进/更改什么?

Here is the console log: 这是控制台日志:

46 1.468903884218341

46 1.1881817088540865

46 4.899728181582378

46 1.5494097713447523

46 2.4958253537304644

46 2.4091648830940953

46 1.4000955420478967

46 1.7560836401632383

46 3.3419380735652897

46 2.8290305398668245

46 2.951901023302089

46 2.9400525658126675

46 2.6769575714598948

46 1.55835425177616

As you can see, the fitness seems to be random 如您所见,适应度似乎是随机的

Some advice... 一些忠告...

  1. Neural networks usually take an input which should somehow be related to the output. 神经网络通常采用输入,该输入应以某种方式与输出相关。 I couldn't find any inputs for the network? 我找不到该网络的任何输入? If you can't come up with any good ideas just use the XOR problem and try to solve it. 如果您无法提出任何好主意,请使用XOR问题并尝试解决它。

  2. When checking if your population is becoming better over time don't look at all brains of each generation. 在检查您的人口是否随着时间的推移而变得更好时,请不要注视每一代人的大脑。 Remember, you are intentionally creating some randomized networks which may or may not be good at your task. 请记住,您是故意创建一些随机网络,这些随机网络可能无法完成您的任务。 Try printing the Top result of each generation and maybe the average score. 尝试打印每一代的最高成绩,也许是平均分数。 In a working genetic algorithm both values should become better over time. 在可行的遗传算法中,两个值都应随时间而变好。 (altough the top score is way more significant & important) (尽管最高分更有意义,也更重要)

  3. (Not directly adressing your issue) Don't use javascript. (不直接解决您的问题)请勿使用javascript。 You could probably transscribe your current code to java/c#/c++. 您可能可以将当前代码转换为java / c#/ c ++。 These languages execute way faster than JS. 这些语言的执行速度比JS快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM