def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor, triple_type: str = 'pos') -> torch.Tensor: """ Gets score using conditionals. :: note: We do not need to worry about the dimentions of the boxes. If it can sensibly broadcast it will. """ triple = torch.stack((head.data, tail.data), dim=-3) int_lengths = head.per_dim_int_length(triple) head_tail_box_vol = torch.sum( torch.log(int_lengths.clamp_min(0) + 1e-8), dim=-1) # score = tail_head_relation_box_vol - tail_relation_box.log_soft_volume( # temp=self.softbox_temp) tail_data = tail.data.view(-1, 1, 2, self.embedding_dim) score = head_tail_box_vol - tail._intersection_volume(tail_data, True) if triple_type == 'pos': triple = torch.stack((head.data, tail.data), dim=-3) target_probs = torch.ones_like(score) if not self.is_eval(): self.surr_loss = self.pull_loss(triple, target_probs, int_lengths) else: self.surr_loss = 0 return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor, label: Tensor) -> torch.Tensor: """ Gets score using conditionals. :: note: We do not need to worry about the dimentions of the boxes. If it can sensibly broadcast it will. """ head.data[..., 0, :] = head.data[..., 0, :] % 1 head.data[..., 1, :] = torch.sigmoid(head.data[..., 1, :]) tail.data[..., 0, :] = tail.data[..., 0, :] % 1 tail.data[..., 1, :] = torch.sigmoid(tail.data[..., 1, :]) triple = torch.stack((head.data, tail.data), dim=-3) int_lengths = head.per_dim_int_length(triple) triple = torch.stack((head.data, tail.data), dim=-3) head_tail_box_vol = head._intersection_volume(triple, True, eps=1e-20) # score = tail_head_relation_box_vol - tail_relation_box.log_soft_volume( # temp=self.softbox_temp) tail_data = tail.data.view(-1, 1, 2, self.embedding_dim) int_lengths_tail = tail.per_dim_int_length(tail_data, True) tail_volume = torch.sum(torch.log(int_lengths_tail.clamp_min(1e-20)), dim=-1) score = head_tail_box_vol - tail_volume triple = torch.stack((head.data, tail.data), dim=-3) target_probs = label if not self.is_eval(): self.surr_loss = self.pull_loss(triple, target_probs, int_lengths) else: self.surr_loss = 0 return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: """ Gets score using conditionals. :: note: We do not need to worry about the dimentions of the boxes. If it can sensibly broadcast it will. """ if self.is_eval(): if len(head.data.shape) > len(tail.data.shape): tail.data = torch.cat(head.data.shape[-3] * [tail.data]) elif len(head.data.shape) < len(tail.data.shape): head.data = torch.cat(tail.data.shape[-3] * [head.data]) head_tail_box_vol = head.intersection_log_soft_volume( tail, temp=self.softbox_temp, gumbel_beta=self.gumbel_beta, bayesian=True) # score = tail_head_relation_box_vol - tail_relation_box.log_soft_volume( # temp=self.softbox_temp) score = head_tail_box_vol - tail.log_soft_volume( temp=self.softbox_temp) if len(np.where(score > 0)[0]): breakpoint() return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: transformed_box = self.get_relation_transform(head, relation) if self.is_eval(): if len(head.data.shape) > len(tail.data.shape): tail.data = torch.cat(head.data.shape[-3] * [tail.data]) elif len(head.data.shape) < len(tail.data.shape): transformed_box.data = torch.cat(tail.data.shape[-3] * [transformed_box.data]) intersection_box = transformed_box.gumbel_intersection( tail, gumbel_beta=self.gumbel_beta) intersection_vol = intersection_box._log_soft_volume_adjusted( intersection_box.z, intersection_box.Z, temp=self.softbox_temp, gumbel_beta=self.gumbel_beta) tail_vol = tail._log_soft_volume_adjusted(tail.z, tail.Z, temp=self.softbox_temp, gumbel_beta=self.gumbel_beta) score = intersection_vol - tail_vol return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation_head: torch.Tensor, relation_tail: torch.Tensor) -> torch.Tensor: head = self.get_relation_transform(box=head, relation=relation_head) tail = self.get_relation_transform(tail, relation_tail) head_tail_box_vol = head.intersection_log_soft_volume( tail, temp=self.softbox_temp) score = head_tail_box_vol - tail.log_soft_volume( temp=self.softbox_temp) return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: head_relation_box = relation.intersection(head) tail_relation_box = relation.intersection(tail) head_tail_relation_intersection_vol = tail_relation_box.intersection_log_soft_volume( head_relation_box, temp=self.softbox_temp) relation_box_vol = relation.log_soft_volume(temp=self.softbox_temp) score = head_tail_relation_intersection_vol - relation_box_vol return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: intersection_box = head.gumbel_intersection( tail, gumbel_beta=self.gumbel_beta) intersection_vol = intersection_box._log_soft_volume_adjusted( intersection_box.z, intersection_box.Z, temp=self.softbox_temp, gumbel_beta=self.gumbel_beta) tail_vol = tail._log_soft_volume_adjusted(tail.z, tail.Z, temp=self.softbox_temp, gumbel_beta=self.gumbel_beta) score = intersection_vol - tail_vol return score
def get_relation_transform(self, box: BoxTensor, relation: torch.Tensor): weight_delta = self.relation_delta_weight(relation) weight_min = self.relation_min_weight(relation) bias_delta = self.relation_delta_bias(relation) bias_min = self.relation_min_bias(relation) if len(box.data.shape) == 3: box.data[:, 0, :] = box.data[:, 0, :].clone() * weight_min + bias_min box.data[:, 1, :] = nn.functional.softplus(box.data[:, 1, :].clone() * weight_delta + bias_delta) else: box.data[:, :, 0, :] = box.data[:, :, 0, :].clone() * weight_min + bias_min box.data[:, :, 1, :] = nn.functional.softplus( box.data[:, :, 1, :].clone() * weight_delta + bias_delta) return box
def _get_triple_score_hard_box(self, head: BoxTensor, tail: BoxTensor, per_dim_op='max', accross_dim_op='max') -> torch.Tensor: """ Do not use this function for this class and its children. Implement get_scores_directly """ return head.contains_violations(tail, per_dim_op=per_dim_op, accross_dim_op=accross_dim_op, margin=self.margin)
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: torch.Tensor) -> torch.Tensor: """ Gets score using conditionals. :: note: We do not need to worry about the dimentions of the boxes. If it can sensibly broadcast it will. """ # get conditionals interval intersection scores numerators = head.dimension_wise_intersection_soft_volume( tail, temp=self.softbox_temp).clamp_min(1e-38) denominators = head.dimension_wise_soft_volume( temp=self.softbox_temp).clamp_min(1e-38) probs = numerators / denominators # shape = (batch, num_dims) weighted_probs = relation * probs score = torch.sum(weighted_probs, dim=-1) return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: """ Gets score using conditionals. :: note: We do not need to worry about the dimentions of the boxes. If it can sensibly broadcast it will. """ #head_relation_box = relation.intersection(head) #tail_relation_box = relation.intersection(tail) # tail_head_relation_box_vol = tail.intersection_log_soft_volume( # head_relation_box, temp=self.softbox_temp) # score = tail_head_relation_box_vol - head_relation_box.log_soft_volume( # temp=self.softbox_temp) head_tail_box_vol = head.intersection_log_soft_volume( tail, temp=self.softbox_temp) # score = tail_head_relation_box_vol - tail_relation_box.log_soft_volume( # temp=self.softbox_temp) score = head_tail_box_vol - tail.log_soft_volume( temp=self.softbox_temp) return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: if self.is_eval(): if len(head.data.shape) > len(tail.data.shape): tail.data = torch.cat(head.data.shape[-3] * [tail.data]) elif len(head.data.shape) < len(tail.data.shape): head.data = torch.cat(tail.data.shape[-3] * [head.data]) intersection_box = head.gumbel_intersection( tail, gumbel_beta=self.gumbel_beta) intersection_vol = intersection_box._log_bessel_volume( intersection_box.z, intersection_box.Z, gumbel_beta=self.gumbel_beta) tail_vol = tail._log_bessel_volume(tail.z, tail.Z, gumbel_beta=self.gumbel_beta) score = intersection_vol - tail_vol return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: if self.is_eval(): if len(head.data.shape) > len(tail.data.shape): tail.data = torch.cat(head.data.shape[-3] * [tail.data]) relation.data = torch.cat(head.data.shape[-3] * [relation.data]) elif len(head.data.shape) < len(tail.data.shape): head.data = torch.cat(tail.data.shape[-3] * [head.data]) relation.data = torch.cat(tail.data.shape[-3] * [relation.data]) tail_relation_box = relation.gumbel_intersection( tail, gumbel_beta=self.gumbel_beta) tail_head_relation_box = tail_relation_box.gumbel_intersection( head, gumbel_beta=self.gumbel_beta) tail_head_relation_box_vol = tail_head_relation_box._log_soft_volume_adjusted( tail_head_relation_box.z, tail_head_relation_box.Z, temp=self.softbox_temp, gumbel_beta=self.gumbel_beta) tail_vol = tail._log_soft_volume_adjusted(tail.z, tail.Z, temp=self.softbox_temp, gumbel_beta=self.gumbel_beta) score_head = tail_head_relation_box_vol - tail_vol return score_head
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: if self.is_eval(): if len(head.data.shape) > len(tail.data.shape): tail.data = torch.cat(head.data.shape[-3] * [tail.data]) elif len(head.data.shape) < len(tail.data.shape): head.data = torch.cat(tail.data.shape[-3] * [head.data]) head_sample = self.reparam_trick(head, gumbel_beta=self.gumbel_beta, n_samples=self.n_samples) tail_sample = self.reparam_trick(tail, gumbel_beta=self.gumbel_beta, n_samples=self.n_samples) intersection_sample_box = head_sample.gumbel_intersection( tail_sample, gumbel_beta=self.gumbel_beta) intersection_box = head.gumbel_intersection( tail, gumbel_beta=self.gumbel_beta) intersection_volume_fwd = intersection_sample_box._log_gumbel_volume( intersection_sample_box.z, intersection_box.Z) intersection_volume_bwd = intersection_sample_box._log_gumbel_volume( intersection_box.z, intersection_sample_box.Z) tail_volume_fwd = tail_sample._log_gumbel_volume(tail.z, tail_sample.Z) tail_volume_bwd = tail_sample._log_gumbel_volume(tail_sample.z, tail.Z) # score = (intersection_volume_fwd + intersection_volume_bwd)/2 - ( # tail_volume_fwd + tail_volume_bwd)/2 intersection_score = torch.logsumexp( torch.stack((intersection_volume_fwd, intersection_volume_bwd)), 0) tail_score = torch.logsumexp( torch.stack((tail_volume_fwd, tail_volume_bwd)), 0) score = intersection_score - tail_score if len(torch.where(score > 0)[0]): breakpoint() return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: """ Gets score using three way intersection We do not need to worry about the dimentions of the boxes. If it can sensibly broadcast it will. """ head_relation_box = relation.intersection(head) tail_relation_box = relation.intersection(tail) score = head_relation_box.intersection_log_soft_volume( tail_relation_box, temp=self.softbox_temp) return score
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor, head_rev: BoxTensor, tail_rev: BoxTensor, relation_rev: BoxTensor) -> torch.Tensor: tail_relation_box = relation.intersection(tail) tail_head_relation_box_vol = tail_relation_box.intersection_log_soft_volume( head, temp=self.softbox_temp) tail_vol = tail.log_soft_volume(temp=self.softbox_temp) score_fwd = tail_head_relation_box_vol - tail_vol tail_relation_box_rev = relation_rev.intersection(tail_rev) tail_head_relation_box_rev_vol = tail_relation_box_rev.intersection_soft_volume(head_rev, temp=self.softbox_temp) tail_rev_vol = tail_rev.log_soft_volume(temp=self.softbox_temp) score_rev = tail_head_relation_box_rev_vol - tail_rev_vol return 0.5*(score_fwd + score_rev)
def _get_triple_score(self, head: BoxTensor, tail: BoxTensor, relation: BoxTensor) -> torch.Tensor: """ Gets score using conditionals. :: note: We do not need to worry about the dimentions of the boxes. If it can sensibly broadcast it will. """ transformed_box = self.get_relation_transform(head, relation) head_tail_box_vol = transformed_box.intersection_log_soft_volume( tail, temp=self.softbox_temp) score = head_tail_box_vol - tail.log_soft_volume( temp=self.softbox_temp) return score
def reparam_trick(self, box: BoxTensor, embedding_keys: torch.Tensor) -> BoxTensor: dev = embedding_keys.device dist = MultivariateNormal( torch.zeros(box.data.shape[0], box.data.shape[-1]).to(dev), torch.eye(box.data.shape[-1]).to(dev)) samples = dist.sample(torch.Size([self.n_samples])) sample = torch.mean(samples, axis=0) L = torch.sqrt(self.sigma(embedding_keys)**2) #Cholesky decomposition shift = (L * sample).view([box.data.shape[0], 1, box.data.shape[-1]]) shift = shift.repeat(1, box.data.shape[-2], 1) #same amount of shift in z & Z box.data = box.data + shift #shift z return box
def reparam_trick(self, box: BoxTensor, gumbel_beta: float = 1., n_samples: int = 10) -> torch.Tensor: dev = box.data.device m = Gumbel( torch.zeros(box.data.shape[0], box.data.shape[-1]).to(dev), torch.tensor([1.0]).to(dev)) samples = m.sample(torch.Size([n_samples])) sample_fwd = torch.mean(samples, axis=0) samples = m.sample(torch.Size([n_samples])) sample_bwd = -torch.mean(samples, axis=0) z = sample_fwd * gumbel_beta + box.z.data Z = sample_bwd * gumbel_beta + box.Z.data return BoxTensor(torch.stack((z, Z), -2))