@@ -0,0 +1,138 @@ | |||
from ray.tune.schedulers import ASHAScheduler | |||
from ray.tune import CLIReporter | |||
from ray import tune | |||
from functools import partial | |||
from hyper_tunning import train_metatl | |||
import argparse | |||
import numpy as np | |||
import torch | |||
import random | |||
from trainer import * | |||
from utils import * | |||
from sampler import * | |||
import copy | |||
def get_params(): | |||
args = argparse.ArgumentParser() | |||
args.add_argument("-data", "--dataset", default="electronics", type=str) | |||
args.add_argument("-seed", "--seed", default=None, type=int) | |||
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("-bs", "--batch_size", default=1024, type=int) | |||
# args.add_argument("-lr", "--learning_rate", default=0.001, type=float) | |||
args.add_argument("-epo", "--epoch", default=1000, 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("-b", "--beta", default=5, 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("-gpu", "--device", default=1, type=int) | |||
args = args.parse_args() | |||
params = {} | |||
for k, v in vars(args).items(): | |||
params[k] = v | |||
params['device'] = torch.device('cuda:0') | |||
return params, args | |||
def main(num_samples, gpus_per_trial=2): | |||
params, args = get_params() | |||
if params['seed'] is not None: | |||
SEED = params['seed'] | |||
torch.manual_seed(SEED) | |||
torch.cuda.manual_seed(SEED) | |||
torch.backends.cudnn.deterministic = True | |||
np.random.seed(SEED) | |||
random.seed(SEED) | |||
user_train, usernum_train, itemnum, user_input_test, user_test, user_input_valid, user_valid = data_load(args.dataset, args.K) | |||
batch_size = params['batch_size'] | |||
# sampler = WarpSampler(user_train, usernum_train, itemnum, batch_size=batch_size, maxlen=args.K, n_workers=1) | |||
# sampler_test = DataLoader(user_input_test, user_test, itemnum, params) | |||
# sampler_valid = DataLoader(user_input_valid, user_valid, itemnum, params) | |||
config = { | |||
# "l1": tune.sample_from(lambda _: 2 ** np.random.randint(2, 9)), | |||
# "l2": tune.sample_from(lambda _: 2 ** np.random.randint(2, 9)), | |||
# "lr": tune.loguniform(1e-4, 1e-1), | |||
# "batch_size": tune.choice([2, 4, 8, 16]) | |||
"embed_dim" : tune.choice([50,75,100,125,150,200]), | |||
# "batch_size" : tune.choice([128,256,512,1024,2048]), | |||
"learning_rate" : tune.choice([0.1,0.01,0.005,0.001,0.0001]), | |||
"beta" : tune.choice([0.1,1,5,10]), | |||
"margin" : tune.choice([1]), | |||
# "sampler":sampler, | |||
# "sampler_test":sampler_test, | |||
# "sampler_valid":sampler_valid, | |||
"itemnum":itemnum, | |||
"params":params, | |||
} | |||
scheduler = ASHAScheduler( | |||
metric="MRR", | |||
mode="max", | |||
max_t=params['epoch'], | |||
grace_period=200, | |||
reduction_factor=2) | |||
reporter = CLIReporter( | |||
# parameter_columns=["l1", "l2", "lr", "batch_size"], | |||
metric_columns=["MRR","NDCG10","NDCG5","NDCG1","Hits10","Hits5","Hits1","training_iteration"]) | |||
result = tune.run( | |||
train_metatl, | |||
resources_per_trial={"cpu": 4, "gpu": gpus_per_trial}, | |||
config=config, | |||
num_samples=num_samples, | |||
scheduler=scheduler, | |||
progress_reporter=reporter, | |||
log_to_file=True, | |||
# resume=True, | |||
local_dir="./ray_local_dir", | |||
name="metatl_rnn1", | |||
) | |||
best_trial = result.get_best_trial("MRR", "max", "last") | |||
print("Best trial config: {}".format(best_trial.config)) | |||
print("Best trial final validation loss: {}".format( | |||
best_trial.last_result["loss"])) | |||
print("Best trial final validation MRR: {}".format( | |||
best_trial.last_result["MRR"])) | |||
print("Best trial final validation NDCG@1: {}".format( | |||
best_trial.last_result["NDCG@1"])) | |||
# | |||
print("=======================================================") | |||
print(result.results_df) | |||
print("=======================================================\n") | |||
# best_trained_model = Net(best_trial.config["l1"], best_trial.config["l2"]) | |||
# device = "cpu" | |||
# if torch.cuda.is_available(): | |||
# device = "cuda:0" | |||
# if gpus_per_trial > 1: | |||
# best_trained_model = nn.DataParallel(best_trained_model) | |||
# best_trained_model.to(device) | |||
# | |||
# best_checkpoint_dir = best_trial.checkpoint.value | |||
# model_state, optimizer_state = torch.load(os.path.join( | |||
# best_checkpoint_dir, "checkpoint")) | |||
# best_trained_model.load_state_dict(model_state) | |||
# | |||
# test_acc = test_accuracy(best_trained_model, device) | |||
# print("Best trial test set accuracy: {}".format(test_acc)) | |||
if __name__ == "__main__": | |||
# You can change the number of GPUs per trial here: | |||
main(num_samples=150, gpus_per_trial=1) |
@@ -0,0 +1,73 @@ | |||
import os | |||
import torch | |||
import torch.nn as nn | |||
from ray import tune | |||
import pickle | |||
import random | |||
import gc | |||
from trainer import Trainer | |||
import numpy as np | |||
from utils import * | |||
from sampler import * | |||
import os | |||
def train_metatl(conf,checkpoint_dir=None): | |||
SEED = conf["params"]['seed'] | |||
torch.manual_seed(SEED) | |||
torch.cuda.manual_seed(SEED) | |||
torch.backends.cudnn.deterministic = True | |||
np.random.seed(SEED) | |||
random.seed(SEED) | |||
params = conf['params'] | |||
user_train, usernum_train, itemnum, user_input_test, user_test, user_input_valid, user_valid = data_load(params['dataset'], params['K']) | |||
sampler = WarpSampler(user_train, usernum_train, itemnum, batch_size=params['batch_size'], maxlen=params['K'], n_workers=1) | |||
sampler_test = DataLoader(user_input_test, user_test, itemnum, params) | |||
sampler_valid = DataLoader(user_input_valid, user_valid, itemnum, params) | |||
ps = { | |||
"batch_size" : conf["params"]['batch_size'], | |||
"learning_rate" : conf['learning_rate'], | |||
"epoch" : conf["params"]['epoch'], | |||
"beta" : conf['beta'], | |||
"embed_dim" : conf['embed_dim'], | |||
"margin" : conf['margin'], | |||
"K" : conf["params"]['K'], | |||
} | |||
trainer = Trainer([sampler, sampler_valid, sampler_test], conf["itemnum"], ps) | |||
# trainer.train() | |||
for epoch in range(ps['epoch']): | |||
for e in range(100): | |||
# sample one batch from data_loader | |||
train_task, curr_rel = trainer.train_data_loader.next_batch() | |||
loss, _, _ = trainer.do_one_step(train_task, iseval=False, curr_rel=curr_rel) | |||
# do evaluation on specific epoch | |||
valid_data = trainer.eval(istest=False, epoch=(-1)) | |||
# print('Epoch {} Testing...'.format(e)) | |||
# test_data = self.eval(istest=True, epoch=e) | |||
if checkpoint_dir: | |||
model_state, optimizer_state = torch.load( | |||
os.path.join(checkpoint_dir, "checkpoint")) | |||
trainer.MetaTL.load_state_dict(model_state) | |||
trainer.optimizer.load_state_dict(optimizer_state) | |||
with tune.checkpoint_dir(epoch) as checkpoint_dir: | |||
path = os.path.join(checkpoint_dir, "checkpoint") | |||
torch.save((trainer.MetaTL.state_dict(), trainer.optimizer.state_dict()), path) | |||
tune.report( | |||
MRR=valid_data["MRR"], NDCG10=valid_data['NDCG@10'], NDCG5=valid_data["NDCG@5"], NDCG1=valid_data["NDCG@1"], | |||
Hits10=valid_data["Hits@10"], Hits5=valid_data["Hits@5"], Hits1=valid_data["Hits@1"], | |||
training_iteration=epoch*100 | |||
) | |||
@@ -6,7 +6,7 @@ from torch.nn import functional as F | |||
class Embedding(nn.Module): | |||
def __init__(self, num_ent, parameter): | |||
super(Embedding, self).__init__() | |||
self.device = parameter['device'] | |||
self.device = torch.device('cuda:0') | |||
self.es = parameter['embed_dim'] | |||
self.embedding = nn.Embedding(num_ent + 1, self.es) | |||
@@ -22,9 +22,11 @@ class MetaLearner(nn.Module): | |||
super(MetaLearner, self).__init__() | |||
self.embed_size = embed_size | |||
self.K = K | |||
self.out_size = out_size | |||
self.hidden_size = out_size | |||
self.rnn = nn.LSTM(embed_size,self.hidden_size,1) | |||
# self.out_size = out_size | |||
# self.hidden_size = out_size | |||
self.out_size = embed_size | |||
self.hidden_size = embed_size | |||
self.rnn = nn.LSTM(embed_size,self.hidden_size,2,dropout=0.2) | |||
# nn.init.xavier_normal_(self.rnn.all_weights) | |||
def forward(self, inputs): | |||
@@ -53,15 +55,15 @@ class EmbeddingLearner(nn.Module): | |||
class MetaTL(nn.Module): | |||
def __init__(self, itemnum, parameter): | |||
super(MetaTL, self).__init__() | |||
self.device = parameter['device'] | |||
self.device = torch.device('cuda:0') | |||
self.beta = parameter['beta'] | |||
self.dropout_p = parameter['dropout_p'] | |||
# self.dropout_p = parameter['dropout_p'] | |||
self.embed_dim = parameter['embed_dim'] | |||
self.margin = parameter['margin'] | |||
self.embedding = Embedding(itemnum, parameter) | |||
self.relation_learner = MetaLearner(parameter['K'] - 1, embed_size=100, num_hidden1=500, | |||
num_hidden2=200, out_size=100, dropout_p=self.dropout_p) | |||
self.relation_learner = MetaLearner(parameter['K'] - 1, embed_size=self.embed_dim, num_hidden1=500, | |||
num_hidden2=200, out_size=100, dropout_p=0) | |||
self.embedding_learner = EmbeddingLearner() | |||
self.loss_func = nn.MarginRankingLoss(self.margin) |
@@ -18,9 +18,10 @@ class Trainer: | |||
self.batch_size = parameter['batch_size'] | |||
self.learning_rate = parameter['learning_rate'] | |||
self.epoch = parameter['epoch'] | |||
self.print_epoch = parameter['print_epoch'] | |||
self.eval_epoch = parameter['eval_epoch'] | |||
self.device = parameter['device'] | |||
# self.print_epoch = parameter['print_epoch'] | |||
# self.eval_epoch = parameter['eval_epoch'] | |||
self.eval_epoch = 50 | |||
self.device = torch.device('cuda:0') | |||
self.MetaTL = MetaTL(itemnum, parameter) | |||
self.MetaTL.to(self.device) | |||
@@ -74,9 +75,9 @@ class Trainer: | |||
train_task, curr_rel = self.train_data_loader.next_batch() | |||
loss, _, _ = self.do_one_step(train_task, iseval=False, curr_rel=curr_rel) | |||
# print the loss on specific epoch | |||
if e % self.print_epoch == 0: | |||
loss_num = loss.item() | |||
print("Epoch: {}\tLoss: {:.4f}".format(e, loss_num)) | |||
# if e % self.print_epoch == 0: | |||
# loss_num = loss.item() | |||
# print("Epoch: {}\tLoss: {:.4f}".format(e, loss_num)) | |||
# do evaluation on specific epoch | |||
if e % self.eval_epoch == 0 and e != 0: | |||
print('Epoch {} Validating...'.format(e)) | |||
@@ -121,9 +122,9 @@ class Trainer: | |||
# print current temp data dynamically | |||
for k in data.keys(): | |||
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() | |||
# 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 | |||
for k in data.keys(): | |||
@@ -131,7 +132,7 @@ class Trainer: | |||
if istest: | |||
print("TEST: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format( | |||
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'])) | |||
else: | |||
print("VALID: \tMRR: {:.3f}\tNDCG@10: {:.3f}\tNDCG@5: {:.3f}\tNDCG@1: {:.3f}\tHits@10: {:.3f}\tHits@5: {:.3f}\tHits@1: {:.3f}\r".format( |
@@ -32,7 +32,7 @@ def data_load(fname, num_sample): | |||
user_train = defaultdict(list) | |||
# assume user/item index starting from 1 | |||
f = open('data/%s/%s_train.csv' % (fname, fname), 'r') | |||
f = open('/home/maheri/metaTL/data/%s/%s_train.csv' % (fname, fname), 'r') | |||
for line in f: | |||
u, i, t = line.rstrip().split('\t') | |||
u = int(u) | |||
@@ -50,7 +50,7 @@ def data_load(fname, num_sample): | |||
User_test_new = defaultdict(list) | |||
f = open('data/%s/%s_test_new_user.csv' % (fname, fname), 'r') | |||
f = open('/home/maheri/metaTL/data/%s/%s_test_new_user.csv' % (fname, fname), 'r') | |||
for line in f: | |||
u, i, t = line.rstrip().split('\t') | |||
u = int(u) |