pub fn batch_mutate(
amount: usize,
mutation_rate: f64,
network: &NeuralNetwork,
outputs: bool,
) -> Vec<NeuralNetwork>
Expand description
Turns one inputted NeuralNetwork
into amount
number of mutated NeuralNetwork
s mutated by mutation.
If outputs
is true then it will also mutate the output weights. It does this through cloning and
calling NeuralNetwork::mutate(mutation)
so it isn’t any more efficent, its simply here for convenience.
Examples found in repository?
examples/simple_use_case.rs (line 38)
21fn main() {
22 /// This is our target, we will consider `NeuralNetworks` that get closer to this to be learning.
23 const TARGET:f64 = 10.0;
24
25 /// The margin of error for the networks.
26 const MARGIN:f64 = 0.1;
27
28 /// This is the `INPUT` for the networks, the goal being for them to "learn" how to take this number as
29 /// an input and output `TARGET`. When they output a value within `MARGIN` of `TARGET` that `NeuralNetwork`
30 /// will be considered to have reach the goal.
31 const INPUT:f64 = 1.0;
32
33 /// The maximum number of `GENERATIONS` that will be ran, less may be ran if a network gets within `margin` of
34 /// the target before `GENERATIONS` number of generations are ran.
35 const GENERATIONS:usize = 10_000;
36
37 // Create a `Vector` containing all `NeuralNetwork`s in the current generation using `batch_mutate()` and `NeuralNetwork::new()`
38 let mut networks:Vec<NeuralNetwork> = batch_mutate(5,0.25,&mut NeuralNetwork::new(1.0,1,3,1), true);
39
40 // This stores the closest value found by the network, it defaults to negative infinity.
41 let mut closest_value:f64 = f64::NEG_INFINITY;
42
43 // Get the current instant so that it can later be used to time how long it took to finish/fail
44 let time:Instant = Instant::now();
45
46 // For `generation` in `GENERATIONS` perform `batch_run()` and check if the networks are getting closer.
47 for generation in 0..GENERATIONS {
48 // Run the networks using `INPUT` as an input and store the output in `output`
49 let outputs:Vec<Vec<f64>> = batch_run(&mut networks, &vec![INPUT]);
50
51 // The `closest_network` used for creating the next generation.
52 let mut closest_network:usize = 0;
53
54 // Loop through every value in `outputs` checking to see if any of the outputs are within `MARGIN` of `TARGET`
55 // And use a range so that we can track the index of the output easily.
56 for output in 0..outputs.len() {
57 // Since the networks are only outputting a single value we can simply grab the first value of the `Vector`
58 // and check if thats within `MARGIN` of `TARGET` using a range.
59 if (TARGET-MARGIN..=TARGET+MARGIN).contains(&outputs[output][0]) {
60 // If true then print the value found by the network, the network itself, the current generation, and exit from the program.
61 println!("Finished in {:?}!\nGeneration: {:?}\nValue: {:?}\nNetwork: {{\nHiddenLayers: {:?}\nOutputLayer: {:?}\n}}", time.elapsed(),generation, outputs[output][0], networks[output].get_weights(), networks[output].get_output_weights());
62 // Exit code 0 on Linux means no problem, on Windows however this should be 256 but that is outside the scope of this example.
63 std::process::exit(0);
64 } else {
65 // If the `output` was not within `MARGIN` of `TARGET` then check if this value is closer to `TARGET` than the last `closest_value`.
66 // and set `closest_value` to `output` if it is closer.
67 if outputs[output][0] < TARGET && outputs[output][0] > closest_value {
68 closest_value = outputs[output][0];
69 closest_network = output;
70 } else if outputs[output][0] > TARGET && outputs[output][0] < closest_value {
71 closest_value = outputs[output][0];
72 closest_network = output;
73 }
74 }
75 }
76
77 // Set all `networks` to various mutations of the `closest_network`.
78 networks = batch_mutate(5, 0.25, &networks[closest_network], true);
79 }
80
81 // If we managed to get through `GENERATIONS` number of generations without getting within `MARGIN` of `TARGET` then output the `closest_value` we found.
82 println!("Failed to get within `MARGIN` within {:?} number of generations, this is the `closest_value` obtained: {:?}. In {:?}", GENERATIONS, closest_value, time.elapsed());
83}