def optimize_crossover(tree_a, tree_b, tree_c, depth, X, labels, oblique):
    d = random.choice(range(depth))
    #for d in reversed(range(depth)):
    nodes_a = ClassificationTree.get_nodes_at_depth(d, tree_a)
    nodes_a = [node for node in nodes_a if not node.is_leaf]
    all_nodes = ClassificationTree.get_nodes_at_depth(d, tree_a)
    all_nodes.extend(ClassificationTree.get_nodes_at_depth(d, tree_b))
    all_nodes.extend(ClassificationTree.get_nodes_at_depth(d, tree_c))
    all_nodes = [node for node in all_nodes if not node.is_leaf]
    #print (node.id for node in nodes_a)
    #worst = nodes_a[np.argmax([ClassificationTree.misclassification_loss(node, X, labels, node.data_idxs, oblique) for node in nodes_a])]
    for node in nodes_a:
        if len(node.data_idxs) > 0:
            best = find_best_branch(all_nodes,  node.data_idxs, X, labels, oblique)
            best.data_idxs = node.data_idxs
            ClassificationTree.replace_node(node, best, tree_a)
Example #2
0
    def prune(self, min_size=1):
        #Prima controllo se ci sono sottoalberi puri.
        #Visito l'albero e verifico se esistono nodi branch ai quali arrivano punti associati a solo una label
        #Poi vedo se il nodo attuale è morto
        T = self.classification_tree
        stack = [T.tree[0]]
        while (stack):
            actual = stack.pop()
            if len(actual.data_idxs) > 0:
                #Se il nodo è puro
                if not actual.is_leaf and all(
                        i == self.y[actual.data_idxs[0]]
                        for i in self.y[actual.data_idxs]):
                    #Devo far diventare una foglia questo nodo con valore pari alla label
                    actual.is_leaf = True
                    actual.left_node = None
                    actual.right_node = None
                    actual.left_node_id = -1
                    actual.right_node_id = -1
                    actual.value = self.y[actual.data_idxs[0]]

                #Se il nodo ha un figlio morto devo sostituire il padre con l'altro figlio
                elif not actual.is_leaf and len(
                        actual.left_node.data_idxs) < min_size:
                    stack.append(actual.right_node)
                    ClassificationTree.replace_node(actual, actual.right_node,
                                                    T)
                elif not actual.is_leaf and len(
                        actual.right_node.data_idxs) < min_size:
                    stack.append(actual.left_node)
                    ClassificationTree.replace_node(actual, actual.left_node,
                                                    T)
                elif not actual.is_leaf:
                    stack.append(actual.right_node)
                    stack.append(actual.left_node)
            ClassificationTree.restore_tree(T)
Example #3
0
    def optimize_node_parallel(self, node, X, y, alfa, complexity):

        rho = 0
        if node.is_leaf:
            rho = 1
        error_best = ClassificationTree.misclassification_loss(
            node, X, y, node.data_idxs,
            self.classification_tree.oblique) + alfa * complexity

        #print("prima parallel")
        #Provo lo split
        if self.classification_tree.oblique:
            node_para, error_para = self.best_svm_split(
                node, X, y, alfa, complexity)
        else:
            node_para, error_para = self.best_parallel_split(
                node, X, y, alfa, complexity)
        #print(node.id, "  fatto parallel plit")

        if error_para < error_best:
            #print("error para migliore")
            error_best = error_para
            ClassificationTree.replace_node(node, node_para,
                                            self.classification_tree)

        #Metto questo if perchè nel caso di svm se il nodo è una foglia pura allora
        #non riesco a fare SVM perchè giustamente si aspetta label differenti.
        #Questo non perde di generalità poichè se il nodo fosse una foglia pura allora
        #creando due nuovi figli e ottimizzando otterremmo un figlio foglia puro e l'altro
        #senza punti. Che avrebbe la stessa loss iniziale del padre. Quindi alla fine la foglia iniziale
        #non verrebbe branchata.
        if node_para.left_node != None and node_para.right_node != None:
            #Errore sul figlio sinistro, se è migliore allora sostituisco
            error_lower = ClassificationTree.misclassification_loss(
                node_para.left_node, X, y, node.data_idxs,
                self.classification_tree.oblique) + alfa * (complexity + rho)
            if error_lower < error_best:
                #print("error lower migliore")
                ClassificationTree.replace_node(node, node_para.left_node,
                                                self.classification_tree)
                error_best = error_lower

            #Errore sul figlio sinistro, se è migliore allora sostituisco
            error_upper = ClassificationTree.misclassification_loss(
                node_para.right_node, X, y, node.data_idxs,
                self.classification_tree.oblique) + alfa * (complexity + rho)
            if error_upper < error_best:
                #print("error upper migliore")
                ClassificationTree.replace_node(node, node_para.right_node,
                                                self.classification_tree)
                error_best = error_upper
        return node