thuwangcy / rechorus Goto Github PK
View Code? Open in Web Editor NEW“Chorus” of recommendation models: a light and flexible PyTorch framework for Top-K recommendation.
License: MIT License
“Chorus” of recommendation models: a light and flexible PyTorch framework for Top-K recommendation.
License: MIT License
It will be better if there is a type hint in all code. For example, when we implement some subclass of basic class BaseModel
, we have no idea about the content and structure of the input variable(s).
想问一下CFKG这个模型,构建的KG数据集是在哪个文件里,也是在data目录里吗
location: ReChorus/src/models/sequential/NARM.py line 61
Reason: #18
Fix Solution: add .cpu() to sort_his_lengths.
history_packed = torch.nn.utils.rnn.pack_padded_sequence(sort_his_vectors, sort_his_lengths.cpu(), batch_first=True)
hi,dear
well done,
will try to reproduce the rp,
btw,could it be used in Recall term ,what's the metrics ?
thx
Nice paper which inspires me a lot ! But I still have two questions:
Thank you for replying
In the model KDA, according to your experimental parameter setting method, I found that the experimental results in your table in github can only be reached for the time being HR@5: 0.5174, NDGG@5: 0.3876, but the result in the paper is 0.4201 and in run.sh The experimental result of more fine-grained parameter setting is not up to 0.47 temporarily. Could you please give me some guidance? Looking forward to your reply
When computing the user_min_interval, you use the interval_matrix = np.abs(time_seqs[:, None] - time_seqs[None, :]). As the diagnal line of the matrix is always all-zero, min_interval = np.min(interval + (interval <= 0) * 0xFFFF) will be 0xFFFF for all users. By the way, I correct the computation of user_min_interval, but the performance of TiSASRec doesn't get any improvement. This seems to be not important.
Hi Wang,
Recently, I was reading the source code of Rechorus. There is something coufused me in BaseRunner.py.
It's about evaluate_method
in BaseRunner.py on line 48.
def evaluate_method(predictions: np.ndarray, topk: list, metrics: list) -> Dict[str, float]:
"""
:param predictions: (-1, n_candidates) shape, the first column is the score for ground-truth item
:param topk: top-K value list
:param metrics: metric string list
:return: a result dict, the keys are metric@topk
"""
evaluations = dict()
sort_idx = (-predictions).argsort(axis=1)
gt_rank = np.argwhere(sort_idx == 0)[:, 1] + 1
for k in topk:
hit = (gt_rank <= k)
for metric in metrics:
key = '{}@{}'.format(metric, k)
if metric == 'HR':
evaluations[key] = hit.mean()
elif metric == 'NDCG':
evaluations[key] = (hit / np.log2(gt_rank + 1)).mean()
else:
raise ValueError('Undefined evaluation metric: {}.'.format(metric))
return evaluations
As the comment says, the first column indicates the score of ground_truth
. The sort_idx
contains the index values of the array values in descending order. The sort_idx == 0
represents the highest record.
My confusion is that the code hit = (gt_rank <= k)
. In my understanding, gt_rank
means the item with the highest score, not necessarily the ground_truth
, but also the random sample item. Can you please explain this for me?
感谢提供如此优异的框架,非常易懂易用!
但是有几个问题:
相比于RecBole,ReChorus将数据集单独预处理确实是更好的方式。
Getting this error while running sample on windows 10, torch 1.7.1
Traceback (most recent call last):
File "main.py", line 116, in
main()
File "main.py", line 74, in main
logging.info('Test Before Training: ' + runner.print_res(model, data_dict['test']))
File "xxx\ReChorus-master\src\helpers\BaseRunner.py", line 221, in print_res
result_dict = self.evaluate(model, data, self.topk, self.metrics)
File "xxx\ReChorus-master\src\helpers\BaseRunner.py", line 197, in evaluate
predictions = self.predict(model, data)
File "xxx\ReChorus-master\src\helpers\BaseRunner.py", line 212, in predict
prediction = model(utils.batch_to_gpu(batch, model.device))['prediction']
File "xxx\lib\site-packages\torch\nn\modules\module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "xxx\ReChorus-master\src\models\general\BPR.py", line 30, in forward
cf_u_vectors = self.u_embeddings(u_ids)
File "xxx\lib\site-packages\torch\nn\modules\module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "xxx\lib\site-packages\torch\nn\modules\sparse.py", line 126, in forward
self.norm_type, self.scale_grad_by_freq, self.sparse)
File "xxx\lib\site-packages\torch\nn\functional.py", line 1852, in embedding
return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)
RuntimeError: Expected tensor for argument #1 'indices' to have scalar type Long; but got torch.IntTensor instead (while checking arguments for embedding)
Hello, can you tell me how the "relational ratio in test set" in the paper Rechorus is calculated? thank you very much
Issue: GRU4Rec model run will encounter runtime error "RuntimeError: 'lengths' argument should be a 1D CPU int64 tensor, but got 1D cuda:0 Long tensor"
Error code location: ReChorus/src/models/sequential/GRU4Rec.py line 52
Reason: in latest pytorch version (maybe after pytorch v1.4), nn.utils.rnn.pack_padded_sequence requires lengths tensor to be CPU int 64 tensor instead of GPU long tensor.
Fix Solution: add .cpu() to sort_his_lengths. e.g.
history_packed = torch.nn.utils.rnn.pack_padded_sequence(sort_his_vectors, sort_his_lengths.cpu(), batch_first=True)
Hi, I was looking for a pytorch implementation of this paper recently. After flipping through GitHub, I found that there is a file called ComiRec in your project. I'm not sure whether it is the complete implement of that paper. Looking forward to your reply. :)
Hi,
I am relatively new to the field. I'm using your package to write some code. Thanks for the contribution to the community by the way!
So when I add a simple linear layer to i_vectors (after passing i_ids to an embedding), I get a strangely high HR (almost 100%). Did I do something wrong? Is it not allowed to use item embedding to make predictions? Thank you in advance!
I run my code using the line python main.py --gpu 0 --num_neg 99 --model_name Linear --emb_size 64 --hidden_size 128 --lr 1e-3 --l2 1e-4 --history_max 20 --dataset 'Grocery_and_Gourmet_Food'
Please see my module below:
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from models.BaseModel import SequentialModel
from utils import layers
class Linear(SequentialModel):
reader = 'SeqReader'
runner = 'BaseRunner'
extra_log_args = ['emb_size', 'num_layers', 'num_heads']
@staticmethod
def parse_model_args(parser):
parser.add_argument('--emb_size', type=int, default=64,
help='Size of embedding vectors.')
parser.add_argument('--num_layers', type=int, default=1,
help='Number of self-attention layers.')
parser.add_argument('--num_heads', type=int, default=4,
help='Number of attention heads.')
return SequentialModel.parse_model_args(parser)
def __init__(self, args, corpus):
super().__init__(args, corpus)
self.emb_size = args.emb_size
self.max_his = args.history_max
self.num_layers = args.num_layers
self.len_range = torch.from_numpy(np.arange(self.max_his)).to(self.device)
self._define_params()
def _define_params(self):
self.i_embeddings = nn.Embedding(self.item_num, self.emb_size)
self.p_embeddings = nn.Embedding(self.max_his + 1, self.emb_size)
self.linear = nn.Linear(self.emb_size, 1 + self.num_neg)
def forward(self, feed_dict):
self.check_list = []
i_ids = feed_dict['item_id'] # [batch_size, -1]
history = feed_dict['history_items'] # [batch_size, history_max]
lengths = feed_dict['lengths'] # [batch_size]
batch_size, seq_len = history.shape
i_vectors = self.i_embeddings(i_ids)
prediction = self.linear(i_vectors.mean(axis=1))
# prediction = self.sedot(stacked_X)
return {'prediction': prediction.view(batch_size, -1)}
In the BERT "mask" is a special token and different from padding token. The padding token won't calculate attention weight, while "mask" token do it. https://github.com/google-research/bert/blob/eedf5716ce1268e56f0a50264a88cafad334ac61/create_pretraining_data.py#L394
if prob < self.model.mask_ratio: mask_seq[idx] = 0 neg_item[idx] = self._neg_sample(seq)
Hi,
Great job on he implementation.
Is there a way that predict method for SASrec works in the following way : (This can be used for real time cases)
Given a new user sequence of items that the user interacted with in real time and the model created based on the training data, a set of recommended items with their scores returns.
Thanks,
Sara
In line 32 of README.md, the name of the fourth argument should be l2
instead of lr
?
Dear authors,
Thanks for your implementations of this framework with several baselines. I wonder whether the implementations of S3Rec and CLRec is ready in the developing folder? I tried to run them directly but faced some errors.
你好,运行各个数据集的参数如何设置呢?谢谢
Hello,
Thanks for implementing this beautiful library. I have a couple of queries:-
Hi, I want to ask whether GRU4Rec can recommend items to users without previous history. At least to me the code seems so.
Hi,
Firstly, the package looks great and informative. Thanks.
I was just working on the models and was interested in optimzing the hyperparameters of the models . I neverthless tried to understand , but was finding it challenging if package such as Optuna can be used for optimizing the hyperparameters.
Any help or comments on this topic would be helpful !
Thanks in advance!
Hello, I am very interested in your work.
I find that "RCF" is used for your baseline, and I want to know what item relations are used in your implementation of RCF on Amazon datasets. If it is convenient for you, can you send me the code of "RCF" that you implemented? Look forward to your reply.
Hi, thanks for the great job.
I found that in
Line 53 in dba1d0b
运行“python main.py --model_name BPRMF --emb_size 64 --lr 1e-3 --l2 1e-6 --dataset Grocery_and_Gourmet_Food --gpu 0”
部分结果为:
Device: cuda
Load corpus from ../data/Grocery_and_Gourmet_Food\BaseReader.pkl
#params: 1497344
BPRMF(
(u_embeddings): Embedding(14682, 64)
(i_embeddings): Embedding(8714, 64)
)
Optimizer: Adam
Epoch 1 loss=0.6931 [7.5 s] dev=(HR@5:1.0000,NDCG@5:1.0000) [6.3 s] *
Epoch 2 loss=0.6931 [6.9 s] dev=(HR@5:1.0000,NDCG@5:1.0000) [6.4 s] *
Epoch 3 loss=0.6931 [7.5 s] dev=(HR@5:1.0000,NDCG@5:1.0000) [6.5 s] *
Epoch 4 loss=0.6931 [7.6 s] dev=(HR@5:1.0000,NDCG@5:1.0000) [6.5 s] *
Epoch 5 loss=0.6931 [7.6 s] dev=(HR@5:1.0000,NDCG@5:1.0000) [6.4 s] *
Epoch 6 loss=0.6931 [7.0 s] dev=(HR@5:1.0000,NDCG@5:1.0000) [6.3 s] *
在使用cpu时计算正常
您好:
关于在CIKM2022(TiMiRec)中使用的CMCC数据集是否可以提供? 😃
感谢 👍
Hi, thanks for the great code!
I would like to ask something about the preprocessing code in Amazon.ipynb, where leave_df is made which I think it shouldn't be.
`
leave_df = out_df.groupby('user_id').head(1)
data_df = out_df.drop(leave_df.index)
`
If it is just to leave the last two items out for dev/test data, why is it included here? I think this would harm getting negative samples since the items in leave_df are excluded during generating test_df and dev_df.
Again, thanks for the great code!
Hi THUwangcy.
I use your lib to run the SASRec model with command as below (cuda environment):
python main.py --model_name SASRec --emb_size 50 --lr 0.001 --l2 0.0 --dataset ml-1m --test_all 1 --history_max 200 --num_layers 2 --num_heads 1 --batch_size 128 --topk 10 --num_workers 2
The parameters are same with the original paper SASRec. But I find the training speed is much slower than the original code for one epoch, even I modify the code to avoid inferring at every epoch.
ReChorus/src/helpers/BaseRunner.py
Lines 121 to 126 in 9a4a783
I ran your implement code of Chorus
my running cmd is
python main.py --model_name Chorus --emb_size 64 --margin 1 --lr 5e-4 --l2 1e-5 --epoch 50 --early_stop 0 --batch_size 512 --dataset 'Grocery_and_Gourmet_Food' --stage 1
python main.py --model_name Chorus --emb_size 64 --margin 1 --lr_scale 0.1 --lr 1e-3 --l2 0 --dataset 'Grocery_and_Gourmet_Food' --base_method 'BPR' --stage 2
The errors message is as follows:
Load corpus from ../data/Grocery_and_Gourmet_Food/KGReader.pkl
#params: 1521509
Chorus(
(u_embeddings): Embedding(14682, 64)
(i_embeddings): Embedding(8714, 64)
(r_embeddings): Embedding(3, 64)
(betas): Embedding(57, 3)
(mus): Embedding(57, 3)
(sigmas): Embedding(57, 3)
(prediction): Linear(in_features=64, out_features=1, bias=False)
(user_bias): Embedding(14682, 1)
(item_bias): Embedding(8714, 1)
(kg_loss): MarginRankingLoss()
)
Traceback (most recent call last):
File "main.py", line 116, in
main()
File "main.py", line 66, in main
model.actions_before_train()
File "/home/zlc/zlc/lhz/DIDN/ReChorus/src/models/sequential/Chorus.py", line 76, in actions_before_train
raise ValueError('Pre-trained KG model does not exist, please run with "--stage 1"')
ValueError: Pre-trained KG model does not exist, please run with "--stage 1"
I was wondering whether the difference was made due to my negligence. Looking forward to your reply! Thanks!
It seems that 'his_vectors' in this line should be 'his_pos_vectors'.
When 'self.add_pos' is set to True, we should use 'his_pos_vectors' instead of 'his_vectors'.
In my experiments, alter 'his_vectors' into 'his_pos_vectors' can lead to significant performance improvement when setting 'self.add_pos' to True.
FYI, the current reference to CFKG is linked to the short paper. A more comprehensive description of CFKG can be found in the journal paper "Learning heterogeneous knowledge base embeddings for explainable recommendation" (https://www.mdpi.com/1999-4893/11/9/137/pdf). It might worth linking to that as well :)
Following the document, Currently I run TiSAS model the output include [[score grouth truth, k-score-item],[....],[....]] and I don't know how to convert score to item? Please help me! Thank for your support.
Hi again 👍
I was writing down some codes and I found that the default parameter 'neg_items' in BaseModel.py is changed from 99 to 1, while amazon.ipynb has still the original 99. Any reason for that? The paper says it's 99, so a bit confusing.
Hi,
thank you for your work!
I read through your code and trained a few models on my dataset (#users 45'000, #items 260'000) using your library and have a question for which I would greatly appreciate your thoughts.
I have the feeling that evaluation results for evaluations using negative sampling are overly confident and do not reflect the actual performance of a model on a dataset. Let's say we have 99 negative samples and add the ground truth label, then the model must only differentiate between 100 classes instead of e.g. 260'000, and can even be sure that the actual class is part of these 100. This approach, IMO, greatly simplifies the task at hand. If that assumption is correct, what is even the point of this strategy (apart from lower computational efficiency)?
Also, would you mind explaining what the below code should do. From my understanding, this piece of code prevents proper evaluation on all the items, because it adjusts what the model has actually predicted.
if dataset.model.test_all:
rows, cols = list(), list()
for i, u in enumerate(dataset.data['user_id']):
clicked_items = list(dataset.corpus.train_clicked_set[u] | dataset.corpus.residual_clicked_set[u])
idx = list(np.ones_like(clicked_items) * i)
rows.extend(idx)
cols.extend(clicked_items)
predictions[rows, cols] = -np.inf
Thank you!
When I use the BERT encoder in the ContraRec framework, the results are normal, but when I use GRU4Rec and Caser, I do not use contrastive learning HR@5 It's 0.2741, using contrastive learning HR@5 It's 0.0759. I modified the encoder parameters and loss directly in the ContraRec framework. Can you give me some help? Thank you!
Hi Wang,
Today I run "GRU4Rec" with command python main.py --model_name GRU4Rec --emb_size 64 --hidden_size 128 --lr 1e-3 --l2 1e-4 --history_max 20
as shown in the code.
However, the results of the run are far from the results mentioned in your paper, Can you give me some guidance?
My result:
(HR@5:0.3203,NDCG@5:0.2223,HR@10:0.4232,NDCG@10:0.2555,HR@20:0.5417,NDCG@20:0.2854,HR@50:0.7626,NDCG@50:0.3289)
In your paper:
(HR@5:0.3704,NDCG@5:0.2643,HR@10:0.4721,NDCG@10:0.2972,
looking forward to your reply.
Hello, I am very interested in your paper 《Contrastive Learning for Sequential Recommendation》. However, I have some questions when reproducing the experiments. The baseline model I reproduced is consistent with the results in your readme table, but the experimental results of the CLRec model are not ideal. The value of the HR@5 metric is only 0.4808. Could you provide the parameters of this model? Or could you point out any possible operational errors on my part?
========================================
cuda available: True
Load corpus from ../data/Grocery_and_Gourmet_Food/BaseReader.pkl
Traceback (most recent call last):
File "main.py", line 116, in
main()
File "main.py", line 56, in main
corpus = pickle.load(open(corpus_path, 'rb'))
File "pandas/_libs/internals.pyx", line 572, in pandas._libs.internals.BlockManager.cinit
TypeError: cinit() takes at least 2 positional arguments (0 given)
This Error shows when I run the code, is the problem with input? Thanks for reply
Warning: ReChorus/src/models/BaseModel.py:147: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
Location: BaseModel.py line 147
Reason: in the latest Numpy, the np.array()
requires to specify dtype=np.object
if the lengths of arrays are different.
Possible Solution: replace line 147 with
if isinstance(feed_dicts[0][key], np.ndarray):
tmp_list = [len(d[key]) for d in feed_dicts]
if any([tmp_list[0] != l for l in tmp_list]):
stack_val = np.array([d[key] for d in feed_dicts], dtype=np.object)
else:
stack_val = np.array([d[key] for d in feed_dicts])
else:
stack_val = np.array([d[key] for d in feed_dicts])
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.