Serenade: Low-Latency Session-Based Recommendations

Overview

Serenade: Low-Latency Session-Based Recommendations

This repository contains the official code for session-based recommender system Serenade, which employs VMIS-kNN. It learns users' preferences by capturing the short-term and sequential patterns from the evolution of user behaviors and predicts interesting next items with low latency with support for millions of distinct items. VMIS-kNN is an index-based variant of a state-of-the-art nearest neighbor algorithm to session-based recommendation, which scales to use cases with hundreds of millions of clicks to search through.

Quick guide: getting started with Serenade.

Table of contents

  1. Downloads
  2. Find the best hyperparameter values
  3. Configure Serenade to use the hyperparameter values
  4. Start the Serenade service
  5. Retrieve recommendations using python
  6. Evaluate the testset
  7. Using your own train- and testset

Downloads

Serenade can be downloaded here. Binary executables are available for Windows, Linux and MacOS. Download the toy example project which contains toy datasets and a preconfigured configuration file.

Extract both downloaded files in the same directoy. You now have the following files:

serving
tpe_hyperparameter_optm
evaluator
train.txt
test.txt
valid.txt
example.toml

Find the best hyperparameter values

The next step is finding the hyperparameters using the train and test-datasets. Serenade uses Tree-Structured Parzen Estimator (TPE) for finding the hyperparameters. TPE achieves low validation errors compared to Exhaustive Grid Search (Bergstra et al). The section [hyperparam] in the example.toml contains the ranges of hyperparameter values that will be explored.

  • The hyperparameter search can be started using:
./tpe_hyperparameter_optm example.toml 

The results will be printed out in the terminal, for example:

===============================================================
===          HYPER PARAMETER OPTIMIZATION RESULTS          ====
===============================================================
MRR@20 for validation data: 0.3197
MRR@20 for test data: 0.3401
enabled business_logic for evaluation:false
best hyperparameter values:
n_most_recent_sessions:1502
neighborhood_size_k:288
idf_weighting:2
last_items_in_session:4
HPO done

and also in the output file defined in the config file, for example:

out_path = "results.csv"

Configure Serenade to use the hyperparameter values

We now update the [model] values in configuration file example.toml to use the hyperparameter values and set the training_data_path with the location of the train.txt. This is the content of the example configuration file with the new [model] paramer values.

config_type = "toml"

[server]
host = "0.0.0.0"
port = 8080
num_workers = 4

[log]
level = "info" # not implemented

[data]
training_data_path="train.txt"

[model]
m_most_recent_sessions = 1502
neighborhood_size_k = 288
max_items_in_session = 4
num_items_to_recommend = 21
idf_weighting = 1

[logic]
enable_business_logic = "false"

[hyperparam]
training_data_path = "train.txt"
test_data_path = "test.txt"
validation_data_path = "valid.txt"
num_iterations = 15
save_records = true
out_path = "results.csv"
enable_business_logic = false
n_most_recent_sessions_range = [100, 2500]
neighborhood_size_k_range = [50, 1500]
last_items_in_session_range = [1, 20]
idf_weighting_range = [0, 5]

Start the Serenade service

Start the serving binary for your platform with the location of the configuration file as argument

./serving example.toml

You can open your webbrowser and goto http://localhost:8080/ you should see an internal page of Serenade.

Serenade exposes Prometheus metrics out-of-the-box for monitoring.

Retrieve recommendations using python

import requests
from requests.exceptions import HTTPError
try:
    myurl = 'http://localhost:8080/v1/recommend'
    params = dict(
        session_id='144',
        user_consent='true',
        item_id='13598',
    )
    response = requests.get(url=myurl, params=params)
    response.raise_for_status()
    # access json content
    jsonResponse = response.json()
    print(jsonResponse)
except HTTPError as http_err:
    print(f'HTTP error occurred: {http_err}')
except Exception as err:
    print(f'Other error occurred: {err}')
