# SASRec.pytorch: a PyTorch implementation of the self-attentive recommender

> SASRec.pytorch is a PyTorch port of the SASRec sequential recommendation model, with a command line training and inference script, an ml-1m example and a LayerNorm variant documented separately. It suits a recommender engineer who wants the self-attentive baseline in PyTorch rather than TensorFlow, and who is prepared to own the data preparation the README leaves out.

**pmixer/SASRec.pytorch** — PyTorch(1.6+) implementation of https://github.com/kang205/SASRec

- Repository: https://github.com/pmixer/SASRec.pytorch
- Stars: 618 · Forks: 134
- Language: TeX
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/pmixer-sasrec-pytorch

## A PyTorch port of the paper author's TensorFlow code

SASRec.pytorch is a PyTorch implementation of SASRec, the self-attentive sequential recommendation model presented by Kang and McAuley at ICDM 2018. The README states the derivation plainly: the code is modified based on the paper author's TensorFlow implementation, switched to PyTorch for simplicity, with issues such as positional embedding usage fixed along the way.

That last point is the most useful thing in the README. SASRec represents a user's history as a sequence of items with learned positional embeddings, and the original TensorFlow code handled the positional embedding in a way that made the model easier to overfit. The README makes the observation explicit, that the fix makes it harder to overfit, and adds a parenthetical that in recommender systems personalization equals overfitting sometimes. That is a specific engineering judgement, and it is the kind of detail that decides whether a port is worth using.

The scope is a reference implementation rather than a product. The code lives in a `python/` directory, the repository also carries a `rust/` directory and a `latex/` directory, and the primary language recorded for the project is TeX, which reflects that the LaTeX sources of a short paper sit alongside the implementation.

The author is explicit about where to look for the full picture. The README points at the paper author's own repository for a detailed introduction and a more complete README, and offers the citation of the original paper for anyone who needs it. The licence is Apache-2.0, and the repository includes a `CITATION.cff` file.

## Training run: the command line and what each flag controls

The README gives a single training invocation, and the flags are the interface to the model.

```bash
python main.py --dataset=ml-1m --train_dir=default --maxlen=200 --dropout_rate=0.2 --device=cuda
```

The dataset flag selects the dataset, with `ml-1m` as the worked example, and the training directory flag names where the run's artefacts go, with `default` used in the example. The sequence length is set with `--maxlen`, and the README uses 200, which is the length of the item sequence the model attends over. The dropout rate is given as 0.2, which is a meaningful value for this model because dropout is one of the two main regularisers in a self-attentive recommender, the other being the masking of the sequence positions.

The device flag selects the compute device, and the example uses `cuda`, so the script expects a GPU for the documented workflow.

What the README does not tell you is as important as what it does. There is no data preparation step documented, no description of the expected input format, no section on dependencies or installation, and no note about how `ml-1m` is obtained or where the script expects to find it. The repository has no `requirements.txt` in its top level entries. A user arriving cold has to work out the input format from the script itself.

That is a normal shape for a research port, and it should be read as such. The value here is a short, readable reference implementation of a known model, not a pipeline you can point at a data warehouse.

## Inference from a checkpoint, and why two runs of the same command differ

Inference has its own mode, sharing the same script with a checkpoint path and an inference-only flag.

```bash
python main.py --device=cuda --dataset=ml-1m --train_dir=default --state_dict_path=[YOUR_CKPT_PATH] --inference_only=true --maxlen=200
```

The checkpoint path is left as a placeholder in the README, which tells you the script expects a saved state dictionary from a previous training run, and the `inference_only` flag skips training and evaluates from that state. The remaining flags match the training invocation, so the evaluation uses the same dataset and sequence length as the run that produced the checkpoint.

The README then addresses the question every practitioner asks about a recommendation model, which is whether the numbers are stable. The answer is that each run is slightly random because negative samples are randomly sampled, and the README shows two consecutive runs to make the point.

```bash
1st run - test (NDCG@10: 0.5897, HR@10: 0.8190)
2nd run - test (NDCG@10: 0.5918, HR@10: 0.8225)
```

Two aspects of those numbers deserve attention. The reported metrics are NDCG at 10 and hit rate at 10, which are the standard offline measures for a top-k recommender, and the two runs differ in the third decimal place on both. Any evaluation you run with this code inherits that variance, because the negative sampling is random and the README documents no seed argument, so the practical move is to fix the randomness in your own driver code before you compare a change against a baseline.

## The LayerNorm variant and its separate results document

The most recent substantive change to the project is a normalisation variant, and it is documented outside the main README.

The update note from 2025-05-23 credits two contributors and states that they added a LayerNorm update for higher NDCG and hit rate, with a link to a document in a fork of the repository, `Result_Norm.md`. The repository in this project also carries a `Result_Norm.md` file at its top level, so the comparison between the default model and the normalised one is meant to be read there.

