Browse Source

Implementing Robustify Negative sampling and undo prepossessing

RNN
mohamad maheri 2 years ago
parent
commit
de53dda45f
5 changed files with 485 additions and 212 deletions
  1. 17
    10
      main.py
  2. 75
    44
      models.py
  3. 39
    100
      sampler.py
  4. 327
    32
      trainer.py
  5. 27
    26
      utils.py

+ 17
- 10
main.py View File

from utils import * from utils import *
from sampler import * from sampler import *
import json import json
import torch


import argparse import argparse


def get_params(): def get_params():
args = argparse.ArgumentParser() args = argparse.ArgumentParser()
args.add_argument("-data", "--dataset", default="electronics", type=str) args.add_argument("-data", "--dataset", default="electronics", type=str)
args.add_argument("-seed", "--seed", default=None, type=int)
args.add_argument("-seed", "--seed", default=7, type=int)
args.add_argument("-K", "--K", default=3, type=int) #NUMBER OF SHOT args.add_argument("-K", "--K", default=3, type=int) #NUMBER OF SHOT


args.add_argument("-dim", "--embed_dim", default=100, type=int)
args.add_argument("-dim", "--embed_dim", default=128, type=int)
args.add_argument("-bs", "--batch_size", default=1024, type=int) args.add_argument("-bs", "--batch_size", default=1024, type=int)
args.add_argument("-lr", "--learning_rate", default=0.001, type=float) args.add_argument("-lr", "--learning_rate", default=0.001, type=float)


args.add_argument("-epo", "--epoch", default=100000, type=int) args.add_argument("-epo", "--epoch", default=100000, type=int)
args.add_argument("-prt_epo", "--print_epoch", default=100, type=int) args.add_argument("-prt_epo", "--print_epoch", default=100, type=int)
args.add_argument("-eval_epo", "--eval_epoch", default=1000, type=int)
args.add_argument("-eval_epo", "--eval_epoch", default=500, type=int)


args.add_argument("-b", "--beta", default=5, type=float) args.add_argument("-b", "--beta", default=5, type=float)
args.add_argument("-m", "--margin", default=1, type=float) args.add_argument("-m", "--margin", default=1, type=float)
args.add_argument("-p", "--dropout_p", default=0.5, type=float) args.add_argument("-p", "--dropout_p", default=0.5, type=float)


args.add_argument("-gpu", "--device", default=0, type=int) args.add_argument("-gpu", "--device", default=0, type=int)
args.add_argument("--number_of_neg",default=5,type=int)
args.add_argument("--number_of_neg",default=1,type=int)






params[k] = v params[k] = v





# params['device'] = torch.device('cuda:'+str(args.device))
params['device'] = args.device
params['device'] = torch.device('cuda:'+str(args.device))
# params['device'] = args.device
# params['device'] = torch.device('cpu') # params['device'] = torch.device('cpu')


return params, args return params, args


if __name__ == '__main__': if __name__ == '__main__':
print(torch.__version__)
print(torch.cuda.is_available()) print(torch.cuda.is_available())
params, args = get_params() params, args = get_params()


params['varset_size'] = 1000
params['alpha'] = 0.5
params['S1'] = 40
params['S2_div_S1'] = 1
params['temperature'] = 1.0
params['warmup'] = 20.0

if params['seed'] is not None: if params['seed'] is not None:
SEED = params['seed'] SEED = params['seed']
torch.manual_seed(SEED) torch.manual_seed(SEED)
print("===============", torch.cuda.device_count(), "=======") print("===============", torch.cuda.device_count(), "=======")
user_train, usernum_train, itemnum, user_input_test, user_test, user_input_valid, user_valid = data_load(args.dataset, args.K) user_train, usernum_train, itemnum, user_input_test, user_test, user_input_valid, user_valid = data_load(args.dataset, args.K)


sampler = WarpSampler(user_train, usernum_train, itemnum, batch_size=args.batch_size, maxlen=args.K, n_workers=3,params=params)
sampler = WarpSampler(user_train, usernum_train, itemnum, batch_size=args.batch_size, maxlen=args.K, n_workers=3)


sampler_test = DataLoader(user_input_test, user_test, itemnum, params) sampler_test = DataLoader(user_input_test, user_test, itemnum, params)


sampler_valid = DataLoader(user_input_valid, user_valid, itemnum, params) sampler_valid = DataLoader(user_input_valid, user_valid, itemnum, params)


print("===============", torch.cuda.device_count(), "=======") print("===============", torch.cuda.device_count(), "=======")

trainer = Trainer([sampler, sampler_valid, sampler_test], itemnum, params)
trainer = Trainer([sampler, sampler_valid, sampler_test], itemnum, params,usernum_train,user_train)
print("===============", torch.cuda.device_count(), "=======") print("===============", torch.cuda.device_count(), "=======")
trainer.train() trainer.train()



+ 75
- 44
models.py View File

import torch import torch
import torch.nn as nn import torch.nn as nn
from torch.nn import functional as F from torch.nn import functional as F
from numpy import linalg as LA
import numpy as np



class Embedding(nn.Module): class Embedding(nn.Module):
def __init__(self, num_ent, parameter): def __init__(self, num_ent, parameter):
# self.device = torch.device('cuda:0') # self.device = torch.device('cuda:0')
self.device = torch.device(parameter['device']) self.device = torch.device(parameter['device'])
self.es = parameter['embed_dim'] self.es = parameter['embed_dim']
self.embedding = nn.Embedding(num_ent + 1, self.es) self.embedding = nn.Embedding(num_ent + 1, self.es)
nn.init.xavier_uniform_(self.embedding.weight) nn.init.xavier_uniform_(self.embedding.weight)


idx = torch.LongTensor(idx).to(self.device) idx = torch.LongTensor(idx).to(self.device)
return self.embedding(idx) return self.embedding(idx)