[2835,10,12068,4313,3097,8028,3545,7812,17519,1164,17935,1277,13335,8655,14664,14556,6868,13509,9248,2498,11724]

The returned json object is a list with recommended items.

Evaluate the testset

The evaluator application can be used to evaluate a test dataset. It reports on several metrics.

  • The evaluation can be started using:
./evaluator example.toml 
===============================================================
===               START EVALUATING TEST FILE               ====
===============================================================
Mrr@20,Ndcg@20,HitRate@20,Popularity@20,Precision@20,Coverage@20,Recall@20,F1score@20
0.3277,0.3553,0.6402,0.0499,0.0680,0.2765,0.4456,0.1180
Qty test evaluations: 931
Prediction latency
p90 (microseconds): 66
p95 (microseconds): 66
p99.5 (microseconds): 66

Using your own train- and testset

A train- and testset must be created from historical user-item click data, outside of Serenade. Each row in the training- or test set should contain an historical user-item interaction event with the following fields:

  • SessionId the ID of the session. Format: 64 bit Integer
  • ItemId the ID of the interacted item. Format: 64 bit Integer
  • Time the time when the user-item interaction occurred. In epoch seconds: 32 bit Floating point.

The last 24 hours in the historical data can be used as test-set while the rest of the sessions can be used as the training-set and written as plain text using a '\t' as field separator. This is an example of a training data CSV file train.txt:

SessionId       ItemId  Time
10036   14957   1592337718.0
10036   14713   1592337765.0
10036   2625    1592338184.0
10037   7267    1591979344.0
10037   13892   1591979380.0
10037   7267    1591979504.0
10037   3595    1591979784.0
10038   6424    1591008704.0

Citation

Serenade - Low-Latency Session-Based Recommendation in e-Commerce at Scale

@article{Kersbergen2022SerenadeScale,
    title = {{Serenade - Low-Latency Session-Based Recommendation in e-Commerce at Scale}},
    year = {2022},
    journal = {SIGMOD},
    author = {Kersbergen, Barrie and Sprangers, Olivier and Schelter, Sebastian}
}

License

This project is licensed under the terms of the Apache 2.0 license.

