From 2a28ea4bd5737832984d494f1a22db5486a5db1b Mon Sep 17 00:00:00 2001 From: hieuddo Date: Tue, 11 Aug 2026 01:57:25 +0800 Subject: [PATCH] add DiffGRM model documentation and example --- README.md | 1 + docs/source/api_ref/models.rst | 5 ++ examples/README.md | 2 + examples/diffgrm_example.py | 94 ++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 examples/diffgrm_example.py diff --git a/README.md b/README.md index f8fafe83..f971ae52 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,7 @@ The table below lists the recommendation models/algorithms featured in Cornac. E | Year | Model and Paper | Type | Environment | Example | | :--: | --------------- | :--: | :---------: | :-----: | | 2025 | [Generating Long Semantic IDs in Parallel for Recommendation (RPG)](cornac/models/rpg), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.rpg.recom_rpg), [paper](https://arxiv.org/abs/2506.05781) | Next-Item / Content-Based | [requirements](cornac/models/rpg/requirements.txt), CPU / GPU | [quick-start](examples/rpg_example.py) +| | [Diffusion-based Generative Recommendation Model (DiffGRM)](cornac/models/diffgrm), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.diffgrm.recom_diffgrm), [paper](https://arxiv.org/abs/2510.21805) | Next-Item / Content-Based | [requirements](cornac/models/diffgrm/requirements.txt), CPU / GPU | [quick-start](examples/diffgrm_example.py) | 2024 | [Comparative Aspects and Opinions Ranking for Recommendation Explanations (Companion)](cornac/models/companion), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.companion.recom_companion), [paper](https://lthoang.com/assets/publications/mlj24.pdf) | Hybrid / Sentiment / Explainable | CPU | [quick-start](examples/companion_example.py) | | [Hypergraphs with Attention on Reviews (HypAR)](cornac/models/hypar), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.hypar.recom_hypar), [paper](https://doi.org/10.1007/978-3-031-56027-9_14)| Hybrid / Sentiment / Explainable | [requirements](cornac/models/hypar/requirements_cu118.txt), CPU / GPU | [quick-start](https://github.com/PreferredAI/HypAR) | | [Learnable Item Tokenization for Generative Recommendation (LETTER)](cornac/models/letter), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.letter.recom_letter), [paper](https://arxiv.org/abs/2405.07314) | Next-Item / Content-Based | [requirements](cornac/models/letter/requirements.txt), CPU / GPU | [quick-start](examples/letter_example.py) diff --git a/docs/source/api_ref/models.rst b/docs/source/api_ref/models.rst index edbebbbc..030b8891 100644 --- a/docs/source/api_ref/models.rst +++ b/docs/source/api_ref/models.rst @@ -11,6 +11,11 @@ Recommender (Generic Class) .. automodule:: cornac.models.recommender :members: +Diffusion-based Generative Recommendation Model (DiffGRM) +--------------------------------------------------------- +.. automodule:: cornac.models.diffgrm.recom_diffgrm + :members: + Comparative Aspects and Opinions Ranking for Recommendation Explanations (Companion) ------------------------------------------------------------------------- .. automodule:: cornac.models.companion.recom_companion diff --git a/examples/README.md b/examples/README.md index 9924135e..44a1be0b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -136,6 +136,8 @@ [rpg_example.py](rpg_example.py) - Parallel generation of long unordered semantic IDs (RPG): OPQ tokenizer + multi-token prediction + graph-guided decoding, with Diginetica dataset. +[diffgrm_example.py](diffgrm_example.py) - Masked-diffusion generation of PSE semantic IDs (DiffGRM) on Amazon Sports with Sentence-T5 item content embeddings, OCN training, and CPD decoding. + ---- ## Next-Basket Algorithms diff --git a/examples/diffgrm_example.py b/examples/diffgrm_example.py new file mode 100644 index 00000000..e01f14a1 --- /dev/null +++ b/examples/diffgrm_example.py @@ -0,0 +1,94 @@ +# Copyright 2026 The Cornac Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""DiffGRM (masked-diffusion Semantic IDs) on Amazon Sports (2014). + +This example follows the DiffGRM Sports data path: per-user leave-last-out +splitting, item text containing title/price/brand/categories/description, +Sentence-T5 content embeddings, PSE tokenization, OCN training, and CPD +decoding. The model overrides the paper-style configuration's per-view loss +and paper decoder with the released pooled-token loss and released decoder +used by the release-fidelity study. + +This is an end-to-end runnable reference, not an artifact-identical +reproduction. PCA and FAISS outputs depend on library versions; the controlled +study uses frozen ``item_sids``. Cornac's standard experiment output is also +item-expanded, whereas the paper and released evaluator report SID-level +metrics. See ``cornac/models/diffgrm/README.md`` for the controlled results and +limitations. + +Requires ``sentence-transformers`` in addition to the packages in +``cornac/models/diffgrm/requirements.txt``. This is a paper-scale experiment; +training and beam evaluation are intended for a GPU. +""" + +import torch +from sentence_transformers import SentenceTransformer + +import cornac +from cornac.data import FeatureModality +from cornac.datasets import amazon_review +from cornac.eval_methods import NextItemEvaluation +from cornac.metrics import MRR, NDCG, Recall +from cornac.models import DiffGRM +from cornac.models.diffgrm import DIFFGRM_SPORTS_CONFIG + +DEVICE = "cuda" if torch.cuda.is_available() else "cpu" +print(f"using device: {DEVICE}") + +data = amazon_review.load_feedback(category="sports") +texts, item_ids = amazon_review.load_text( + category="sports", + include_description=True, +) + +encoder = SentenceTransformer("sentence-t5-base", device=DEVICE) +features = encoder.encode(texts, batch_size=256, show_progress_bar=True) +del encoder # release encoder memory before fitting DiffGRM +if DEVICE == "cuda": + torch.cuda.empty_cache() + +next_item_eval = NextItemEvaluation.leave_last_out( + data=data, + exclude_unknowns=True, + verbose=True, + item_feature=FeatureModality(features=features, ids=item_ids), +) + +models = [ + DiffGRM( + **{ + **DIFFGRM_SPORTS_CONFIG, + "view_loss_reduction": "token_mean", + "scoring": "released", + "device": DEVICE, + "verbose": True, + "seed": 2024, + } + ), +] + +metrics = [ + Recall(k=5), + Recall(k=10), + NDCG(k=5), + NDCG(k=10), + MRR(), +] + +cornac.Experiment( + eval_method=next_item_eval, + models=models, + metrics=metrics, +).run()