def recover_feature_from_edges(self, edge_list): """ Recover sibling feature and grandchild feature from a list of edges The process consists of two stages: * Find sibling and grandchild relation respectively * Generate feature for them and aggregate into one feature vector """ sibling_list = self.find_sibling_relation(edge_list) grandchild_list = self.find_grandchild_relation(edge_list) fv = feature_vector.FeatureVector() for head, dep in edge_list: local_fv = self.get_local_vector(head, dep) fv.aggregate(local_fv) for head, dep, sib in sibling_list: local_fv = self.get_local_vector(head, dep, [sib], self.SECOND_ORDER_SIBLING_ONLY) fv.aggregate(local_fv) for head, dep, gc in grandchild_list: local_fv = self.get_local_vector(head, dep, [gc], self.SECOND_ORDER_GRANDCHILD_ONLY) fv.aggregate(local_fv) return fv
def recover_feature_from_edges(self, edge_list): """ Return a feature vector instance containing the features implied by edge list """ fv = feature_vector.FeatureVector() for head, dep in edge_list: local_fv = self.get_local_vector(head, dep) fv.aggregate(local_fv) return fv
def get_local_vector(self, head_index, dep_index, other_index_list=None, feature_type=None): """ Return first order local vector, which includes * Unigram feature * Bigram feature * In-between feature * Surrounding feature Argument other_index_list and feature_type is not used for first order features, but we keep them for compatibility purpose. """ local_fv = feature_vector.FeatureVector() self.add_local_vector(local_fv, head_index, dep_index) return local_fv
def __init__(self, file_data, **kwargs): # Load in the data by file name or by data structure. if type(file_data) is str: self.image = numpy.asarray( cv.LoadImageM(file_data, cv.CV_LOAD_IMAGE_GRAYSCALE)) elif type(file_data) is numpy.ndarray: self.image = file_data.copy() else: raise ValueError( "Constructor argument must be path to image file or Numpy ndarray." ) # Extract out our coefficients. self.radial_coefficients, self.circular_coefficients = self.get_coefficients( **kwargs) # Construct our vector of features. self.feature_vector = feature_vector.FeatureVector(self)
def get_local_vector(self, head_index, dep_index, other_index_list=None, feature_type=0): """ Given an edge, return its local vector To support higher order feature, use other_index_list. The content of other_index_list is determined by argument feature_type, which specifies how the content of other_index_list will be interpreted. See below. 1st-order features are added no matter which higher-order feature we are using. Higher-order features are specified by argument feature_type. The values are defined below: ---------------------------------------------------------------------------- | feature_type Description other_index_list | |--------------------------------------------------------------------------| | 0 Normal 1st order features None or [] (Won't be used) | | | | 1 2nd order sibling type with [0]: Sibling index or None* | | 1st order feature | | | | 2 2nd order grand child type [0]: grand child index | | with 1st order feature | | | | 3 2nd order sibling type** See (1) | | | | 4 2nd order grand child type** See (2) | |--------------------------------------------------------------------------| | * If [0] == None, then type 1 degrades to type 0 | | ** By default, type 3 and 4 does not include lower order features. This | | two options are useful for some applications of feature vector | ---------------------------------------------------------------------------- (More on the way...) :param head_index: The index of the head node :type head_index: integer :param dep_index: The index of the dependency node :type dep_node: integer :param other_index_list: The index of """ if debug.debug.log_feature_request_flag is True: self.first_order_generator.log_feature_request(head_index, dep_index, other_index_list, feature_type) # Deal with the case when feature type == 1 (sibling) # but the sibling is None. In this case the situation # degrades to a normal dependency relation if feature_type == self.SECOND_ORDER_SIBLING and \ other_index_list[0] is None: feature_type = self.FIRST_ORDER # For these two types there is not need to compute first order if feature_type == self.SECOND_ORDER_GRANDCHILD_ONLY or \ feature_type == self.SECOND_ORDER_SIBLING_ONLY: # Empty one. In this case local_fv_1st should not be used local_fv_1st = None else: #~key = (head_index, dep_index) #~self.first_order_cache_total += 1 #~# WE COMPUTE FIRST ORDER FEATURE HERE!!!! #~if key in self.first_order_feature_cache: #~ # cache hit: retrieve from the cache (and probably copy later) #~ local_fv_1st = self.first_order_feature_cache[key] #~ self.first_order_cache_hit += 1 #~else: #~ # Decorated with dist and dir; do not do this again #~ local_fv_1st = self.first_order_generator.get_local_vector(head_index, dep_index) local_fv_1st = self.first_order_generator.get_local_vector(head_index, dep_index) # Fast path: return directly if only 1st order are evaluated if feature_type == self.FIRST_ORDER: # Make sure the returned value is not written!! return local_fv_1st #~else: #~ # We will make change to the reference, so just copy it, to avoid #~ # writing into the cached value #~ local_fv_1st = copy.copy(local_fv_1st) # Initialize an empty local vector to hold all 2nd order features (sibling or grandchild) local_fv_second_order = feature_vector.FeatureVector() if (feature_type == self.SECOND_ORDER_SIBLING or feature_type == self.SECOND_ORDER_SIBLING_ONLY): sibling_index = other_index_list[0] self.get_2nd_sibling_feature(local_fv_second_order, head_index, dep_index, sibling_index) # From sibling to dependent node (we assume the sibling # node is between the head and dependent node) self.first_order_generator.add_dir_and_dist(local_fv_second_order, sibling_index, dep_index) if feature_type == self.SECOND_ORDER_SIBLING_ONLY: return local_fv_second_order elif (feature_type == self.SECOND_ORDER_GRANDCHILD or feature_type == self.SECOND_ORDER_GRANDCHILD_ONLY): grandchild_index = other_index_list[0] self.get_2nd_grandparent_feature(local_fv_second_order, head_index, dep_index, grandchild_index) # From dependent node to grand child self.first_order_generator.add_dir_and_dist(local_fv_second_order, dep_index, grandchild_index) if feature_type == self.SECOND_ORDER_GRANDCHILD_ONLY: return local_fv_second_order else: raise TypeError("Feature type %d not supported yet" % (feature_type, )) # Just rename local_fv = local_fv_1st ############################################## # Merge basic 1st order features and higher order features # If memory error is reported here (possibly when the set of # higher order features are large), then just add one line: # local_fv_higher_order.pop(i) for i in local_fv_second_order.keys(): local_fv[i] = 1 # We could use this single line instead: # local_fv.aggregate(local_fv_second_order) # And actually it is faster than merging manually # But it would not run on local machine without hvector installation ############################################## return local_fv