| n_score = score[:, pos_num:] | n_score = score[:, pos_num:] | ||||
| return p_score, n_score | return p_score, n_score | ||||
| def bpr_loss(p_scores, n_values): | |||||
| p1 = p_scores[:,0,None] | |||||
| p2 = p_scores[:,1,None] | |||||
| num_neg = n_values.shape[1] | |||||
| half_index = int(num_neg/2) | |||||
| d1 = torch.sub(p1,n_values[:,0:half_index]) | |||||
| d2 = torch.sub(p2,n_values[:,half_index:]) | |||||
| t = F.logsigmoid(torch.add(d1,d2)) | |||||
| loss = (-1) * t.sum() / n_values.shape[1] | |||||
| return loss | |||||
| class MetaTL(nn.Module): | class MetaTL(nn.Module): | ||||
| def __init__(self, itemnum, parameter): | def __init__(self, itemnum, parameter): | ||||
| self.embedding_learner = EmbeddingLearner() | self.embedding_learner = EmbeddingLearner() | ||||
| self.loss_func = nn.MarginRankingLoss(self.margin) | self.loss_func = nn.MarginRankingLoss(self.margin) | ||||
| self.rel_q_sharing = dict() | self.rel_q_sharing = dict() | ||||
| def split_concat(self, positive, negative): | def split_concat(self, positive, negative): | ||||
| y = torch.Tensor([1]).to(self.device) | y = torch.Tensor([1]).to(self.device) | ||||
| self.zero_grad() | self.zero_grad() | ||||
| sorted,indecies = torch.sort(n_score, descending=True,dim=1) | |||||
| n_values = sorted[:,0:p_score.shape[1]] | |||||
| loss = self.loss_func(p_score, n_values, y) | |||||
| # sorted,indecies = torch.sort(n_score, descending=True,dim=1) | |||||
| # n_values = sorted[:,0:p_score.shape[1]] | |||||
| n_values = n_score | |||||
| loss = bpr_loss(p_score,n_values) | |||||
| # loss = self.loss_func(p_score, n_values, y) | |||||
| loss.backward(retain_graph=True) | loss.backward(retain_graph=True) | ||||
| grad_meta = rel.grad | grad_meta = rel.grad | ||||
| rel_q = rel - self.beta*grad_meta | rel_q = rel - self.beta*grad_meta | ||||
| self.rel_q_sharing[curr_rel] = rel_q | self.rel_q_sharing[curr_rel] = rel_q | ||||
| rel_q = rel_q.expand(-1, num_q + num_n, -1, -1) | rel_q = rel_q.expand(-1, num_q + num_n, -1, -1) |
| seq = np.zeros([maxlen], dtype=np.int32) | seq = np.zeros([maxlen], dtype=np.int32) | ||||
| pos = np.zeros([maxlen], dtype=np.int32) | pos = np.zeros([maxlen], dtype=np.int32) | ||||
| neg = np.zeros([maxlen*30], dtype=np.int32) | |||||
| neg = np.zeros([maxlen*5], dtype=np.int32) | |||||
| if len(user_train[user]) < maxlen: | if len(user_train[user]) < maxlen: | ||||
| nxt_idx = len(user_train[user]) - 1 | nxt_idx = len(user_train[user]) - 1 | ||||
| # for idx in range(maxlen*30 - 1): | # for idx in range(maxlen*30 - 1): | ||||
| # support_negative_triples.append([seq[-1], curr_rel, neg[idx]]) | # support_negative_triples.append([seq[-1], curr_rel, neg[idx]]) | ||||
| for j in range(30): | |||||
| for j in range(5): | |||||
| for idx in range(maxlen-1): | for idx in range(maxlen-1): | ||||
| support_negative_triples.append([seq[idx], curr_rel, neg[j*maxlen + idx]]) | support_negative_triples.append([seq[idx], curr_rel, neg[j*maxlen + idx]]) | ||||
| seq = np.zeros([self.maxlen], dtype=np.int32) | seq = np.zeros([self.maxlen], dtype=np.int32) | ||||
| pos = np.zeros([self.maxlen - 1], dtype=np.int32) | pos = np.zeros([self.maxlen - 1], dtype=np.int32) | ||||
| # neg = np.zeros([self.maxlen*30 - 1], dtype=np.int32) | # neg = np.zeros([self.maxlen*30 - 1], dtype=np.int32) | ||||
| neg = np.zeros([self.maxlen * 30], dtype=np.int32) | |||||
| neg = np.zeros([self.maxlen * 5], dtype=np.int32) | |||||
| idx = self.maxlen - 1 | idx = self.maxlen - 1 | ||||
| # for idx in range(len(neg)): | # for idx in range(len(neg)): | ||||
| # support_negative_triples.append([seq[-1],curr_rel,neg[idx]]) | # support_negative_triples.append([seq[-1],curr_rel,neg[idx]]) | ||||
| for j in range(30): | |||||
| for j in range(5): | |||||
| for idx in range(self.maxlen-1): | for idx in range(self.maxlen-1): | ||||
| support_negative_triples.append([seq[idx], curr_rel, neg[j * self.maxlen + idx]]) | support_negative_triples.append([seq[idx], curr_rel, neg[j * self.maxlen + idx]]) | ||||