ds@mcpanalytics.aiEmail your data and your question and get an answer about your own data, with the method shown.Email your data and question. Get an answer.
WHITEPAPER

Session-Based Recommendations: Technical Deep Dive

By MCP Analytics Team | Published , updated

• 8 min read • Association & Recommendations

Executive Summary

Session-based recommenders suggest the next item using only what a visitor has done in the current session, without a user profile. They suit anonymous visitors, first visits and settings where long-term profiles are unavailable or unwanted, and they range from simple co-visit counts to neural sequence models.

This paper is a method guide. It explains the main approaches, how to evaluate them without leaking the future, and what to weigh in deciding between them. The only numbers in it come from one simulation, whose code is shown; they describe that simulated setup and are not a claim about any company, platform or data set.

Key Points

  • A simple transition model is a strong baseline. In the simulation, recommending what most often followed the last item viewed put the true next item in the top 5 for 45.1% of next-item predictions (every prefix of two or more items of each held-out session, averaged over three runs), against 21.5% for popularity.
  • Using the whole session helped further here. A nearest-neighbour method over similar sessions reached 61.3% at the same cutoff and 89.1% in the top 20, though its results varied a lot between runs (49.5% to 70.2% at the top 5).
  • Evaluation design decides what you learn. Split by time, predict the next item within each held-out session and report the cutoff (top 5, top 20) with the baseline beside it.
  • Cost and privacy claims need your own numbers. Infrastructure savings, conversion lift and compliance effects depend on your systems and are measured, not assumed.

Recommendation: start with popularity and last-item transitions as baselines, add a session-neighbour or sequence model only if it beats them on a time-split holdout, repeat the evaluation over several splits because results vary, and test the winner in a live experiment before committing.

1. Introduction

1.1 The Problem

Many visits are anonymous, first-time or on a new device, so a recommender built on long-term user histories has nothing to work with. Within a session there is still signal: what a visitor looked at, in what order, shows what they want now.

1.2 What This Paper Covers

  • The main families of session-based recommenders
  • How to evaluate them fairly
  • A reproducible comparison of three simple methods
  • Practical guidance on deciding and deploying

2. Background

2.1 Families of Methods

  • Popularity: recommend what is most viewed or bought overall. A necessary baseline.
  • Item-to-item and transition models: count how often item B follows item A in sessions (co-visitation or first-order Markov chains) and recommend the most frequent followers of the last item seen.
  • Session nearest neighbours: find past sessions most similar to the current one and recommend items they contained (Ludewig and Jannach, 2018, compare such methods with neural ones).
  • Neural sequence models: recurrent networks such as GRU4Rec (Hidasi and colleagues, 2016) and attention or transformer models such as SASRec (Kang and McAuley, 2018) and BERT4Rec (Sun and colleagues, 2019) learn sequence patterns from many sessions.

2.2 What Session-Based Does Not Solve

A new item with no sessions has no history, so cold start for items remains. Session identifiers and click streams can still be personal data under privacy law, so avoiding long-term profiles reduces but does not remove obligations; check requirements with your own counsel. Any claim about cost or conversion effects is an empirical matter for your systems.

3. Approach

3.1 Evaluation

The usual task is next-item prediction: given the first t items of a held-out session, does the recommended list contain item t + 1? Report the share of cases where it does within the top K (hit rate or recall at K), and optionally the rank of the true item (mean reciprocal rank). Split training and test data by time so the test sessions come after the training sessions, and compare every method with popularity.

3.2 Offline Is Not Online

Next-item accuracy measures how well a method reproduces past behavior, including the effects of the system that produced it. It does not measure incremental sales or satisfaction. Treat offline results as a screen and confirm with a controlled experiment.

3.3 Operational Considerations

Latency, memory and update frequency depend on the method. Transition counts and nearest-neighbour lookups can be updated incrementally with simple infrastructure; neural models need training and serving infrastructure. Measure these on your own stack.

4. A Reproducible Comparison

The simulation generates synthetic browsing sessions: 400 items in 20 topic clusters, popularity that follows a Zipf-like skew, and sessions of 4 to 10 different items in which a visitor mostly stays on one topic. It trains three methods on 4,000 sessions and tests next-item prediction on 400 held-out sessions, repeating the whole experiment with three random seeds: global popularity; counts of what followed the last item; and a nearest-neighbour method that scores items from the 100 most similar training sessions by cosine similarity of their item sets. Every method is barred from recommending an item already in the session, and sessions contain no repeats, so the comparison is like for like.

import numpy as np
from collections import Counter, defaultdict

N_ITEMS, N_CLUSTERS = 400, 20

