Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: fix bugs when running Random, ADMMSLIM, and SLIMElastic with negative sampling evaluations #1997

Merged
merged 2 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions recbole/config/configurator.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,9 +433,9 @@ def _set_default_parameters(self):
)
for op_args in default_train_neg_sample_args:
if op_args not in self.final_config_dict["train_neg_sample_args"]:
self.final_config_dict["train_neg_sample_args"][
op_args
] = default_train_neg_sample_args[op_args]
self.final_config_dict["train_neg_sample_args"][op_args] = (
default_train_neg_sample_args[op_args]
)

# eval_args checking
default_eval_args = {
Expand Down
6 changes: 3 additions & 3 deletions recbole/data/dataset/customized_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ def data_augmentation(self):
for i, (index, length) in enumerate(
zip(item_list_index, item_list_length)
):
new_dict[self.neg_item_list_field][i][
:length
] = self.neg_item_list[index]
new_dict[self.neg_item_list_field][i][:length] = (
self.neg_item_list[index]
)

new_data.update(Interaction(new_dict))
self.inter_feat = new_data
6 changes: 3 additions & 3 deletions recbole/data/dataset/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,9 +651,9 @@ def _fill_nan(self):
else:
dtype = np.int64 if ftype == FeatureType.TOKEN_SEQ else np.float
feat[field] = feat[field].apply(
lambda x: np.array([], dtype=dtype)
if isinstance(x, float)
else x
lambda x: (
np.array([], dtype=dtype) if isinstance(x, float) else x
)
)

def _normalize(self):
Expand Down
6 changes: 3 additions & 3 deletions recbole/data/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ def __call__(self, dataset, interaction):

shuffle_index = list(range(reorder_begin, reorder_begin + reorder_len))
random.shuffle(shuffle_index)
reorder_item_seq[
reorder_begin : reorder_begin + reorder_len
] = reorder_item_seq[shuffle_index]
reorder_item_seq[reorder_begin : reorder_begin + reorder_len] = (
reorder_item_seq[shuffle_index]
)

reorder_seq_list.append(
torch.tensor(reorder_item_seq, dtype=torch.long, device=device)
Expand Down
9 changes: 9 additions & 0 deletions recbole/evaluator/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ class GAUC(AbstractMetric):

:math:`rank_i` is the descending rank of the i-th items in :math:`R(u)`.
"""

metric_type = EvaluatorType.RANKING
metric_need = ["rec.meanrank"]

Expand Down Expand Up @@ -393,6 +394,7 @@ class MAE(LossMetric):

:math:`|S|` represents the number of pairs in :math:`S`.
"""

smaller = True

def __init__(self, config):
Expand All @@ -413,6 +415,7 @@ class RMSE(LossMetric):
.. math::
\mathrm{RMSE} = \sqrt{\frac{1}{|{S}|} \sum_{(u, i) \in {S}}(\hat{r}_{u i}-r_{u i})^{2}}
"""

smaller = True

def __init__(self, config):
Expand All @@ -434,6 +437,7 @@ class LogLoss(LossMetric):
.. math::
LogLoss = \frac{1}{|S|} \sum_{(u,i) \in S}(-((r_{u i} \ \log{\hat{r}_{u i}}) + {(1 - r_{u i})}\ \log{(1 - \hat{r}_{u i})}))
"""

smaller = True

def __init__(self, config):
Expand Down Expand Up @@ -461,6 +465,7 @@ class ItemCoverage(AbstractMetric):
.. math::
\mathrm{Coverage@K}=\frac{\left| \bigcup_{u \in U} \hat{R}(u) \right|}{|I|}
"""

metric_type = EvaluatorType.RANKING
metric_need = ["rec.items", "data.num_items"]

Expand Down Expand Up @@ -509,6 +514,7 @@ class AveragePopularity(AbstractMetric):

:math:`\phi(i)` is the number of interaction of item i in training data.
"""

metric_type = EvaluatorType.RANKING
smaller = True
metric_need = ["rec.items", "data.count_items"]
Expand Down Expand Up @@ -582,6 +588,7 @@ class ShannonEntropy(AbstractMetric):
:math:`p(i)` is the probability of recommending item i
which is the number of item i in recommended list over all items.
"""

metric_type = EvaluatorType.RANKING
metric_need = ["rec.items"]

Expand Down Expand Up @@ -637,6 +644,7 @@ class GiniIndex(AbstractMetric):
:math:`P{(i)}` represents the number of times all items appearing in the recommended list,
which is indexed in non-decreasing order (P_{(i)} \leq P_{(i+1)}).
"""

metric_type = EvaluatorType.RANKING
smaller = True
metric_need = ["rec.items", "data.num_items"]
Expand Down Expand Up @@ -699,6 +707,7 @@ class TailPercentage(AbstractMetric):
If you want to use this metric, please set the parameter 'tail_ratio' in the config
which can be an integer or a float in (0,1]. Otherwise it will default to 0.1.
"""

metric_type = EvaluatorType.RANKING
metric_need = ["rec.items", "data.count_items"]

Expand Down
1 change: 1 addition & 0 deletions recbole/model/exlib_recommender/lightgbm.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

class LightGBM(lgb.Booster):
r"""LightGBM is inherited from lgb.Booster"""

type = ModelType.DECISIONTREE
input_type = InputType.POINTWISE

Expand Down
1 change: 1 addition & 0 deletions recbole/model/exlib_recommender/xgboost.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

class XGBoost(xgb.Booster):
r"""XGBoost is inherited from xgb.Booster"""

type = ModelType.DECISIONTREE
input_type = InputType.POINTWISE

Expand Down
2 changes: 1 addition & 1 deletion recbole/model/general_recommender/admmslim.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def predict(self, interaction):
.flatten()
)

return add_noise(torch.from_numpy(r))
return add_noise(torch.from_numpy(r)).to(self.device)

def full_sort_predict(self, interaction):
user = interaction[self.USER_ID].cpu().numpy()
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/bpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

class BPR(GeneralRecommender):
r"""BPR is a basic matrix factorization model that be trained in the pairwise way."""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/cdae.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CDAE(GeneralRecommender, AutoEncoderMixin):
for top-N recommendation that utilizes the idea of Denoising Auto-Encoders.
We implement the the CDAE model with only user dataloader.
"""

input_type = InputType.POINTWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/convncf.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class ConvNCF(GeneralRecommender):
We carefully design the data interface and use sparse tensor to train and test efficiently.
We implement the model following the original author with a pairwise training mode.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/dgcf.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class DGCF(GeneralRecommender):
we carefully design the data interface and use sparse tensor to train and test efficiently.
We implement the model following the original author with a pairwise training mode.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
7 changes: 4 additions & 3 deletions recbole/model/general_recommender/diffrec.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class DiffRec(GeneralRecommender, AutoEncoderMixin):
Note that DiffRec simultaneously ranks all items for each user.
We implement the the DiffRec model with only user dataloader.
"""

input_type = InputType.LISTWISE

def __init__(self, config, dataset):
Expand Down Expand Up @@ -141,9 +142,9 @@ def __init__(self, config, dataset):
self.device
)
if self.beta_fixed:
self.betas[
0
] = 0.00001 # Deep Unsupervised Learning using Noneequilibrium Thermodynamics 2.4.1
self.betas[0] = (
0.00001 # Deep Unsupervised Learning using Noneequilibrium Thermodynamics 2.4.1
)
# The variance \beta_1 of the first step is fixed to a small constant to prevent overfitting.
assert len(self.betas.shape) == 1, "betas must be 1-D"
assert (
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/dmf.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class DMF(GeneralRecommender):
For a better performance and stability, we replace cosine similarity to inner-product when calculate
final score of user's and item's embedding.
"""

input_type = InputType.POINTWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/ease.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class EASE(GeneralRecommender):
strengths of auto-encoders and neighborhood-based approaches.

"""

input_type = InputType.POINTWISE
type = ModelType.TRADITIONAL

Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/gcmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class GCMC(GeneralRecommender):

We implement the model following the original author with a pairwise training mode.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/itemknn.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def compute_similarity(self, method, block_size=100):

class ItemKNN(GeneralRecommender):
r"""ItemKNN is a basic model that compute item similarity with the interaction matrix."""

input_type = InputType.POINTWISE
type = ModelType.TRADITIONAL

Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/lightgcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class LightGCN(GeneralRecommender):

We implement the model following the original author with a pairwise training mode.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/line.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class LINE(GeneralRecommender):

We implement the model to train users and items embedding for recommendation.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/macridvae.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class MacridVAE(GeneralRecommender, AutoEncoderMixin):

We implement the model following the original author.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/multidae.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class MultiDAE(GeneralRecommender, AutoEncoderMixin):

We implement the the MultiDAE model with only user dataloader.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/multivae.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class MultiVAE(GeneralRecommender, AutoEncoderMixin):

We implement the MultiVAE model with only user dataloader.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/ncl.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class NCL(GeneralRecommender):
r"""NCL is a neighborhood-enriched contrastive learning paradigm for graph collaborative filtering.
Both structural and semantic neighbors are explicitly captured as contrastive learning objects.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/neumf.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class NeuMF(GeneralRecommender):
Our implementation only contains a rough pretraining function.

"""

input_type = InputType.POINTWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/ngcf.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class NGCF(GeneralRecommender):
r"""NGCF is a model that incorporate GNN for recommendation.
We implement the model following the original author with a pairwise training mode.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/nncf.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class NNCF(GeneralRecommender):
r"""NNCF is an neural network enhanced matrix factorization model which also captures neighborhood information.
We implement the NNCF model with three ways to process neighborhood information.
"""

input_type = InputType.POINTWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/pop.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

class Pop(GeneralRecommender):
r"""Pop is an fundamental model that always recommend the most popular item."""

input_type = InputType.POINTWISE
type = ModelType.TRADITIONAL

Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/ract.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class RaCT(GeneralRecommender, AutoEncoderMixin):

We implement the RaCT model with only user dataloader.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
2 changes: 1 addition & 1 deletion recbole/model/general_recommender/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def calculate_loss(self, interaction):
return torch.nn.Parameter(torch.zeros(1))

def predict(self, interaction):
return torch.rand(len(interaction)).squeeze(-1)
return torch.rand(len(interaction), device=self.device).squeeze(-1)

def full_sort_predict(self, interaction):
batch_user_num = interaction[self.USER_ID].shape[0]
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/recvae.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class RecVAE(GeneralRecommender, AutoEncoderMixin):

We implement the model following the original author
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/sgl.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class SGL(GeneralRecommender):

We implement the model following the original author with a pairwise training mode.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/simplex.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class SimpleX(GeneralRecommender):

We implement the model following the original author with a pairwise training mode.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
3 changes: 2 additions & 1 deletion recbole/model/general_recommender/slimelastic.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class SLIMElastic(GeneralRecommender):
regularized optimization problem.

"""

input_type = InputType.POINTWISE
type = ModelType.TRADITIONAL

Expand Down Expand Up @@ -99,7 +100,7 @@ def predict(self, interaction):
(self.interaction_matrix[user, :].multiply(self.item_similarity[:, item].T))
.sum(axis=1)
.getA1()
)
).to(self.device)

return r

Expand Down
1 change: 1 addition & 0 deletions recbole/model/general_recommender/spectralcf.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class SpectralCF(GeneralRecommender):
For a better stability, we replace :math:`U U^T` with identity matrix :math:`I` and
replace :math:`U \Lambda U^T` with laplace matrix :math:`L`.
"""

input_type = InputType.PAIRWISE

def __init__(self, config, dataset):
Expand Down
Loading
Loading