{
"cells": [
{
"cell_type": "markdown",
"id": "a5cabd6c",
"metadata": {},
"source": [
"# Benchmark inference speed: RecTools wrapper for LightFM\n",
"\n",
"Comparing speed of inference: RecTools LightFM wrapper vs original LightFM framework. Inference on Movielens 20-m dataset\n",
"\n",
"Real speed may vary depending on actual hardware and library versions\n",
"\n",
"LightFM library is required to run this notebook. You can install it with `pip install rectools[lightfm]`"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1f08be62",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.4.0\n",
"1.17\n"
]
}
],
"source": [
"import rectools\n",
"import lightfm\n",
"print(rectools.__version__)\n",
"print(lightfm.__version__)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b2ebfbf0",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import warnings\n",
"import time\n",
"\n",
"from pathlib import Path\n",
"from pprint import pprint\n",
"\n",
"import pandas as pd\n",
"import numpy as np\n",
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from rectools import Columns\n",
"from rectools.dataset import Dataset\n",
"from rectools.models import LightFMWrapperModel\n",
"\n",
"from lightfm import LightFM\n",
"\n",
"os.environ[\"OPENBLAS_NUM_THREADS\"] = \"1\"\n",
"sns.set_theme(style=\"whitegrid\")"
]
},
{
"cell_type": "markdown",
"id": "f282396f",
"metadata": {},
"source": [
"## Load data: Movielens 20m"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "887df4ed",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Archive: ml-20m.zip\n",
" inflating: ml-20m/genome-scores.csv \n",
" inflating: ml-20m/genome-tags.csv \n",
" inflating: ml-20m/links.csv \n",
" inflating: ml-20m/movies.csv \n",
" inflating: ml-20m/ratings.csv \n",
" inflating: ml-20m/README.txt \n",
" inflating: ml-20m/tags.csv \n",
"CPU times: user 266 ms, sys: 105 ms, total: 371 ms\n",
"Wall time: 32.5 s\n"
]
}
],
"source": [
"%%time\n",
"!wget -q https://files.grouplens.org/datasets/movielens/ml-20m.zip -O ml-20m.zip\n",
"!unzip -o ml-20m.zip\n",
"!rm ml-20m.zip"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "d51c0ce5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(20000263, 4)\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" user_id | \n",
" item_id | \n",
" weight | \n",
" datetime | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 1 | \n",
" 2 | \n",
" 3.5 | \n",
" 1112486027 | \n",
"
\n",
" \n",
" | 1 | \n",
" 1 | \n",
" 29 | \n",
" 3.5 | \n",
" 1112484676 | \n",
"
\n",
" \n",
" | 2 | \n",
" 1 | \n",
" 32 | \n",
" 3.5 | \n",
" 1112484819 | \n",
"
\n",
" \n",
" | 3 | \n",
" 1 | \n",
" 47 | \n",
" 3.5 | \n",
" 1112484727 | \n",
"
\n",
" \n",
" | 4 | \n",
" 1 | \n",
" 50 | \n",
" 3.5 | \n",
" 1112484580 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" user_id item_id weight datetime\n",
"0 1 2 3.5 1112486027\n",
"1 1 29 3.5 1112484676\n",
"2 1 32 3.5 1112484819\n",
"3 1 47 3.5 1112484727\n",
"4 1 50 3.5 1112484580"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratings = pd.read_csv(\n",
" \"ml-20m/ratings.csv\",\n",
" header=0,\n",
" names=[Columns.User, Columns.Item, Columns.Weight, Columns.Datetime],\n",
")\n",
"print(ratings.shape)\n",
"ratings.head()"
]
},
{
"cell_type": "markdown",
"id": "c5a14248",
"metadata": {},
"source": [
"## Train LightFM model with different latent factors dimension size"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "3d5dd974",
"metadata": {},
"outputs": [],
"source": [
"def make_base_model(factors: int):\n",
" return LightFMWrapperModel(LightFM(no_components=factors, loss=\"bpr\"))\n",
"\n",
"dataset = Dataset.construct(ratings)\n",
"\n",
"fitted_models = {}\n",
"\n",
"factors = list(range(64, 257, 64))\n",
"for n_factors in factors:\n",
" model = make_base_model(n_factors)\n",
" model.fit(dataset)\n",
" fitted_models[n_factors] = model"
]
},
{
"cell_type": "markdown",
"id": "ba8aabb7",
"metadata": {},
"source": [
"## Compute inference speed for both frameworks on all models"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "28beba31",
"metadata": {},
"outputs": [],
"source": [
"# we will use 8 threads for both RecTools and LightFM inference\n",
"# we will run each experiment 10 times to get mean values\n",
"NUM_THREADS = 8\n",
"K_RECOS = 10\n",
"NUM_REPEATS = 10"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "353d3651",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"138493\n"
]
}
],
"source": [
"# prepare external (real) movielens user ids for RecTools inference\n",
"train_users = dataset.user_id_map.external_ids\n",
"\n",
"# prepare internal sparse matrix user and items ids for LightFM inference\n",
"user_ids = dataset.user_id_map.internal_ids\n",
"item_ids = dataset.item_id_map.internal_ids\n",
"n_users = len(user_ids)\n",
"n_items = len(item_ids)\n",
"\n",
"assert len(train_users) == len(user_ids)\n",
"print(len(train_users))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "7ad97dfc",
"metadata": {},
"outputs": [],
"source": [
"def benchmark_rectools(models, n_users):\n",
" results = []\n",
" users = train_users[:n_users]\n",
" for run in range(NUM_REPEATS):\n",
" for n_factors, model in models.items():\n",
" start = time.time()\n",
" \n",
" # RecTools inference. It is processed by batches of users internally\n",
" model.n_threads = NUM_THREADS\n",
" recos = model.recommend(\n",
" users=users,\n",
" dataset=dataset,\n",
" k=K_RECOS,\n",
" filter_viewed=False,\n",
" add_rank_col=False\n",
" )\n",
" \n",
" elapsed = time.time() - start\n",
" results.append({\"factors\": n_factors, \"framework\": \"rectools\", \"inference_speed\": elapsed, \"run\": run})\n",
" return results"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "e49dc8fc",
"metadata": {},
"outputs": [],
"source": [
"def benchmark_lightfm_batch(models, n_users, batch_size = 1000):\n",
" results = []\n",
" users = user_ids[:n_users]\n",
" for run in range(NUM_REPEATS):\n",
" for n_factors, model in models.items():\n",
" # get LightFM framework model from RecTools wrapper\n",
" lightfm_model = model.model\n",
" start = time.time()\n",
"\n",
" # LightFM inference. We proceed it by batches to avoid memory problems\n",
" reco_by_batch = []\n",
" n_batches = n_users // batch_size \n",
" if n_users % batch_size > 0:\n",
" n_batches += 1\n",
" for i_batch in range(n_batches):\n",
" batch_users_ids = users[i_batch * batch_size : (i_batch + 1) * batch_size]\n",
" batch_scores = lightfm_model.predict(\n",
" user_ids = np.repeat(batch_users_ids, n_items),\n",
" item_ids = np.tile(item_ids, len(batch_users_ids)),\n",
" num_threads = NUM_THREADS\n",
" ).reshape(len(batch_users_ids), n_items) \n",
" # scores are not sorted so we need to sort them and get top K_RECOS items for each user\n",
" batch_unsorted_reco_positions = batch_scores.argpartition(-K_RECOS, axis=1)[:, -K_RECOS:]\n",
" batch_unsorted_reco_scores = np.take_along_axis(batch_scores, batch_unsorted_reco_positions, axis=1)\n",
" batch_recs = np.take_along_axis(\n",
" batch_unsorted_reco_positions, batch_unsorted_reco_scores.argsort()[:, ::-1], axis=1\n",
" )\n",
" reco_by_batch.append(batch_recs)\n",
" reco_by_batch = np.vstack(reco_by_batch)\n",
"\n",
" elapsed = time.time() - start\n",
" results.append({\"factors\": n_factors, \"framework\": \"lightfm\", \"inference_speed\": elapsed, \"run\": run})\n",
" return results"
]
},
{
"cell_type": "markdown",
"id": "ffe77189",
"metadata": {},
"source": [
"## Benchmark frameworks\n",
"\n",
"Be careful when running this code. Inference with all the repeats and settings for all 140k train users takes a lot of time. \n",
"\n",
"We advice to select about 10k users for comparison on regular hardware and skip full comparison"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4be0aa77",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Num users for inference: 10000\n"
]
}
],
"source": [
"# inference for 10k users on Movielens-20m\n",
"\n",
"N_USERS = 10000\n",
"print(f\"Num users for inference: {N_USERS}\")\n",
"rectools_results_ten_k = benchmark_rectools(fitted_models, n_users=N_USERS)\n",
"lightfm_results_batch_ten_k = benchmark_lightfm_batch(fitted_models, n_users=N_USERS)\n",
"results_ten_k = pd.DataFrame(lightfm_results_batch_ten_k + rectools_results_ten_k)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "7052bf5d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Num users for inference: 138493\n"
]
}
],
"source": [
"# inference for all train users on Movielens-20m\n",
"\n",
"print(f\"Num users for inference: {n_users}\")\n",
"rectools_results = benchmark_rectools(fitted_models, n_users=n_users)\n",
"lightfm_results_batch = benchmark_lightfm_batch(fitted_models, n_users=n_users)\n",
"results_all = pd.DataFrame(lightfm_results_batch + rectools_results)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "54d610e9",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" factors | \n",
" framework | \n",
" inference_speed | \n",
" run | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 64 | \n",
" lightfm | \n",
" 135.769374 | \n",
" 0 | \n",
"
\n",
" \n",
" | 1 | \n",
" 128 | \n",
" lightfm | \n",
" 160.676028 | \n",
" 0 | \n",
"
\n",
" \n",
" | 2 | \n",
" 192 | \n",
" lightfm | \n",
" 190.658902 | \n",
" 0 | \n",
"
\n",
" \n",
" | 3 | \n",
" 256 | \n",
" lightfm | \n",
" 204.438340 | \n",
" 0 | \n",
"
\n",
" \n",
" | 4 | \n",
" 64 | \n",
" lightfm | \n",
" 134.842623 | \n",
" 1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" factors framework inference_speed run\n",
"0 64 lightfm 135.769374 0\n",
"1 128 lightfm 160.676028 0\n",
"2 192 lightfm 190.658902 0\n",
"3 256 lightfm 204.438340 0\n",
"4 64 lightfm 134.842623 1"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results_all.head()"
]
},
{
"cell_type": "markdown",
"id": "035c3c13",
"metadata": {},
"source": [
"## Compare the difference\n",
"\n",
"### Inference speed\n",
"- RecTools wrapper has 5 to 25 times faster inference then original LightFM framework on the same number of threads"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "92e283e1",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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MDU1VXFERESUkzKVcNWvXx/379/Ps05+y3Nrx8/PD35+fsWKj6isWb16Na5evQoAWLNmDRYsWKDiiIiIKCflbg4XEf2fp0+fyv+Ojo5WYSRERJQXJlxEREREImPCRURERCQyJlxEREREImPCRURERCQyJlxEREREImPCRURERCQyJlxEREREImPCRURERCQyJlxEREREImPCRURERCQyJlxEIpPJhPwrlQMVZT+IiFShTP14NVFFpKYmwcp9FxD7OqnE2377LlXh7xkhR0t8GwBgUtMAk/q2EaVtIqLKgAkXUSmIfZ2EqBdvS7zdLKlM4W8xtkFERMXHIUUiIiIikTHhIiIiIhIZEy4iIiIikTHhIirH1HUN/+/vqoa51iMiItViwkVUjulauaJKdRNUqW4CXUtXVYdDRES54FWKROWYuq4hDOw9VR0GERHlg2e4iIiIiETGhIuIiIhIZEy4iIiIiETGhIuIiIhIZEy4iIiIiETGhIuIiIhIZEy4iIiIiETGhIuIiIhIZEVOuO7evYuwsDCFsj/++ANDhgzBF198ga1btxY7OCIiIqKKoMgJ15IlSxAeHi5/HBMTg4CAADx79gwAsHDhQuzZs6f4ERIRERGVc0VOuO7duwdnZ2f544MHD0JNTQ379+/HL7/8gm7dumH37t0lEiQRERFReVbkhOvdu3cwNDSUP46IiICbmxuMjIwAAG5uboiOji52gERERETlXZETrlq1auHx48cAgJcvX+LOnTtwc3OTL3///j3U1Dgnn4iIiKhKUVfs3Lkztm/fjoyMDNy4cQOamprw8PCQL79//z5MTU1LJEgiIiKi8qzICdfkyZMRHx+PgwcPQl9fHwsWLEDNmjUBAMnJyTh69CiGDBlSYoESERERlVdFTriqVq2KZcuW5bhMV1cX586dg7a2dpEDIyIiIqooipxw5UVNTQ36+vpiNE1ERERU7hQ44QoODi504xKJBOPHjy9w/ejoaGzcuBE3btzAw4cPYWFhoXRzVQD45ZdfsGHDBjx//hzm5uaYMmUKOnXqlG/7cXFx+P777/Hnn39CQ0MDHh4emDVrFvT09Aq1X0RERESFUayESyKRAAAEQVAqFwSh0AnXw4cPERERAQcHB8hkMqV2AeD333/HN998g3HjxsHV1RXh4eEICAjAjh074OjomGvbmZmZGD16NABg2bJl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REREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJDImXEREREQiY8JFREREJLIqqg6gsI4cOYJDhw7hzp07SEpKQoMGDeDj44N+/fpBIpHkup67uztiY2OVym/evAktLS0xQyYiIqJKrtwlXFu2bIGJiQkCAwNRvXp1XLhwAd988w1evHiBgICAPNft1q0bRo0apVCmqakpZrhERERE5S/h+vnnn2FkZCR/3Lp1ayQkJGDz5s3w9/eHmlruo6Q1a9aEo6NjKURJRERE9H/K3Ryuj5OtbE2aNEFycjJSUlJUEBERERFR3srdGa6cXLt2DcbGxtDT08uz3uHDh7F3715oaGigRYsWmD59OmxsbIq9fUEQCpzsSSQS6OjoFHubZUVqaioEQVB1GGUW+7tyqUj9zb7OX0Xqb6Dy9bkgCHnO/S5p5T7hunr1KsLDwzFz5sw867m7u8Pe3h716tVDTEwM1q5di8GDB+PAgQMwNTUtVgyZmZm4e/dugerq6OjA1ta2WNsrS6KiopCamqrqMMos9nflUpH6m32dv4rU30Dl7PPSnMddrhOuFy9eYMqUKWjVqhWGDRuWZ92vv/5a/neLFi3g5uYGT09PbNy4EXPnzi1WHBoaGrCysipQ3dLMpkuDubl5pfpGVFjs78qlIvU3+zp/Fam/gcrX548ePSrV7ZXbhCspKQljxoyBoaEhgoKC8pwsn5PatWvD2dkZd+7cKXYsEokEurq6xW6nPKpIp9Mpf+zvyoN9XflUtj4v7YS5XCZcaWlp8PPzw7t377Bnzx7o6+urOiQiIiKiXJW7qxSzsrIwefJkREZGYsOGDTA2Ni5SO3Fxcbh27Rrs7OxKOEIiIiIiReXuDNe8efNw5swZBAYGIjk5GdevX5cvs7W1haamJoYPH47nz5/j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\n",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Comparison on 10k users\n",
"sns.barplot(data=results_ten_k, x=\"factors\", y=\"inference_speed\", hue=\"framework\", palette=[\"steelblue\", \"crimson\"]);\n",
"plt.xlabel('Factors')\n",
"plt.ylabel('Seconds')\n",
"plt.title(\"LightFM model inference speed for 10k users on Movielens 20m\")\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "8afea9f4",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Comparison on 140k users\n",
"sns.barplot(data=results_all, x=\"factors\", y=\"inference_speed\", hue=\"framework\", palette=[\"steelblue\", \"crimson\"]);\n",
"plt.xlabel('Factors')\n",
"plt.ylabel('Seconds')\n",
"plt.title(\"LightFM model inference speed for all 140k users on Movielens 20m\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "bbb92b60",
"metadata": {},
"source": [
"### Other benefits of RecTools wrapper\n",
"- No need for manual construction of sparse matrixes over interactions and users/items features\n",
"- No need for manual processing of retrived scores and ranking\n",
"- Model has the same interface with all other RecTools models and can be compared easily\n",
"- `filter_viewed` and `items_to_recommend` options\n",
"\n",
"### How is the speed optimized?\n",
"We are using vectorization of LightFM user/item feature factors and biases (which already provided x2 speed boost to the original library). For even faster inference we use implicit library optimized matrix_factorization top_k method over the constructed vectors."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "rect",
"language": "python",
"name": "rect"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}