def build_tree(self): """Updates self.tree (the tree structure) based on closest nodes, bottom up.""" c = tf.math.softplus(self.c) items = self.get_all_items() tot_levels = self.tot_levels nodes = [self.get_all_nodes_level(l) for l in range(tot_levels)] # closest_node_to_items is a numpy array of size (n_items, ) # holding the parent node index from one level up. closest_node_to_items = ( sum(self.nodes_per_level[:tot_levels - 1]) + tf.math.argmin(hyp_utils.hyp_distance_all_pairs( items, nodes[tot_levels - 1], c), axis=1)).numpy() # closest_node_to_nodes is a numpy array of size (n_tot_nodes, ) # holding the parent node index from one level up. Root index is -1. closest_node_to_nodes = -np.ones(sum(self.nodes_per_level)) for l in range(1, tot_levels): first_ind = sum(self.nodes_per_level[:l]) last_ind = sum(self.nodes_per_level[:l + 1]) closest_node_to_nodes[first_ind:last_ind] = ( sum(self.nodes_per_level[:l - 1]) + tf.math.argmin(hyp_utils.hyp_distance_all_pairs( nodes[l], nodes[l - 1], c), axis=1)).numpy() self.tree = tree_utils.build_tree(closest_node_to_items, closest_node_to_nodes, self.nodes_per_level)
def similarity_score(self, lhs, rhs, eval_mode): c = tf.math.softplus(self.c) if eval_mode and self.rhs_dep_lhs: return -hyp_utils.hyp_distance_batch_rhs(lhs, rhs, c)**2 elif eval_mode and not self.rhs_dep_lhs: return -hyp_utils.hyp_distance_all_pairs(lhs, rhs, c)**2 return -hyp_utils.hyp_distance(lhs, rhs, c)**2
def get_scores_targets(self, input_tensor): """Computes pairs' scores as well as scores againts all possible items. Args: input_tensor: Tensor of size batch_size x 2 containing pairs' indices. Returns: scores: Numpy array of size batch_size x n_items containing users' scores against all possible items in the CF. targets: Numpy array of size batch_size x 1 containing pairs' scores. """ c = tf.math.softplus(self.c) users = self.get_users(input_tensor[:, 0]) items = self.get_all_items() user_item_distance = hyp_utils.hyp_distance_all_pairs(users, items, c) scores = (-user_item_distance).numpy() targets = scores[np.arange(scores.shape[0]), input_tensor[:, 1]].reshape((-1, 1)) return scores, targets
def top_k_from_dist(self, user, embeddings, k): c = tf.math.softplus(self.c) user_emb_distance = tf.reshape( hyp_utils.hyp_distance_all_pairs(tf.reshape(user, [1, -1]), embeddings, c), [-1]) return tf.math.top_k(-user_emb_distance, k=k)[1]