nextrec 0.4.10__tar.gz → 0.4.12__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. {nextrec-0.4.10 → nextrec-0.4.12}/PKG-INFO +32 -11
  2. {nextrec-0.4.10 → nextrec-0.4.12}/README.md +31 -10
  3. {nextrec-0.4.10 → nextrec-0.4.12}/README_en.md +30 -9
  4. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/conf.py +1 -1
  5. nextrec-0.4.12/nextrec/__version__.py +1 -0
  6. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/callback.py +44 -54
  7. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/features.py +35 -22
  8. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/layers.py +64 -68
  9. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/loggers.py +2 -2
  10. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/metrics.py +9 -5
  11. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/model.py +162 -106
  12. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/cli.py +16 -5
  13. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/data/preprocessor.py +4 -4
  14. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/loss/loss_utils.py +1 -1
  15. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/generative/__init__.py +1 -1
  16. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/eulernet.py +44 -75
  17. nextrec-0.4.12/nextrec/models/ranking/ffm.py +275 -0
  18. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/lr.py +1 -3
  19. nextrec-0.4.12/nextrec/models/representation/cl4srec.py +0 -0
  20. nextrec-0.4.12/nextrec/models/representation/lightgcn.py +0 -0
  21. nextrec-0.4.12/nextrec/models/representation/mf.py +0 -0
  22. nextrec-0.4.12/nextrec/models/representation/s3rec.py +0 -0
  23. nextrec-0.4.12/nextrec/models/retrieval/__init__.py +0 -0
  24. nextrec-0.4.12/nextrec/models/sequential/sasrec.py +0 -0
  25. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/utils/__init__.py +2 -1
  26. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/utils/console.py +9 -1
  27. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/utils/model.py +14 -0
  28. {nextrec-0.4.10 → nextrec-0.4.12}/pyproject.toml +1 -1
  29. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_generative_models.py +1 -1
  30. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_ranking_models.py +37 -0
  31. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/movielen_match_dssm.py +2 -1
  32. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/run_all_match_models.py +4 -1
  33. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/run_all_ranking_models.py +2 -0
  34. nextrec-0.4.10/nextrec/__version__.py +0 -1
  35. nextrec-0.4.10/tutorials/example_match_dssm.py +0 -130
  36. {nextrec-0.4.10 → nextrec-0.4.12}/.github/workflows/publish.yml +0 -0
  37. {nextrec-0.4.10 → nextrec-0.4.12}/.github/workflows/tests.yml +0 -0
  38. {nextrec-0.4.10 → nextrec-0.4.12}/.gitignore +0 -0
  39. {nextrec-0.4.10 → nextrec-0.4.12}/.readthedocs.yaml +0 -0
  40. {nextrec-0.4.10 → nextrec-0.4.12}/CODE_OF_CONDUCT.md +0 -0
  41. {nextrec-0.4.10 → nextrec-0.4.12}/CONTRIBUTING.md +0 -0
  42. {nextrec-0.4.10 → nextrec-0.4.12}/LICENSE +0 -0
  43. {nextrec-0.4.10 → nextrec-0.4.12}/MANIFEST.in +0 -0
  44. {nextrec-0.4.10 → nextrec-0.4.12}/assets/Feature Configuration.png +0 -0
  45. {nextrec-0.4.10 → nextrec-0.4.12}/assets/Model Parameters.png +0 -0
  46. {nextrec-0.4.10 → nextrec-0.4.12}/assets/Training Configuration.png +0 -0
  47. {nextrec-0.4.10 → nextrec-0.4.12}/assets/Training logs.png +0 -0
  48. {nextrec-0.4.10 → nextrec-0.4.12}/assets/logo.png +0 -0
  49. {nextrec-0.4.10 → nextrec-0.4.12}/assets/mmoe_tutorial.png +0 -0
  50. {nextrec-0.4.10 → nextrec-0.4.12}/assets/nextrec_diagram.png +0 -0
  51. {nextrec-0.4.10 → nextrec-0.4.12}/assets/test data.png +0 -0
  52. {nextrec-0.4.10 → nextrec-0.4.12}/dataset/ctcvr_task.csv +0 -0
  53. {nextrec-0.4.10 → nextrec-0.4.12}/dataset/ecommerce_task.csv +0 -0
  54. {nextrec-0.4.10 → nextrec-0.4.12}/dataset/match_task.csv +0 -0
  55. {nextrec-0.4.10 → nextrec-0.4.12}/dataset/movielens_100k.csv +0 -0
  56. {nextrec-0.4.10 → nextrec-0.4.12}/dataset/multitask_task.csv +0 -0
  57. {nextrec-0.4.10 → nextrec-0.4.12}/dataset/ranking_task.csv +0 -0
  58. {nextrec-0.4.10 → nextrec-0.4.12}/docs/en/Getting started guide.md +0 -0
  59. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/Makefile +0 -0
  60. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/index.md +0 -0
  61. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/make.bat +0 -0
  62. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/modules.rst +0 -0
  63. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/nextrec.basic.rst +0 -0
  64. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/nextrec.data.rst +0 -0
  65. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/nextrec.loss.rst +0 -0
  66. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/nextrec.rst +0 -0
  67. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/nextrec.utils.rst +0 -0
  68. {nextrec-0.4.10 → nextrec-0.4.12}/docs/rtd/requirements.txt +0 -0
  69. {nextrec-0.4.10 → nextrec-0.4.12}/docs/zh//345/277/253/351/200/237/344/270/212/346/211/213.md" +0 -0
  70. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/__init__.py +0 -0
  71. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/__init__.py +0 -0
  72. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/activation.py +0 -0
  73. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/basic/session.py +0 -0
  74. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/data/__init__.py +0 -0
  75. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/data/batch_utils.py +0 -0
  76. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/data/data_processing.py +0 -0
  77. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/data/data_utils.py +0 -0
  78. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/data/dataloader.py +0 -0
  79. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/loss/__init__.py +0 -0
  80. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/loss/listwise.py +0 -0
  81. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/loss/pairwise.py +0 -0
  82. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/loss/pointwise.py +0 -0
  83. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/generative/tiger.py +0 -0
  84. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/multi_task/__init__.py +0 -0
  85. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/multi_task/esmm.py +0 -0
  86. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/multi_task/mmoe.py +0 -0
  87. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/multi_task/ple.py +0 -0
  88. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/multi_task/poso.py +0 -0
  89. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/multi_task/share_bottom.py +0 -0
  90. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/__init__.py +0 -0
  91. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/afm.py +0 -0
  92. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/autoint.py +0 -0
  93. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/dcn.py +0 -0
  94. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/dcn_v2.py +0 -0
  95. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/deepfm.py +0 -0
  96. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/dien.py +0 -0
  97. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/din.py +0 -0
  98. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/fibinet.py +0 -0
  99. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/fm.py +0 -0
  100. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/masknet.py +0 -0
  101. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/pnn.py +0 -0
  102. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/widedeep.py +0 -0
  103. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/ranking/xdeepfm.py +0 -0
  104. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/representation/__init__.py +0 -0
  105. /nextrec-0.4.10/nextrec/models/ranking/ffm.py → /nextrec-0.4.12/nextrec/models/representation/autorec.py +0 -0
  106. /nextrec-0.4.10/nextrec/models/retrieval/__init__.py → /nextrec-0.4.12/nextrec/models/representation/bpr.py +0 -0
  107. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/representation/rqvae.py +0 -0
  108. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/retrieval/dssm.py +0 -0
  109. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/retrieval/dssm_v2.py +0 -0
  110. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/retrieval/mind.py +0 -0
  111. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/retrieval/sdm.py +0 -0
  112. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/models/retrieval/youtube_dnn.py +0 -0
  113. {nextrec-0.4.10/nextrec/models/generative → nextrec-0.4.12/nextrec/models/sequential}/hstu.py +0 -0
  114. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/utils/config.py +0 -0
  115. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/utils/data.py +0 -0
  116. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/utils/embedding.py +0 -0
  117. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/utils/feature.py +0 -0
  118. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec/utils/torch_utils.py +0 -0
  119. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/NextRec-CLI.md +0 -0
  120. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/NextRec-CLI_zh.md +0 -0
  121. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/feature_config.yaml +0 -0
  122. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/afm.yaml +0 -0
  123. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/autoint.yaml +0 -0
  124. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/dcn.yaml +0 -0
  125. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/deepfm.yaml +0 -0
  126. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/din.yaml +0 -0
  127. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/esmm.yaml +0 -0
  128. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/fibinet.yaml +0 -0
  129. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/fm.yaml +0 -0
  130. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/masknet.yaml +0 -0
  131. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/mmoe.yaml +0 -0
  132. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/ple.yaml +0 -0
  133. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/pnn.yaml +0 -0
  134. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/poso.yaml +0 -0
  135. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/share_bottom.yaml +0 -0
  136. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/widedeep.yaml +0 -0
  137. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/model_configs/xdeepfm.yaml +0 -0
  138. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/predict_config.yaml +0 -0
  139. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/predict_config_template.yaml +0 -0
  140. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/train_config.yaml +0 -0
  141. {nextrec-0.4.10 → nextrec-0.4.12}/nextrec_cli_preset/train_config_template.yaml +0 -0
  142. {nextrec-0.4.10 → nextrec-0.4.12}/pytest.ini +0 -0
  143. {nextrec-0.4.10 → nextrec-0.4.12}/requirements.txt +0 -0
  144. {nextrec-0.4.10 → nextrec-0.4.12}/scripts/format_code.py +0 -0
  145. {nextrec-0.4.10 → nextrec-0.4.12}/test/__init__.py +0 -0
  146. {nextrec-0.4.10 → nextrec-0.4.12}/test/conftest.py +0 -0
  147. {nextrec-0.4.10 → nextrec-0.4.12}/test/helpers.py +0 -0
  148. {nextrec-0.4.10 → nextrec-0.4.12}/test/run_tests.py +0 -0
  149. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_base_model_regularization.py +0 -0
  150. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_layers.py +0 -0
  151. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_losses.py +0 -0
  152. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_match_models.py +0 -0
  153. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_multitask_models.py +0 -0
  154. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_preprocessor.py +0 -0
  155. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_utils_console.py +0 -0
  156. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_utils_data.py +0 -0
  157. {nextrec-0.4.10 → nextrec-0.4.12}/test/test_utils_embedding.py +0 -0
  158. {nextrec-0.4.10 → nextrec-0.4.12}/test_requirements.txt +0 -0
  159. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/distributed/example_distributed_training.py +0 -0
  160. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/distributed/example_distributed_training_large_dataset.py +0 -0
  161. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/example_multitask.py +0 -0
  162. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/example_ranking_din.py +0 -0
  163. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/movielen_ranking_deepfm.py +0 -0
  164. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/notebooks/en/Build semantic ID with RQ-VAE.ipynb +0 -0
  165. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/notebooks/en/Hands on dataprocessor.ipynb +0 -0
  166. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/notebooks/en/Hands on nextrec.ipynb +0 -0
  167. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/notebooks/zh//344/275/277/347/224/250RQ-VAE/346/236/204/345/273/272/350/257/255/344/271/211ID.ipynb" +0 -0
  168. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/notebooks/zh//345/246/202/344/275/225/344/275/277/347/224/250DataProcessor/350/277/233/350/241/214/351/242/204/345/244/204/347/220/206.ipynb" +0 -0
  169. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/notebooks/zh//345/277/253/351/200/237/345/205/245/351/227/250nextrec.ipynb" +0 -0
  170. {nextrec-0.4.10 → nextrec-0.4.12}/tutorials/run_all_multitask_models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextrec
3
- Version: 0.4.10
3
+ Version: 0.4.12
4
4
  Summary: A comprehensive recommendation library with match, ranking, and multi-task learning models
5
5
  Project-URL: Homepage, https://github.com/zerolovesea/NextRec
6
6
  Project-URL: Repository, https://github.com/zerolovesea/NextRec
@@ -66,7 +66,7 @@ Description-Content-Type: text/markdown
66
66
  ![Python](https://img.shields.io/badge/Python-3.10+-blue.svg)
67
67
  ![PyTorch](https://img.shields.io/badge/PyTorch-1.10+-ee4c2c.svg)
68
68
  ![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)
69
- ![Version](https://img.shields.io/badge/Version-0.4.10-orange.svg)
69
+ ![Version](https://img.shields.io/badge/Version-0.4.12-orange.svg)
70
70
 
71
71
  中文文档 | [English Version](README_en.md)
72
72
 
@@ -99,7 +99,7 @@ NextRec是一个基于PyTorch的现代推荐系统框架,旨在为研究工程
99
99
 
100
100
  ## NextRec近期进展
101
101
 
102
- - **12/12/2025** 在v0.4.10中加入了[RQ-VAE](/nextrec/models/representation/rqvae.py)模块。配套的[数据集](/dataset/ecommerce_task.csv)和[代码](tutorials/notebooks/zh/使用RQ-VAE构建语义ID.ipynb)已经同步在仓库中
102
+ - **12/12/2025** 在v0.4.12中加入了[RQ-VAE](/nextrec/models/representation/rqvae.py)模块。配套的[数据集](/dataset/ecommerce_task.csv)和[代码](tutorials/notebooks/zh/使用RQ-VAE构建语义ID.ipynb)已经同步在仓库中
103
103
  - **07/12/2025** 发布了NextRec CLI命令行工具,它允许用户根据配置文件进行一键训练和推理,我们提供了相关的[教程](/nextrec_cli_preset/NextRec-CLI_zh.md)和[教学代码](/nextrec_cli_preset)
104
104
  - **03/12/2025** NextRec获得了100颗🌟!感谢大家的支持
105
105
  - **06/12/2025** 在v0.4.1中支持了单机多卡的分布式DDP训练,并且提供了配套的[代码](tutorials/distributed)
@@ -240,11 +240,11 @@ nextrec --mode=train --train_config=path/to/train_config.yaml
240
240
  nextrec --mode=predict --predict_config=path/to/predict_config.yaml
241
241
  ```
242
242
 
243
- > 截止当前版本0.4.10,NextRec CLI支持单机训练,分布式训练相关功能尚在开发中。
243
+ > 截止当前版本0.4.12,NextRec CLI支持单机训练,分布式训练相关功能尚在开发中。
244
244
 
245
245
  ## 兼容平台
246
246
 
247
- 当前最新版本为0.4.10,所有模型和测试代码均已在以下平台通过验证,如果开发者在使用中遇到兼容问题,请在issue区提出错误报告及系统版本:
247
+ 当前最新版本为0.4.12,所有模型和测试代码均已在以下平台通过验证,如果开发者在使用中遇到兼容问题,请在issue区提出错误报告及系统版本:
248
248
 
249
249
  | 平台 | 配置 |
250
250
  |------|------|
@@ -260,7 +260,9 @@ nextrec --mode=predict --predict_config=path/to/predict_config.yaml
260
260
  | 模型 | 论文 | 年份 | 状态 |
261
261
  |------|------|------|------|
262
262
  | [FM](nextrec/models/ranking/fm.py) | Factorization Machines | ICDM 2010 | 已支持 |
263
+ | [LR](nextrec/models/ranking/lr.py) | Logistic Regression | - | 已支持 |
263
264
  | [AFM](nextrec/models/ranking/afm.py) | Attentional Factorization Machines: Learning the Weight of Feature Interactions via Attention Networks | IJCAI 2017 | 已支持 |
265
+ | [FFM](nextrec/models/ranking/ffm.py) | Field-aware Factorization Machines | RecSys 2016 | 已支持 |
264
266
  | [DeepFM](nextrec/models/ranking/deepfm.py) | DeepFM: A Factorization-Machine based Neural Network for CTR Prediction | IJCAI 2017 | 已支持 |
265
267
  | [Wide&Deep](nextrec/models/ranking/widedeep.py) | Wide & Deep Learning for Recommender Systems | DLRS 2016 | 已支持 |
266
268
  | [xDeepFM](nextrec/models/ranking/xdeepfm.py) | xDeepFM: Combining Explicit and Implicit Feature Interactions | KDD 2018 | 已支持 |
@@ -272,16 +274,24 @@ nextrec --mode=predict --predict_config=path/to/predict_config.yaml
272
274
  | [DIN](nextrec/models/ranking/din.py) | Deep Interest Network for Click-Through Rate Prediction | KDD 2018 | 已支持 |
273
275
  | [DIEN](nextrec/models/ranking/dien.py) | Deep Interest Evolution Network for Click-Through Rate Prediction | AAAI 2019 | 已支持 |
274
276
  | [MaskNet](nextrec/models/ranking/masknet.py) | MaskNet: Introducing Feature-wise Gating Blocks for High-dimensional Sparse Recommendation Data | 2020 | 已支持 |
277
+ | [EulerNet](nextrec/models/ranking/eulernet.py) | EulerNet: Efficient and Effective Feature Interaction Modeling with Euler's Formula | SIGIR 2021 | 已支持 |
275
278
 
276
279
  ### 召回模型
277
280
 
278
281
  | 模型 | 论文 | 年份 | 状态 |
279
282
  |------|------|------|------|
280
- | [DSSM](nextrec/models/match/dssm.py) | Learning Deep Structured Semantic Models | CIKM 2013 | 已支持 |
281
- | [DSSM v2](nextrec/models/match/dssm_v2.py) | DSSM with pairwise BPR-style optimization | - | 已支持 |
282
- | [YouTube DNN](nextrec/models/match/youtube_dnn.py) | Deep Neural Networks for YouTube Recommendations | RecSys 2016 | 已支持 |
283
- | [MIND](nextrec/models/match/mind.py) | Multi-Interest Network with Dynamic Routing | CIKM 2019 | 已支持 |
284
- | [SDM](nextrec/models/match/sdm.py) | Sequential Deep Matching Model | - | 已支持 |
283
+ | [DSSM](nextrec/models/retrieval/dssm.py) | Learning Deep Structured Semantic Models | CIKM 2013 | 已支持 |
284
+ | [DSSM v2](nextrec/models/retrieval/dssm_v2.py) | DSSM with pairwise BPR-style optimization | - | 已支持 |
285
+ | [YouTube DNN](nextrec/models/retrieval/youtube_dnn.py) | Deep Neural Networks for YouTube Recommendations | RecSys 2016 | 已支持 |
286
+ | [MIND](nextrec/models/retrieval/mind.py) | Multi-Interest Network with Dynamic Routing | CIKM 2019 | 已支持 |
287
+ | [SDM](nextrec/models/retrieval/sdm.py) | Sequential Deep Matching Model | - | 已支持 |
288
+
289
+ ### 序列推荐模型
290
+
291
+ | 模型 | 论文 | 年份 | 状态 |
292
+ |------|------|------|------|
293
+ | [SASRec](nextrec/models/sequential/sasrec.py) | Self-Attentive Sequential Recommendation | KDD 2018 | 开发中 |
294
+ | [HSTU](nextrec/models/sequential/hstu.py) | Actions speak louder than words: Trillion-parameter sequential transducers for generative recommendations | arXiv 2024 | 已支持 |
285
295
 
286
296
  ### 多任务模型
287
297
 
@@ -298,7 +308,18 @@ nextrec --mode=predict --predict_config=path/to/predict_config.yaml
298
308
  | 模型 | 论文 | 年份 | 状态 |
299
309
  |------|------|------|------|
300
310
  | [TIGER](nextrec/models/generative/tiger.py) | Recommender Systems with Generative Retrieval | NeurIPS 2023 | 开发中 |
301
- | [HSTU](nextrec/models/generative/hstu.py) | Hierarchical Sequential Transduction Units | - | 已支持 |
311
+
312
+ ### 表征模型
313
+
314
+ | 模型 | 论文 | 年份 | 状态 |
315
+ |------|------|------|------|
316
+ | [RQ-VAE](nextrec/models/representation/rqvae.py) | RQ-VAE: RQVAE for Generative Retrieval | - | 已支持 |
317
+ | [BPR](nextrec/models/representation/bpr.py) | Bayesian Personalized Ranking | UAI 2009 | 开发中 |
318
+ | [MF](nextrec/models/representation/mf.py) | Matrix Factorization Techniques for Recommender Systems | - | 开发中 |
319
+ | [AutoRec](nextrec/models/representation/autorec.py) | AutoRec: Autoencoders Meet Collaborative Filtering | WWW 2015 | 开发中 |
320
+ | [LightGCN](nextrec/models/representation/lightgcn.py) | LightGCN: Simplifying and Powering Graph Convolution Network for Recommendation | SIGIR 2020 | 开发中 |
321
+ | [S3Rec](nextrec/models/representation/s3rec.py) | S3-Rec: Self-Supervised Learning for Sequential Recommendation | CIKM 2020 | 开发中 |
322
+ | [CL4SRec](nextrec/models/representation/cl4srec.py) | CL4SRec: Contrastive Learning for Sequential Recommendation | 2021 | 开发中 |
302
323
 
303
324
  ---
304
325
 
@@ -7,7 +7,7 @@
7
7
  ![Python](https://img.shields.io/badge/Python-3.10+-blue.svg)
8
8
  ![PyTorch](https://img.shields.io/badge/PyTorch-1.10+-ee4c2c.svg)
9
9
  ![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)
10
- ![Version](https://img.shields.io/badge/Version-0.4.10-orange.svg)
10
+ ![Version](https://img.shields.io/badge/Version-0.4.12-orange.svg)
11
11
 
12
12
  中文文档 | [English Version](README_en.md)
13
13
 
@@ -40,7 +40,7 @@ NextRec是一个基于PyTorch的现代推荐系统框架,旨在为研究工程
40
40
 
41
41
  ## NextRec近期进展
42
42
 
43
- - **12/12/2025** 在v0.4.10中加入了[RQ-VAE](/nextrec/models/representation/rqvae.py)模块。配套的[数据集](/dataset/ecommerce_task.csv)和[代码](tutorials/notebooks/zh/使用RQ-VAE构建语义ID.ipynb)已经同步在仓库中
43
+ - **12/12/2025** 在v0.4.12中加入了[RQ-VAE](/nextrec/models/representation/rqvae.py)模块。配套的[数据集](/dataset/ecommerce_task.csv)和[代码](tutorials/notebooks/zh/使用RQ-VAE构建语义ID.ipynb)已经同步在仓库中
44
44
  - **07/12/2025** 发布了NextRec CLI命令行工具,它允许用户根据配置文件进行一键训练和推理,我们提供了相关的[教程](/nextrec_cli_preset/NextRec-CLI_zh.md)和[教学代码](/nextrec_cli_preset)
45
45
  - **03/12/2025** NextRec获得了100颗🌟!感谢大家的支持
46
46
  - **06/12/2025** 在v0.4.1中支持了单机多卡的分布式DDP训练,并且提供了配套的[代码](tutorials/distributed)
@@ -181,11 +181,11 @@ nextrec --mode=train --train_config=path/to/train_config.yaml
181
181
  nextrec --mode=predict --predict_config=path/to/predict_config.yaml
182
182
  ```
183
183
 
184
- > 截止当前版本0.4.10,NextRec CLI支持单机训练,分布式训练相关功能尚在开发中。
184
+ > 截止当前版本0.4.12,NextRec CLI支持单机训练,分布式训练相关功能尚在开发中。
185
185
 
186
186
  ## 兼容平台
187
187
 
188
- 当前最新版本为0.4.10,所有模型和测试代码均已在以下平台通过验证,如果开发者在使用中遇到兼容问题,请在issue区提出错误报告及系统版本:
188
+ 当前最新版本为0.4.12,所有模型和测试代码均已在以下平台通过验证,如果开发者在使用中遇到兼容问题,请在issue区提出错误报告及系统版本:
189
189
 
190
190
  | 平台 | 配置 |
191
191
  |------|------|
@@ -201,7 +201,9 @@ nextrec --mode=predict --predict_config=path/to/predict_config.yaml
201
201
  | 模型 | 论文 | 年份 | 状态 |
202
202
  |------|------|------|------|
203
203
  | [FM](nextrec/models/ranking/fm.py) | Factorization Machines | ICDM 2010 | 已支持 |
204
+ | [LR](nextrec/models/ranking/lr.py) | Logistic Regression | - | 已支持 |
204
205
  | [AFM](nextrec/models/ranking/afm.py) | Attentional Factorization Machines: Learning the Weight of Feature Interactions via Attention Networks | IJCAI 2017 | 已支持 |
206
+ | [FFM](nextrec/models/ranking/ffm.py) | Field-aware Factorization Machines | RecSys 2016 | 已支持 |
205
207
  | [DeepFM](nextrec/models/ranking/deepfm.py) | DeepFM: A Factorization-Machine based Neural Network for CTR Prediction | IJCAI 2017 | 已支持 |
206
208
  | [Wide&Deep](nextrec/models/ranking/widedeep.py) | Wide & Deep Learning for Recommender Systems | DLRS 2016 | 已支持 |
207
209
  | [xDeepFM](nextrec/models/ranking/xdeepfm.py) | xDeepFM: Combining Explicit and Implicit Feature Interactions | KDD 2018 | 已支持 |
@@ -213,16 +215,24 @@ nextrec --mode=predict --predict_config=path/to/predict_config.yaml
213
215
  | [DIN](nextrec/models/ranking/din.py) | Deep Interest Network for Click-Through Rate Prediction | KDD 2018 | 已支持 |
214
216
  | [DIEN](nextrec/models/ranking/dien.py) | Deep Interest Evolution Network for Click-Through Rate Prediction | AAAI 2019 | 已支持 |
215
217
  | [MaskNet](nextrec/models/ranking/masknet.py) | MaskNet: Introducing Feature-wise Gating Blocks for High-dimensional Sparse Recommendation Data | 2020 | 已支持 |
218
+ | [EulerNet](nextrec/models/ranking/eulernet.py) | EulerNet: Efficient and Effective Feature Interaction Modeling with Euler's Formula | SIGIR 2021 | 已支持 |
216
219
 
217
220
  ### 召回模型
218
221
 
219
222
  | 模型 | 论文 | 年份 | 状态 |
220
223
  |------|------|------|------|
221
- | [DSSM](nextrec/models/match/dssm.py) | Learning Deep Structured Semantic Models | CIKM 2013 | 已支持 |
222
- | [DSSM v2](nextrec/models/match/dssm_v2.py) | DSSM with pairwise BPR-style optimization | - | 已支持 |
223
- | [YouTube DNN](nextrec/models/match/youtube_dnn.py) | Deep Neural Networks for YouTube Recommendations | RecSys 2016 | 已支持 |
224
- | [MIND](nextrec/models/match/mind.py) | Multi-Interest Network with Dynamic Routing | CIKM 2019 | 已支持 |
225
- | [SDM](nextrec/models/match/sdm.py) | Sequential Deep Matching Model | - | 已支持 |
224
+ | [DSSM](nextrec/models/retrieval/dssm.py) | Learning Deep Structured Semantic Models | CIKM 2013 | 已支持 |
225
+ | [DSSM v2](nextrec/models/retrieval/dssm_v2.py) | DSSM with pairwise BPR-style optimization | - | 已支持 |
226
+ | [YouTube DNN](nextrec/models/retrieval/youtube_dnn.py) | Deep Neural Networks for YouTube Recommendations | RecSys 2016 | 已支持 |
227
+ | [MIND](nextrec/models/retrieval/mind.py) | Multi-Interest Network with Dynamic Routing | CIKM 2019 | 已支持 |
228
+ | [SDM](nextrec/models/retrieval/sdm.py) | Sequential Deep Matching Model | - | 已支持 |
229
+
230
+ ### 序列推荐模型
231
+
232
+ | 模型 | 论文 | 年份 | 状态 |
233
+ |------|------|------|------|
234
+ | [SASRec](nextrec/models/sequential/sasrec.py) | Self-Attentive Sequential Recommendation | KDD 2018 | 开发中 |
235
+ | [HSTU](nextrec/models/sequential/hstu.py) | Actions speak louder than words: Trillion-parameter sequential transducers for generative recommendations | arXiv 2024 | 已支持 |
226
236
 
227
237
  ### 多任务模型
228
238
 
@@ -239,7 +249,18 @@ nextrec --mode=predict --predict_config=path/to/predict_config.yaml
239
249
  | 模型 | 论文 | 年份 | 状态 |
240
250
  |------|------|------|------|
241
251
  | [TIGER](nextrec/models/generative/tiger.py) | Recommender Systems with Generative Retrieval | NeurIPS 2023 | 开发中 |
242
- | [HSTU](nextrec/models/generative/hstu.py) | Hierarchical Sequential Transduction Units | - | 已支持 |
252
+
253
+ ### 表征模型
254
+
255
+ | 模型 | 论文 | 年份 | 状态 |
256
+ |------|------|------|------|
257
+ | [RQ-VAE](nextrec/models/representation/rqvae.py) | RQ-VAE: RQVAE for Generative Retrieval | - | 已支持 |
258
+ | [BPR](nextrec/models/representation/bpr.py) | Bayesian Personalized Ranking | UAI 2009 | 开发中 |
259
+ | [MF](nextrec/models/representation/mf.py) | Matrix Factorization Techniques for Recommender Systems | - | 开发中 |
260
+ | [AutoRec](nextrec/models/representation/autorec.py) | AutoRec: Autoencoders Meet Collaborative Filtering | WWW 2015 | 开发中 |
261
+ | [LightGCN](nextrec/models/representation/lightgcn.py) | LightGCN: Simplifying and Powering Graph Convolution Network for Recommendation | SIGIR 2020 | 开发中 |
262
+ | [S3Rec](nextrec/models/representation/s3rec.py) | S3-Rec: Self-Supervised Learning for Sequential Recommendation | CIKM 2020 | 开发中 |
263
+ | [CL4SRec](nextrec/models/representation/cl4srec.py) | CL4SRec: Contrastive Learning for Sequential Recommendation | 2021 | 开发中 |
243
264
 
244
265
  ---
245
266
 
@@ -7,7 +7,7 @@
7
7
  ![Python](https://img.shields.io/badge/Python-3.10+-blue.svg)
8
8
  ![PyTorch](https://img.shields.io/badge/PyTorch-1.10+-ee4c2c.svg)
9
9
  ![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)
10
- ![Version](https://img.shields.io/badge/Version-0.4.10-orange.svg)
10
+ ![Version](https://img.shields.io/badge/Version-0.4.12-orange.svg)
11
11
 
12
12
  English | [中文文档](README.md)
13
13
 
@@ -185,11 +185,11 @@ nextrec --mode=train --train_config=path/to/train_config.yaml
185
185
  nextrec --mode=predict --predict_config=path/to/predict_config.yaml
186
186
  ```
187
187
 
188
- > As of version 0.4.10, NextRec CLI supports single-machine training; distributed training features are currently under development.
188
+ > As of version 0.4.12, NextRec CLI supports single-machine training; distributed training features are currently under development.
189
189
 
190
190
  ## Platform Compatibility
191
191
 
192
- The current version is 0.4.10. All models and test code have been validated on the following platforms. If you encounter compatibility issues, please report them in the issue tracker with your system version:
192
+ The current version is 0.4.12. All models and test code have been validated on the following platforms. If you encounter compatibility issues, please report them in the issue tracker with your system version:
193
193
 
194
194
  | Platform | Configuration |
195
195
  |----------|---------------|
@@ -207,7 +207,9 @@ The current version is 0.4.10. All models and test code have been validated on t
207
207
  | Model | Paper | Year | Status |
208
208
  |-------|-------|------|--------|
209
209
  | [FM](nextrec/models/ranking/fm.py) | Factorization Machines | ICDM 2010 | Supported |
210
+ | [LR](nextrec/models/ranking/lr.py) | Logistic Regression | - | Supported |
210
211
  | [AFM](nextrec/models/ranking/afm.py) | Attentional Factorization Machines: Learning the Weight of Feature Interactions via Attention Networks | IJCAI 2017 | Supported |
212
+ | [FFM](nextrec/models/ranking/ffm.py) | Field-aware Factorization Machines | RecSys 2016 | Supported |
211
213
  | [DeepFM](nextrec/models/ranking/deepfm.py) | DeepFM: A Factorization-Machine based Neural Network for CTR Prediction | IJCAI 2017 | Supported |
212
214
  | [Wide&Deep](nextrec/models/ranking/widedeep.py) | Wide & Deep Learning for Recommender Systems | DLRS 2016 | Supported |
213
215
  | [xDeepFM](nextrec/models/ranking/xdeepfm.py) | xDeepFM: Combining Explicit and Implicit Feature Interactions | KDD 2018 | Supported |
@@ -219,16 +221,24 @@ The current version is 0.4.10. All models and test code have been validated on t
219
221
  | [DIN](nextrec/models/ranking/din.py) | Deep Interest Network for CTR Prediction | KDD 2018 | Supported |
220
222
  | [DIEN](nextrec/models/ranking/dien.py) | Deep Interest Evolution Network | AAAI 2019 | Supported |
221
223
  | [MaskNet](nextrec/models/ranking/masknet.py) | MaskNet: Feature-wise Gating Blocks for High-dimensional Sparse Recommendation Data | 2020 | Supported |
224
+ | [EulerNet](nextrec/models/ranking/eulernet.py) | EulerNet: Efficient and Effective Feature Interaction Modeling with Euler's Formula | SIGIR 2021 | Supported |
222
225
 
223
226
  ### Retrieval Models
224
227
 
225
228
  | Model | Paper | Year | Status |
226
229
  |-------|-------|------|--------|
227
- | [DSSM](nextrec/models/match/dssm.py) | Learning Deep Structured Semantic Models | CIKM 2013 | Supported |
228
- | [DSSM v2](nextrec/models/match/dssm_v2.py) | DSSM with pairwise BPR-style optimization | - | Supported |
229
- | [YouTube DNN](nextrec/models/match/youtube_dnn.py) | Deep Neural Networks for YouTube Recommendations | RecSys 2016 | Supported |
230
- | [MIND](nextrec/models/match/mind.py) | Multi-Interest Network with Dynamic Routing | CIKM 2019 | Supported |
231
- | [SDM](nextrec/models/match/sdm.py) | Sequential Deep Matching Model | - | Supported |
230
+ | [DSSM](nextrec/models/retrieval/dssm.py) | Learning Deep Structured Semantic Models | CIKM 2013 | Supported |
231
+ | [DSSM v2](nextrec/models/retrieval/dssm_v2.py) | DSSM with pairwise BPR-style optimization | - | Supported |
232
+ | [YouTube DNN](nextrec/models/retrieval/youtube_dnn.py) | Deep Neural Networks for YouTube Recommendations | RecSys 2016 | Supported |
233
+ | [MIND](nextrec/models/retrieval/mind.py) | Multi-Interest Network with Dynamic Routing | CIKM 2019 | Supported |
234
+ | [SDM](nextrec/models/retrieval/sdm.py) | Sequential Deep Matching Model | - | Supported |
235
+
236
+ ### Sequential Recommendation Models
237
+
238
+ | Model | Paper | Year | Status |
239
+ |-------|-------|------|--------|
240
+ | [SASRec](nextrec/models/sequential/sasrec.py) | Self-Attentive Sequential Recommendation | KDD 2018 | In Progress |
241
+ | [HSTU](nextrec/models/sequential/hstu.py) | Actions speak louder than words: Trillion-parameter sequential transducers for generative recommendations | arXiv 2024 | Supported |
232
242
 
233
243
  ### Multi-task Models
234
244
 
@@ -245,7 +255,18 @@ The current version is 0.4.10. All models and test code have been validated on t
245
255
  | Model | Paper | Year | Status |
246
256
  |-------|-------|------|--------|
247
257
  | [TIGER](nextrec/models/generative/tiger.py) | Recommender Systems with Generative Retrieval | NeurIPS 2023 | In Progress |
248
- | [HSTU](nextrec/models/generative/hstu.py) | Hierarchical Sequential Transduction Units | - | Supported |
258
+
259
+ ### Representation Models
260
+
261
+ | Model | Paper | Year | Status |
262
+ |-------|-------|------|--------|
263
+ | [RQ-VAE](nextrec/models/representation/rqvae.py) | RQ-VAE: RQVAE for Generative Retrieval | - | Supported |
264
+ | [BPR](nextrec/models/representation/bpr.py) | Bayesian Personalized Ranking | UAI 2009 | In Progress |
265
+ | [MF](nextrec/models/representation/mf.py) | Matrix Factorization Techniques for Recommender Systems | - | In Progress |
266
+ | [AutoRec](nextrec/models/representation/autorec.py) | AutoRec: Autoencoders Meet Collaborative Filtering | WWW 2015 | In Progress |
267
+ | [LightGCN](nextrec/models/representation/lightgcn.py) | LightGCN: Simplifying and Powering Graph Convolution Network for Recommendation | SIGIR 2020 | In Progress |
268
+ | [S3Rec](nextrec/models/representation/s3rec.py) | S3-Rec: Self-Supervised Learning for Sequential Recommendation | CIKM 2020 | In Progress |
269
+ | [CL4SRec](nextrec/models/representation/cl4srec.py) | CL4SRec: Contrastive Learning for Sequential Recommendation | 2021 | In Progress |
249
270
 
250
271
  ---
251
272
 
@@ -11,7 +11,7 @@ sys.path.insert(0, str(PROJECT_ROOT / "nextrec"))
11
11
  project = "NextRec"
12
12
  copyright = "2025, Yang Zhou"
13
13
  author = "Yang Zhou"
14
- release = "0.4.10"
14
+ release = "0.4.12"
15
15
 
16
16
  extensions = [
17
17
  "myst_parser",
@@ -0,0 +1 @@
1
+ __version__ = "0.4.12"
@@ -22,10 +22,10 @@ class Callback:
22
22
  """
23
23
  Base callback.
24
24
 
25
- Notes (DDP):
26
- - In distributed training, the training loop runs on every rank.
27
- - For callbacks with side effects (saving, logging, etc.), set
28
- ``run_on_main_process_only=True`` to avoid multi-rank duplication.
25
+ Notes for DDP training:
26
+ In distributed training, the training loop runs on every rank.
27
+ For callbacks with side effects (saving, logging, etc.), set
28
+ ``run_on_main_process_only=True`` to avoid multi-rank duplication.
29
29
  """
30
30
 
31
31
  run_on_main_process_only: bool = False
@@ -70,7 +70,7 @@ class Callback:
70
70
 
71
71
 
72
72
  class CallbackList:
73
- """Container for managing multiple callbacks."""
73
+ """Generates a list of callbacks"""
74
74
 
75
75
  def __init__(self, callbacks: Optional[list[Callback]] = None):
76
76
  self.callbacks = callbacks or []
@@ -78,61 +78,41 @@ class CallbackList:
78
78
  def append(self, callback: Callback):
79
79
  self.callbacks.append(callback)
80
80
 
81
- def set_model(self, model):
81
+ def call(self, fn_name: str, *args, **kwargs):
82
82
  for callback in self.callbacks:
83
- callback.set_model(model)
83
+ if not callback.should_run():
84
+ continue
85
+ getattr(callback, fn_name)(*args, **kwargs)
86
+
87
+ def set_model(self, model):
88
+ self.call("set_model", model)
84
89
 
85
90
  def set_params(self, params: dict):
86
- for callback in self.callbacks:
87
- callback.set_params(params)
91
+ self.call("set_params", params)
88
92
 
89
93
  def on_train_begin(self, logs: Optional[dict] = None):
90
- for callback in self.callbacks:
91
- if not callback.should_run():
92
- continue
93
- callback.on_train_begin(logs)
94
+ self.call("on_train_begin", logs)
94
95
 
95
96
  def on_train_end(self, logs: Optional[dict] = None):
96
- for callback in self.callbacks:
97
- if not callback.should_run():
98
- continue
99
- callback.on_train_end(logs)
97
+ self.call("on_train_end", logs)
100
98
 
101
99
  def on_epoch_begin(self, epoch: int, logs: Optional[dict] = None):
102
- for callback in self.callbacks:
103
- if not callback.should_run():
104
- continue
105
- callback.on_epoch_begin(epoch, logs)
100
+ self.call("on_epoch_begin", epoch, logs)
106
101
 
107
102
  def on_epoch_end(self, epoch: int, logs: Optional[dict] = None):
108
- for callback in self.callbacks:
109
- if not callback.should_run():
110
- continue
111
- callback.on_epoch_end(epoch, logs)
103
+ self.call("on_epoch_end", epoch, logs)
112
104
 
113
105
  def on_batch_begin(self, batch: int, logs: Optional[dict] = None):
114
- for callback in self.callbacks:
115
- if not callback.should_run():
116
- continue
117
- callback.on_batch_begin(batch, logs)
106
+ self.call("on_batch_begin", batch, logs)
118
107
 
119
108
  def on_batch_end(self, batch: int, logs: Optional[dict] = None):
120
- for callback in self.callbacks:
121
- if not callback.should_run():
122
- continue
123
- callback.on_batch_end(batch, logs)
109
+ self.call("on_batch_end", batch, logs)
124
110
 
125
111
  def on_validation_begin(self, logs: Optional[dict] = None):
126
- for callback in self.callbacks:
127
- if not callback.should_run():
128
- continue
129
- callback.on_validation_begin(logs)
112
+ self.call("on_validation_begin", logs)
130
113
 
131
114
  def on_validation_end(self, logs: Optional[dict] = None):
132
- for callback in self.callbacks:
133
- if not callback.should_run():
134
- continue
135
- callback.on_validation_end(logs)
115
+ self.call("on_validation_end", logs)
136
116
 
137
117
 
138
118
  class EarlyStopper(Callback):
@@ -146,6 +126,20 @@ class EarlyStopper(Callback):
146
126
  restore_best_weights: bool = True,
147
127
  verbose: int = 1,
148
128
  ):
129
+ """
130
+ Callback to stop training early if no improvement.
131
+
132
+ Args:
133
+ monitor: Metric name to monitor.
134
+ patience: Number of epochs with no improvement after which training will be stopped.
135
+ mode: One of {'min', 'max'}. In 'min' mode, training will stop when the
136
+ monitored metric has stopped decreasing; in 'max' mode it will stop
137
+ when the monitored metric has stopped increasing.
138
+ min_delta: Minimum change in the monitored metric to qualify as an improvement.
139
+ restore_best_weights: Whether to restore model weights from the epoch with the best value
140
+ of the monitored metric.
141
+ verbose: Verbosity mode. 1: messages will be printed. 0: silent.
142
+ """
149
143
  super().__init__()
150
144
  self.monitor = monitor
151
145
  self.patience = patience
@@ -233,6 +227,7 @@ class CheckpointSaver(Callback):
233
227
  save_best_only: If True, only save when the model is considered the "best".
234
228
  save_freq: Frequency of checkpoint saving ('epoch' or integer for every N epochs).
235
229
  verbose: Verbosity mode.
230
+ run_on_main_process_only: Whether to run this callback only on the main process in DDP.
236
231
  """
237
232
 
238
233
  def __init__(
@@ -274,7 +269,6 @@ class CheckpointSaver(Callback):
274
269
  self.checkpoint_path.parent.mkdir(parents=True, exist_ok=True)
275
270
 
276
271
  def on_epoch_end(self, epoch: int, logs: Optional[dict] = None):
277
- logging.info("")
278
272
  logs = logs or {}
279
273
 
280
274
  should_save = False
@@ -283,9 +277,6 @@ class CheckpointSaver(Callback):
283
277
  elif isinstance(self.save_freq, int) and (epoch + 1) % self.save_freq == 0:
284
278
  should_save = True
285
279
 
286
- if not should_save and self.save_best_only:
287
- should_save = False
288
-
289
280
  # Check if this is the best model
290
281
  current = logs.get(self.monitor)
291
282
  is_best = False
@@ -297,11 +288,7 @@ class CheckpointSaver(Callback):
297
288
 
298
289
  if should_save:
299
290
  if not self.save_best_only or is_best:
300
- checkpoint_path = (
301
- self.checkpoint_path.parent
302
- / f"{self.checkpoint_path.stem}{self.checkpoint_path.suffix}"
303
- )
304
- self.save_checkpoint(checkpoint_path, epoch, logs)
291
+ self.save_checkpoint(self.checkpoint_path, epoch, logs)
305
292
 
306
293
  if is_best:
307
294
  # Use save_path directly without adding _best suffix since it may already contain it
@@ -371,7 +358,9 @@ class LearningRateScheduler(Callback):
371
358
  # Step the scheduler
372
359
  if hasattr(self.scheduler, "step"):
373
360
  # Some schedulers need metrics
374
- if "val_loss" in (logs or {}) and hasattr(self.scheduler, "mode"):
361
+ if logs is None:
362
+ logs = {}
363
+ if "val_loss" in logs and hasattr(self.scheduler, "mode"):
375
364
  self.scheduler.step(logs["val_loss"])
376
365
  else:
377
366
  self.scheduler.step()
@@ -399,7 +388,6 @@ class MetricsLogger(Callback):
399
388
  self.run_on_main_process_only = True
400
389
  self.log_freq = log_freq
401
390
  self.verbose = verbose
402
- self.batch_count = 0
403
391
 
404
392
  def on_epoch_end(self, epoch: int, logs: Optional[dict] = None):
405
393
  if self.verbose > 0 and (
@@ -416,8 +404,10 @@ class MetricsLogger(Callback):
416
404
  logging.info(f"Epoch {epoch + 1}: {metrics_str}")
417
405
 
418
406
  def on_batch_end(self, batch: int, logs: Optional[dict] = None):
419
- self.batch_count += 1
420
- if self.verbose > 1 and self.log_freq == "batch":
407
+ if self.verbose > 1 and (
408
+ self.log_freq == "batch"
409
+ or (isinstance(self.log_freq, int) and (batch + 1) % self.log_freq == 0)
410
+ ):
421
411
  logs = logs or {}
422
412
  metrics_str = " - ".join(
423
413
  [
@@ -2,7 +2,7 @@
2
2
  Feature definitions
3
3
 
4
4
  Date: create on 27/10/2025
5
- Checkpoint: edit on 02/12/2025
5
+ Checkpoint: edit on 20/12/2025
6
6
  Author: Yang Zhou, zyaztec@gmail.com
7
7
  """
8
8
 
@@ -12,22 +12,20 @@ from nextrec.utils.embedding import get_auto_embedding_dim
12
12
  from nextrec.utils.feature import normalize_to_list
13
13
 
14
14
 
15
- class BaseFeature(object):
15
+ class BaseFeature:
16
16
  def __repr__(self):
17
17
  params = {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
18
18
  param_str = ", ".join(f"{k}={v!r}" for k, v in params.items())
19
19
  return f"{self.__class__.__name__}({param_str})"
20
20
 
21
21
 
22
- class SequenceFeature(BaseFeature):
22
+ class EmbeddingFeature(BaseFeature):
23
23
  def __init__(
24
24
  self,
25
25
  name: str,
26
26
  vocab_size: int,
27
- max_len: int = 20,
28
27
  embedding_name: str = "",
29
28
  embedding_dim: int | None = 4,
30
- combiner: str = "mean",
31
29
  padding_idx: int | None = None,
32
30
  init_type: str = "normal",
33
31
  init_params: dict | None = None,
@@ -39,13 +37,15 @@ class SequenceFeature(BaseFeature):
39
37
  ):
40
38
  self.name = name
41
39
  self.vocab_size = vocab_size
42
- self.max_len = max_len
43
40
  self.embedding_name = embedding_name or name
44
- self.embedding_dim = embedding_dim or get_auto_embedding_dim(vocab_size)
41
+ self.embedding_dim = (
42
+ get_auto_embedding_dim(vocab_size)
43
+ if embedding_dim is None
44
+ else embedding_dim
45
+ )
45
46
 
46
47
  self.init_type = init_type
47
48
  self.init_params = init_params or {}
48
- self.combiner = combiner
49
49
  self.padding_idx = padding_idx
50
50
  self.l1_reg = l1_reg
51
51
  self.l2_reg = l2_reg
@@ -54,13 +54,15 @@ class SequenceFeature(BaseFeature):
54
54
  self.freeze_pretrained = freeze_pretrained
55
55
 
56
56
 
57
- class SparseFeature(BaseFeature):
57
+ class SequenceFeature(EmbeddingFeature):
58
58
  def __init__(
59
59
  self,
60
60
  name: str,
61
61
  vocab_size: int,
62
+ max_len: int = 20,
62
63
  embedding_name: str = "",
63
64
  embedding_dim: int | None = 4,
65
+ combiner: str = "mean",
64
66
  padding_idx: int | None = None,
65
67
  init_type: str = "normal",
66
68
  init_params: dict | None = None,
@@ -70,19 +72,26 @@ class SparseFeature(BaseFeature):
70
72
  pretrained_weight: torch.Tensor | None = None,
71
73
  freeze_pretrained: bool = False,
72
74
  ):
73
- self.name = name
74
- self.vocab_size = vocab_size
75
- self.embedding_name = embedding_name or name
76
- self.embedding_dim = embedding_dim or get_auto_embedding_dim(vocab_size)
75
+ super().__init__(
76
+ name=name,
77
+ vocab_size=vocab_size,
78
+ embedding_name=embedding_name,
79
+ embedding_dim=embedding_dim,
80
+ padding_idx=padding_idx,
81
+ init_type=init_type,
82
+ init_params=init_params,
83
+ l1_reg=l1_reg,
84
+ l2_reg=l2_reg,
85
+ trainable=trainable,
86
+ pretrained_weight=pretrained_weight,
87
+ freeze_pretrained=freeze_pretrained,
88
+ )
89
+ self.max_len = max_len
90
+ self.combiner = combiner
77
91
 
78
- self.init_type = init_type
79
- self.init_params = init_params or {}
80
- self.padding_idx = padding_idx
81
- self.l1_reg = l1_reg
82
- self.l2_reg = l2_reg
83
- self.trainable = trainable
84
- self.pretrained_weight = pretrained_weight
85
- self.freeze_pretrained = freeze_pretrained
92
+
93
+ class SparseFeature(EmbeddingFeature):
94
+ pass
86
95
 
87
96
 
88
97
  class DenseFeature(BaseFeature):
@@ -95,7 +104,11 @@ class DenseFeature(BaseFeature):
95
104
  ):
96
105
  self.name = name
97
106
  self.input_dim = max(int(input_dim or 1), 1)
98
- self.embedding_dim = embedding_dim or self.input_dim
107
+ self.embedding_dim = self.input_dim if embedding_dim is None else embedding_dim
108
+ if use_embedding and self.embedding_dim == 0:
109
+ raise ValueError(
110
+ "[Features Error] DenseFeature: use_embedding=True is incompatible with embedding_dim=0"
111
+ )
99
112
  if embedding_dim is not None and embedding_dim > 1:
100
113
  self.use_embedding = True
101
114
  else: