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]]) | ||||