def get_baseline_scoring_fn(pred_wei, pred_bias, C, ent_vecs): """ Get a scoring function for the relpron dataset :param pred_wei: weights of semantic functions :param pred_bias: biases of semantic functions :param ent_vecs: zero-context mean-field vectors, by pred index :return: scoring function """ # Set up semantic functions semfuncs = [get_semfunc(pred_wei[i], pred_bias[i]) for i in range(len(pred_wei))] def score(term, description, **kwargs): """ Calculate how much the triple implies the target :param term: noun index :param description: (SBJ-or-OBJ, (verb, agent, patient)) :return: probability """ which, triple = description if which == 'SBJ': i = 1 elif which == 'OBJ': i = 2 else: raise ValueError(which) marg = marginal_approx(ent_vecs[triple[i]], C) return semfuncs[term](marg) return score
def get_scoring_fn(pred_wei, pred_bias, C, meanfield_vecs): """ Get a scoring function for the relpron dataset :param pred_wei: weights of semantic functions :param pred_bias: biases of semantic functions :param C: total cardinality :param meanfield_vecs: mean-field vectors for relpron triples :return: scoring function """ # Set up semantic functions semfuncs = [get_semfunc(pred_wei[i], pred_bias[i]) for i in range(len(pred_wei))] # Get marginal distributions marg = [[marginal_approx(prob, C) for prob in triple] for triple in meanfield_vecs] def scoring_fn(term, description, **kwargs): """ Calculate how much the triple implies the term :param term: noun index :param description: (index-of-SBJ-or-OBJ, index-of-triple) :return: probability """ which, index = description return semfuncs[term](marg[index][which]) return scoring_fn
def add_semfunc_scores(scores, param_subdir='simplevec', meanfield_subdir='meanfield_freq', basic_length=7, full_length=11, C_index=8, pred_list=pred_list, constr=(), test_fn=test_all_implies, **test_fn_kwargs): "Add new scores" # Process each file prev_basic_name = None # Avoid reloading vectors for filename in sorted(os.listdir(os.path.join(AUX_DIR, meanfield_subdir))): # Process filename name = filename.split('.')[0] settings = tuple(name.split('-')) # Ignore auxiliary files if len(settings) != full_length: continue # Ignore files if we haven't loaded that version of the dataset if settings[0] != prefix or int(settings[1]) != thresh: continue # Ignore files we've already evaluated if settings in scores: continue # Ignore files that don't match the given constraints: if any(settings[pos] not in [str(x).replace('.', '') for x in val] for pos, val in constr): continue # Extract information from filename basic_name = '-'.join(settings[:basic_length]) C = int(settings[C_index]) # Load the parameter vectors print(filename) if basic_name != prev_basic_name: with gzip.open( os.path.join(AUX_DIR, param_subdir, basic_name + '.pkl.gz'), 'rb') as f: param_vec = pickle.load(f) prev_basic_name = basic_name # Load the biases with gzip.open( os.path.join(AUX_DIR, meanfield_subdir, name + '-bias.pkl.gz'), 'rb') as f: bias = pickle.load(f) # Construct the semantic functions semfuncs = {i: get_semfunc(param_vec[i], bias[i]) for i in pred_list} # Load the entity vectors with gzip.open(os.path.join(AUX_DIR, meanfield_subdir, filename), 'rb') as f: meanfield_vec = pickle.load(f) marginal_vec = { i: marginal_approx(meanfield_vec[i], C) for i in pred_list } # Test scores[settings] = test_fn(marginal_vec, semfuncs, **test_fn_kwargs)
def get_meanfield_fn(pred_wei, pred_bias, link_wei, ent_bias, C, init_vecs): """ Get a function mapping vso triples to meanfield vectors :param pred_wei: weights of semantic functions :param pred_bias: biases of semantic functions :param link_wei: link weight matrix :param ent_bias: entity bias :param C: total cardinality :param init_vecs: zero-context mean-field vectors, by pred index :return: scoring function """ # Set up semantic functions semfuncs = [get_semfunc(pred_wei[i], pred_bias[i]) for i in range(len(pred_wei))] # Set up constant function D = pred_wei.shape[1] constant = get_semfunc(np.zeros(D), 0) av_ent = np.ones(D) * (C/D) def meanfield_fn(triple, **kwargs): """ Calculate meanfield vectors for the triple. For OOV items, the semfunc is a constant function. :param triple: (verb, agent, patient) :return: probability """ sf = [] vecs = [] for i in triple: if i is None: sf.append(constant) vecs.append(av_ent) else: sf.append(semfuncs[i]) vecs.append(init_vecs[i]) meanfield_vecs = mean_field_vso(sf, link_wei, ent_bias, C=C, vecs=vecs, **kwargs) return meanfield_vecs return meanfield_fn
def load_scoring_fn(filename, option='implies', **kwargs): "Load a scoring function" # Load files pred_wei, pred_bias, C, meanfield_vecs = load_weights_and_vectors( filename, meanfield_dir='meanfield_gs2011', **kwargs) # Set up semantic functions semfuncs = [ get_semfunc(pred_wei[i], pred_bias[i]) for i in range(len(pred_wei)) ] # Get marginal distributions marg = [marginal_approx(prob, C) for prob, _, _ in meanfield_vecs] if option == 'implies': def scoring_fn(i, j): """ Calculate how much each verbal predicate is true of the other verb's entity :param i: triple index :param j: triple index :return: product of probabilities """ # Get verb semfuncs and verb entities funcs = (semfuncs[verbs[i]], semfuncs[verbs[j]]) ents = (marg[i], marg[j]) # Multiply probs return funcs[0](ents[1]) * funcs[1](ents[0]) elif option == 'similarity': def scoring_fn(i, j): """ Calculate how similar the entities are :param i: triple index :param j: triple index :return: cosine similarity """ # Get verb entities ents = (marg[i], marg[j]) # Get cosine similarity return cosine(*ents) else: raise ValueError('option not recognised') return scoring_fn
def load_semfunc_model(name, param_subdir, meanfield_subdir, basic_length, full_length, C_index): "Load a semfunc model" settings = tuple(name.split('-')) basic_name = '-'.join(settings[:basic_length]) C = int(settings[C_index]) # Load the semantic functions with gzip.open(os.path.join(AUX_DIR, param_subdir, basic_name + '.pkl.gz'), 'rb') as f: param_vec = pickle.load(f) with gzip.open( os.path.join(AUX_DIR, meanfield_subdir, name + '-bias.pkl.gz'), 'rb') as f: bias = pickle.load(f) semfuncs = {i: get_semfunc(param_vec[i], bias[i]) for i in pred_list} # Load the entity vectors with gzip.open(os.path.join(AUX_DIR, meanfield_subdir, name + '.pkl.gz'), 'rb') as f: meanfield_vec = pickle.load(f) marginal_vec = {i: marginal_approx(meanfield_vec[i], C) for i in pred_list} return marginal_vec, semfuncs
def get_semfuncs_from_vectors(name, bias_method, scale, C, target=None, Z=None, alpha=None, pred_list=None, vectors=None, freq=None, as_dict=False, include_bias=False, directory='simplevec'): """ Get semantic functions from given weights :param name: name of parameter file :param bias_method: how to initialise biases ('target' or 'frequency') :param scale: factor to multiply simple vectors by :param C: total cardinality :param target: desired energy for an 'untypical' vector (only for bias method 'target') :param Z: weighted predicate truth of rest of vocabulary (only for bias method 'frequency') :param alpha: smoothing of frequency in generation (only for bias method 'frequency') :param pred_list: list of predicates to use :param as_dict: return as a dict (default as a list) :param include_bias: return all biases as an array :return: semantic functions (, bias) """ prefix, thresh, dim, *_ = name.split('-') dim = int(dim) # Predicates to use if pred_list is None: preds, _ = get_test_preds(prefix, thresh) pred_list = sorted(preds) # Load vectors if vectors is None: with gzip.open(os.path.join(AUX_DIR, directory, name + '.pkl.gz'), 'rb') as f: all_vectors = pickle.load(f) if isinstance(all_vectors, np.ndarray): if pred_list is False: vectors = all_vectors else: vectors = all_vectors[pred_list] del all_vectors # Conserve memory elif isinstance(all_vectors, dict): vectors = np.array([all_vectors[i] for i in pred_list]) else: raise TypeError # Multiply by the scale factor vec = vectors * scale # Don't use negative weights in bias calculation vec_for_bias = vec.clip(0) # Define bias of predicates if bias_method == 'target': # Maximum activation of each predicate high = np.partition(vec_for_bias, -C, axis=1)[:, -C:].sum(axis=1) # Average activation if the top units are not used but still nouny/verby other = (vec_for_bias.sum(1) - high) / (dim - C) * C # Minimum pred bias makes an average predicate have the target energy bias = other + target # For preds with a bigger gap between max and other activation, # make the bias the average of the two gap = high - other mask = (gap > 2 * target) bias[mask] = other[mask] + gap[mask] / 2 elif bias_method == 'frequency': # freq[i] ~ freq[i]^alpha / (Z + freq[i]^alpha) semfunc[i](ent) if freq is None: freq = get_verb_noun_freq(prefix, thresh, pred_list) ent = np.ones(dim * 2) * C / dim bias = np.dot(vec_for_bias, ent) + np.log(1 / freq / (1 + Z * freq**-alpha) - 1) else: raise ValueError('bias method not recognised') # Define semantic functions if as_dict: semfuncs = { i: get_semfunc(v, b) for i, v, b in zip(pred_list, vec, bias) } else: semfuncs = [get_semfunc(v, b) for v, b in zip(vec, bias)] if include_bias: return semfuncs, bias else: return semfuncs