add perl example code
This commit is contained in:
1 parent
9cd2d19fb9
commit
090961c733
6 files changed
+29813
No files matched your search
@@ -0,0 +1,43 @@
|
||||
{
|
||||
double n_4639, n_4920, n_601, n_1863, n_7065, n_output;
|
||||
n_4639 = 1 / (1 + exp(-1 * 5 * (
|
||||
0.0000000000000000000000000000000000000000000000000000000
|
||||
+ (n_one * -0.7865729571529459507317483257793355733156204223632812500)
|
||||
+ (n_two * 0.8809346930053569835195048653986304998397827148437500000)
|
||||
)));
|
||||
n_4920 = 1 / (1 + exp(-1 * 5 * (
|
||||
0.0000000000000000000000000000000000000000000000000000000
|
||||
+ (n_one * 0.8143148554908640202043557110300753265619277954101562500)
|
||||
+ (n_4639 * 0.7663975023791630425407106486090924590826034545898437500)
|
||||
+ (n_two * -0.2546305433438110221722183723613852635025978088378906250)
|
||||
)));
|
||||
n_601 = 1 / (1 + exp(-1 * 5 * (
|
||||
0.3050293740764479788474261567898793146014213562011718750
|
||||
+ (n_one * -1.7579643686798800406023701725644059479236602783203125000)
|
||||
+ (n_4639 * -0.7117026436492900343111500660597812384366989135742187500)
|
||||
+ (n_4920 * 0.6600543182741239744970584979455452412366867065429687500)
|
||||
+ (n_two * -1.0312303447979600523609633455635048449039459228515625000)
|
||||
)));
|
||||
n_1863 = 1 / (1 + exp(-1 * 5 * (
|
||||
0.0000000000000000000000000000000000000000000000000000000
|
||||
+ (n_one * 0.4067102473422800068547644514183048158884048461914062500)
|
||||
+ (n_4639 * 0.8935708684473929741542974625190254300832748413085937500)
|
||||
+ (n_two * -0.0171564060099979008577886219200081541202962398529052734)
|
||||
+ (n_601 * 0.5111012475277429967235320873442105948925018310546875000)
|
||||
)));
|
||||
n_7065 = 1 / (1 + exp(-1 * 5 * (
|
||||
-0.0614492704162033429038380916153982980176806449890136719
|
||||
+ (n_4639 * 0.7968332799177390013412036751105915755033493041992187500)
|
||||
+ (n_601 * 0.5417244666303689948350097438378725200891494750976562500)
|
||||
)));
|
||||
n_output = 1 / (1 + exp(-1 * 5 * (
|
||||
0.0520650055457407973102945675236696843057870864868164062
|
||||
+ (n_1863 * -3.8456383168042500564354213565820828080177307128906250000)
|
||||
+ (n_one * 10.0000000000000000000000000000000000000000000000000000000)
|
||||
+ (n_4920 * 0.1524713339586759863752973842565552331507205963134765625)
|
||||
+ (n_7065 * -0.2138580237347930124158779108256567269563674926757812500)
|
||||
+ (n_two * 10.0000000000000000000000000000000000000000000000000000000)
|
||||
+ (n_601 * -2.4282240918724999900746297498699277639389038085937500000)
|
||||
)));
|
||||
return n_output;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,176 @@
|
||||
Generations
|
||||
|
||||
# calculate number of offspring allowed per species
|
||||
for each species,
|
||||
identify the average and the min/max fitness values
|
||||
add 1 to all of those numbers (for mathematical simplicity)
|
||||
take the sum of the averages
|
||||
for each species
|
||||
divide the total by the species average
|
||||
multiply that number by the target population size
|
||||
subtract from it that number times stagnant generations count
|
||||
store the floor()ed result as allowed offspring count
|
||||
count the total offspring allocated above
|
||||
if less than target population size
|
||||
allocate remaining to most-fit species
|
||||
for each species
|
||||
multiply offspring by 10% to get the 'elitism' offspring count
|
||||
if elitism less than 2, set it at 2
|
||||
if this is more than the total offspring allowed, species dies
|
||||
subtract the elitism count from the allowed count to get remaining
|
||||
allocate 50% to be created via crossover
|
||||
50% will include only some weights from less fit parent
|
||||
50% will include one additional structural element, too
|
||||
and the other 50% via mutation
|
||||
all of which are weight adjusted by up to 10% per weight
|
||||
65% of which are by weight adjustment only
|
||||
20% add a new connection
|
||||
10% split a current connection / add node
|
||||
5% delete an existing connection
|
||||
|
||||
# identify rankings within species
|
||||
for each species,
|
||||
make a list of members sorted by fitness, descending
|
||||
|
||||
# identify dominance within species
|
||||
# used to determine breeding priority
|
||||
for each species
|
||||
calculate sum of fitness values of all members of species
|
||||
for each member of species
|
||||
calculate fitness / sum of fitness
|
||||
|
||||
# elitism
|
||||
take the first N networks from the sorted species member list
|
||||
copy each one, verbatim, to the next generation
|
||||
|
||||
# mutation
|
||||
for each species
|
||||
calculate 'remaining' as number of mutation offspring allowed
|
||||
for each member of the species, in fitness order (descending)
|
||||
multiply its dominance value times allowed offspring
|
||||
round() the number to the nearest integer.
|
||||
if number is 0, round up to 1
|
||||
if number is greater than remaining, reduce to remaining
|
||||
while this number is > 0
|
||||
create a new mutation of this organism
|
||||
and copy it to the next generation
|
||||
decrement the number, and the 'remaining' number
|
||||
if 'remaining' is 0, exit loop
|
||||
|
||||
# to mutate a single organism
|
||||
copy the organism to a new structure
|
||||
give the new one a new ID
|
||||
for each connection
|
||||
assign a new weight that is +/- up to 10% of current value
|
||||
save random() number
|
||||
if random < delete threshold, delete a connection
|
||||
else if < split threshold, split a connection
|
||||
else if < add threshold, add a connection
|
||||
|
||||
# crossover
|
||||
for each species
|
||||
calculate 'remaining' as number of offspring allowed, times 2
|
||||
for each member of the species, in fitness order (descending)
|
||||
multiply its dominance value times allowed offspring
|
||||
round() the number to the nearest integer.
|
||||
if number is 0, round up to 1
|
||||
if number is greater than remaining, reduce to remaining
|
||||
push this member onto a list of breeders <number> times
|
||||
randomize the list of breeders
|
||||
while the list of breeders is not empty
|
||||
pop the first entry off the front of the list
|
||||
search the list for the first entry that is not the same
|
||||
while the first entry is the same as the other entry
|
||||
pop it off and push it on to the end
|
||||
crossover these two to make a new one
|
||||
|
||||
# to crossover two specimens
|
||||
copy the more fit parent's genome
|
||||
for each connection in the more fit parent's genome
|
||||
if a match occurs in less fit parent
|
||||
50/50 chance of using the weight from the less fit parent
|
||||
50/50 chance of selecting ONE structural element from the less
|
||||
fit parent and copying it into the new genome
|
||||
move the newly created offspring into the next generation
|
||||
|
||||
# speciation
|
||||
-initially, each member belongs to the species of its parents.
|
||||
-if two organisms have the same structure, they belong in the same
|
||||
species, regardless of who their parents were.
|
||||
|
||||
for every member of the population
|
||||
compose a string representing the structure of the network
|
||||
store a hash entry with structure as key
|
||||
store in the record
|
||||
list of members
|
||||
highest fitness value of any member
|
||||
total fitness of all members
|
||||
count of members
|
||||
for each structure
|
||||
calculate average fitness
|
||||
sort the structures by highest average fitness
|
||||
start with an empty species list
|
||||
for each structure, while species count < max
|
||||
form a new species with that structure as basis
|
||||
sort the members by fitness, highest first
|
||||
for the rest of the structures
|
||||
identify the structure(s) that are most compatible with this one
|
||||
if only one, add all members to that species
|
||||
otherwise, assign each member to the compatible structure whose
|
||||
average is closest to that of the new member
|
||||
and update the average for that species
|
||||
for each new species
|
||||
build a list of records with:
|
||||
new species (pointer),
|
||||
old species name or proposed new name,
|
||||
number of members from that old species in this new species
|
||||
average fitness of those members
|
||||
average fitness of new species
|
||||
sort that master list by
|
||||
average fitness of members voting for a particular assignment
|
||||
average fitness of new species
|
||||
number of members voting for name
|
||||
go through the list of species name votes
|
||||
if the proposed name is already taken, reject the vote
|
||||
if the proposed species has already been given a name, reject
|
||||
otherwise, assign that name to that species
|
||||
go through the list of species, in fitness order, descending
|
||||
if the species doesn't have a name, give it a new one
|
||||
give every member the name of their new species, if different
|
||||
|
||||
|
||||
|
||||
offspring priority per topology
|
||||
1st place network copied verbatim - elite
|
||||
1st elite with randomly 'adjusted' weights
|
||||
1st elite with 'average' crossover with 2nd place
|
||||
1st elite with 'random' crossover with 2nd place
|
||||
2nd place network copied verbatim
|
||||
2nd elite with randomly adjusted weights
|
||||
1st elite with 'average' crossover with random other
|
||||
2nd elite with 'average' crossover with random other
|
||||
1st elite with 'random' crossover with random other
|
||||
2nd elite with 'random' crossover with random other
|
||||
all new weights
|
||||
|
||||
if after allocating offspring, there remain open slots
|
||||
one of
|
||||
75% - add a new connection
|
||||
20% - split a node
|
||||
5% - delete a connection
|
||||
|
||||
as topologies optimize, their improvement slows
|
||||
when it ceases to improve, the investment in it decreases
|
||||
stagnation penalty incremented
|
||||
when an improvement is made, cut the penalty in half
|
||||
when the investment drops below threshold, the elite is 'archived'
|
||||
and further investment in it ceases
|
||||
if a mutation produces this same topology again,
|
||||
treat the event as an improvement
|
||||
cut stagnation penalty in half
|
||||
include archived elite and new member as gene pool
|
||||
|
||||
as the investment in a topology decreases,
|
||||
the more resources are available for more promising avenues
|
||||
|
||||
instead of 'species' we will call it 'topology'
|
||||
@@ -0,0 +1,68 @@
|
||||
$data = {
|
||||
# settings controlling the operation of the experiment
|
||||
'settings' => {
|
||||
'experiment' => 'xor',
|
||||
'population' => 100, # desired number of networks
|
||||
'limit' => 10, # max offspring per topology
|
||||
'penalty' => 10, # max investment/stagnant topology
|
||||
'retest-elites' => 0,
|
||||
'save-epochs' => 0,
|
||||
'activation' => 'perl',
|
||||
'max-weight' => 10,
|
||||
'gain' => 5,
|
||||
'debug' => 0,
|
||||
'topology-limit' => 50,
|
||||
# 'allow-recurrent' => 1,
|
||||
},
|
||||
# the state of the experiment
|
||||
'save' => {
|
||||
'unique-id' => 0, # innovation id
|
||||
'generation' => 0, # which generation this is
|
||||
'max-fitness' => 0,
|
||||
'max-weight' => 0,
|
||||
'min-weight' => 0,
|
||||
},
|
||||
# nodes listed by the unique node-id
|
||||
'nodes' => {
|
||||
'one' => {
|
||||
'id' => 'one', # redundant, but useful
|
||||
'type' => 'input',
|
||||
},
|
||||
'two' => {
|
||||
'id' => 'two', # redundant, but useful
|
||||
'type' => 'input',
|
||||
},
|
||||
'bias' => {
|
||||
'id' => 'bias', # redundant, but useful
|
||||
'type' => 'input',
|
||||
},
|
||||
'output' => {
|
||||
'id' => 'output', # redundant, but useful
|
||||
'type' => 'output',
|
||||
'function' => 'sigmoid',
|
||||
'gain' => '5',
|
||||
},
|
||||
},
|
||||
# one entry per network in the population
|
||||
'population' => {
|
||||
'initial' => {
|
||||
'id' => 'initial',
|
||||
'fitness' => 0,
|
||||
'elite' => 0,
|
||||
'nodes' => {
|
||||
'one' => {},
|
||||
'two' => {},
|
||||
'bias' => {},
|
||||
'output' => {},
|
||||
},
|
||||
},
|
||||
},
|
||||
# a record of all the topologies in the population
|
||||
# this tracks statistics about each one
|
||||
'topologies' => {},
|
||||
# for all nodes formed by splitting connections, the
|
||||
# mapping between the nodes connected and the node created
|
||||
# exists primarily for search-speed
|
||||
# can be removed before saving,
|
||||
'node-lookup' => {},
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use neat;
|
||||
|
||||
my $neat = new neat( "start.xor.pl" );
|
||||
|
||||
my $FINISHED = 0;
|
||||
|
||||
$SIG{INT} = sub { $FINISHED = 1 };
|
||||
|
||||
my $inputs = [
|
||||
{ 'bias' => 1, 'one' => 0, 'two' => 0, 'output' => 0, 'expected' => 0 },
|
||||
{ 'bias' => 1, 'one' => 1, 'two' => 0, 'output' => 0, 'expected' => 1 },
|
||||
{ 'bias' => 1, 'one' => 0, 'two' => 1, 'output' => 0, 'expected' => 1 },
|
||||
{ 'bias' => 1, 'one' => 1, 'two' => 1, 'output' => 0, 'expected' => 0 },
|
||||
];
|
||||
|
||||
sub EvaluateXOR
|
||||
{
|
||||
my $net = shift;
|
||||
|
||||
# why retest someone who hasn't changed?
|
||||
return $net->{'fitness'}
|
||||
if ( $net->{'elite'} );
|
||||
|
||||
my $total = 0;
|
||||
my $values;
|
||||
my $average;
|
||||
my $i;
|
||||
my $difference;
|
||||
$total = 0;
|
||||
for ( $i = 0 ; $i < 4 ; $i++ )
|
||||
{
|
||||
$values = Copy( $inputs->[$i] );
|
||||
$neat->Activate( $net, $values );
|
||||
# printf( " %d%d=%lf", $values->{'one'}, $values->{'two'},
|
||||
# $values->{'output'} );
|
||||
$difference = abs( $values->{'output'} - $values->{'expected'} );
|
||||
$total += $difference;
|
||||
}
|
||||
# printf( " [1m%lf[0m\n", 1 - $average );
|
||||
my $fitness = 1 - ( $total / 4 );
|
||||
$FINISHED = 1 if ( $total < 0.04 ); # close enough!
|
||||
return $fitness;
|
||||
}
|
||||
|
||||
$neat->EvaluationFunction( \&EvaluateXOR );
|
||||
|
||||
# initial generation
|
||||
$neat->EvaluateAll();
|
||||
|
||||
my $count = 0;
|
||||
while ( ! $FINISHED )
|
||||
{
|
||||
$neat->Epoch();
|
||||
printf( "%s\n", $neat->Stats() );
|
||||
$neat->EvaluateAll();
|
||||
#$FINISHED = 1 if ( ++$count == 100 );
|
||||
}
|
||||
|
||||
$neat->Champions();
|
||||
$neat->Save( "xor.final.pl" );
|
||||
|
||||
my $champion = $neat->ChampionNetwork();
|
||||
my $code = $neat->ActivationFunction_C_PartialEval( $champion,
|
||||
{ bias => 1 } );
|
||||
open INDENT, "|indent -st > activate.xor.c";
|
||||
print INDENT $code;
|
||||
close INDENT;
|
||||
#system "cat activate.xor.c";
|
||||
Reference in new issue
Block a user