Struct neuralneat::Species
source · pub struct Species { /* private fields */ }
Implementations§
source§impl Species
impl Species
sourcepub fn stats(&self) -> SpeciesStats
pub fn stats(&self) -> SpeciesStats
Returns the SpeciesStats at a moment in time. (If you need updated statistics you must call this method each time you need them.)
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of Genomes in the Species.
Examples found in repository?
examples/compare.rs (line 67)
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
println!("Usage: '{} train' to train a new comparer.", args[0]);
println!("Usage: '{} evaluate serialized_genome.json input1 input2' to evaluate with an existing genome.", args[0]);
return;
}
if args[1] == "train" {
// One input node for each input in the TrainingData structure
let input_nodes = 2;
// One output node with the "prediction"
let output_nodes = 1;
// Create a new gene pool with an initial population of genomes
let mut gene_pool = Pool::with_defaults(input_nodes, output_nodes);
let training_data = load_training_data(TRAINING_DATA_STRING, 4, 1);
// These variables are used to keep track of the top performer, so we
// can write it out later.
let mut best_genome: Option<Genome> = None;
let mut best_fitness = 0.0;
// We use a label here to allow us to break out if we find a genome
// with a perfect score before we run through all of the generations.
'outer: for generation in 0..1000 {
println!("Evaluating generation {}", generation + 1);
let total_species = gene_pool.len();
for s in 0..total_species {
let species = &mut gene_pool[s];
let genomes_in_species = species.len();
for g in 0..genomes_in_species {
let genome = &mut species[g];
let mut fitness = 0.0;
for td in &training_data {
// Evaluate the genome using the training data as the
// initial inputs.
genome.evaluate(&td.inputs[0..2].to_vec(), None, None);
// We add this to the existing fitness for the genome
// to ensure that the genomes with the best score across
// all tests will have the highest overall fitness.
fitness += fitness_func(genome.get_outputs()[0], td.expected[0]);
}
// Update the genome with the calculate fitness score.
// (This is important, as this fitness score is needed to
// spawn the next generation correctly.)
genome.update_fitness(fitness);
if fitness > best_fitness {
println!(
"Species {} Genome {} increased best fitness to {}",
s, g, best_fitness
);
best_fitness = fitness;
best_genome = Some(genome.clone());
}
if fitness == PERFECT_SCORE {
println!("Found a perfect genome!");
break 'outer;
}
}
}
// Spawn the next generation.
gene_pool.new_generation();
}
println!("Serializing best genome to winner.json");
serde_json::to_writer(&File::create("winner.json").unwrap(), &best_genome.unwrap())
.unwrap();
} else {
if args.len() < 5 {
println!("Usage: '{} evaluate serialized_genome.json input1 input2' to evaluate with an existing genome.", args[0]);
return;
}
let mut genome: Genome = serde_json::from_reader(File::open(&args[2]).unwrap()).unwrap();
let input1 = args[3]
.parse::<f32>()
.expect("Couldn't parse input1 as f32");
let input2 = args[4]
.parse::<f32>()
.expect("Couldn't parse input2 as f32");
genome.evaluate(&vec![input1, input2], None, None);
if genome.get_outputs()[0] > 0.5 {
println!("Predicted that {} is greater than {}!", input1, input2);
} else {
println!(
"Predicted that {} is equal or less than {}!",
input1, input2
);
}
}
}
More examples
examples/adding.rs (line 46)
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
println!("Usage: '{} train' to train a new comparer.", args[0]);
println!("Usage: '{} evaluate serialized_genome.json input1 input2 input3 input4' to evaluate with an existing genome.", args[0]);
return;
}
if args[1] == "train" {
// One input node for each input in the TrainingData structure
let input_nodes = 4;
// One output node with the "prediction"
let output_nodes = 1;
// Create a new gene pool with an initial population of genomes
let mut gene_pool = Pool::with_defaults(input_nodes, output_nodes);
let training_data = load_training_data(TRAINING_DATA_STRING, 4, 1);
// These variables are used to keep track of the top performer, so we
// can write it out later.
let mut best_genome: Option<Genome> = None;
let mut best_fitness = 0.0;
// We will test genomes from 100 generations
for generation in 0..100 {
println!("Evaluating generation {}", generation + 1);
let total_species = gene_pool.len();
// As genomes diverge in structure and configuration, they will
// be divided into separate species.
for s in 0..total_species {
let species = &mut gene_pool[s];
let genomes_in_species = species.len();
for g in 0..genomes_in_species {
let genome = &mut species[g];
let mut fitness = 0.0;
for td in &training_data {
// Evaluate the genome using the training data as the
// initial inputs.
genome.evaluate(
&td.inputs[0..4].to_vec(),
Some(linear_activation),
Some(linear_activation),
);
// We add this to the existing fitness for the genome
// to ensure that the genomes with the best score across
// all tests will have the highest overall fitness.
fitness += adding_fitness_func(&genome.get_outputs(), &td.expected);
}
// Update the genome with the calculate fitness score.
// (This is important, as this fitness score is needed to
// spawn the next generation correctly.)
genome.update_fitness(fitness);
if fitness > best_fitness {
println!(
"Species {} Genome {} increased best fitness to {}",
s, g, best_fitness
);
best_fitness = fitness;
best_genome = Some(genome.clone());
}
}
}
// Spawn the next generation.
gene_pool.new_generation();
}
println!("Serializing best genome to winner.json");
serde_json::to_writer(&File::create("winner.json").unwrap(), &best_genome.unwrap())
.unwrap();
} else {
if args.len() < 7 {
println!("Usage: '{} evaluate serialized_genome.json input1 input2 input3 input4' to evaluate with an existing genome.", args[0]);
return;
}
let mut genome: Genome = serde_json::from_reader(File::open(&args[2]).unwrap()).unwrap();
let input1 = args[3]
.parse::<f32>()
.expect("Couldn't parse input1 as f32");
let input2 = args[4]
.parse::<f32>()
.expect("Couldn't parse input2 as f32");
let input3 = args[5]
.parse::<f32>()
.expect("Couldn't parse input1 as f32");
let input4 = args[6]
.parse::<f32>()
.expect("Couldn't parse input2 as f32");
// Note that this is the exact same function we used in training
// further up!
genome.evaluate(
&vec![input1, input2, input3, input4],
Some(linear_activation),
Some(linear_activation),
);
println!(
"Sum of inputs is..........{}",
genome.get_outputs()[0] as u32
);
}
}
Trait Implementations§
Auto Trait Implementations§
impl RefUnwindSafe for Species
impl Send for Species
impl Sync for Species
impl Unpin for Species
impl UnwindSafe for Species
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more