def run(seed, n_train=4000, n_test=400):
    rng = np.random.default_rng(seed)
    cluster_of = rng.integers(0, N_CLUSTERS, size=N_ITEMS)
    members = [np.flatnonzero(cluster_of == c) for c in range(N_CLUSTERS)]
    popularity = rng.zipf(1.6, size=N_ITEMS).astype(float)       # a few items are far more popular than the rest

    def make_session():
        """A browsing session of 4-10 different items: the visitor picks a topic and mostly stays on it, weighted by popularity."""
        topic = rng.integers(0, N_CLUSTERS); length = rng.integers(4, 11); items = []
        while len(items) < length:
            pool = members[topic] if rng.random() < 0.8 else np.arange(N_ITEMS)
            w = popularity[pool]; item = int(rng.choice(pool, p=w / w.sum()))
            if item not in items: items.append(item)             # no repeats within a session
        return items

    train = [make_session() for _ in range(n_train)]
    test = [make_session() for _ in range(n_test)]
    pop_rank = [i for i, _ in Counter(i for s in train for i in s).most_common()]
    follow = defaultdict(Counter)                                  # what followed each item in training sessions
    for s in train:
        for a, b in zip(s, s[1:]): follow[a][b] += 1
    item_sessions = defaultdict(set)
    for k, s in enumerate(train):
        for i in set(s): item_sessions[i].add(k)

    def rec_pop(prefix): return [i for i in pop_rank if i not in prefix]
    def rec_follow(prefix):
        top = [i for i, _ in follow[prefix[-1]].most_common(20) if i not in prefix]
        return list(dict.fromkeys(top + rec_pop(prefix)))
    def rec_knn(prefix, k=100):
        overlap = Counter()
        for i in set(prefix):
            for sid in item_sessions[i]: overlap[sid] += 1
        p = set(prefix); scores = Counter()
        for sim, sid in sorted(((v / np.sqrt(len(p) * len(set(train[sid]))), sid) for sid, v in overlap.items()), reverse=True)[:k]:
            for i in set(train[sid]) - p: scores[i] += sim      # cosine similarity between the two item sets
        return list(dict.fromkeys([i for i, _ in scores.most_common(20)] + rec_pop(prefix)))

    def hit_rate(recommend, top_k):
        hits = n = 0
        for s in test:
            for t in range(2, len(s)):                             # predict item t from the first t items only
                hits += s[t] in recommend(s[:t])[:top_k]; n += 1
        return hits / n
    return {name: (hit_rate(rec, 5), hit_rate(rec, 20)) for name, rec in
            [("popularity", rec_pop), ("last item -> next item counts", rec_follow), ("similar-session neighbours", rec_knn)]}

runs = [run(seed) for seed in (31, 32, 33)]
print("share of next items found in the top-K recommendations (400 held-out sessions per run, 3 runs; mean and range)")
print(f"{'model':32s} {'K=5':>20s} {'K=20':>20s}")
for name in runs[0]:
    cells = []
    for j in (0, 1):
        v = np.array([r[name][j] for r in runs]) * 100
        cells.append(f"{v.mean():5.1f}% ({v.min():4.1f}-{v.max():4.1f})")
    print(f"{name:32s} {cells[0]:>20s} {cells[1]:>20s}")

Output:

share of next items found in the top-K recommendations (400 held-out sessions per run, 3 runs; mean and range)
model                                             K=5                 K=20
popularity                          21.5% (17.5-26.9)    31.9% (26.1-40.8)
last item -> next item counts       45.1% (37.0-52.0)    68.6% (62.9-73.6)
similar-session neighbours          61.3% (49.5-70.2)    89.1% (80.1-94.8)

Both session methods were far ahead of popularity at both cutoffs, and the neighbour method, which uses every item in the session, was ahead of last-item transitions in all three runs. The runs differ a good deal (the top-5 figure for the neighbour method ranged from 49.5% to 70.2%), which is why the table shows the range: with only a few hundred test sessions a single run can mislead. In this setup the visitor's topic is spread across the whole session, so using all of it pays. With other data, such as strongly ordered behavior, or with larger neighbour or sequence models, the ordering can change; the result describes this design only.

5. Practical Guidance

Point 1: Build the Baselines First

Popularity and last-item transitions take little effort and set the bar. A more complex model that does not beat them on a time-split holdout is not worth its cost.

Point 2: Split by Time and Predict Within Sessions

Do not shuffle sessions between training and test. Evaluate each prefix of each test session and report the cutoff used.

Point 3: Combine With Profiles Where You Have Them

For logged-in users with history, a profile-based model may add information. Compare a hybrid with session-only on both groups rather than assuming one approach for all visitors.

Point 4: Measure Cost and Latency on Your Stack

Record training time, memory and response time for each candidate on your own data and hardware, and weigh them against the accuracy gain.

Point 5: Confirm With an Experiment

Run a controlled test with a clear primary metric, a planned sample size and a stopping rule before concluding that a recommender changes outcomes.

6. Conclusion

Session-based recommendation is a practical answer to anonymous traffic, and simple methods are a strong place to start. In the simulation here, last-item transition counts roughly doubled the hit rate of popularity at the top-5 cutoff, and a session-neighbour method that uses the whole session did better again, with wide variation between runs. Build baselines, evaluate on a time split over several runs, and confirm with an experiment before investing in more complex models.

Your turn

Bring your own data and the question you actually need answered.

MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai

Frequently Asked Questions

What is a session-based recommender?

A system that recommends the next item from the sequence of items a visitor has interacted with in the current session, without needing a stored profile of that visitor.

When is a session-based approach appropriate?

When many visitors are anonymous or new, when long-term profiles are unavailable or unwanted, or when the current intent matters more than long-term taste.

How should I evaluate one?

Split training and test data by time, predict the next item for each prefix of each test session, report hit rate at a stated cutoff against popularity and simple transition baselines, then confirm in a controlled experiment.

Are neural models always better?

No. Published comparisons find that simple methods are often competitive, so test them on your data against strong simple baselines.

Does a session-based system remove privacy obligations?

It reduces what is stored but session data can still be personal data. Check your obligations for the data you do collect.

References & Further Reading

  • Hidasi, B., Karatzoglou, A., Baltrunas, L., & Tikk, D. (2016). Session-based recommendations with recurrent neural networks. International Conference on Learning Representations.
  • Ludewig, M., & Jannach, D. (2018). Evaluation of session-based recommendation algorithms. User Modeling and User-Adapted Interaction, 28(4-5), 331-390.
  • Kang, W.-C., & McAuley, J. (2018). Self-attentive sequential recommendation. IEEE International Conference on Data Mining, 197-206.
  • Sun, F., et al. (2019). BERT4Rec: Sequential recommendation with bidirectional encoder representations from transformer. Proceedings of the 28th ACM International Conference on Information and Knowledge Management, 1441-1450.