From 7159e0be34ae9ec3923ba52742ec1a4aeba746ff Mon Sep 17 00:00:00 2001 From: amazingDD <1172392977@gmail.com> Date: Sun, 14 Aug 2022 22:36:43 +0800 Subject: [PATCH] update 2.3.0 --- README.md | 2 +- daisy/__init__.py | 2 +- daisy/assets/basic.yaml | 4 ++-- daisy/model/EASERecommender.py | 2 +- daisy/model/FMRecommender.py | 6 +++--- daisy/model/Item2VecRecommender.py | 4 ++-- daisy/model/LightGCNRecommender.py | 2 +- daisy/model/MFRecommender.py | 4 ++-- daisy/model/NFMRecommender.py | 6 +++--- daisy/model/NGCFRecommender.py | 2 +- daisy/model/NeuMFRecommender.py | 6 +++--- daisy/model/VAECFRecommender.py | 11 ++++++----- daisy/utils/parser.py | 3 +-- run_examples/tune.py | 8 +++++--- setup.py | 4 ++-- 15 files changed, 34 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index ee43d6a..a269fb4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

![PyPI - Python Version](https://img.shields.io/badge/pyhton-3.5%2B-blue) -[![Version](https://img.shields.io/badge/version-2.2.0-orange)](https://github.com/AmazingDD/daisyRec) +[![Version](https://img.shields.io/badge/version-2.3.0-orange)](https://github.com/AmazingDD/daisyRec) ![GitHub repo size](https://img.shields.io/github/repo-size/AmazingDD/daisyRec) ![GitHub](https://img.shields.io/github/license/AmazingDD/daisyRec) [![arXiv](https://img.shields.io/badge/arXiv-daisyRec-%23B21B1B)](https://arxiv.org/abs/2206.10848) diff --git a/daisy/__init__.py b/daisy/__init__.py index 0203e20..6e6ab28 100644 --- a/daisy/__init__.py +++ b/daisy/__init__.py @@ -1 +1 @@ -__version__ = 'v2.2.0' +__version__ = 'v2.3.0' diff --git a/daisy/assets/basic.yaml b/daisy/assets/basic.yaml index 62689c4..e9307db 100644 --- a/daisy/assets/basic.yaml +++ b/daisy/assets/basic.yaml @@ -4,9 +4,9 @@ reproducibility: True state: ~ optimization_metric: 'ndcg' -hyperopt_trail: 20 +hyperopt_trail: 30 tune_testset: False -hyperopt_pack: '{}' +tune_pack: '{}' algo_name: 'mf' val_method: 'tsbr' diff --git a/daisy/model/EASERecommender.py b/daisy/model/EASERecommender.py index bc3c490..ad40dd7 100644 --- a/daisy/model/EASERecommender.py +++ b/daisy/model/EASERecommender.py @@ -47,7 +47,7 @@ def fit(self, train_set): self.interaction_matrix = X # user_num * item_num def predict(self, u, i): - self.interaction_matrix[u, :].multiply(self.item_similarity[:, i].T).sum(axis=1).getA1() + return self.interaction_matrix[u, :].multiply(self.item_similarity[:, i].T).sum(axis=1).getA1()[0] def rank(self, test_loader): rec_ids = None diff --git a/daisy/model/FMRecommender.py b/daisy/model/FMRecommender.py index bb8aac7..f2c1f0b 100644 --- a/daisy/model/FMRecommender.py +++ b/daisy/model/FMRecommender.py @@ -97,7 +97,7 @@ def calc_loss(self, batch): def predict(self, u, i): u = torch.tensor(u, device=self.device) i = torch.tensor(i, device=self.device) - pred = self.forward(u, i).cpu() + pred = self.forward(u, i).cpu().item() return pred @@ -122,11 +122,11 @@ def rank(self, test_loader): return rec_ids.cpu().numpy() def full_rank(self, u): - u = torch.tensor(u, self.device) + u = torch.tensor(u, device=self.device) user_emb = self.embed_user(u) items_emb = self.embed_item.weight scores = torch.matmul(user_emb, items_emb.transpose(1, 0)) # (item_num,) - scores += self.u_bias(u) + self.i_bias.weight + self.bias_ + scores += self.u_bias(u) + self.i_bias.weight.squeeze() + self.bias_ return torch.argsort(scores, descending=True)[:self.topk].cpu().numpy() diff --git a/daisy/model/Item2VecRecommender.py b/daisy/model/Item2VecRecommender.py index bc7b2dc..3060ba2 100644 --- a/daisy/model/Item2VecRecommender.py +++ b/daisy/model/Item2VecRecommender.py @@ -79,7 +79,7 @@ def predict(self, u, i): item_emb = self.shared_embedding(i) pred = (user_emb * item_emb).sum(dim=-1) - return pred.cpu() + return pred.cpu().item() def rank(self, test_loader): rec_ids = torch.tensor([], device=self.device) @@ -101,7 +101,7 @@ def rank(self, test_loader): return rec_ids.cpu().numpy() def full_rank(self, u): - u = torch.tensor(u, self.device) + u = torch.tensor(u, device=self.device) user_emb = self.user_embedding(u) items_emb = self.shared_embedding.weight diff --git a/daisy/model/LightGCNRecommender.py b/daisy/model/LightGCNRecommender.py index 66f9249..cfd6b3d 100644 --- a/daisy/model/LightGCNRecommender.py +++ b/daisy/model/LightGCNRecommender.py @@ -176,7 +176,7 @@ def predict(self, u, i): i_embedding = self.restore_item_e[i] pred = torch.matmul(u_embedding, i_embedding.t()) - return pred.cpu() + return pred.cpu().item() def rank(self, test_loader): if self.restore_user_e is None or self.restore_item_e is None: diff --git a/daisy/model/MFRecommender.py b/daisy/model/MFRecommender.py index 648ea52..5026662 100644 --- a/daisy/model/MFRecommender.py +++ b/daisy/model/MFRecommender.py @@ -99,7 +99,7 @@ def calc_loss(self, batch): def predict(self, u, i): u = torch.tensor(u, device=self.device) i = torch.tensor(i, device=self.device) - pred = self.forward(u, i).cpu() + pred = self.forward(u, i).cpu().item() return pred @@ -124,7 +124,7 @@ def rank(self, test_loader): def full_rank(self, u): - u = torch.tensor(u, self.device) + u = torch.tensor(u, device=self.device) user_emb = self.embed_user(u) items_emb = self.embed_item.weight diff --git a/daisy/model/NFMRecommender.py b/daisy/model/NFMRecommender.py index da1c0ce..c2a22a2 100644 --- a/daisy/model/NFMRecommender.py +++ b/daisy/model/NFMRecommender.py @@ -151,7 +151,7 @@ def calc_loss(self, batch): def predict(self, u, i): u = torch.tensor(u, device=self.device) i = torch.tensor(i, device=self.device) - pred = self.forward(u, i).cpu() + pred = self.forward(u, i).cpu().item() return pred @@ -192,7 +192,7 @@ def rank(self, test_loader): return rec_ids.cpu().numpy() def full_rank(self, u): - u = torch.tensor(u, self.device) + u = torch.tensor(u, device=self.device) user_emb = self.embed_user(u) # factor items_emb = self.embed_item.weight # item_num * factor @@ -202,7 +202,7 @@ def full_rank(self, u): if self.num_layers: fm = self.deep_layers(fm) # item_num * factor fm += self.u_bias(u) + self.i_bias.weight + self.bias_ - scores = self.prediction(fm) # item_num + scores = self.prediction(fm).squeeze() # item_num return torch.argsort(scores, descending=True)[:self.topk].cpu().numpy() diff --git a/daisy/model/NGCFRecommender.py b/daisy/model/NGCFRecommender.py index 14acbb9..bef6cec 100644 --- a/daisy/model/NGCFRecommender.py +++ b/daisy/model/NGCFRecommender.py @@ -217,7 +217,7 @@ def predict(self, u, i): i_embedding = self.restore_item_e[i] pred = torch.matmul(u_embedding, i_embedding.t()) - return pred.cpu() + return pred.cpu().item() def rank(self, test_loader): if self.restore_user_e is None or self.restore_item_e is None: diff --git a/daisy/model/NeuMFRecommender.py b/daisy/model/NeuMFRecommender.py index 0dbcf54..b3955dc 100644 --- a/daisy/model/NeuMFRecommender.py +++ b/daisy/model/NeuMFRecommender.py @@ -171,7 +171,7 @@ def calc_loss(self, batch): def predict(self, u, i): u = torch.tensor(u, device=self.device) i = torch.tensor(i, device=self.device) - pred = self.forward(u, i).cpu() + pred = self.forward(u, i).cpu().item() return pred @@ -206,10 +206,10 @@ def rank(self, test_loader): rec_ids = torch.cat((rec_ids, rank_list), 0) - return rec_ids + return rec_ids.cpu().numpy() def full_rank(self, u): - u = torch.tensor(u, self.device) + u = torch.tensor(u, device=self.device) if not self.model == 'MLP': embed_user_GMF = self.embed_user_GMF(u) # factor diff --git a/daisy/model/VAECFRecommender.py b/daisy/model/VAECFRecommender.py index 1a91493..f67711d 100644 --- a/daisy/model/VAECFRecommender.py +++ b/daisy/model/VAECFRecommender.py @@ -7,6 +7,7 @@ year={2018} } ''' +import math import torch import torch.nn as nn import torch.nn.functional as F @@ -81,7 +82,7 @@ def forward(self, rating_matrix): h = self.encoder(h) mu = h[:, :int(self.lat_dim / 2)] - logvar = h[:, int(self.lat_dim / 2):] + logvar = h[:, math.ceil(self.lat_dim / 2):] z = self.reparameterize(mu, logvar) z = self.decoder(z) @@ -109,13 +110,13 @@ def calc_loss(self, batch): return loss def predict(self, u, i): - u = torch.tensor(u, device=self.device) - i = torch.tensor(i, device=self.device) + u = torch.tensor([u], device=self.device) + i = torch.tensor([i], device=self.device) rating_matrix = self.get_user_rating_matrix(u) scores, _, _ = self.forward(rating_matrix) - return scores[[torch.arange(len(i)).to(self.device), i]].cpu() + return scores[[torch.arange(len(i)).to(self.device), i]].cpu().item() def rank(self, test_loader): rec_ids = torch.tensor([], device=self.device) @@ -137,7 +138,7 @@ def rank(self, test_loader): return rec_ids.cpu().numpy() def full_rank(self, u): - u = torch.tensor(u, device=self.device) + u = torch.tensor([u], device=self.device) rating_matrix = self.get_user_rating_matrix(u) scores, _, _ = self.forward(rating_matrix) diff --git a/daisy/utils/parser.py b/daisy/utils/parser.py index f74d42d..ae42946 100644 --- a/daisy/utils/parser.py +++ b/daisy/utils/parser.py @@ -9,9 +9,8 @@ def parse_args(): help='the metric to be optimized for hyper-parameter tuning via HyperOpt') parser.add_argument('--hyperopt_trail', type=int, - default=30, help='the number of trails of HyperOpt') - parser.add_argument('--hyperopt_pack', + parser.add_argument('--tune_pack', type=str, help='record the searching space of hyper-parameters for HyperOpt') # common settings diff --git a/run_examples/tune.py b/run_examples/tune.py index b4ece9b..df0cbdd 100644 --- a/run_examples/tune.py +++ b/run_examples/tune.py @@ -1,3 +1,4 @@ +from ast import Global import json import optuna import numpy as np @@ -102,7 +103,7 @@ config['logger'] = logger ''' unpack hyperparameters to tune ''' - param_dict = json.loads(config['hyperopt_pack']) + param_dict = json.loads(config['tune_pack']) algo_name = config['algo_name'] kpi_name = config['optimization_metric'] tune_param_names = tune_params_config[algo_name] @@ -133,6 +134,7 @@ ''' define optimization target function ''' def objective(trial): + global TRIAL_CNT for param in tune_param_names: if param not in param_dict.keys(): continue @@ -145,7 +147,7 @@ def objective(trial): param, param_dict[param]['min'], param_dict[param]['max'], 1 if step is None else step) elif param_type_config[param] == 'float': config[param] = trial.suggest_float( - param, param_dict[param]['min'], param_dict[param]['max'], param_dict[param]['step']) + param, param_dict[param]['min'], param_dict[param]['max'], step=param_dict[param]['step']) else: raise ValueError(f'Invalid parameter type for {param}...') else: @@ -224,7 +226,7 @@ def objective(trial): ''' record the best choices ''' logger.info(f'Trial {study.best_trial.number} get the best {kpi_name}({study.best_trial.value}) with params: {study.best_trial.params}') - line = ','.join([study.best_params[param] for param in tune_param_names]) + f',{study.best_value:.4f}\n' + line = ','.join([str(study.best_params[param]) for param in tune_param_names]) + f',{study.best_value:.4f}\n' f.write(line) f.flush() f.close() diff --git a/setup.py b/setup.py index 276e265..681405b 100644 --- a/setup.py +++ b/setup.py @@ -44,14 +44,14 @@ # package_dir={"": "daisy"}, package_data={"": ["*.yaml"]}, # packages = find_packages(exclude=['tests*']), - version='v2.2.0', # Ideally should be same as your GitHub release tag varsion + version='v2.3.0', # Ideally should be same as your GitHub release tag varsion description=('An easy-to-use library for recommender systems.'), long_description=long_description, # long_description_content_type="text/markdown", author='Yu Di', author_email='di.yu.2021@mitb.smu.edu.sg', url='https://github.com/AmazingDD/daisyRec', - download_url='https://github.com/AmazingDD/daisyRec/archive/refs/tags/v2.2.0.tar.gz', + download_url='https://github.com/AmazingDD/daisyRec/archive/refs/tags/v2.3.0.tar.gz', keywords=['ranking', 'recommendation'], # include_package_data=True, install_requires=install_requires,