class MetaLearner(nn.Module): class MetaLearner(nn.Module):
def __init__(self, K, embed_size=100, num_hidden1=500, num_hidden2=200, out_size=100, dropout_p=0.5): def __init__(self, K, embed_size=100, num_hidden1=500, num_hidden2=200, out_size=100, dropout_p=0.5):
super(MetaLearner, self).__init__() super(MetaLearner, self).__init__()
self.out_size = embed_size self.out_size = embed_size
self.hidden_size = embed_size self.hidden_size = embed_size
# self.rnn = nn.LSTM(embed_size,self.hidden_size,2,dropout=0.2) # self.rnn = nn.LSTM(embed_size,self.hidden_size,2,dropout=0.2)
self.rnn = nn.GRU(input_size=embed_size,hidden_size=self.hidden_size, num_layers=1)
self.rnn = nn.GRU(input_size=embed_size, hidden_size=self.embed_size * 2, num_layers=1)
self.activation = nn.LeakyReLU()
self.linear = nn.Linear(self.embed_size * 2, self.embed_size)
self.norm = nn.BatchNorm1d(num_features=self.out_size)


# nn.init.xavier_normal_(self.rnn.all_weights)
# nn.init.xavier_normal_(self.linear.weight)


def forward(self, inputs):
def forward(self, inputs, evaluation=False):
size = inputs.shape size = inputs.shape
x = torch.stack([inputs[:,0,0,:],inputs[:,0,1,:],inputs[:,1,1,:]],dim=1)
x = x.transpose(0,1)
x = torch.stack([inputs[:, 0, 0, :], inputs[:, 0, 1, :], inputs[:, 1, 1, :]], dim=1)
x = x.transpose(0, 1)


# _,(x,c) = self.rnn(x) # _,(x,c) = self.rnn(x)
x,c = self.rnn(x)
x, c = self.rnn(x)
x = x[-1] x = x[-1]
x = x.squeeze(0)
if not evaluation:
x = x.squeeze(0)

x = self.activation(x)
x = self.linear(x)
x = self.norm(x)


return x.view(size[0], 1, 1, self.out_size) return x.view(size[0], 1, 1, self.out_size)



class EmbeddingLearner(nn.Module): class EmbeddingLearner(nn.Module):
def __init__(self): def __init__(self):
super(EmbeddingLearner, self).__init__() super(EmbeddingLearner, self).__init__()
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,device):

def bpr_loss(p_scores, n_values, device):
ratio = int(n_values.shape[1] / p_scores.shape[1]) ratio = int(n_values.shape[1] / p_scores.shape[1])
temp_pvalues = torch.tensor([],device=device)
temp_pvalues = torch.tensor([], device=device)
for i in range(p_scores.shape[1]): for i in range(p_scores.shape[1]):
temp_pvalues = torch.cat((temp_pvalues, p_scores[:, i, None].expand(-1, ratio)), dim=1) temp_pvalues = torch.cat((temp_pvalues, p_scores[:, i, None].expand(-1, ratio)), dim=1)


d = torch.sub(temp_pvalues,n_values)
d = torch.sub(temp_pvalues, n_values)
t = F.logsigmoid(d) t = F.logsigmoid(d)
loss = -1 * (1.0/n_values.shape[1]) * t.sum(dim=1)
loss = -1 * (1.0 / n_values.shape[1]) * t.sum(dim=1)
loss = loss.sum(dim=0) loss = loss.sum(dim=0)
return loss return loss


def bpr_max_loss(p_scores, n_values,device):
s = F.softmax(n_values,dim=1)

def bpr_max_loss(p_scores, n_values, device):
s = F.softmax(n_values, dim=1)
ratio = int(n_values.shape[1] / p_scores.shape[1]) ratio = int(n_values.shape[1] / p_scores.shape[1])
temp_pvalues = torch.tensor([],device=device)
temp_pvalues = torch.tensor([], device=device)
for i in range(p_scores.shape[1]): for i in range(p_scores.shape[1]):
temp_pvalues = torch.cat((temp_pvalues,p_scores[:,i,None].expand(-1,ratio)),dim=1)
temp_pvalues = torch.cat((temp_pvalues, p_scores[:, i, None].expand(-1, ratio)), dim=1)


d = torch.sigmoid(torch.sub(temp_pvalues,n_values))
t = torch.mul(s,d)
d = torch.sigmoid(torch.sub(temp_pvalues, n_values))
t = torch.mul(s, d)
loss = -1 * torch.log(t.sum(dim=1)) loss = -1 * torch.log(t.sum(dim=1))
loss = loss.sum() loss = loss.sum()
return loss return loss


def bpr_max_loss_regularized(p_scores, n_values,device,l=0.0001):
s = F.softmax(n_values,dim=1)

def bpr_max_loss_regularized(p_scores, n_values, device, l=0.0001):
s = F.softmax(n_values, dim=1)
ratio = int(n_values.shape[1] / p_scores.shape[1]) ratio = int(n_values.shape[1] / p_scores.shape[1])
temp_pvalues = torch.tensor([],device=device)
temp_pvalues = torch.tensor([], device=device)
for i in range(p_scores.shape[1]): for i in range(p_scores.shape[1]):
temp_pvalues = torch.cat((temp_pvalues,p_scores[:,i,None].expand(-1,ratio)),dim=1)
temp_pvalues = torch.cat((temp_pvalues, p_scores[:, i, None].expand(-1, ratio)), dim=1)


d = torch.sigmoid(torch.sub(temp_pvalues,n_values))
t = torch.mul(s,d)
d = torch.sigmoid(torch.sub(temp_pvalues, n_values))
t = torch.mul(s, d)
loss = -1 * torch.log(t.sum(dim=1)) loss = -1 * torch.log(t.sum(dim=1))
loss = loss.sum() loss = loss.sum()


loss2 = torch.mul(s,n_values**2)
loss2 = torch.mul(s, n_values ** 2)
loss2 = loss2.sum(dim=1) loss2 = loss2.sum(dim=1)
loss2 = loss2.sum() loss2 = loss2.sum()
return loss + l*loss2
return loss + l * loss2


def top_loss(p_scores, n_values,device):

def top_loss(p_scores, n_values, device):
ratio = int(n_values.shape[1] / p_scores.shape[1]) ratio = int(n_values.shape[1] / p_scores.shape[1])
temp_pvalues = torch.tensor([],device=device)
temp_pvalues = torch.tensor([], device=device)
for i in range(p_scores.shape[1]): for i in range(p_scores.shape[1]):
temp_pvalues = torch.cat((temp_pvalues, p_scores[:, i, None].expand(-1, ratio)), dim=1) temp_pvalues = torch.cat((temp_pvalues, p_scores[:, i, None].expand(-1, ratio)), dim=1)


t1 = torch.sigmoid(torch.sub(n_values , temp_pvalues))
t2 = torch.sigmoid(torch.pow(n_values,2))
t = torch.add(t1,t2)
t1 = torch.sigmoid(torch.sub(n_values, temp_pvalues))
t2 = torch.sigmoid(torch.pow(n_values, 2))
t = torch.add(t1, t2)
t = t.sum(dim=1) t = t.sum(dim=1)
loss = t / n_values.shape[1] loss = t / n_values.shape[1]
loss = loss.sum(dim=0) loss = loss.sum(dim=0)
self.embedding = Embedding(itemnum, parameter) self.embedding = Embedding(itemnum, parameter)


self.relation_learner = MetaLearner(parameter['K'] - 1, embed_size=self.embed_dim, num_hidden1=500, self.relation_learner = MetaLearner(parameter['K'] - 1, embed_size=self.embed_dim, num_hidden1=500,
num_hidden2=200, out_size=100, dropout_p=0)
num_hidden2=200, out_size=100, dropout_p=0)


self.embedding_learner = EmbeddingLearner() self.embedding_learner = EmbeddingLearner()
# self.loss_func = nn.MarginRankingLoss(self.margin)
self.loss_func = nn.MarginRankingLoss(self.margin)
# self.loss_func = bpr_max_loss # self.loss_func = bpr_max_loss
self.loss_func = bpr_loss
# self.loss_func = bpr_loss


self.rel_q_sharing = dict() self.rel_q_sharing = dict()


negative[:, :, 1, :]], 1).unsqueeze(2) negative[:, :, 1, :]], 1).unsqueeze(2)
return pos_neg_e1, pos_neg_e2 return pos_neg_e1, pos_neg_e2


def fast_forward(self, tasks, curr_rel=''):
with torch.no_grad():
sup = self.embedding(tasks)
K = sup.shape[1]
rel_q = self.rel_q_sharing[curr_rel]
sup_neg_e1, sup_neg_e2 = sup[:, :, 0, :], sup[:, :, 1, :]
a = sup_neg_e1.cpu().detach().numpy()
b = rel_q.squeeze(1).cpu().detach().numpy()
b = np.tile(b, (1, a.shape[-2], 1))
c = sup_neg_e2.cpu().detach().numpy()
# print(a.shape,b.shape,c.shape)
scores = -LA.norm(a + b - c, 2, -1)
return scores

def forward(self, task, iseval=False, curr_rel=''): def forward(self, task, iseval=False, curr_rel=''):
# transfer task string into embedding # transfer task string into embedding
support, support_negative, query, negative = [self.embedding(t) for t in task] support, support_negative, query, negative = [self.embedding(t) for t in task]


K = support.shape[1] # num of K
K = support.shape[1] # num of K
num_sn = support_negative.shape[1] # num of support negative num_sn = support_negative.shape[1] # num of support negative
num_q = query.shape[1] # num of query
num_n = negative.shape[1] # num of query negative
num_q = query.shape[1] # num of query
num_n = negative.shape[1] # num of query negative


rel = self.relation_learner(support)
rel = self.relation_learner(support, iseval)
rel.retain_grad() rel.retain_grad()


rel_s = rel.expand(-1, K+num_sn, -1, -1)
rel_s = rel.expand(-1, K + num_sn, -1, -1)


if iseval and curr_rel != '' and curr_rel in self.rel_q_sharing.keys(): if iseval and curr_rel != '' and curr_rel in self.rel_q_sharing.keys():
rel_q = self.rel_q_sharing[curr_rel] rel_q = self.rel_q_sharing[curr_rel]


p_score, n_score = self.embedding_learner(sup_neg_e1, sup_neg_e2, rel_s, K) p_score, n_score = self.embedding_learner(sup_neg_e1, sup_neg_e2, rel_s, K)


# 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) # sorted,indecies = torch.sort(n_score, descending=True,dim=1)
# n_values = sorted[:,0:p_score.shape[1]] # n_values = sorted[:,0:p_score.shape[1]]


# loss = self.loss_func(p_score, n_values, y)
loss = self.loss_func(p_score,n_score,device=self.device)
loss = self.loss_func(p_score, n_score, y)
# loss = self.loss_func(p_score,n_score,device=self.device)
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)


que_neg_e1, que_neg_e2 = self.split_concat(query, negative)
que_neg_e1, que_neg_e2 = self.split_concat(query, negative)
p_score, n_score = self.embedding_learner(que_neg_e1, que_neg_e2, rel_q, num_q) p_score, n_score = self.embedding_learner(que_neg_e1, que_neg_e2, rel_q, num_q)


return p_score, n_score return p_score, n_score

+ 39
- 100
sampler.py View File

import sys import sys
import copy import copy
import torch
import random import random
import numpy as np import numpy as np
from collections import defaultdict, Counter from collections import defaultdict, Counter
from multiprocessing import Process, Queue from multiprocessing import Process, Queue




def random_neq(l, r, s, user_train,usernum):
# t = np.random.randint(l, r)
# while t in s:
# t = np.random.randint(l, r)
# return t
# user = np.random.choice(1, usernum + 1)
def random_neq(l, r, s):
t = np.random.randint(l, r)
while t in s:
t = np.random.randint(l, r)
return t


# user = random.randint(1,usernum+1)
# while len(user_train[user])<3:
# user = random.randint(1, usernum + 1)
# candid_item = user_train[user][random.randint(0, len(user_train[user])-1)]
#
# while candid_item in s:
# while len(user_train[user]) < 3:
# user = random.randint(1, usernum + 1)
# candid_item = user_train[user][random.randint(0, len(user_train[user])-1)]
# return candid_item


user = random.choice(list(user_train.keys()))
item = random.choice(user_train[user])
def sample_function_mixed(user_train, usernum, itemnum, batch_size, maxlen, result_queue, SEED):
def sample():