Comments
  • add configuration file and toy dataset to release

    add configuration file and toy dataset to release

    It would be nice if the configuration file and a small 'toy' dataset could be added to the file with the binary executables. So that all files necessary are available at once and in one place.

    opened by alex-de-zwart 2
  • minor improvements on readme and release CI

    minor improvements on readme and release CI

    • add icons at the beginning of README: Crate Version, API docs, Crate License
    • removed step for installing unnecessary libraries in the beginning of the release CI
    opened by paulobarchi 1
  • Sync versioning between `github` and `cargo crate`

    Sync versioning between `github` and `cargo crate`

    Currently our github workflow generates binary artifacts and cargo crate. The workflow takes care of the versioning for the artifacts, but it does not update the versioning for the cargo crate (in the cargo.toml file), so there's a mismatch of version numbers between these -- and, if cargo.toml is not updated with the right version, the pipeline fails to publish the crate. Investigate and propose a reasonable way to sync versioning.

    enhancement 
    opened by paulobarchi 0
  • Replace current way of working with config file to use `serde` and `config`

    Replace current way of working with config file to use `serde` and `config`

    The config library currently used is not the most used/supported by the Rust community. It would be great to replace the current approach to use serde and config (example: https://github.com/paulobarchi/stdbm/blob/main/src/settings.rs).

    enhancement 
    opened by paulobarchi 0
  • Make the offline prediction latencies configurable by a user

    Make the offline prediction latencies configurable by a user

    The evaluate_file.rs presents the prediction latencies.

    These percentiles that are shown are currently hardcoded.

    Make the percentiles configurable using the config file.

    in the config file introduce a new section that evaluate_file.rs should use: [evaluation] latency_percentiles = [0, 25, 50, 75, 90, 99.5]

    enhancement good first issue 
    opened by bkersbergen 0
  • Add the VSKNN_STAN algorithm

    Add the VSKNN_STAN algorithm

    Add the VSKNN_STAN algorithm.

    The VSKNN_STAN algorithm is introduced in the paper: Empirical Analysis of Session-Based Recommendation Algorithms

    VSKNN_STAN combines the ideas from STAN and VS-kNN in a single approach and adds a sequence-aware item scoring procedure. Its very likely that the VSKNN_STAN algorithm can leverage the VMISIndex to do its computation.

    A python implementation can be found here: https://github.com/rn5l/session-rec/blob/master/algorithms/knn/vstan.py

    enhancement 
    opened by bkersbergen 0
  • Add the STAN algorithm

    Add the STAN algorithm

    Add the STAN algorithm to Serenade. Sequence and Time Aware Neighborhood for Session-based Recommendations: STAN https://dl.acm.org/doi/10.1145/3331184.3331322

    This method called “Sequence and Time Aware Neighborhood” was presented at SIGIR ’19. STAN is based on SKNN, but it additionally takes into account the following factors for making recommendations: i) the position of an item in the current session, ii) the recency of a past session w.r.t. to the current session, and iii) the position of a recommendable item in a neighboring session. Their results show that STAN significantly improves over SKNN.

    Its very likely that the STAN algorithm can leverage the VMISIndex to do its computation.

    A python implementation of STAN can be found here: https://github.com/rn5l/session-rec/blob/master/algorithms/knn/stan.py

    enhancement 
    opened by bkersbergen 0
  • Make the evaluation metric configurable

    Make the evaluation metric configurable

    The evaluation metric (MRR@20) that is used for hyperparameter search is currently hardcoded. Serenade has supports for multiple evaluation metrics such as MRR, F1, HitRate, Ndcg, Popularity. Precision, Recall etc.

    The choice for which evaluation metric to be used, should be configurable by the user via the configuration file.

    Proposed solution: in the config file introduce a new variable for the section 'hyperparam' used by tpe_hyperparameter_optm.rs: metric_name = "MRR" metric_length = 20

    in the config file introduce a new section that evaluate_file.rs should use: [evaluation] metric_name = "MRR" metric_length = 20 training_data_path = "train.txt" test_data_path = "test.txt"

    Both the tpe_hyperparameter_optm.rs and evaluate_file.rs should be included to support this feature.

    The trait SessionMetric could be extended with a function fn is_larger_better(&self) -> bool
    By default all metrics must return true for fn is_larger_better except for popularity.rs which should return false

    The tpe_hyperparameter_optm.rs ( line 130 ) should use the 'max' or 'min' score depending on the is_larger_better value.

    enhancement good first issue 
    opened by bkersbergen 0
Releases(v0.3.1)
Owner
bol.com
Code makes bol.com, the largest Dutch online retail platform.
bol.com
A pure, low-level tensor program representation enabling tensor program optimization via program rewriting

Glenside is a pure, low-level tensor program representation which enables tensor program optimization via program rewriting, using rewriting frameworks such as the egg equality saturation library.

Gus Smith 45 Dec 28, 2022
Low effort scraping Python's pickle format in Rust. It is to complete pickle parsing as BeautifulSoup was to complete HTML parsing.

repugnant-pickle Because it is, isn't it? This is a Rust crate for dealing with the Python pickle format. It also has support for opening PyTorch file

Kerfuffle 7 Apr 7, 2023
Rust based Cross-GPU Machine Learning

HAL : Hyper Adaptive Learning Rust based Cross-GPU Machine Learning. Why Rust? This project is for those that miss strongly typed compiled languages.

Jason Ramapuram 83 Dec 20, 2022
Rust crate to create Anki decks. Based on the python library genanki

genanki-rs: A Rust Crate for Generating Anki Decks With genanki-rs you can easily generate decks for the popular open source flashcard platform Anki.

Yannick Funk 63 Dec 23, 2022
Narwhal and Tusk A DAG-based Mempool and Efficient BFT Consensus.