This matters more than a typical feature note because the change touches how the model trains. Normalisation inside a stacked self-attention block changes the optimisation behaviour of the whole network, and the claim is a quality improvement, not a convenience. The credited names are Wentworth1028 and Tiny-Snow, which tells you the project takes outside contributions.

The other update, dated 2026-09-17, is academic rather than code related. The author refined the previous year's short paper so the ideas could be read more easily, with a link to an arXiv entry numbered 2504.09596. The paper and the code are being maintained together, and the repository is where the short paper's LaTeX sources live in the `latex/` directory.

For an adopter the practical takeaway is that the default behaviour of the script and the behaviour described in the results document are not the same thing, and the comparison between them is a deliberate experiment rather than an accident. Read `Result_Norm.md` before you treat either set of numbers as the baseline for your own data.

## Where this fits, and what it deliberately leaves to you

The honest framing is that SASRec.pytorch is a compact, readable implementation of a published model, positioned between a research artifact and a starting point.

The difference from the original TensorFlow repository is worth stating precisely, because the README recommends the original for the detailed introduction. The original is the paper author's own code and carries the fuller documentation and the paper's own experiment setup. This port exists to offer the same model in PyTorch, with the positional embedding handling corrected and a LayerNorm variant added by contributors. If you want to understand the method, read the original; if you want to build on it in PyTorch, this is the codebase you will be editing.

The alternative approach, and the one the README does not discuss, is to write the training loop yourself against a maintained recommendation library. That buys you evaluation harnesses, negative sampling strategies and data loaders that this repository has none of, at the cost of reimplementing the model. The trade is between a few hundred lines of readable model code and a large amount of surrounding infrastructure.

The limitations of this repository follow directly from what it does not contain. There is no dataset preparation, so the input format has to be discovered from the code. There is no packaging, no versioned releases and no PyPI distribution, so the project has to be vendored or forked. There is no serving path, no model export and no online evaluation, so the inference mode in the script is a batch script that prints metrics rather than something you could put in front of a user. And the evaluation is offline only, on the two standard ranking metrics, with no information about how the model behaves in a live recommender where the candidate set, the latency budget and the feedback loop all matter.

The license is Apache-2.0, which is permissive and makes forking a low friction decision. The last push was on 2026-09-17, and the repository has no GitHub releases, so there is no tagged version to pin.

## Conclusion

SASRec.pytorch is a good starting point for a team that already has sequential interaction data and wants a self-attentive recommender in PyTorch, since it gives you a working training script, an inference path from a checkpoint and a documented LayerNorm variant to compare against. It is a poor fit if you need data ingestion, evaluation on real business metrics, serving code or a maintained package, because the repository provides none of that. Verify first that your interaction data is already in the layout the script expects, since the README documents no preparation step, and pin the random seed before you compare the two published runs, which differ only because negative sampling is random.

## FAQ

### How do I train SASRec.pytorch on the ml-1m dataset?

The README gives one command: `python main.py --dataset=ml-1m --train_dir=default --maxlen=200 --dropout_rate=0.2 --device=cuda`. The repository does not document a data preparation step, so the dataset is expected to be available already.

### How do I run inference only with a saved checkpoint in SASRec.pytorch?

Use the same script with a state dictionary path and the inference flag, for example `python main.py --device=cuda --dataset=ml-1m --train_dir=default --state_dict_path=[YOUR_CKPT_PATH] --inference_only=true --maxlen=200`.

### Why do two SASRec.pytorch runs give different NDCG and hit rate values?

The README states that each run is slightly random because negative samples are randomly sampled, showing two consecutive runs at NDCG@10 of 0.5897 and 0.5918 and HR@10 of 0.8190 and 0.8225.

### What does the LayerNorm update in SASRec.pytorch change?

The update note from 2025-05-23 says a LayerNorm version was added for higher NDCG and hit rate, and the comparison is documented in the Result_Norm.md file in the repository.

### How does SASRec.pytorch differ from the original TensorFlow implementation?

The README says it is modified based on the paper author's TensorFlow implementation, switched to PyTorch 1.6 for simplicity, with fixes such as the positional embedding usage, which the author notes makes the model harder to overfit. It also points readers to the original repository for a detailed introduction and a more complete README.

### What licence is SASRec.pytorch under?

Apache-2.0, with the LICENSE file at the top of the repository, and a CITATION.cff file for citation metadata. The README also provides BibTeX entries for both the original SASRec paper and this implementation.

## Sources

- [Issues](https://github.com/pmixer/SASRec.pytorch/issues)
- [License: Apache-2.0](https://github.com/pmixer/SASRec.pytorch/blob/main/LICENSE)
- [pmixer/SASRec.pytorch on GitHub](https://github.com/pmixer/SASRec.pytorch)
- [README](https://github.com/pmixer/SASRec.pytorch/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pmixer-sasrec-pytorch
