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 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 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 get_mutation_prob(mut_id, root_node): default_mutation_prob = 0.7 if mut_id == MutationStrengthEnum.weak.value: mutation_strength = 0.2 return mutation_strength / (node_depth(root_node) + 1) elif mut_id == MutationStrengthEnum.mean.value: mutation_strength = 1.0 return mutation_strength / (node_depth(root_node) + 1) elif mut_id == MutationStrengthEnum.strong.value: mutation_strength = 5.0 return mutation_strength / (node_depth(root_node) + 1) else: return default_mutation_prob
def growth_mutation(chain: Any, requirements, chain_generation_params, max_depth: int, local_growth=True) -> Any: """ This mutation selects a random node in a tree, generates new subtree, and replaces the selected node's subtree. :param local_growth: if true then maximal depth of new subtree equals depth of tree located in selected random node, if false then previous depth of selected node doesn't affect to new subtree depth, maximal depth of new subtree just should satisfy depth constraint in parent tree """ random_layer_in_chain = randint(0, chain.depth - 1) node_from_chain = choice(nodes_from_height(chain, 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) \ < max_depth if is_primary_node_selected: new_subtree = chain_generation_params.primary_node_func( model_type=choice(requirements.primary)) else: if local_growth: max_depth = node_depth(node_from_chain) else: max_depth = max_depth - node_height(chain, node_from_chain) new_subtree = random_chain( chain_generation_params=chain_generation_params, requirements=requirements, max_depth=max_depth).root_node chain.replace_node_with_parents(node_from_chain, new_subtree) return chain
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 get_mutation_prob(mut_id, root_node): default_mutation_prob = 0.7 if mut_id in list(MutationStrengthEnum): mutation_strength = mut_id.value mutation_prob = mutation_strength / (node_depth(root_node) + 1) else: mutation_prob = default_mutation_prob return mutation_prob
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