Migrate SLi-Rec from TensorFlow to PyTorch - #2358
Open
miguelgfierro wants to merge 17 commits into
Open
Conversation
Port the time-aware LSTM cell (Time4LSTMCell) and a dynamic_rnn-equivalent scan driver from TF to PyTorch as the first component of the SLi-Rec migration. Weight-copied parity vs the TF cell: single-step m/c diff ~1e-7, full padded sequence rnn_outputs diff ~6e-8. Includes the migration design doc. Signed-off-by: miguelgfierro <[email protected]>
Faithful port of SequentialIterator (parser_one_line, load_data_from_file, _convert_data) without TF placeholders. Verified bit-identical to the TF iterator on real slirec data: parser, eval-batch arrays, and train-batch arrays including in-batch negative sampling under a shared RNG seed. Signed-off-by: miguelgfierro <[email protected]>
Standalone nn.Module SLi-Rec (mirroring graphrec/lightgcn.py's API) built on a reusable SequentialBaseModel: shared user/item/cate embeddings, unmasked ASVD Attention, masked AttentionFcn, FcnNet MLP head (Linear->BN->Dropout->Activation), softmax pairwise loss, unique-embedding regularization, and fit/run_eval/predict/ load_model reusing deeprec_utils.cal_metric. Verified end-to-end on real slirec data: untrained baseline auc~0.48 (TF ~0.4857), loss starts at the random value ~1.61 and decreases, epoch-1 valid auc 0.513. Applies black to the new modules. Signed-off-by: miguelgfierro <[email protected]>
Plain-function pytest (no classes) covering: Time4LSTMCell gate-equation parity and time-column asymmetry, scan padding zeroing, ASVD/masked attention behavior, FcnNet 2D/3D shapes, dataset time-feature/mask/negative-sampling structure, the E==H dimension-coupling guard, model forward shape, and a fit+eval smoke run on tiny synthetic vocabs/data (no Amazon download; CPU-friendly). 12 passed. Signed-off-by: miguelgfierro <[email protected]>
Repoint cell 3 imports to the PyTorch SLI_RECModel and SequentialDataset (aliased as SequentialIterator so input_creator is unchanged); drop the tensorflow import and print torch's version instead. Every other cell (prepare_hparams, fit, run_eval, predict, load_model, store_metadata) is unchanged, so the functional test test_slirec_quickstart_functional runs as-is. Public API preserved. Signed-off-by: miguelgfierro <[email protected]>
Component parity (~1e-7) and end-to-end training: PyTorch test AUC 0.7361 vs target 0.7183 and TF ref 0.7174, passing the functional-test tolerance. Signed-off-by: miguelgfierro <[email protected]>
miguelgfierro
requested review from
SimonYansenZhao,
anargyri,
loomlike and
wav8k
as code owners
July 13, 2026 16:23
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
Drop docs/superpowers/specs/2026-07-13-slirec-pytorch-migration-design.md from the tree and add docs/superpowers/ to .gitignore so generated design docs are never committed. Signed-off-by: miguelgfierro <[email protected]>
SLi-Rec is now provided by the PyTorch port, so remove the TF version and its TF-only time-aware cell file (used exclusively by TF SLi-Rec): - delete sequential/sli_rec.py and sequential/rnn_cell_implement.py - drop the TF slirec unit (test_slirec_component_definition) and smoke (test_model_slirec) tests and their test_groups.yml entries - docs/models.rst: remove the RNN Cells section and repoint SLIRec at the PyTorch modules The other five TF sequential models (asvd, caser, gru, nextitnet, sum) are unaffected; their tests still collect. Signed-off-by: miguelgfierro <[email protected]>
… models Rather than repurposing the shared sequential quickstart, add a dedicated examples/00_quick_start/slirec_amazon.ipynb for the PyTorch SLi-Rec (cleared outputs, SLi-Rec-only imports). Restore sequential_recsys_amazondataset.ipynb to its original form and switch its default active model from the now-removed TF SLi-Rec to A2SVD (same IJCAI'19 paper), with a pointer to the new notebook. Repoint the slirec_quickstart fixture and the README links at slirec_amazon.ipynb. Signed-off-by: miguelgfierro <[email protected]>
Drop the prepare_hparams/HParams/yaml dependency from the PyTorch SLi-Rec API in favor of explicit arguments, mirroring examples/.../lightgcn_deep_dive.ipynb: - SLI_RECModel(user_vocab, item_vocab, cate_vocab, item_embedding_dim=32, cate_embedding_dim=8, hidden_size=40, attention_size=40, layer_sizes=[100,64], att_fcn_layer_sizes=[80,40], dropout=[0.3,0.3], ...): architecture on the ctor. - fit(train_file, valid_file, epochs, batch_size, learning_rate, train_num_ngs, valid_num_ngs, embed_l2, layer_l2, ...): training knobs on fit. - run_eval/predict take batch_size + metric lists explicitly. - SequentialDataset takes vocab paths + max_seq_length; batch_size moves to load_data_from_file. The model builds the loader internally. - Notebook slirec_amazon.ipynb defines params as plain Python and passes them explicitly; the functional test drops the yaml_file param. Behavior preserved: untrained baseline AUC 0.4802 is bit-identical to the hparams version (same init/RNG order); unit tests 12/12 pass. Signed-off-by: miguelgfierro <[email protected]>
anargyri
reviewed
Jul 21, 2026
anargyri
reviewed
Jul 21, 2026
Signed-off-by: miguelgfierro <[email protected]>
Signed-off-by: miguelgfierro <[email protected]>
Signed-off-by: miguelgfierro <[email protected]>
A2SVDModel._build_seq_graph reads hparams.attention_size, but asvd.yaml never defined it, so running A2SVD with its own config file raised AttributeError. Use 40, the same value as sli_rec.yaml. Signed-off-by: miguelgfierro <[email protected]>
Signed-off-by: miguelgfierro <[email protected]>
The pytorch subpackage already disambiguates the implementation, so sli_rec_pytorch.py, rnn_cell_pytorch.py, sequential_base_pytorch.py, sequential_dataset_pytorch.py and test_sli_rec_pytorch.py lose the suffix. All imports, docs and the quickstart notebook are updated. Signed-off-by: miguelgfierro <[email protected]>
… cell Signed-off-by: miguelgfierro <[email protected]>
Collaborator
Author
|
@anargyri I updated the code, please take a look |
anargyri
reviewed
Aug 3, 2026
| assert logit.shape == (n, 1) | ||
|
|
||
|
|
||
| def test_slirec_fit_and_eval_smoke(synthetic_slirec): |
Collaborator
There was a problem hiding this comment.
Are these methods used anywhere?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Migrates the SLi-Rec sequential recommender from TensorFlow (TF-1.x graph mode) to PyTorch, as part of the TF→PyTorch migration tracked in #2302.
The port is a self-contained
nn.Modulemirroring the existing PyTorchgraphrec/lightgcn.pyand thelightgcn_deep_divenotebook: all hyper-parameters are explicit arguments — noprepare_hparams/yaml/HParamsobject. Architecture goes on the constructor, training knobs onfit, evaluation knobs onrun_eval; it reuses only the framework-agnostic metric functions indeeprec_utils. The TensorFlow SLi-Rec is removed and replaced by this port; the five other TF sequential models (asvd, caser, gru, nextitnet, sum) and the shared TF base are untouched.New files
recommenders/models/deeprec/models/sequential/pytorch/rnn_cell_pytorch.py—Time4LSTMCell+ adynamic_rnn-equivalent scan driver.recommenders/models/deeprec/models/sequential/pytorch/sequential_base_pytorch.py— shared embeddings, unmasked ASVDAttention,FcnNetMLP head, softmax pairwise loss, unique-embedding regularization, and thefit/run_eval/predictlifecycle.recommenders/models/deeprec/models/sequential/pytorch/sli_rec_pytorch.py—SLI_RECModel(forward== the TF_build_seq_graph) + maskedAttentionFcn.recommenders/models/deeprec/io/sequential_dataset_pytorch.py— faithful port ofSequentialIterator(parsing, time features, padding, in-batch negatives).tests/unit/recommenders/models/test_sli_rec_pytorch.py— 12 plain-function unit tests.examples/00_quick_start/slirec_amazon.ipynb— a dedicated PyTorch SLi-Rec quickstart that defines parameters as plain Python and passes them explicitly (noprepare_hparams), so the functional test still exercises SLi-Rec end-to-end.Removed (TensorFlow SLi-Rec)
recommenders/models/deeprec/models/sequential/sli_rec.pyand its TF-only time-aware cell filernn_cell_implement.py(used exclusively by TF SLi-Rec).test_slirec_component_definition) and smoke (test_model_slirec) tests and theirtest_groups.ymlentries.docs/models.rst: the RNN Cells section; the SLIRec section now points at the PyTorch modules.Changed
tests/conftest.py— theslirec_quickstartnotebook fixture points at the newslirec_amazon.ipynb; README links updated.examples/00_quick_start/sequential_recsys_amazondataset.ipynb— kept as the shared multi-model quickstart, but its default active model is switched from the removed TF SLi-Rec to A2SVD (same IJCAI'19 paper), with a pointer to the new SLi-Rec notebook. The other TF sequential models are unaffected.Validation
Component-level parity (weights copied TF→PyTorch, on the real slirec data):
m/cdiff ~1e-7; full padded-sequencernn_outputsdiff ~6e-8; padded steps exactly zero.End-to-end training (10 epochs, batch 400, seed 42,
embed_l2=layer_l2=0— the functional-test config):The functional test asserts
auc == pytest.approx(0.7183, rel=0.1, abs=0.05)→ accepts[0.6465, 0.7901]. The PyTorch test AUC 0.7355 passes comfortably and exceeds both the 0.7183 target and the TF reference (group_auc 0.7201 vs TF 0.7073). Unit tests: 12/12 pass on CPU. The untrained baseline AUC (0.4802) is bit-identical to the earlierhparams-based version, confirming the explicit-params refactor preserves initialization and behavior.Related Issues
Checklist
blackto format the code.