while item in s:
user = random.choice(list(user_train.keys()))
item = random.choice(user_train[user])
return item

def random_negetive_batch(l, r, s, user_train,usernum, batch_users):
user = np.random.choice(batch_users)
candid_item = user_train[user][np.random.randint(0, len(user_train[user]))]

while candid_item in s:
user = np.random.choice(batch_users)
candid_item = user_train[user][np.random.randint(0, len(user_train[user]))]
return candid_item


def sample_function_mixed(user_train, usernum, itemnum, batch_size, maxlen, result_queue, SEED,number_of_neg):

def sample(user,batch_users):
if random.random()<=0.5:
# user = np.random.randint(1, usernum + 1)
# while len(user_train[user]) <= 1: user = np.random.randint(1, usernum + 1)
if random.random() < 0.5:
user = np.random.randint(1, usernum + 1)
while len(user_train[user]) <= 1: user = np.random.randint(1, usernum + 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-1)*number_of_neg + 1], dtype=np.int32)
neg = np.zeros([maxlen], 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
else: else:
nxt_idx = np.random.randint(maxlen,len(user_train[user]))
nxt_idx = np.random.randint(maxlen, len(user_train[user]))


nxt = user_train[user][nxt_idx] nxt = user_train[user][nxt_idx]
idx = maxlen - 1 idx = maxlen - 1


ts = set(user_train[user]) ts = set(user_train[user])
for i in reversed(user_train[user][(nxt_idx - maxlen) : nxt_idx ]):
for i in reversed(user_train[user][min(0, nxt_idx - 1 - maxlen): nxt_idx - 1]):
seq[idx] = i seq[idx] = i
pos[idx] = nxt pos[idx] = nxt
# if nxt != 0: neg[idx] = random_neq(1, itemnum + 1, ts, user_train,usernum)
if nxt != 0: neg[idx] = random_neq(1, itemnum + 1, ts)
nxt = i nxt = i
idx -= 1 idx -= 1
if idx == -1: break if idx == -1: break


for i in range(len(neg)):
# neg[i] = random_neq(1, itemnum + 1, ts, user_train,usernum)
neg[i] = random_negetive_batch(1, itemnum + 1, ts, user_train, usernum, batch_users = batch_users)

curr_rel = user curr_rel = user
support_triples, support_negative_triples, query_triples, negative_triples = [], [], [], [] support_triples, support_negative_triples, query_triples, negative_triples = [], [], [], []
for idx in range(maxlen-1):
support_triples.append([seq[idx],curr_rel,pos[idx]])
# support_negative_triples.append([seq[idx],curr_rel,neg[idx]])
# support_negative_triples.append([seq[-1], curr_rel, neg[idx]])

# for idx in range(maxlen*30 - 1):
# support_negative_triples.append([seq[-1], curr_rel, neg[idx]])
for j in range(number_of_neg):
for idx in range(maxlen-1):
support_negative_triples.append([seq[idx], curr_rel, neg[j*(maxlen-1) + idx]])

query_triples.append([seq[-1],curr_rel,pos[-1]])
negative_triples.append([seq[-1],curr_rel,neg[-1]])
for idx in range(maxlen - 1):
support_triples.append([seq[idx], curr_rel, pos[idx]])
support_negative_triples.append([seq[idx], curr_rel, neg[idx]])
query_triples.append([seq[-1], curr_rel, pos[-1]])
negative_triples.append([seq[-1], curr_rel, neg[-1]])


return support_triples, support_negative_triples, query_triples, negative_triples, curr_rel return support_triples, support_negative_triples, query_triples, negative_triples, curr_rel


else: else:
# print("bug happened in sample_function_mixed")
# user = np.random.randint(1, usernum + 1)
# while len(user_train[user]) <= 1: user = np.random.randint(1, usernum + 1)
user = np.random.randint(1, usernum + 1)
while len(user_train[user]) <= 1: user = np.random.randint(1, usernum + 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*number_of_neg], dtype=np.int32)
neg = np.zeros([maxlen], dtype=np.int32)


list_idx = random.sample([i for i in range(len(user_train[user]))], maxlen + 1) list_idx = random.sample([i for i in range(len(user_train[user]))], maxlen + 1)
list_item = [user_train[user][i] for i in sorted(list_idx)] list_item = [user_train[user][i] for i in sorted(list_idx)]
for i in reversed(list_item[:-1]): for i in reversed(list_item[:-1]):
seq[idx] = i seq[idx] = i
pos[idx] = nxt pos[idx] = nxt
# if nxt != 0: neg[idx] = random_neq(1, itemnum + 1, ts)
if nxt != 0: neg[idx] = random_neq(1, itemnum + 1, ts)
nxt = i nxt = i
idx -= 1 idx -= 1
if idx == -1: break if idx == -1: break


curr_rel = user curr_rel = user
support_triples, support_negative_triples, query_triples, negative_triples = [], [], [], [] support_triples, support_negative_triples, query_triples, negative_triples = [], [], [], []

for i in range(len(neg)):
# neg[i] = random_neq(1, itemnum + 1, ts, user_train,usernum)
neg[i] = random_negetive_batch(1, itemnum + 1, ts, user_train, usernum, batch_users = batch_users)

for j in range(number_of_neg):
for idx in range(maxlen-1):
support_negative_triples.append([seq[idx], curr_rel, neg[j*maxlen + idx]])

for idx in range(maxlen-1):
support_triples.append([seq[idx],curr_rel,pos[idx]])
# support_negative_triples.append([seq[idx],curr_rel,neg[idx]])
query_triples.append([seq[-1],curr_rel,pos[-1]])
negative_triples.append([seq[-1],curr_rel,neg[-1]])
for idx in range(maxlen - 1):
support_triples.append([seq[idx], curr_rel, pos[idx]])
support_negative_triples.append([seq[idx], curr_rel, neg[idx]])
query_triples.append([seq[-1], curr_rel, pos[-1]])
negative_triples.append([seq[-1], curr_rel, neg[-1]])


return support_triples, support_negative_triples, query_triples, negative_triples, curr_rel return support_triples, support_negative_triples, query_triples, negative_triples, curr_rel


np.random.seed(SEED) np.random.seed(SEED)

while True: while True:
one_batch = [] one_batch = []

users = []
for i in range(batch_size):
user = np.random.randint(1, usernum + 1)
while len(user_train[user]) <= 1: user = np.random.randint(1, usernum + 1)
users.append(user)

for i in range(batch_size): for i in range(batch_size):
one_batch.append(sample(user = users[i], batch_users = users))
one_batch.append(sample())


support, support_negative, query, negative, curr_rel = zip(*one_batch) support, support_negative, query, negative, curr_rel = zip(*one_batch)


result_queue.put(([support, support_negative, query, negative], curr_rel)) result_queue.put(([support, support_negative, query, negative], curr_rel))



class WarpSampler(object): class WarpSampler(object):
def __init__(self, User, usernum, itemnum, batch_size=64, maxlen=10, n_workers=1,params = None):
def __init__(self, User, usernum, itemnum, batch_size=64, maxlen=10, n_workers=1):
self.result_queue = Queue(maxsize=n_workers * 10) self.result_queue = Queue(maxsize=n_workers * 10)
self.processors = [] self.processors = []
for i in range(n_workers): for i in range(n_workers):
self.processors.append( self.processors.append(
Process(target=sample_function_mixed, args=(User, Process(target=sample_function_mixed, args=(User,
usernum,
itemnum,
batch_size,
maxlen,
self.result_queue,
np.random.randint(2e9),
params['number_of_neg']
)))
usernum,
itemnum,
batch_size,
maxlen,
self.result_queue,
np.random.randint(2e9)
)))
self.processors[-1].daemon = True self.processors[-1].daemon = True
self.processors[-1].start() self.processors[-1].start()


for p in self.processors: for p in self.processors:
p.terminate() p.terminate()
p.join() p.join()



+ 327
- 32
trainer.py View File

from models import * from models import *
import os import os
import sys import sys
import torch
import shutil import shutil
import logging import logging
import numpy as np import numpy as np
import random
import copy
from operator import itemgetter
import gc




class Trainer: class Trainer:
def __init__(self, data_loaders, itemnum, parameter):
def __init__(self, data_loaders, itemnum, parameter, user_train_num, user_train):
# print(user_train)
self.parameter = parameter self.parameter = parameter
# data loader # data loader
self.train_data_loader = data_loaders[0] self.train_data_loader = data_loaders[0]
self.batch_size = parameter['batch_size'] self.batch_size = parameter['batch_size']
self.learning_rate = parameter['learning_rate'] self.learning_rate = parameter['learning_rate']
self.epoch = parameter['epoch'] self.epoch = parameter['epoch']
# self.print_epoch = parameter['print_epoch']
# self.eval_epoch = parameter['eval_epoch']
# self.device = torch.device(parameter['device'])
self.device = parameter['device'] self.device = parameter['device']

self.MetaTL = MetaTL(itemnum, parameter) self.MetaTL = MetaTL(itemnum, parameter)
self.MetaTL.to(parameter['device']) self.MetaTL.to(parameter['device'])

self.optimizer = torch.optim.Adam(self.MetaTL.parameters(), self.learning_rate) self.optimizer = torch.optim.Adam(self.MetaTL.parameters(), self.learning_rate)

if parameter['eval_epoch']: if parameter['eval_epoch']:
self.eval_epoch = parameter['eval_epoch'] self.eval_epoch = parameter['eval_epoch']
else: else:
self.eval_epoch = 1000 self.eval_epoch = 1000


self.varset_size = parameter['varset_size']
self.user_train = user_train
self.warmup = parameter['warmup']
self.alpha = parameter['alpha']
self.S1 = parameter['S1']
self.S2_div_S1 = parameter['S2_div_S1']
self.temperature = parameter['temperature']
self.itemnum = itemnum
self.user_train_num = user_train_num
# init the two candidate sets for monitoring variance
self.candidate_cur = np.random.choice(itemnum, [user_train_num + 1, self.varset_size])
# for i in range(1,user_train_num+1):
# for j in range(self.varset_size):
# while self.candidate_cur[i, j] in user_train[i]:
# self.candidate_cur[i, j] = random.randint(1, itemnum)

# self.candidate_nxt = [np.random.choice(itemnum, [user_train_num+1, self.varset_size]) for _ in range(5)]
# for c in range(5):
# for i in range(1,user_train_num+1):
# for j in range(self.varset_size):
# while self.candidate_nxt[c][i, j] in user_train[i]:
# self.candidate_nxt[c][i, j] = random.randint(1, itemnum)

self.Mu_idx = {}
for i in range(user_train_num + 1):
Mu_idx_tmp = random.sample(list(range(self.varset_size)), self.S1)
self.Mu_idx[i] = Mu_idx_tmp

# todo : calculate score of positive items
self.score_cand_cur = {}
self.score_pos_cur = {}

# final candidate after execution of change_mu (after one_step) (for later epochs)
self.final_negative_items = {}

def change_mu(self, p_score, n_score, epoch_cur, users, train_task):
negitems = {}
negitems_candidates_all = {}

# for i in users:
# negitems_candidates_all[i] = self.Mu_idx[i]
negitems_candidates_all = self.Mu_idx.copy()

ratings_positems = p_score.cpu().detach().numpy()
ratings_positems = np.reshape(ratings_positems, [-1])

# added
cnt = 0
for i in users:
self.score_pos_cur[i] = ratings_positems[cnt]
cnt += 1

Mu_items_all = {index: value[negitems_candidates_all[i]] for index, value in enumerate(self.candidate_cur)}

task = np.array(train_task[2])
task = np.tile(task, reps=(1, self.S1, 1))
task[:, :, 2] = np.array(itemgetter(*users)(Mu_items_all))

ratings_candidates_all = self.MetaTL.fast_forward(task, users)

hisscore_candidates_all = [self.score_cand_cur[i][:, negitems_candidates_all[i]] for user in users]
hisscore_pos_all = ratings_positems.copy()

hisscore_candidates_all = np.array(hisscore_candidates_all).transpose((1, 0, 2))

hisscore_pos_all = np.array(hisscore_pos_all)
hisscore_pos_all = hisscore_pos_all[:, np.newaxis]
hisscore_pos_all = np.tile(hisscore_pos_all, (hisscore_candidates_all.shape[0], 1, 1))

hislikelihood_candidates_all = 1 / (1 + np.exp(hisscore_pos_all - hisscore_candidates_all))

mean_candidates_all = np.mean(hislikelihood_candidates_all[:, :], axis=0)
variance_candidates_all = np.zeros(mean_candidates_all.shape)
for i in range(hislikelihood_candidates_all.shape[0]):
variance_candidates_all += (hislikelihood_candidates_all[i, :, :] - mean_candidates_all) ** 2
variance_candidates_all = np.sqrt(variance_candidates_all / hislikelihood_candidates_all.shape[0])

likelihood_candidates_all = \
1 / (1 + np.exp(np.expand_dims(ratings_positems, -1) - ratings_candidates_all))

# Top sampling strategy by score + alpha * std
item_arg_all = None
if self.alpha >= 0:
# item_arg_all = np.argmax(likelihood_candidates_all +
# self.alpha * min(1, epoch_cur / self.warmup)
# * variance_candidates_all, axis=1)
a = likelihood_candidates_all + self.alpha * min(1, epoch_cur / self.warmup) * variance_candidates_all
item_arg_all = np.argpartition(a, kth=(-2), axis=1)
item_arg_all = np.array(item_arg_all)[:, -2:]
else:
item_arg_all = np.argmax(variance_candidates_all, axis=1)

# negitems = { user : self.candidate_cur[user][negitems_candidates_all[user][item_arg_all[index]]] for index,user in enumerate(users)}
negitems0 = {user: self.candidate_cur[user][negitems_candidates_all[user][item_arg_all[index][0]]] for
index, user in enumerate(users)}
negitems1 = {user: self.candidate_cur[user][negitems_candidates_all[user][item_arg_all[index][1]]] for
index, user in enumerate(users)}

###############################
for i in users:
self.final_negative_items[i] = [negitems0[i], negitems1[i]]
###############################

# update Mu
negitems_mu_candidates = {}

for i in users:
Mu_set = set(self.Mu_idx[i])

while len(self.Mu_idx[i]) < self.S1 * (1 + self.S2_div_S1):
random_item = random.randint(0, self.candidate_cur.shape[1] - 1)
while random_item in Mu_set:
random_item = random.randint(0, self.candidate_cur.shape[1] - 1)
self.Mu_idx[i].append(random_item)

negitems_mu_candidates[i] = self.Mu_idx[i]

negitems_mu = {}
negitems_mu = {user: self.candidate_cur[user][negitems_mu_candidates[user]] for user in users}

task = np.array(train_task[2])
task = np.tile(task, reps=(1, self.S1 * (1 + self.S2_div_S1), 1))
task[:, :, 2] = np.array(itemgetter(*users)(negitems_mu))

ratings_mu_candidates = self.MetaTL.fast_forward(task, users)
ratings_mu_candidates = ratings_mu_candidates / self.temperature

if np.any(np.isnan(ratings_mu_candidates)):
print("nan happend in ratings_mu_candidates")
ratings_mu_candidates = np.nan_to_num(ratings_mu_candidates)

ratings_mu_candidates = np.exp(ratings_mu_candidates) / np.reshape(
np.sum(np.exp(ratings_mu_candidates), axis=1), [-1, 1])

if np.any(np.isnan(ratings_mu_candidates)):
print("nan happend__2 in ratings_mu_candidates")
ratings_mu_candidates = self.MetaTL.fast_forward(task, users)
ratings_mu_candidates = ratings_mu_candidates / self.temperature
ratings_mu_candidates = ratings_mu_candidates + 100
ratings_mu_candidates = np.exp(ratings_mu_candidates) / np.reshape(
np.sum(np.exp(ratings_mu_candidates), axis=1), [-1, 1])

user_set = set()
cnt = 0
for i in users:
if i in user_set:
continue
else:
user_set.add(i)
cache_arg = np.random.choice(self.S1 * (1 + self.S2_div_S1), self.S1,
p=ratings_mu_candidates[cnt], replace=False)
self.Mu_idx[i] = np.array(self.Mu_idx[i])[cache_arg].tolist()
cnt += 1

second_cand = 0
del negitems, ratings_positems, Mu_items_all, task, ratings_candidates_all, hisscore_candidates_all, hisscore_pos_all
del hislikelihood_candidates_all, mean_candidates_all, variance_candidates_all, likelihood_candidates_all, second_cand
del negitems_mu, ratings_mu_candidates, user_set
gc.collect()

def change_candidate(self, epoch_count):
score_1epoch_nxt = []
for c in range(5):
# todo: implement proper funciton
pred = self.MetaTL(self.MetaTL.rel_q_sharing.keys(), self.candidate_nxt[c])
score_1epoch_nxt.append(np.array(pred))

# score_1epoch_nxt.append(np.array(/
# [EvalUser.predict_fast(model, sess, num_user, num_item, parallel_users=100,
# predict_data=candidate_nxt[c])]))
# score_1epoch_pos = np.array(
# [EvalUser.predict_pos(model, sess, num_user, max_posid, parallel_users=100, predict_data=train_pos)])
# todo: implement proper function
score_1epoch_pos = self.MetaTL(user_train, train_data)

# delete the score_cand_cur[0,:,:] at the earlist timestamp
if epoch_count >= 5 or epoch_count == 0:
self.score_pos_cur = np.delete(self.score_pos_cur, 0, 0)

for c in range(5):
self.score_cand_nxt[c] = np.concatenate([self.score_cand_nxt[c], score_1epoch_nxt[c]], axis=0)
self.score_pos_cur = np.concatenate([self.score_pos_cur, score_1epoch_pos], axis=0)

score_cand_cur = np.copy(self.score_cand_nxt[0])
candidate_cur = np.copy(self.candidate_nxt[0])
for c in range(4):
self.candidate_nxt[c] = np.copy(self.candidate_nxt[c + 1])
self.score_cand_nxt[c] = np.copy(self.score_cand_nxt[c + 1])
self.candidate_nxt[4] = np.random.choice(list(range(1, self.itemnum)), [self.user_train_num, self.varset_size])
for i in range(self.user_train_num):
for j in range(self.varset_size):
while self.candidate_nxt[4][i, j] in self.user_train[i]:
self.candidate_nxt[4][i, j] = random.randint(0, self.itemnum - 1)
self.score_cand_nxt[4] = np.delete(self.score_cand_nxt[4], list(range(5)), 0)


def rank_predict(self, data, x, ranks): def rank_predict(self, data, x, ranks):
# query_idx is the idx of positive score # query_idx is the idx of positive score
data['NDCG@1'] += 1 / np.log2(rank + 1) data['NDCG@1'] += 1 / np.log2(rank + 1)
data['MRR'] += 1.0 / rank data['MRR'] += 1.0 / rank


def do_one_step(self, task, iseval=False, curr_rel=''):
def do_one_step(self, task, iseval=False, curr_rel='', epoch=None, train_task=None, epoch_count=None):
loss, p_score, n_score = 0, 0, 0 loss, p_score, n_score = 0, 0, 0

if not iseval: if not iseval:
task_new = copy.deepcopy(np.array(task[2]))

cnt = 0

for user in curr_rel:
if user in self.final_negative_items:
for index, t in enumerate(task[1][cnt]):
if index % 2 == 0:
t[2] = self.final_negative_items[user][0]
else:
t[2] = self.final_negative_items[user][1]
cnt += 1

self.optimizer.zero_grad() self.optimizer.zero_grad()
p_score, n_score = self.MetaTL(task, iseval, curr_rel) p_score, n_score = self.MetaTL(task, iseval, curr_rel)
y = torch.Tensor([1]).to(self.device) y = torch.Tensor([1]).to(self.device)
loss = self.MetaTL.loss_func(p_score, n_score,self.device)
loss = self.MetaTL.loss_func(p_score, n_score, y)
loss.backward() loss.backward()
self.optimizer.step() self.optimizer.step()

# task_new = np.array(task[2])
task_new = np.tile(task_new, reps=(1, self.varset_size, 1))
task_new[:, :, 2] = np.array(itemgetter(*curr_rel)(self.candidate_cur))
data = self.MetaTL.fast_forward(task_new, curr_rel)

# prepare score_cand_cur (make all users to have the same number of history scores)
temp = min(epoch_count, 4)
for index, user in enumerate(curr_rel):
if (not user in self.score_cand_cur):
self.score_cand_cur[user] = np.array([data[index]])
elif len(self.score_cand_cur[user]) <= temp:
self.score_cand_cur[user] = np.concatenate(
[self.score_cand_cur[user], np.array([data[index]])], axis=0)

self.change_mu(p_score, n_score, epoch_count, curr_rel, task)

elif curr_rel != '': elif curr_rel != '':
p_score, n_score = self.MetaTL(task, iseval, curr_rel) p_score, n_score = self.MetaTL(task, iseval, curr_rel)
y = torch.Tensor([1]).to(self.device) y = torch.Tensor([1]).to(self.device)
loss = self.MetaTL.loss_func(p_score, n_score,self.device)
loss = self.MetaTL.loss_func(p_score, n_score, y)
return loss, p_score, n_score return loss, p_score, n_score


def train(self): def train(self):
best_epoch = 0 best_epoch = 0
best_value = 0 best_value = 0
bad_counts = 0 bad_counts = 0
epoch_count = 0


# training by epoch # training by epoch
for e in range(self.epoch): for e in range(self.epoch):
if e % 10 == 0: print("epoch:", e)

# sample one batch from data_loader # sample one batch from data_loader
train_task, curr_rel = self.train_data_loader.next_batch() train_task, curr_rel = self.train_data_loader.next_batch()
loss, _, _ = self.do_one_step(train_task, iseval=False, curr_rel=curr_rel)

# change task negative samples using mu_idx
loss, _, _ = self.do_one_step(train_task, iseval=False, curr_rel=curr_rel, epoch=e, train_task=train_task,
epoch_count=epoch_count)

# after ten epoch epoch
if (e % 2500 == 0) and e != 0:
# init the two candidate sets for monitoring variance
self.candidate_cur = np.random.choice(self.itemnum, [self.user_train_num + 1, self.varset_size])
for i in range(1, self.user_train_num + 1):
for j in range(self.varset_size):
while self.candidate_cur[i, j] in self.user_train[i]:
self.candidate_cur[i, j] = random.randint(1, self.itemnum)

self.Mu_idx = {}
for i in range(self.user_train_num + 1):
Mu_idx_tmp = random.sample(list(range(self.varset_size)), self.S1)
self.Mu_idx[i] = Mu_idx_tmp

self.score_cand_cur = {}
self.score_pos_cur = {}
self.final_negative_items = {}

# reset epoch_count has many effects on the chnage_mu and one_step and train function
epoch_count = 0

# after one epoch
elif e % 25 == 0 and e != 0:
self.check_complenteness(epoch_count)
print("epoch_count:", epoch_count)
print("=========================\n\n")
epoch_count += 1


# do evaluation on specific epoch # do evaluation on specific epoch
if e % self.eval_epoch == 0 and e != 0: if e % self.eval_epoch == 0 and e != 0:


print('Epoch {} Testing...'.format(e)) print('Epoch {} Testing...'.format(e))
test_data = self.eval(istest=True, epoch=e) test_data = self.eval(istest=True, epoch=e)

# original = r'/content/results.txt'
# target = r'/content/drive/MyDrive/MetaTL/MetaTL_v3/results.txt'
# shutil.copyfile(original, target)

# print(self.candidate_cur[curr_rel[0]],self.score_cand_cur[curr_rel[0]])
print('Finish') print('Finish')


def eval(self, istest=False, epoch=None): def eval(self, istest=False, epoch=None):
# self.MetaTL.eval()
torch.backends.cudnn.enabled = False
self.MetaTL.eval()

self.MetaTL.rel_q_sharing = dict() self.MetaTL.rel_q_sharing = dict()


if istest: if istest:
# print current temp data dynamically # print current temp data dynamically
for k in data.keys(): for k in data.keys():
temp[k] = data[k] / t temp[k] = data[k] / t
# sys.stdout.write("{}\tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format(
# t, temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'], temp['Hits@1']))
# sys.stdout.flush()


# print overall evaluation result and return it # print overall evaluation result and return it
for k in data.keys(): for k in data.keys():
data[k] = round(data[k] / t, 3) data[k] = round(data[k] / t, 3)


print("\n")
if istest: if istest:
print("TEST: \t test_loss: ",total_loss.detach().item())
print("TEST: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format(
temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'], temp['Hits@1']),"\n")
print("TEST: \t test_loss: ", total_loss.detach().item())
print(
"TEST: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format(
temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'],
temp['Hits@1']))
with open('results.txt', 'a') as f: with open('results.txt', 'a') as f:
f.writelines("TEST: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r\n\n".format(
temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'], temp['Hits@1']))
f.writelines(
"TEST: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r\n\n".format(
temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'],
temp['Hits@1']))
else: else:
print("VALID: \t validation_loss: ", total_loss.detach().item() )
print("VALID: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format(
temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'], temp['Hits@1']))
with open("results.txt",'a') as f:
f.writelines("VALID: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format(
temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'], temp['Hits@1']))

return data
print("VALID: \t validation_loss: ", total_loss.detach().item())
print(
"VALID: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format(
temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'],
temp['Hits@1']))
with open("results.txt", 'a') as f:
f.writelines(
"VALID: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format(
temp['MRR'], temp['NDCG@10'], temp['NDCG@5'], temp['NDCG@1'], temp['Hits@10'], temp['Hits@5'],
temp['Hits@1']))

print("\n")
del total_loss, p_score, n_score
gc.collect()
self.MetaTL.train()
torch.backends.cudnn.enabled = True
return data

def check_complenteness(self, epoch_count):

# un_users = set()

for user in list(self.user_train.keys()):
if not user in self.score_cand_cur:
self.score_cand_cur[user] = np.array([np.zeros(self.varset_size)])

num = epoch_count - len(self.score_cand_cur[user]) + 1
if num > 0 and len(self.score_cand_cur[user]) < 5:
# if num!=1 : print("bug happend1")
# un_users.add(user)
self.score_cand_cur[user] = np.concatenate(
[self.score_cand_cur[user], np.array([self.score_cand_cur[user][-1]])], axis=0)

if epoch_count >= 4:
t = 0
for user in list(self.score_cand_cur.keys()):
t = user
# self.score_cand_cur[user] = np.delete(self.score_cand_cur[user], 0, 0)
self.score_cand_cur[user] = self.score_cand_cur[user][-4:]

+ 27
- 26
utils.py View File

from multiprocessing import Process, Queue from multiprocessing import Process, Queue


# sampler for batch generation # sampler for batch generation
def random_neq(l, r, s,user_train):
# t = np.random.randint(l, r)
# while t in s:
# t = np.random.randint(l, r)
# return t
def random_neq(l, r, s):
t = np.random.randint(l, r)
while t in s:
t = np.random.randint(l, r)
return t


user = random.choice(list(user_train.keys()))
item = random.choice(user_train[user])
while item in s:
user = random.choice(list(user_train.keys()))
item = random.choice(user_train[user])
return item
# user = random.choice(list(user_train.keys()))
# item = random.choice(user_train[user])
#
# while item in s:
# user = random.choice(list(user_train.keys()))
# item = random.choice(user_train[user])
# return item




def trans_to_cuda(variable): def trans_to_cuda(variable):
self.itemnum = itemnum self.itemnum = itemnum


if parameter['number_of_neg']:
self.number_of_neg = parameter['number_of_neg']
else:
self.number_of_neg = 5
# if parameter['number_of_neg']:
# self.number_of_neg = parameter['number_of_neg']
# else:
# self.number_of_neg = 5




def next_one_on_eval(self): def next_one_on_eval(self):
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 * self.number_of_neg], dtype=np.int32)
# neg = np.zeros([self.maxlen * self.number_of_neg], dtype=np.int32)
neg = np.zeros([self.maxlen - 1], dtype=np.int32)

idx = self.maxlen - 1 idx = self.maxlen - 1


ts = set(self.train[u]) ts = set(self.train[u])
seq[idx] = i seq[idx] = i
if idx > 0: if idx > 0:
pos[idx - 1] = i pos[idx - 1] = i
# if i != 0: neg[idx - 1] = random_neq(1, self.itemnum + 1, ts,self.train)
if i != 0: neg[idx - 1] = random_neq(1, self.itemnum + 1, ts)
idx -= 1 idx -= 1
if idx == -1: break if idx == -1: break


for i in range(len(neg)):
neg[i] = random_neq(1, self.itemnum + 1, ts,self.train)
# for i in range(len(neg)):
# neg[i] = random_neq(1, self.itemnum + 1, ts,self.train)


curr_rel = u curr_rel = u
support_triples, support_negative_triples, query_triples, negative_triples = [], [], [], [] support_triples, support_negative_triples, query_triples, negative_triples = [], [], [], []
for idx in range(self.maxlen-1): for idx in range(self.maxlen-1):
support_triples.append([seq[idx],curr_rel,pos[idx]]) support_triples.append([seq[idx],curr_rel,pos[idx]])
# support_negative_triples.append([seq[idx],curr_rel,neg[idx]])
support_negative_triples.append([seq[idx],curr_rel,neg[idx]])
# support_negative_triples.append([seq[-1],curr_rel,neg[idx]]) # support_negative_triples.append([seq[-1],curr_rel,neg[idx]])


# 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]])
# print("injam",self.maxlen,list(range(self.maxlen-1))) # print("injam",self.maxlen,list(range(self.maxlen-1)))
# print("====") # print("====")
for j in range(self.number_of_neg):
for idx in range(self.maxlen-1):
# print(j * self.maxlen + idx)
support_negative_triples.append([seq[idx], curr_rel, neg[j * (self.maxlen-1) + idx]])
# for j in range(self.number_of_neg):
# for idx in range(self.maxlen-1):
# # print(j * self.maxlen + idx)
# support_negative_triples.append([seq[idx], curr_rel, neg[j * (self.maxlen-1) + idx]])
# print("=end=\n\n") # print("=end=\n\n")


rated = ts rated = ts

Loading…
Cancel
Save