def test_drop_mutation_for_linear_graph(): """ Tests single_drop mutation can remove node """ linear_two_nodes = OptGraph(OptNode('logit', [OptNode('scaling')])) linear_one_node = OptGraph(OptNode('logit')) composer_requirements = GPComposerRequirements(primary=['scaling'], secondary=['logit'], mutation_prob=1) graph_params = GraphGenerationParams( adapter=DirectAdapter(), rules_for_constraint=DEFAULT_DAG_RULES) successful_mutation_drop = False for _ in range(100): graph_after_mutation = mutation(types=[MutationTypesEnum.single_drop], params=graph_params, ind=Individual(linear_two_nodes), requirements=composer_requirements, log=default_log(__name__), max_depth=2).graph if not successful_mutation_drop: successful_mutation_drop = \ graph_after_mutation.root_node.descriptive_id == linear_one_node.root_node.descriptive_id else: break assert successful_mutation_drop
def test_edge_mutation_for_graph(): """ Tests edge mutation can add edge between nodes """ graph_without_edge = \ OptGraph(OptNode('logit', [OptNode('one_hot_encoding', [OptNode('scaling')])])) primary = OptNode('scaling') graph_with_edge = \ OptGraph(OptNode('logit', [OptNode('one_hot_encoding', [primary]), primary])) composer_requirements = GPComposerRequirements( primary=['scaling', 'one_hot_encoding'], secondary=['logit', 'scaling'], mutation_prob=1) graph_params = GraphGenerationParams( adapter=DirectAdapter(), rules_for_constraint=DEFAULT_DAG_RULES) successful_mutation_edge = False for _ in range(100): graph_after_mutation = mutation(types=[MutationTypesEnum.single_edge], params=graph_params, ind=Individual(graph_without_edge), requirements=composer_requirements, log=default_log(__name__), max_depth=graph_with_edge.depth).graph if not successful_mutation_edge: successful_mutation_edge = \ graph_after_mutation.root_node.descriptive_id == graph_with_edge.root_node.descriptive_id else: break assert successful_mutation_edge
def test_intermediate_add_mutation_for_linear_graph(): """ Tests single_add mutation can add node between two existing nodes """ linear_two_nodes = OptGraph(OptNode('logit', [OptNode('scaling')])) linear_three_nodes_inner = \ OptGraph(OptNode('logit', [OptNode('one_hot_encoding', [OptNode('scaling')])])) composer_requirements = GPComposerRequirements( primary=['scaling'], secondary=['one_hot_encoding'], mutation_prob=1) graph_params = GraphGenerationParams( adapter=DirectAdapter(), rules_for_constraint=DEFAULT_DAG_RULES) successful_mutation_inner = False for _ in range(100): graph_after_mutation = mutation(types=[MutationTypesEnum.single_add], params=graph_params, ind=Individual(linear_two_nodes), requirements=composer_requirements, log=default_log(__name__), max_depth=3).graph if not successful_mutation_inner: successful_mutation_inner = \ graph_after_mutation.root_node.descriptive_id == linear_three_nodes_inner.root_node.descriptive_id else: break assert successful_mutation_inner
def reproduce(self, selected_individual_first, selected_individual_second=None) -> Tuple[Any]: if selected_individual_second: new_inds = crossover( self.parameters.crossover_types, selected_individual_first, selected_individual_second, crossover_prob=self.requirements.crossover_prob, max_depth=self.max_depth, log=self.log, params=self.graph_generation_params) else: new_inds = [selected_individual_first] new_inds = tuple([ mutation(types=self.parameters.mutation_types, params=self.graph_generation_params, ind=new_ind, requirements=self.requirements, max_depth=self.max_depth, log=self.log) for new_ind in new_inds ]) for ind in new_inds: ind.fitness = None return new_inds
def test_mutation(): adapter = PipelineAdapter() ind = Individual(adapter.adapt(pipeline_first())) mutation_types = [MutationTypesEnum.none] log = default_log(__name__) graph_gener_params = GraphGenerationParams() task = Task(TaskTypesEnum.classification) primary_model_types, _ = OperationTypesRepository().suitable_operation( task_type=task.task_type) secondary_model_types = ['xgboost', 'knn', 'lda', 'qda'] composer_requirements = GPComposerRequirements( primary=primary_model_types, secondary=secondary_model_types, mutation_prob=1) new_ind = mutation(mutation_types, graph_gener_params, ind, composer_requirements, log=log, max_depth=3) assert new_ind.graph == ind.graph mutation_types = [MutationTypesEnum.growth] composer_requirements = GPComposerRequirements( primary=primary_model_types, secondary=secondary_model_types, mutation_prob=0) new_ind = mutation(mutation_types, graph_gener_params, ind, composer_requirements, log=log, max_depth=3) assert new_ind.graph == ind.graph ind = Individual(adapter.adapt(pipeline_fifth())) new_ind = mutation(mutation_types, graph_gener_params, ind, composer_requirements, log=log, max_depth=3) assert new_ind.graph == ind.graph
def test_boosting_mutation_for_linear_graph(): """ Tests boosting mutation can add correct boosting cascade """ linear_one_node = OptGraph(OptNode('knn', [OptNode('scaling')])) init_node = OptNode('scaling') model_node = OptNode('knn', [init_node]) boosting_graph = \ OptGraph( OptNode('logit', [model_node, OptNode('linear', [OptNode('class_decompose', [model_node, init_node])])])) composer_requirements = GPComposerRequirements(primary=['scaling'], secondary=['logit'], mutation_prob=1) graph_params = GraphGenerationParams( adapter=PipelineAdapter(), advisor=PipelineChangeAdvisor(task=Task(TaskTypesEnum.classification)), rules_for_constraint=DEFAULT_DAG_RULES) successful_mutation_boosting = False for _ in range(100): graph_after_mutation = mutation(types=[boosting_mutation], params=graph_params, ind=Individual(linear_one_node), requirements=composer_requirements, log=default_log(__name__), max_depth=2).graph if not successful_mutation_boosting: successful_mutation_boosting = \ graph_after_mutation.root_node.descriptive_id == boosting_graph.root_node.descriptive_id else: break assert successful_mutation_boosting # check that obtained pipeline can be fitted pipeline = PipelineAdapter().restore(graph_after_mutation) data = file_data() pipeline.fit(data) result = pipeline.predict(data) assert result is not None
def _create_randomized_pop_from_inital_pipeline( self, initial_pipeline) -> List[Individual]: """ Fill first population with mutated variants of the initial_pipeline :param initial_pipeline: Initial assumption for first population :return: list of individuals """ initial_req = deepcopy(self.requirements) initial_req.mutation_prob = 1 randomized_pop = ([ mutation(types=self.parameters.mutation_types, params=self.graph_generation_params, ind=Individual(deepcopy(initial_pipeline)), requirements=initial_req, max_depth=self.max_depth, log=self.log, add_to_history=False) for _ in range(self.requirements.pop_size) ]) return randomized_pop