New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Neural evolution algorithms implementation (CNE, NEAT, HyperNEAT) #686
Changes from 1 commit
dc27518
88788d6
6ab9add
ca73f95
30ec0ba
7fdd7ca
e4fbabd
3c8aa62
cbb79a2
65f093d
eb16ce2
c6976ac
8919bb9
ee548b6
faf47a2
adc45b2
95c2e53
1ee07a0
39ef07b
74fb4a0
d0883f4
a605eef
e059af0
6c11f32
3c10995
57d4165
6a770ec
cce115b
2a9899c
1a2cfd8
dacc2e6
2a4c715
6f901a1
a80f5f7
3db85fd
8168779
554a279
1fe7d73
ff45785
48e15c4
fc982b9
66b0f41
109f05b
8054f00
5ef61fe
f213dd8
f234ebd
96ccef5
24f9baf
4decb0e
c46436e
000d6aa
2599077
408b40f
0fc792c
847db95
10b99ab
da55507
beb8ba8
3b66431
9480379
4483fc8
190e639
4cd0054
668fa6e
62d5885
e176571
dec32ac
bc178c3
432331b
0944516
d66bb14
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -181,6 +181,27 @@ class Genome { | |
return -1; // Id start from 0. | ||
} | ||
|
||
// Whether link exist and enabled. | ||
bool ContainEnabledLink(ssize_t innovId) const { | ||
for(ssize_t i=0; i < NumLink(); ++i) { | ||
if (aLinkGenes[i].InnovationId() == innovId && | ||
aLinkGenes[i].Enabled()) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
// Whether link exist. | ||
bool ContainLink(ssize_t innovId) const { | ||
for(ssize_t i=0; i < NumLink(); ++i) { | ||
if (aLinkGenes[i].InnovationId() == innovId) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we use size_t as return type, we can't use -1, maybe we can start with 1 and return 0? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I agree. |
||
|
||
// Calculate Neuron depth. | ||
ssize_t NeuronDepth(ssize_t id) { | ||
// TODO: if contains loop in network. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -218,6 +218,9 @@ class NEAT { | |
// Crossover link weights. | ||
// NOTICE: assume momGenome is the better genome. | ||
// NOTICE: assume childGenome is empty. | ||
// NOTICE: in the NEAT paper, disabled links also can crossover, calculate distance, etc. | ||
// Is it really a good idea??? | ||
// If not, we will need to change CrossoverLinkAndNeuron, and Disjoint, and WeightDiff. | ||
void CrossoverLinkAndNeuron(Genome& momGenome, Genome& dadGenome, Genome& childGenome) { | ||
// Add input and output neuron genes to child genome. | ||
for (ssize_t i=0; i<(momGenome.NumInput() + momGenome.NumOutput()); ++i) { | ||
|
@@ -226,10 +229,12 @@ class NEAT { | |
|
||
// Iterate to add link genes and neuron genes to child genome. | ||
for (ssize_t i=0; i<momGenome.NumLink(); ++i) { | ||
ssize_t innovId = momGenome.aLinkGenes[i].InnovationId(); | ||
ssize_t innovId = momGenome.aLinkGenes[i].InnovationId(); | ||
ssize_t idx = dadGenome.GetLinkIndex(innovId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the names of the genomes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! |
||
bool linkContainedInDad = (idx != -1); | ||
double randNum = mlpack::math::Random(); | ||
|
||
if (idx == -1 && momGenome.aLinkGenes[i].Enabled()) { // exceed or disjoint | ||
if (!linkContainedInDad) { // exceed or disjoint | ||
childGenome.AddLink(momGenome.aLinkGenes[i]); | ||
|
||
// Add from neuron | ||
|
@@ -249,7 +254,7 @@ class NEAT { | |
continue; | ||
} | ||
|
||
if (idx != -1 && momGenome.aLinkGenes[i].Enabled() && mlpack::math::Random() < 0.5) { | ||
if (linkContainedInDad && randNum < 0.5) { | ||
childGenome.AddLink(momGenome.aLinkGenes[i]); | ||
|
||
// Add from neuron | ||
|
@@ -269,7 +274,7 @@ class NEAT { | |
continue; | ||
} | ||
|
||
if (idx != -1 && momGenome.aLinkGenes[i].Enabled() && mlpack::math::Random() >= 0.5) { | ||
if (linkContainedInDad && randNum >= 0.5) { | ||
childGenome.AddLink(dadGenome.aLinkGenes[idx]); | ||
|
||
// Add from neuron TODO: make it a function?? check whether crossover is correct. | ||
|
@@ -307,16 +312,16 @@ class NEAT { | |
|
||
for (ssize_t i=0; i<genome1.NumLink(); ++i) { | ||
ssize_t innovId = genome1.aLinkGenes[i].InnovationId(); | ||
ssize_t idx = genome2.GetLinkIndex(innovId); | ||
if (idx == -1 && genome1.aLinkGenes[i].Enabled()) { | ||
bool linkContainedInGenome2 = genome2.ContainLink(innovId); | ||
if (!linkContainedInGenome2) { | ||
++numDisjoint; | ||
} | ||
} | ||
} | ||
|
||
for (ssize_t i=0; i<genome2.NumLink(); ++i) { | ||
ssize_t innovId = genome2.aLinkGenes[i].InnovationId(); | ||
ssize_t idx = genome1.GetLinkIndex(innovId); | ||
if (idx == -1 && genome2.aLinkGenes[i].Enabled()) { | ||
bool linkContainedInGenome1 = genome1.ContainLink(innovId); | ||
if (!linkContainedInGenome1) { | ||
++numDisjoint; | ||
} | ||
} | ||
|
@@ -334,7 +339,8 @@ class NEAT { | |
for (ssize_t i=0; i<genome1.NumLink(); ++i) { | ||
ssize_t innovId = genome1.aLinkGenes[i].InnovationId(); | ||
ssize_t idx = genome2.GetLinkIndex(innovId); | ||
if (idx != -1 && genome1.aLinkGenes[i].Enabled()) { | ||
bool linkContainedInGenome2 = (idx != -1); | ||
if (linkContainedInGenome2) { | ||
deltaW += std::abs(genome1.aLinkGenes[i].Weight() - genome2.aLinkGenes[idx].Weight()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If genome2 is disabled, isn't the weight difference, just the weight of genome1? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the NEAT paper, only calculate the difference of matched links. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh! I misunderstood. I think you are right. |
||
++coincident; | ||
} | ||
|
@@ -371,18 +377,28 @@ class NEAT { | |
Species newSpecies = Species(); | ||
newSpecies.AddGenome(genome); | ||
newSpecies.Id(aPopulation.NextSpeciesId()); // NOTICE: changed species id. | ||
newSpecies.StaleAge(0); | ||
aPopulation.AddSpecies(newSpecies); | ||
} | ||
|
||
// Remove stale species. | ||
void RemoveStaleSpecies(Population& population, ssize_t staleAgeThreshold) { | ||
for (ssize_t i=0; i<population.NumSpecies(); ++i) { | ||
if (population.aSpecies[i].StaleAge() > staleAgeThreshold) { | ||
population.RemoveSpecies(i); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function could cause an error, because we can't increase
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! thanks, I revised it. 2016-07-16 10:37 GMT-06:00 Marcus Edel notifications@github.com:
|
||
} | ||
} | ||
} | ||
|
||
// Set adjusted fitness. | ||
void AdjustFitness() { | ||
for (ssize_t i=0; i<aPopulation.NumSpecies(); ++i) { | ||
if (aPopulation.aSpecies[i].SpeciesSize() > 0) { | ||
for (ssize_t j=0; j<aPopulation.aSpecies[i].SpeciesSize(); ++j) { | ||
double fitness = aPopulation.aSpecies[i].aGenomes[j].Fitness(); | ||
ssize_t speciesSize = aPopulation.aSpecies[i].SpeciesSize(); | ||
void AdjustFitness(Population& population) { | ||
for (ssize_t i=0; i<population.NumSpecies(); ++i) { | ||
if (population.aSpecies[i].SpeciesSize() > 0) { | ||
for (ssize_t j=0; j<population.aSpecies[i].SpeciesSize(); ++j) { | ||
double fitness = population.aSpecies[i].aGenomes[j].Fitness(); | ||
ssize_t speciesSize = population.aSpecies[i].SpeciesSize(); | ||
double adjustedFitness = fitness / speciesSize; | ||
aPopulation.aSpecies[i].aGenomes[j].AdjustedFitness(adjustedFitness); | ||
population.aSpecies[i].aGenomes[j].AdjustedFitness(adjustedFitness); | ||
} | ||
} | ||
} | ||
|
@@ -404,12 +420,15 @@ class NEAT { | |
} | ||
|
||
// Evolve. | ||
void Evolve() { | ||
|
||
} | ||
|
||
private: | ||
// Task. | ||
TaskType aTask; | ||
|
||
// Seed genome. It is used for init species. | ||
// Seed genome. It is used for init population. | ||
Genome aSeedGenome; | ||
|
||
// Population to evolve. | ||
|
@@ -442,6 +461,9 @@ class NEAT { | |
// Threshold for judge whether belong to same species. | ||
double aCompatThreshold; | ||
|
||
// Threshold for species stale age. | ||
ssize_t aStaleAgeThreshold; | ||
|
||
}; | ||
|
||
} // namespace ne | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we split the if condition, we could return right after we found the neuron with the specified
innovId
, enabled or not.