def get_classes(hierarchy: Tree, output_all_nodes=False): """ Return all classes associated with a hierarchy. The classes are sorted in alphabetical order using their label, putting all leaf nodes first and the non-leaf nodes afterwards. Args: hierarhcy: The hierarchy to use. all_nodes: Set to true if the non-leaf nodes (excepted the origin) must also be included. Return: A pair (classes, positions) of the array of all classes (sorted) and the associated tree positions. """ def get_classes_from_positions(positions): classes = [get_label(hierarchy[p]) for p in positions] class_order = np.argsort( classes) # we output classes in alphabetical order positions = [positions[i] for i in class_order] classes = [classes[i] for i in class_order] return classes, positions positions = hierarchy.treepositions("leaves") classes, positions = get_classes_from_positions(positions) if output_all_nodes: positions_nl = [ p for p in hierarchy.treepositions() if p not in positions ] classes_nl, positions_nl = get_classes_from_positions(positions_nl) classes += classes_nl positions += positions_nl return classes, positions
def _get_lbrb_const_length(t : tree.Tree): lb_const_lengths = 0 max_lb_const_length = 0 lb_const_num = 0 rb_const_lengths = 0 max_rb_const_length = 0 rb_const_num = 0 # total_length = len(t.leaves()) for position in t.treepositions(): # print(t[position]) if not (isinstance(t[position],str) or isinstance(t[position][0],str)): if len(t[position][0]) == 2: lb_const_num += 1 this_length = len(t[position][0].leaves()) lb_const_lengths += this_length if this_length > max_lb_const_length: max_lb_const_length = this_length if len(t[position][1]) == 2: rb_const_num += 1 this_length = len(t[position][1].leaves()) rb_const_lengths += this_length if this_length > max_rb_const_length: max_rb_const_length = this_length rb_const_lengths = rb_const_lengths/rb_const_num if rb_const_num != 0 else 0 lb_const_lengths = lb_const_lengths/lb_const_num if lb_const_num != 0 else 0 # max_lb_const_length /= total_length # max_rb_const_length /= total_length return lb_const_lengths, rb_const_lengths, max_lb_const_length, max_rb_const_length
def translate(tree: Tree, translation_rules: list, draw=False): put_left = list( filter( lambda i: isinstance(tree[i], Tree) and tree[i].label() in translation_rules and not 'put_left' in locals(), tree.treepositions()))[0] if len(tree) != 0 else [] if len(put_left) != 0: tree = apply_translation(put_left, tree) if tree[tree.treepositions()[-2]].label() not in [ Nonterminal("AUX"), Nonterminal("VERB") ]: tree = apply_translation(tree.treepositions()[-2], tree) if draw: tree.draw() return tree
def __init__(self, hierarchy: Tree, classes: List[str], weights: Tree): """ Initialise the loss with a given hierarchy. Args: hierarchy: The hierarchy used to define the loss. classes: A list of classes defining the order of all nodes. weights: The weights as a tree of similar shapre as hierarchy. """ super(YOLOLoss, self).__init__() assert hierarchy.treepositions() == weights.treepositions() self.cascade = SoftmaxCascade(hierarchy, classes) weights_dict = { get_label(hierarchy[p]): get_label(weights[p]) for p in weights.treepositions() } self.weights = torch.nn.Parameter(torch.unsqueeze( torch.tensor([weights_dict[c] for c in classes], dtype=torch.float32), 0), requires_grad=False)
def __init__(self, hierarchy: Tree, classes: List[str], weights: Tree): super(HierarchicalLLLoss, self).__init__() assert hierarchy.treepositions() == weights.treepositions() # the tree positions of all the leaves positions_leaves = { get_label(hierarchy[p]): p for p in hierarchy.treepositions("leaves") } num_classes = len(positions_leaves) # we use classes in the given order positions_leaves = [positions_leaves[c] for c in classes] # the tree positions of all the edges (we use the bottom node position) positions_edges = hierarchy.treepositions()[ 1:] # the first one is the origin # map from position tuples to leaf/edge indices index_map_leaves = { positions_leaves[i]: i for i in range(len(positions_leaves)) } index_map_edges = { positions_edges[i]: i for i in range(len(positions_edges)) } # edge indices corresponding to the path from each index to the root edges_from_leaf = [[ index_map_edges[position[:i]] for i in range(len(position), 0, -1) ] for position in positions_leaves] # get max size for the number of edges to the root num_edges = max([len(p) for p in edges_from_leaf]) # helper that returns all leaf positions from another position wrt to the original position def get_leaf_positions(position): node = hierarchy[position] if isinstance(node, Tree): return node.treepositions("leaves") else: return [()] # indices of all leaf nodes for each edge index leaf_indices = [[ index_map_leaves[position + leaf] for leaf in get_leaf_positions(position) ] for position in positions_edges] # save all relevant information as pytorch tensors for computing the loss on the gpu self.onehot_den = torch.nn.Parameter(torch.zeros( [num_classes, num_classes, num_edges]), requires_grad=False) self.onehot_num = torch.nn.Parameter(torch.zeros( [num_classes, num_classes, num_edges]), requires_grad=False) self.weights = torch.nn.Parameter(torch.zeros([num_classes, num_edges]), requires_grad=False) # one hot encoding of the numerators and denominators and store weights for i in range(num_classes): for j, k in enumerate(edges_from_leaf[i]): self.onehot_num[i, leaf_indices[k], j] = 1.0 self.weights[i, j] = get_label(weights[positions_edges[k]]) for j, k in enumerate(edges_from_leaf[i][1:]): self.onehot_den[i, leaf_indices[k], j] = 1.0 self.onehot_den[ i, :, j + 1] = 1.0 # the last denominator is the sum of all leaves