编辑:我成功地聚集了几个简单的例子https://github.com/developer239/neural-network-playground
有没有人能帮我简单巧妙地教网如何解决XOR或其他类似的问题?但是使用NEAT技术以便我不必指定训练数据集?
使用javascript:https://github.com/cazala/synaptic或https://github.com/wagenaartje/neataptic
1. Initialize network
2. Generate generation
3. Go through each genome in generation and evaluate its fitness (how good it is)
4. Take 2 best genomes from generation
5. Merge genomes 50 / 50 at random
6. Mutate final genome
7. Generate second generation
这将非常有帮助。这里使用了相同的teqnique:
https://github.com/ivanseidel/IAMDinosaur
https://www.youtube.com/watch?v=P7XHzqZjXQs
我查看了源代码,但是有很多东西要继续。我理解一般的想法。但是我不知道如何实施解决方案。
谢谢:)
答案 0 :(得分:1)
有一个关于Neataptic' README.md的例子。
// this network learns the XOR gate (through neuro-evolution)
var network = new Network(2,1);
var trainingSet = [
{ input: [0,0], output: [0] },
{ input: [0,1], output: [1] },
{ input: [1,0], output: [1] },
{ input: [1,1], output: [0] }
];
await network.evolve(trainingSet, {
equal: true,
error: 0.03
});
Neataptic将其全部内置,因此您只需提供一个数据集即可。如果您需要有关如何设置的详细信息,请read this article。
对于动态解决方案的问题,必须实现自定义循环和适应度函数。
答案 1 :(得分:1)
我知道这是一个很老的问题,并且消炎药的使用并不广泛,但是我发现了一种更简单的实施方法,因此我想与大家分享
const { Neat } = require('neataptic');
function fitness(network) {
let score = 0;
score += Math.abs(0 - network.activate([0,0])[0]);
score += Math.abs(1 - network.activate([0,1])[0]);
score += Math.abs(1 - network.activate([1,0])[0]);
score += Math.abs(0 - network.activate([1,1])[0]);
score = -score;
return score;
}
(async () => {
const neat = new Neat(2 ,1 ,fitness, {});
for (let i = 0; i < 10000; i++) {
await neat.evolve();
}
const fittest = neat.getFittest();
console.log(fitness(fittest));
console.log(fittest.activate([0,0]));
console.log(fittest.activate([0,1]));
console.log(fittest.activate([1,0]));
console.log(fittest.activate([1,1]));
})();
答案 2 :(得分:0)
我设法编写了自己的解决方案。您可以在此处找到它:https://github.com/developer239/neural-network-playground/tree/master/neatXOR
与文档中的解决方案的主要区别在于,genetic.js
您可以动态地更改学习过程。
这是输入文件:
const genetic = require('./genetic')
genetic.generateRandomPopulation()
for (let iteration = 0; iteration < 1000; iteration += 1) {
genetic.live()
genetic.evolve()
}
const genom = genetic.neat.population[0]
console.log(`
Result for genom with index 0 in the newest population. Note that selection / mutation happened
after we called last evolve function so this is not necessarily the best genome in the population.
[0, 0] = ${genom.activate([0, 0])} (should be 0)
[1, 1] = ${genom.activate([1, 1])} (should be 0)
[0, 1] = ${genom.activate([0, 1])} (should be 1)
[1, 0] = ${genom.activate([1, 0])} (should be 1)
`)
这是genetic.js
档案:
const { Neat, architect } = require('neataptic')
module.exports = {
neat: null, // https://wagenaartje.github.io/neataptic/docs/neat/
possibleInputs: [
[0, 0], // expected output 0
[1, 1], // expected output 0
[0, 1], // expected output 1
[1, 0], // expected output 1
],
generateRandomPopulation: function () {
this.neat = new Neat(
2, // number of inputs
1, // number of outputs
null, // fitnessFunction - in this example we are calculating fitness inside live method
{
elitism: 5, // this sets how many genomes in population will be passed into next generation without mutation https://www.researchgate.net/post/What_is_meant_by_the_term_Elitism_in_the_Genetic_Algorithm
mutationRate: 0.3, // sets the mutation rate. If set to 0.3, 30% of the new population will be mutated. Default is 0.3
network: // https://wagenaartje.github.io/neataptic/docs/architecture/network/
new architect.Random(
2,
3,
1,
),
},
)
},
// the closer the output gets to expectedOutput the better
// note that optimal fitness in this example is 0 neural network seems to work fine though
calculateFitness: function (expectedOutput, output) {
let closeCount = Math.abs(expectedOutput - output)
let fitness = closeCount * -1
return fitness
},
live: function () {
// increment generation index
this.neat.generation += 1
// loop through each genome
for (let genomeIndex in this.neat.population) {
const possibleInputs = this.possibleInputs
const genome = this.neat.population[genomeIndex]
genome.score = 0
// loop through each input
for (let i = 0; i < possibleInputs.length; i += 1) {
let input = possibleInputs[i]
// test each input
let output = genome.activate(input)[0]
// calculate fitness for each output
// we have 4 different inputs so the total score is sum of 4 different fitness values
if (i <= 1) {
genome.score += this.calculateFitness(0, output)
} else {
genome.score += this.calculateFitness(1, output)
}
}
}
},
evolve: function () {
const neat = this.neat
console.log(`[generation ${neat.generation}] Average score: ${neat.getAverage()} (the closer to zero the better)`)
// sort by genome.score in descending order
neat.sort()
// our new population will be here
let newPopulation = []
// we want to push neat.elitism number of best genomes into the new population automatically
for (let i = 0; i < neat.elitism; i++) {
newPopulation.push(neat.population[i])
}
// we want to get offspring from the current population and push it into the new population
for (let i = 0; i < neat.popsize - neat.elitism; i++) {
newPopulation.push(neat.getOffspring())
}
// set new population
neat.population = newPopulation
// mutate the population
neat.mutate()
},
}