This repo contains a prototype of Narwhal and Tusk. It supplements the paper Narwhal and Tusk: A DAG-based Mempool and Efficient BFT Consensus.

Facebook Research 134 Dec 8, 2022
Graph-based Approximate Nearest Neighbor Search

granne* granne (graph-based retrieval of approximate nearest neighbors) is a Rust library for approximate nearest neighbor search based on Hierarchica

null 283 Dec 21, 2022
A Rust🦀 implementation of CRAFTML, an Efficient Clustering-based Random Forest for Extreme Multi-label Learning

craftml-rs A Rust implementation of CRAFTML, an Efficient Clustering-based Random Forest for Extreme Multi-label Learning (Siblini et al., 2018). Perf

Tom Dong 15 Nov 6, 2022
Label Propagation Algorithm by Rust. Label propagation (LP) is graph-based semi-supervised learning (SSL). LGC and CAMLP have been implemented.

label-propagation-rs Label Propagation Algorithm by Rust. Label propagation (LP) is graph-based semi-supervised learning (SSL). A simple LGC and a mor

vaaaaanquish 4 Sep 15, 2021
zenoh-flow aims at providing a zenoh-based data-flow programming framework for computations that span from the cloud to the device.

Eclipse Zenoh-Flow Zenoh-Flow provides a zenoh-based dataflow programming framework for computations that span from the cloud to the device. ⚠️ This s

null 35 Dec 12, 2022
High performance distributed framework for training deep learning recommendation models based on PyTorch.

PERSIA (Parallel rEcommendation tRaining System with hybrId Acceleration) is developed by AI platform@Kuaishou Technology, collaborating with ETH. It

null 340 Dec 30, 2022
A naive density-based clustering algorithm written in Rust

Density-based clustering This a pure Rust implementation of a naive density-based clustering algorithm similar to DBSCAN. Here, 50 points are located

chris m 0 Mar 19, 2020
Rust implementation of user-based collaborative filtering

Rucommender Recommendation system written in Rust Overview An implementation in Rust of a collaborative filtering recommendations algorithm with a use

null 0 Sep 15, 2018
A high level, easy to use gpgpu crate based on wgpu

A high level, easy to use gpgpu crate based on wgpu. It is made for very large computations on powerful gpus

null 18 Nov 26, 2022
Small program which groups images based on the GPS position.

gps-cluster This small program will take some pictures in input, and based on the metadata on every image, it will group them by their GPS position, i

Alessio Bandiera 2 Sep 12, 2022
GBS/LSDj visualizer based on SameBoy and FFmpeg

GBPresenter GBPresenter is a tool I wrote to generate visualizations of GameBoy chiptunes, based on SameBoy, FFmpeg, and Slint. The visualization desi

Noah Sweilem 30 Jun 24, 2023
Redis backed session store for async-session using fred.rs.

async-fred-session Redis backed session store for async-session using fred.rs. This work is mostly based on async-redis-session. use async_fred_sessio

void* 4 Feb 28, 2023
Rain's Rust CLI recommendations

Rain's Rust CLI recommendations This living document comprises my recommendations for how to organize and manage Rust CLI applications. In this docume

null 69 Nov 27, 2022
Extremely low-latency chain data to Stackers, with a dose of mild humour on the side

Ronin Hello there! Ronin is a ultra-speed Stacks API server. It's super lightweight, but scales easily. Why are we making this? Because we don't like

Syvita Guild 11 Mar 29, 2022
Extreme Bevy is what you end up with by following my tutorial series on how to make a low-latency p2p web game.

Extreme Bevy Extreme Bevy is what you end up with by following my tutorial series on how to make a low-latency p2p web game. There game can be played

Johan Klokkhammer Helsing 39 Jan 5, 2023
Get unix time (nanoseconds) in blazing low latency with high precision

RTSC Get unix time (nanoseconds) in blazing low latency with high precision. About 5xx faster than SystemTime::now(). Performance OS CPU benchmark rts

Ⅲx 8 Jul 14, 2022