def test_generation(self): genome1 = create_genome_structure( 5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) genome2 = create_genome_structure( 5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) agent1 = Agent(1, genome1) agent2 = Agent(2, genome2) members = [agent1, agent2] species = [ Species(1, genome2, [agent1, agent2], max_species_fitness=10, generation_max_species_fitness=3, adjust_fitness=8) ] seed = 10 generation = Generation(2, seed, members, species) self.assertEqual(2, generation.number) self.assertEqual(species, generation.species_list) self.assertEqual(members, generation.agents) self.assertEqual(seed, generation.seed)
def test_mutate_add_connection(self): config = NeatConfig(connection_initial_min_weight=-3, connection_initial_max_weight=3, allow_recurrent_connections=True, probability_mutate_add_connection=0.4, mutate_connection_tries=2) self.genome.connections = [] # Random values for with seed 1 # rnd.uniform(0, 1) = 0.417022004702574 -> No mutation _, conn = mutate_add_connection(self.genome, self.rnd, self.inn_generator, config) self.assertEqual(0, len(self.genome.connections)) self.assertIsNone(conn) # Set higher config value, reset random config.probability_mutate_add_connection = 1 self.rnd = np.random.RandomState(1) # Random values for with seed 1 # rnd.uniform(0, 1) = 0.417022004702574 -> Mutate # rnd.randint(low=0,high=4) = 0 # rnd.randint(low=0,high=2) = 0 # rnd.uniform(low=-3, high=3) = -2.9993137510959307 _, new_con1 = mutate_add_connection(self.genome, self.rnd, self.inn_generator, config) self.assertEqual(1, len(self.genome.connections)) self.assertEqual(4, new_con1.innovation_number) self.assertEqual(self.node_input1.innovation_number, new_con1.input_node) self.assertEqual(self.node_hidden1.innovation_number, new_con1.output_node) self.assertAlmostEqual(-2.9993137510959307, new_con1.weight, delta=0.0000000001) # Random values # rnd.uniform(0, 1) = 0.00011437481734488664 -> Mutate # rnd.randint(low=0,high=4) = 3 # rnd.randint(low=0,high=2) = 0 # rnd.uniform(low=-3, high=3) = -2.445968431387213 _, new_con2 = mutate_add_connection(self.genome, self.rnd, self.inn_generator, config) self.assertEqual(2, len(self.genome.connections)) self.assertEqual(5, new_con2.innovation_number) self.assertEqual(self.node_output1.innovation_number, new_con2.input_node) self.assertEqual(self.node_hidden1.innovation_number, new_con2.output_node) self.assertAlmostEqual(-2.445968431387213, new_con2.weight, delta=0.0000000001) # Brute force - check if all nodes are connected after 1000 tries for _ in range(1000): _, _ = mutate_add_connection(self.genome, self.rnd, self.inn_generator, config) # Maximum connections with recurrent self.assertEqual(8, len(self.genome.connections)) # Set recurrent to false config.allow_recurrent = False genome_feed_forward = Genome(1, self.nodes, connections=[]) for _ in range(1000): genome_feed_forward, _ = mutate_add_connection(genome_feed_forward, self.rnd, self.inn_generator, config) # Maximum connections with recurrent=false self.assertEqual(5, len(genome_feed_forward.connections))
def test_mutate_add_node(self): config = NeatConfig(probability_mutate_add_node=0.1, bias_initial_min=-3, bias_initial_max=3) genome, node, con1, con2 = mutate_add_node(self.genome, self.rnd, self.inn_generator, config) # Should not mutate self.assertEqual(self.genome, genome) self.assertIsNone(node) self.assertIsNone(con1) self.assertIsNone(con2) # Set probability high, and reset randomState config.probability_mutate_add_node = 1 self.rnd = np.random.RandomState(1) self.node_output1.activation_function = modified_sigmoid_activation # Random values for with seed 1 # rnd.uniform(0, 1) = 0.417022004702574 -> Mutate # rnd.randint(low=0,high=4) = 0 -> connection1 # rnd.uniform(0, 1) = -0.9325573593386588 -> Take activation function of out node # rnd.uniform(-3, 3) = -2.23125331242386 -> Bias for new node node_size_before = len(self.genome.nodes) connections_size_before = len(self.connections) genome, node, con1, con2 = mutate_add_node(self.genome, self.rnd, self.inn_generator, config) # Check if 1 node and 2 connections were added self.assertEqual(genome, self.genome) self.assertEqual(node_size_before + 1, len(genome.nodes)) self.assertEqual(connections_size_before + 2, len(genome.connections)) # Check if old connection was disabled self.assertFalse(self.connection1.enabled) # Check the generated node self.assertEqual(NodeType.HIDDEN, node.node_type) self.assertEqual(modified_sigmoid_activation, node.activation_function) self.assertEqual(4, node.innovation_number) self.assertAlmostEqual(-2.23125331242386, node.bias, delta=0.0000000001) self.assertEqual(0.5, node.x_position) # Check 1 connection self.assertEqual(4, con1.innovation_number) self.assertEqual(self.connection1.input_node, con1.input_node) self.assertEqual(node.innovation_number, con1.output_node) self.assertEqual(1, con1.weight) self.assertTrue(con1.enabled) # Check 2 connection self.assertEqual(5, con2.innovation_number) self.assertEqual(node.innovation_number, con2.input_node) self.assertEqual(self.connection1.output_node, con2.output_node) self.assertEqual(self.connection1.weight, con2.weight) self.assertTrue(con2.enabled)
def setUp(self) -> None: self.optimizer_single = NeatOptimizerSingleCore() self.callback = MockCallback() self.challenge = MockChallenge() self.optimizer_single.register_callback(self.callback) self.config = NeatConfig(population_size=150)
def test_create_offspring_pairs(self): agent_id_generator = AgentIDGeneratorSingleCore() config = NeatConfig() rnd = np.random.RandomState(1) # First 10 random values # rnd.randint(3) = 1 # rnd.randint(3) = 0 # rnd.randint(3) = 0 # rnd.randint(3) = 1 # rnd.randint(3) = 1 # rnd.randint(3) = 0 # rnd.randint(3) = 0 # rnd.randint(3) = 1 tuple_list = ss.create_offspring_pairs(self.species1, 4, agent_id_generator, self.generation, rnd, config) # Test tuples agent_id_generator = AgentIDGeneratorSingleCore() self.assertEqual(4, len(tuple_list)) self.assertEqual((self.agent2.id, self.agent1.id, agent_id_generator.get_agent_id()), tuple_list[0]) self.assertEqual((self.agent1.id, self.agent2.id, agent_id_generator.get_agent_id()), tuple_list[1]) self.assertEqual((self.agent2.id, self.agent1.id, agent_id_generator.get_agent_id()), tuple_list[2]) self.assertEqual((self.agent1.id, self.agent2.id, agent_id_generator.get_agent_id()), tuple_list[3])
def test_config(self): config = NeatConfig(population_size=200, connection_min_weight=-10, connection_max_weight=10) self.assertEqual(200, config.population_size) self.assertEqual(-10, config.connection_min_weight) self.assertEqual(10, config.connection_max_weight)
def test_species(self): genome1 = create_genome_structure(5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) genome2 = create_genome_structure(5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) members = [Agent(1, genome1)] species = Species(1, genome2, members, max_species_fitness=10, generation_max_species_fitness=3, adjust_fitness=8) self.assertEqual(genome2, species.representative) self.assertEqual(8, species.adjusted_fitness) self.assertEqual(10, species.max_species_fitness) self.assertEqual(3, species.generation_max_species_fitness) self.assertEqual(members, species.members) self.assertEqual(1, species.id_)
def test_set_new_genome_bias(self): config = NeatConfig(bias_initial_min=-3, bias_initial_max=3) modified_genome = set_new_genome_bias(self.genome, self.rnd, config) # Input nodes should be skipped self.assertEqual(0, modified_genome.nodes[0].bias) self.assertEqual(0, modified_genome.nodes[1].bias) self.assertAlmostEqual(-0.4978679717845562, modified_genome.nodes[2].bias, delta=0.0000001) self.assertAlmostEqual(1.3219469606529488, modified_genome.nodes[3].bias, delta=0.0000001)
def test_cross_over(self): node1_1 = Node(1, NodeType.INPUT, 1.1, step_activation, 0) node1_2 = Node(2, NodeType.INPUT, 1.2, step_activation, 0) node1_5 = Node(5, NodeType.OUTPUT, 1.5, step_activation, 1) node1_7 = Node(7, NodeType.HIDDEN, 1.7, step_activation, 0.5) nodes1 = [node1_1, node1_2, node1_5, node1_7] node2_1 = Node(1, NodeType.INPUT, 2.1, modified_sigmoid_activation, 0) node2_2 = Node(2, NodeType.INPUT, 2.2, modified_sigmoid_activation, 0) node2_4 = Node(4, NodeType.OUTPUT, 2.4, modified_sigmoid_activation, 1) node2_7 = Node(7, NodeType.HIDDEN, 2.7, modified_sigmoid_activation, 0.5) node2_8 = Node(8, NodeType.HIDDEN, 2.8, modified_sigmoid_activation, 0.5) nodes2 = [node2_1, node2_2, node2_4, node2_7, node2_8] connection1_1 = Connection(innovation_number=1, input_node=1, output_node=2, weight=1.2, enabled=False) connection1_2 = Connection(innovation_number=2, input_node=1, output_node=2, weight=1.2, enabled=True) connection1_4 = Connection(innovation_number=4, input_node=1, output_node=2, weight=1.2, enabled=True) connection1_7 = Connection(innovation_number=7, input_node=1, output_node=2, weight=1.2, enabled=False) connections1 = [connection1_1, connection1_2, connection1_4, connection1_7] connection2_1 = Connection(innovation_number=1, input_node=1, output_node=2, weight=1.2, enabled=False) connection2_2 = Connection(innovation_number=2, input_node=1, output_node=2, weight=1.2, enabled=True) connection2_3 = Connection(innovation_number=3, input_node=1, output_node=2, weight=1.2, enabled=True) connection2_5 = Connection(innovation_number=5, input_node=1, output_node=2, weight=1.2, enabled=True) connection2_7 = Connection(innovation_number=7, input_node=1, output_node=2, weight=1.2, enabled=False) connections2 = [connection2_1, connection2_2, connection2_3, connection2_5, connection2_7] more_fit_parent = Genome(1, nodes1, connections1) less_fit_parent = Genome(2, nodes2, connections2) config = NeatConfig(probability_enable_gene=0.31) # Random values: # 1 rnd.uniform(0, 1) = 0.417022004702574 -> First node (node1_1) # 1 rnd.uniform(0, 1) = 0.7203244934421581 -> Second node(node2_2) # 1 rnd.uniform(0, 1) = 0.00011437481734488664 -> First node (node7_1) # 1 rnd.uniform(0, 1) = 0.30233257263183977 -> Select first connection (connection1_1) # 1 rnd.uniform(0, 1) = 0.14675589081711304 -> Re-enable connection (connection1_1) # 1 rnd.uniform(0, 1) = 0.0923385947687978 -> Select first connection (connection1_2) # 1 rnd.uniform(0, 1) = 0.1862602113776709 -> Select first connection (connection1_7) # 1 rnd.uniform(0, 1) = 0.34556072704304774 -> Re-enable connection False (connection1_7) child_nodes, child_connections = cross_over(more_fit_parent, less_fit_parent, self.rnd, config) # Check nodes self.assertEqual(4, len(child_nodes)) self.compare_nodes(node1_1, child_nodes[0]) self.compare_nodes(node2_2, child_nodes[1]) self.compare_nodes(node1_5, child_nodes[2]) self.compare_nodes(node1_7, child_nodes[3]) # Check connections self.assertEqual(4, len(child_connections)) connection1_1.enabled = True self.compare_connections(connection1_1, child_connections[0]) self.compare_connections(connection1_2, child_connections[1]) self.compare_connections(connection1_4, child_connections[2]) self.compare_connections(connection1_7, child_connections[3])
def evaluate(self, optimizer: NeatOptimizer, seed: int = None, **kwargs): time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") # Reporter for fitness values self.fitness_reporter = FitnessReporter() self.species_reporter = SpeciesReporter() self.time_reporter = TimeReporter() self.check_point_reporter = CheckPointReporter( "/tmp/breakout/{}/".format(time), "breakout", lambda _: True) # Register this class as callback optimizer.register_callback(self) optimizer.register_reporters(self.time_reporter, self.species_reporter, self.fitness_reporter, self.check_point_reporter) # Config config = NeatConfig(allow_recurrent_connections=False, population_size=150, compatibility_threshold=3, weight_mutation_type="normal", weight_mutation_normal_sigma=1.3, connection_initial_min_weight=-1, connection_initial_max_weight=1, connection_min_weight=-15, connection_max_weight=15, bias_mutation_type="normal", bias_mutation_normal_sigma=1.3, bias_initial_min=-1, bias_initial_max=1, bias_min=-15, bias_max=15, compatibility_factor_disjoint_genes=1.0, compatibility_factor_matching_genes=0.5, probability_mutate_add_connection=0.5, probability_mutate_add_node=0.2, compatibility_genome_size_threshold=0) # Progressbar size self.progressbar_max = config.population_size # Create random seed, if none is specified if seed is None: seed = np.random.RandomState().randint(2**24) logger.info("Used Seed: {}".format(seed)) # Create the challenge self.challenge = BreakoutChallenge() # Start evaluation optimizer.evaluate(amount_input_nodes=128, amount_output_nodes=2, activation_function=sigmoid_activation, challenge=self.challenge, config=config, seed=seed)
def setUp(self) -> None: self.config = NeatConfig(population_size=10) self.generation = gs.create_initial_generation( 3, 2, step_activation, InnovationNumberGeneratorSingleCore(), SpeciesIDGeneratorSingleCore(), AgentIDGeneratorSingleCore(), self.config, 1) for i, agent in zip(range(len(self.generation.agents)), self.generation.agents): agent.fitness = i
def test_create_initial_generation(self): config = NeatConfig(population_size=150, connection_max_weight=10, connection_min_weight=-10) generation1 = gs.create_initial_generation( 10, 3, step_activation, InnovationNumberGeneratorSingleCore(), SpeciesIDGeneratorSingleCore(), AgentIDGeneratorSingleCore(), config, seed=1) generation2 = gs.create_initial_generation( 10, 3, step_activation, InnovationNumberGeneratorSingleCore(), SpeciesIDGeneratorSingleCore(), AgentIDGeneratorSingleCore(), config, seed=1) self.assertEqual(0, generation1.number) self.assertEqual(0, generation2.number) self.assertEqual(150, len(generation1.agents)) # Compare if generations and generated genomes are the same for agent1, agent2 in zip(generation1.agents, generation2.agents): self.assertEqual(agent1.genome.seed, agent2.genome.seed) for node1, node2, i in zip(agent1.genome.nodes, agent2.genome.nodes, range(len(agent1.genome.nodes))): self.assertEqual(node1.innovation_number, node2.innovation_number) self.assertEqual(i, node1.innovation_number) self.assertEqual(node1.bias, node2.bias) if node1.node_type != NodeType.INPUT: self.assertNotAlmostEqual(0, node1.bias, delta=0.000000000001) # Check connection weights for connection1, connection2, i in zip( agent1.genome.connections, agent2.genome.connections, range(len(agent1.genome.connections))): self.assertEqual(connection1.weight, connection2.weight) self.assertEqual(connection1.innovation_number, connection2.innovation_number) self.assertEqual(i, connection1.innovation_number) self.assertNotAlmostEqual(0, connection1.weight, delta=0.000000000001)
def test_agent(self): genome = create_genome_structure(5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) agent = Agent(1, genome) self.assertEqual(1, agent.id) self.assertEqual(genome, agent.genome) self.assertIsNone(agent.neural_network) self.assertEqual(0, agent.fitness) self.assertEqual(0, agent.adjusted_fitness)
def setUp(self) -> None: self.config = NeatConfig(population_size=7) self.inno_num_generator = InnovationNumberGeneratorSingleCore() self.species_id_generator = SpeciesIDGeneratorSingleCore() self.agent_id_generator = AgentIDGeneratorSingleCore() self.genome1 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome2 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome3 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome4 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome5 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome6 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome7 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.agent1 = Agent(1, self.genome1) self.agent1.fitness = 1 self.agent2 = Agent(2, self.genome2) self.agent2.fitness = 2 self.agent3 = Agent(3, self.genome3) self.agent3.fitness = 3 self.agent4 = Agent(4, self.genome4) self.agent4.fitness = 4 self.agent5 = Agent(5, self.genome5) self.agent5.fitness = 5 self.agent6 = Agent(6, self.genome6) self.agent6.fitness = 6 self.agent7 = Agent(7, self.genome7) self.agent7.fitness = 7 self.species1 = Species( self.species_id_generator.get_species_id(), self.agent1.genome, [self.agent1, self.agent1, self.agent2, self.agent3]) self.species2 = Species(self.species_id_generator.get_species_id(), self.agent4.genome, [self.agent4, self.agent5]) self.species3 = Species(self.species_id_generator.get_species_id(), self.agent6.genome, [self.agent6, self.agent7])
def test_set_new_genome_weights(self): original_genome = Genome(123, [Node(1, NodeType.INPUT, 1.1, step_activation, 0)], [Connection(124, 10, 20, 1.2, True), Connection("124124", 12, 22, 0.8, False)]) config = NeatConfig(connection_initial_min_weight=-10, connection_initial_max_weight=10) new_genome = set_new_genome_weights(original_genome, np.random.RandomState(2), config=config) # First 3 random values # 1. -1.2801019571599248 # 2. -9.481475363442174 # 3. -1.293552147634463 self.assertAlmostEqual(-1.2801019571599248, new_genome.connections[0].weight, delta=0.00000001) self.assertAlmostEqual(-9.481475363442174, new_genome.connections[1].weight, delta=0.00000001)
def test_create_initial_generation_genome(self): genome = Genome(20, [ Node("abc", NodeType.INPUT, 0.3, step_activation, 0), Node("def", NodeType.OUTPUT, 0.4, step_activation, 1) ], [ Connection("x", "abc", "def", 1.0, True), Connection("y", "def", "abc", -5, True) ]) generation = gs.create_initial_generation_genome( genome, InnovationNumberGeneratorSingleCore(), SpeciesIDGeneratorSingleCore(), AgentIDGeneratorSingleCore(), NeatConfig(population_size=3), seed=1) self.assertEqual(3, len(generation.agents)) self.assertEqual(0, generation.number) self.assertEqual(1, len(generation.species_list)) self.assertEqual(3, len(generation.species_list[0].members)) self.assertEqual(1, generation.seed) # First three random numbers # 1 - 12710949 # 2 - 4686059 # 3 - 6762380 self.assertEqual(12710949, generation.agents[0].genome.seed) self.assertEqual(4686059, generation.agents[1].genome.seed) self.assertEqual(6762380, generation.agents[2].genome.seed) for node1, node2, node3, i in zip(generation.agents[0].genome.nodes, generation.agents[1].genome.nodes, generation.agents[2].genome.nodes, range(3)): self.assertEqual(node1.innovation_number, node2.innovation_number) self.assertEqual(node2.innovation_number, node3.innovation_number) self.assertEqual(node3.innovation_number, i) for connection1, connection2, connection3, i in zip( generation.agents[0].genome.connections, generation.agents[1].genome.connections, generation.agents[2].genome.connections, range(3)): self.assertEqual(connection1.innovation_number, connection2.innovation_number) self.assertEqual(connection2.innovation_number, connection3.innovation_number) self.assertEqual(connection3.innovation_number, i)
def test_create_genome_structure(self): config = NeatConfig() input_nodes = 100 output_nodes = 50 generated_structure = gs.create_genome_structure( amount_input_nodes=input_nodes, amount_output_nodes=output_nodes, activation_function=step_activation, config=config, generator=InnovationNumberGeneratorSingleCore()) self.assertEqual(input_nodes + output_nodes, len(generated_structure.nodes)) self.assertEqual(input_nodes * output_nodes, len(generated_structure.connections)) for node, i in zip(generated_structure.nodes, range(input_nodes + output_nodes)): self.assertEqual(i, node.innovation_number) self.assertEqual(step_activation, node.activation_function) self.assertEqual(0, node.bias) if i < input_nodes: self.assertEqual(NodeType.INPUT, node.node_type, msg="Value i={}".format(i)) self.assertEqual(0, node.x_position) else: self.assertEqual(NodeType.OUTPUT, node.node_type, msg="Value i={}".format(i)) self.assertEqual(1, node.x_position) for connection, i in zip(generated_structure.connections, range(input_nodes * output_nodes)): self.assertEqual(i, connection.innovation_number) self.assertEqual(0, connection.weight)
def test_mutate_weights_uniform(self): config = NeatConfig(probability_weight_mutation=0.6, probability_random_weight_mutation=0.5, connection_min_weight=-4, connection_max_weight=4, connection_initial_min_weight=-3, connection_initial_max_weight=3, weight_mutation_type="uniform", weight_mutation_uniform_max_change=1) # Random values for with seed 1 # First connection # rnd.uniform(0, 1) = 0.417022004702574 -> Mutate yes # rnd.uniform(0, 1) = 0.7203244934421581 -> Perturb weight # rnd.uniform(-1, 1) = -0.9997712503653102 -> Value to be subtracted (and clamped) # Second connection # rnd.uniform(0, 1) = 0.30233257263183977 -> Mutate yes # rnd.uniform(0, 1) = 0.14675589081711304 -> Random weight # rnd.uniform(-3, 3) = -2.445968431387213 -> new random weight # Third connection # rnd.uniform(0, 1) = 0.1862602113776709 -> Mutate yes # rnd.uniform(0, 1) = 0.34556072704304774 -> Random weight # rnd.uniform(-3, 3) = -0.6193951546159804 -> new random weight # Fourth connection # rnd.uniform(0, 1) = 0.538816734003357 -> Mutate yes # rnd.uniform(0, 1) = 0.4191945144032948 -> Random weight # rnd.uniform(-3, 3) = 1.1113170023805568 -> new random weight con1_expected_weight = self.connection1.weight - 0.9997712503653102 new_genome = mutate_weights(self.genome, self.rnd, config) # Same object self.assertEqual(self.genome, new_genome) self.assertAlmostEqual(con1_expected_weight, self.connection1.weight, delta=0.000000000001) self.assertAlmostEqual(-2.445968431387213, self.connection2.weight, delta=0.000000000001) self.assertAlmostEqual(-0.6193951546159804, self.connection3.weight, delta=0.000000000001) self.assertAlmostEqual(1.1113170023805568, self.connection4.weight, delta=0.000000000001)
def test_mutate_weights_normal(self): config = NeatConfig(probability_weight_mutation=0.6, probability_random_weight_mutation=0.5, connection_min_weight=-3, connection_max_weight=3, weight_mutation_type="normal", weight_mutation_normal_sigma=0.5) # Random values for with seed 1 # First connection # rnd.uniform(0, 1) = 0.417022004702574 -> Mutate yes # rnd.uniform(0, 1) = 0.7203244934421581 -> Perturb weight # rnd.normal(scale=0.5) = -0.26408587613172785 -> Value to be subtracted (and clamped) # Second connection # rnd.uniform(0, 1) = 0.39676747423066994 -> Mutate yes # rnd.uniform(0, 1) = 0.538816734003357 -> Perturb weight # rnd.normal(scale=0.5) = -0.5364843110780853 -> Value to be subtracted (and clamped) # Third connection # rnd.uniform(0, 1) = 0.4191945144032948 -> Mutate yes # rnd.uniform(0, 1) = 0.6852195003967595 -> Perturb weight # rnd.normal(scale=0.5) = 0.15951954802854929 -> Value to be added (and clamped) # Fourth connection # rnd.uniform(0, 1) = 0.027387593197926163 -> Mutate yes # rnd.uniform(0, 1) = 0.6704675101784022 -> Perturb weight # rnd.normal(scale=0.5) = -0.12468518773870504 -> Value to be subtracted (and clamped) connection1_new_weight = self.connection1.weight - 0.26408587613172785 connection2_new_weight = self.connection2.weight - 0.5364843110780853 connection3_new_weight = self.connection3.weight + 0.15951954802854929 connection4_new_weight = self.connection4.weight - 0.12468518773870504 new_genome = mutate_weights(self.genome, self.rnd, config) # Same object self.assertEqual(self.genome, new_genome) self.assertAlmostEqual(connection1_new_weight, self.connection1.weight, delta=0.000000000001) self.assertAlmostEqual(connection2_new_weight, self.connection2.weight, delta=0.000000000001) self.assertAlmostEqual(connection3_new_weight, self.connection3.weight, delta=0.000000000001) self.assertAlmostEqual(connection4_new_weight, self.connection4.weight, delta=0.000000000001)
def test_mutate_bias_uniform(self): config = NeatConfig(probability_bias_mutation=0.6, bias_max=3, bias_min=-3, bias_initial_min=-2, bias_initial_max=2, probability_random_bias_mutation=0.5, bias_mutation_uniform_max_change=1, bias_mutation_type="uniform") # rnd.uniform(0, 1) = 0.417022004702574 -> Mutate # rnd.uniform(0, 1) = 0.7203244934421581 -> Perturb # rnd.uniform(-1, 1) = -0.9997712503653102 -> Substract form bias # rnd.uniform(0, 1) = 0.30233257263183977 -> Mutate # rnd.uniform(0, 1) = 0.14675589081711304 -> Random weight # rnd.uniform(-2, 2) = -1.6306456209248088 -> new random weight old_output_bias = self.node_output1.bias new_genome = mutate_bias(self.genome, self.rnd, config) self.assertAlmostEqual(old_output_bias - 0.9997712503653102, new_genome.nodes[2].bias, delta=0.000000001) self.assertAlmostEqual(-1.6306456209248088, new_genome.nodes[3].bias, delta=0.0000000001)
def test_mutate_bias_normal(self): config = NeatConfig(probability_bias_mutation=0.6, bias_max=3, bias_min=-3, bias_initial_min=-2, bias_initial_max=2, probability_random_bias_mutation=0.6, bias_mutation_normal_sigma=1.0, bias_mutation_type="normal") # rnd.uniform(0, 1) = 0.417022004702574 -> Mutate # rnd.uniform(0, 1) = 0.7203244934421581 -> Perturb # rnd.normal(scale=1) = -0.5281717522634557 -> Substract form bias # rnd.uniform(0, 1) = 0.39676747423066994 -> Mutate # rnd.uniform(0, 1) = 0.538816734003357 -> Random weight # rnd.uniform(-2, 2) = -0.3232219423868208 -> new random weight old_output_bias = self.node_output1.bias new_genome = mutate_bias(self.genome, self.rnd, config) self.assertAlmostEqual(old_output_bias - 0.5281717522634557, new_genome.nodes[2].bias, delta=0.000000001) self.assertAlmostEqual(-0.3232219423868208, new_genome.nodes[3].bias, delta=0.0000000001)
def test_build_generation_from_genome(self): initial_genome = Genome(20, [ Node(1, NodeType.INPUT, 0, step_activation, 0), Node(2, NodeType.OUTPUT, 0.4, step_activation, 1) ], [Connection(1, 1, 2, 1.0, True), Connection(2, 1, 2, -5, True)]) rnd = np.random.RandomState(1) generation = gs._build_generation_from_genome( initial_genome, SpeciesIDGeneratorSingleCore(), AgentIDGeneratorSingleCore(), 19, rnd, NeatConfig(population_size=3)) self.assertEqual(3, len(generation.agents)) self.assertEqual(0, generation.number) self.assertEqual(1, len(generation.species_list)) self.assertEqual(3, len(generation.species_list[0].members)) self.assertEqual(19, generation.seed) # First three random numbers # 1 - 12710949 # 2 - 4686059 # 3 - 6762380 self.assertEqual(12710949, generation.agents[0].genome.seed) self.assertEqual(4686059, generation.agents[1].genome.seed) self.assertEqual(6762380, generation.agents[2].genome.seed) # Check if every weight and bias is not equal to 0 for agent, i in zip(generation.agents, range(len(generation.agents))): genome = agent.genome self.assertEqual(i, agent.id) for node in genome.nodes: # Input nodes can have bias 0 if node.node_type == NodeType.INPUT: continue self.assertNotAlmostEqual(0, node.bias, delta=0.00000000001) for conn in genome.connections: self.assertNotAlmostEqual(0, conn.weight, delta=0.00000000001)
def evaluate_fix_structure(self, optimizer: NeatOptimizer, seed: int = None): optimizer.register_callback(self) config = NeatConfig(allow_recurrent_connections=False, population_size=150, compatibility_threshold=3, connection_min_weight=-5, connection_max_weight=5, bias_min=-5, bias_max=5, probability_mutate_add_node=0, probability_mutate_add_connection=0) # Create random seed, if none is specified if seed is None: seed = np.random.RandomState().randint(2**24) logger.info("Used Seed: {}".format(seed)) genome = Genome(0, [ Node(0, NodeType.INPUT, 0, modified_sigmoid_activation, 0), Node(1, NodeType.INPUT, 0, modified_sigmoid_activation, 0), Node(2, NodeType.OUTPUT, 0, modified_sigmoid_activation, 1), Node(3, NodeType.HIDDEN, 0, modified_sigmoid_activation, 0.5), Node(4, NodeType.HIDDEN, 0, modified_sigmoid_activation, 0.5) ], [ Connection(1, 0, 3, 0.1, True), Connection(2, 1, 3, 0.1, True), Connection(3, 0, 4, 0.1, True), Connection(4, 1, 4, 0.1, True), Connection(5, 3, 2, 0.1, True), Connection(6, 4, 2, 0.1, True) ]) optimizer.evaluate_genome_structure(genome_structure=genome, challenge=ChallengeXOR(), config=config, seed=seed)
def test_randomize_weight_bias(self): genome = Genome(20, [ Node(1, NodeType.INPUT, 0.0, step_activation, 0), Node(2, NodeType.OUTPUT, 0.0, step_activation, 1) ], [Connection(3, 1, 2, 0, True), Connection(4, 2, 1, 0, True)]) config = NeatConfig(bias_initial_min=1, bias_initial_max=2, connection_initial_min_weight=3, connection_initial_max_weight=4) randomized_genome = gs._randomize_weight_bias(genome, np.random.RandomState(1), config) for node in randomized_genome.nodes: if node.node_type == NodeType.INPUT: self.assertEqual(0, node.bias) else: self.assertTrue(1 <= node.bias <= 2) for conn in randomized_genome.connections: self.assertTrue(3 <= conn.weight <= 4)
def setUp(self) -> None: self.config = NeatConfig(compatibility_factor_matching_genes=1, compatibility_factor_disjoint_genes=2, compatibility_threshold=2.5, compatibility_genome_size_threshold=0, population_size=8) self.g1_nodes = [ Node(1, NodeType.INPUT, 0, step_activation, 0), Node(2, NodeType.INPUT, 0, step_activation, 0), Node(3, NodeType.OUTPUT, 1.2, step_activation, 1), Node(4, NodeType.HIDDEN, 1.5, step_activation, 0.5), Node(6, NodeType.HIDDEN, 0.5, step_activation, 0.5), Node(7, NodeType.HIDDEN, 0.2, step_activation, 0.25) ] self.g1_connections = [ Connection(1, 1, 3, 1.2, True), Connection(2, 2, 3, 0.5, False), Connection(3, 1, 4, -1.2, True), Connection(4, 4, 3, 0.2, True), Connection(5, 2, 6, 2.0, True), Connection(6, 6, 3, -1.1, False) ] self.g1 = Genome(1, self.g1_nodes, self.g1_connections) self.g2_nodes = [ Node(1, NodeType.INPUT, 0, step_activation, 0), Node(2, NodeType.INPUT, 0, step_activation, 0), Node(3, NodeType.OUTPUT, 0.2, step_activation, 1), Node(4, NodeType.HIDDEN, 1.2, step_activation, 0.5), Node(5, NodeType.HIDDEN, 2.8, step_activation, 0.5) ] self.g2_connections = [ Connection(1, 1, 3, 0.8, True), Connection(2, 2, 3, 1.5, True), Connection(3, 1, 4, 1.2, True), Connection(4, 4, 3, 3.2, True), Connection(6, 6, 3, -1.1, False), Connection(7, 6, 3, -0.1, False), Connection(8, 1, 4, -1.1, False) ] self.g2 = Genome(2, self.g2_nodes, self.g2_connections) self.agent1 = Agent(1, self.g1) self.agent1.fitness = 1 self.agent2 = Agent(2, self.g2) self.agent2.fitness = 2 # Add some more agents, and complete species self.inno_num_generator = InnovationNumberGeneratorSingleCore() self.species_id_generator = SpeciesIDGeneratorSingleCore() self.genome3 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome4 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome5 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome6 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome7 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.genome8 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) self.agent3 = Agent(3, self.genome3) self.agent3.fitness = 3 self.agent4 = Agent(4, self.genome4) self.agent4.fitness = 4 self.agent5 = Agent(5, self.genome5) self.agent5.fitness = 5 self.agent6 = Agent(6, self.genome6) self.agent6.fitness = 6 self.agent7 = Agent(7, self.genome7) self.agent7.fitness = 7 self.agent8 = Agent(8, self.genome8) self.agent8.fitness = 8 self.species1 = Species(self.species_id_generator.get_species_id(), self.agent1.genome, [self.agent1, self.agent2, self.agent3], max_species_fitness=1.5, generation_max_species_fitness=10) self.species2 = Species(self.species_id_generator.get_species_id(), self.agent4.genome, [self.agent4, self.agent5, self.agent6], max_species_fitness=7, generation_max_species_fitness=5) self.species3 = Species(self.species_id_generator.get_species_id(), self.agent6.genome, [self.agent7, self.agent8], max_species_fitness=0, generation_max_species_fitness=6) self.generation = Generation( 21, 2, agents=[ self.agent1, self.agent2, self.agent3, self.agent4, self.agent5, self.agent6, self.agent7, self.agent8 ], species_list=[self.species1, self.species2, self.species3])
def evaluate(self, optimizer: NeatOptimizer, seed: int = None, **kwargs): time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") # Create reporter self.fitness_reporter = FitnessReporter() self.species_reporter = SpeciesReporter() self.time_reporter = TimeReporter() self.check_point_reporter = CheckPointReporter( "/tmp/xor/{}/".format(time), "xor_genome_", lambda _: False) # Register this class as callback and reporter optimizer.register_callback(self) optimizer.register_reporters(self.time_reporter, self.fitness_reporter, self.species_reporter, self.check_point_reporter) config = NeatConfig(allow_recurrent_connections=False, population_size=150, compatibility_threshold=3, connection_min_weight=-15, connection_max_weight=15, bias_min=-15, bias_max=15, compatibility_factor_disjoint_genes=1.0, compatibility_factor_matching_genes=0.5, probability_mutate_add_connection=0.5, probability_mutate_add_node=0.2) # config = NeatConfig(allow_recurrent_connections=False, # population_size=150, # compatibility_threshold=3, # connection_min_weight=-15, # connection_max_weight=15, # bias_min=-15, # bias_max=15, # compatibility_factor_disjoint_genes=1.0, # compatibility_factor_matching_genes=0.4, # probability_mutate_add_connection=0.05, # probability_mutate_add_node=0.03) # Specify the config # config = NeatConfig(allow_recurrent_connections=False, # population_size=400, # compatibility_threshold=3, # weight_mutation_type="normal", # weight_mutation_normal_sigma=1.3, # connection_initial_min_weight=-5, # connection_initial_max_weight=5, # connection_min_weight=-5, # connection_max_weight=5, # bias_mutation_type="normal", # bias_mutation_normal_sigma=1.3, # bias_initial_min=-1, # bias_initial_max=1, # bias_min=-5, # bias_max=5, # compatibility_factor_disjoint_genes=1.0, # compatibility_factor_matching_genes=0.4, # probability_mutate_add_connection=0.05, # probability_mutate_add_node=0.03, # compatibility_genome_size_threshold=10) # Create random seed, if none is specified if seed is None: seed = np.random.RandomState().randint(2**24) logger.info("Used Seed: {}".format(seed)) optimizer.evaluate(amount_input_nodes=2, amount_output_nodes=1, activation_function=tanh_activation, challenge=ChallengeXOR(), config=config, seed=seed)
def setUp(self) -> None: self.config = NeatConfig(population_size=10)