def onepoint_crossover(chain_first: Any, chain_second: Any, requirements) -> Any: max_depth = requirements.max_depth pairs_of_nodes = equivalent_subtree(chain_first, chain_second) if pairs_of_nodes: node_from_chain_first, node_from_chain_second = choice(pairs_of_nodes) summary_depth = node_depth(chain_first.root_node) - node_depth( node_from_chain_first) + node_depth(node_from_chain_second) if summary_depth <= max_depth and summary_depth != 0: chain_first.replace_node_with_parents(node_from_chain_first, node_from_chain_second) return chain_first
def get_mutation_prob(mut_id, root_node): default_mutation_prob = 0.7 if mut_id == MutationPowerEnum.weak.value: mutation_strength = 0.2 return mutation_strength / (node_depth(root_node) + 1) elif mut_id == MutationPowerEnum.mean.value: mutation_strength = 1.0 return mutation_strength / (node_depth(root_node) + 1) elif mut_id == MutationPowerEnum.strong.value: mutation_strength = 5.0 return mutation_strength / (node_depth(root_node) + 1) else: return default_mutation_prob
def growth_mutation(chain: Any, parameters: MutationParams, local_growth=True) -> Any: random_layer_in_chain = randint(0, chain.depth - 1) node_from_chain = choice( nodes_from_height(chain.root_node, random_layer_in_chain)) if local_growth: is_primary_node_selected = (not node_from_chain.nodes_from) or ( node_from_chain.nodes_from and node_from_chain != chain.root_node and randint(0, 1)) else: is_primary_node_selected = randint(0, 1) and not node_height(chain, node_from_chain) \ < parameters.requirements.max_depth if is_primary_node_selected: new_subtree = parameters.primary_node_func( model_type=choice(parameters.requirements.primary)) else: if local_growth: max_depth = node_depth(node_from_chain) else: max_depth = parameters.requirements.max_depth - node_height( chain, node_from_chain) new_subtree = random_ml_chain(parameters.chain_class, parameters.secondary_node_func, parameters.primary_node_func, parameters.requirements, max_depth=max_depth).root_node chain.replace_node_with_parents(node_from_chain, new_subtree) return chain
def subtree_crossover(chain_first: Any, chain_second: Any, requirements) -> Any: max_depth = requirements.max_depth random_layer_in_chain_first = randint(0, chain_first.depth - 1) random_layer_in_chain_second = randint(0, chain_second.depth - 1) if chain_first.depth - 1 != 0 and chain_second.depth - 1 != 0: if random_layer_in_chain_first == 0 and random_layer_in_chain_second == 0: if randint(0, 1): random_layer_in_chain_first = randint(1, chain_first.depth - 1) else: random_layer_in_chain_second = randint(1, chain_second.depth - 1) node_from_chain_first = choice( nodes_from_height(chain_first.root_node, random_layer_in_chain_first)) node_from_chain_second = choice( nodes_from_height(chain_second.root_node, random_layer_in_chain_second)) summary_depth = random_layer_in_chain_first + node_depth( node_from_chain_second) if summary_depth <= max_depth and summary_depth != 0: chain_first.replace_node_with_parents(node_from_chain_first, node_from_chain_second) return chain_first
def one_point_crossover(chain_first: Any, chain_second: Any, max_depth: int) -> Any: """Finds common structural parts between two trees, and after that randomly chooses the location of nodes, subtrees of which will be swapped""" pairs_of_nodes = equivalent_subtree(chain_first, chain_second) if pairs_of_nodes: node_from_chain_first, node_from_chain_second = choice(pairs_of_nodes) layer_in_chain_first = node_depth( chain_first.root_node) - node_depth(node_from_chain_first) layer_in_chain_second = node_depth( chain_second.root_node) - node_depth(node_from_chain_second) replace_subtrees(chain_first, chain_second, node_from_chain_first, node_from_chain_second, layer_in_chain_first, layer_in_chain_second, max_depth) return chain_first, chain_second
def nn_growth_mutation(chain: Any, parameters: MutationParams, local_growth=True) -> Any: ComposerVisualiser.visualise(chain) primary_nodes = parameters.requirements.primary secondary_nodes = parameters.requirements.secondary random_layer_in_chain = randint(0, node_depth(chain.root_node)) print(random_layer_in_chain) print(node_depth(chain.root_node) + 1) node_from_chain = choice( nodes_from_height(chain.root_node, random_layer_in_chain)) if local_growth: is_primary_node_selected = (not node_from_chain.nodes_from) or ( node_from_chain.nodes_from and node_from_chain != chain.root_node and randint(0, 1)) else: is_primary_node_selected = randint(0, 1) and not node_height(chain, node_from_chain) \ < parameters.requirements.max_depth if is_primary_node_selected: new_node_type = choice(primary_nodes) new_layer_params = get_random_layer_params(new_node_type, parameters.requirements) new_subtree = parameters.primary_node_func( layer_params=new_layer_params) chain.replace_node_with_parents(node_from_chain, new_subtree) else: if local_growth: max_depth = node_depth(node_from_chain) else: max_depth = parameters.requirements.max_depth - random_layer_in_chain new_node_type = choice(secondary_nodes) new_layer_params = get_random_layer_params(new_node_type, parameters.requirements) new_subtree = parameters.secondary_node_func( layer_params=new_layer_params) offspring_size = randint(parameters.requirements.min_arity, parameters.requirements.max_arity) for _ in range(offspring_size): random_nn_branch( secondary_node_func=parameters.secondary_node_func, primary_node_func=parameters.primary_node_func, requirements=parameters.requirements, max_depth=max_depth, start_height=(node_height(chain, node_from_chain)), node_parent=new_subtree) chain.replace_node_with_parents(node_from_chain, new_subtree)
def growth_mutation(chain: Any, chain_class, secondary_node_func: Callable, primary_node_func: Callable, requirements) -> Any: chain_copy = deepcopy(chain) random_layer_in_chain = randint(0, chain_copy.depth - 1) node_from_chain = choice( nodes_from_height(chain_copy, random_layer_in_chain)) is_primary_node_selected = (not node_from_chain.nodes_from) or ( node_from_chain.nodes_from and node_from_chain != chain_copy.root_node and randint(0, 1)) if is_primary_node_selected: new_subtree = primary_node_func( model_type=choice(requirements.primary)) else: max_depth = node_depth(node_from_chain) new_subtree = random_chain(chain_class, secondary_node_func, primary_node_func, requirements, max_depth=max_depth).root_node chain_copy.replace_node_with_parents(node_from_chain, new_subtree) return chain_copy