diff --git a/notebooks/nn_response_evaluation.ipynb b/notebooks/nn_response_evaluation.ipynb
new file mode 100644
index 0000000..7689c1f
--- /dev/null
+++ b/notebooks/nn_response_evaluation.ipynb
@@ -0,0 +1,1671 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "5nmr5qtyi4l6dv4003f5hk",
+ "execution_id": "b4c3a56f-dd79-4dc8-9c15-e451a726c6d8"
+ },
+ "source": [
+ "# RS evaluation with a custom response model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "a23y5u7l746q73y0tqxss",
+ "execution_id": "b0740c39-9cda-411d-b832-490de8695080"
+ },
+ "source": [
+ "## Imports and preparations"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "# !pip install jupyter-black\n",
+ "%load_ext jupyter_black"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "import sys\n",
+ "\n",
+ "os.environ[\"JAVA_HOME\"] = \"/usr\"\n",
+ "os.environ[\"PYSPARK_PYTHON\"] = sys.executable\n",
+ "os.environ[\"PYSPARK_DRIVER_PYTHON\"] = sys.executable\n",
+ "os.environ[\"CUDA_LAUNCH_BLOCKING\"] = \"1\"\n",
+ "os.environ[\"OMP_NUM_THREADS\"] = \"32\"\n",
+ "os.environ[\"NUMBA_NUM_THREADS\"] = \"4\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "cellId": "jlz0twee16goe1fisulv5"
+ },
+ "outputs": [],
+ "source": [
+ "import random\n",
+ "import time\n",
+ "import scipy\n",
+ "import torch\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import warnings\n",
+ "\n",
+ "from pyspark import SparkConf, StorageLevel\n",
+ "from pyspark.ml import Pipeline\n",
+ "from pyspark.sql import SparkSession\n",
+ "import pyspark.sql.functions as sf\n",
+ "from replay.models import UCB\n",
+ "from tqdm.auto import tqdm\n",
+ "\n",
+ "from experiments.response_models.utils import plot_metric, calc_metric\n",
+ "from pyspark.sql.functions import col"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "cellId": "jlz0twee16goe1fisulv5"
+ },
+ "outputs": [],
+ "source": [
+ "from sim4rec.modules import RealDataGenerator\n",
+ "from sim4rec.modules import Simulator\n",
+ "from sim4rec.response import BernoulliResponse, ActionModelTransformer\n",
+ "\n",
+ "\n",
+ "def warn(*args, **kwargs):\n",
+ " pass\n",
+ "\n",
+ "\n",
+ "warnings.warn = warn"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# path to spark tmp folder and simulator checkpoints\n",
+ "SPARK_LOCAL_DIR = \"./tmp/task_1\"\n",
+ "CHECKPOINT_DIR = \"./tmp/task_1_checkpoints\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "cellId": "ku55idy38nqtlrc187ucq"
+ },
+ "outputs": [],
+ "source": [
+ "%%bash -s \"$CHECKPOINT_DIR\" \"$SPARK_LOCAL_DIR\"\n",
+ "# simulator saves the interaction history between users and recommender system\n",
+ "# to rerun the simulation cycle or begin a new one, clear the directory or use another CHECKPOINT_DIR\n",
+ "rm -rf $1 $2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "cellId": "v1uc08ym8h8d7qxpmsop4"
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "WARNING: An illegal reflective access operation has occurred\n",
+ "WARNING: Illegal reflective access by org.apache.spark.unsafe.Platform (file:/root/.cache/pypoetry/virtualenvs/sim4rec-lKa0R1gD-py3.9/lib/python3.9/site-packages/pyspark/jars/spark-unsafe_2.12-3.1.3.jar) to constructor java.nio.DirectByteBuffer(long,int)\n",
+ "WARNING: Please consider reporting this to the maintainers of org.apache.spark.unsafe.Platform\n",
+ "WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations\n",
+ "WARNING: All illegal access operations will be denied in a future release\n",
+ "24/11/24 21:38:08 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable\n",
+ "Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties\n",
+ "Setting default log level to \"WARN\".\n",
+ "To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).\n",
+ "24/11/24 21:38:09 WARN SparkConf: Note that spark.local.dir will be overridden by the value set by the cluster manager (via SPARK_LOCAL_DIRS in mesos/standalone/kubernetes and LOCAL_DIRS in YARN).\n"
+ ]
+ }
+ ],
+ "source": [
+ "NUM_THREADS = 4\n",
+ "\n",
+ "spark = (\n",
+ " SparkSession.builder.appName(\"simulator\")\n",
+ " .master(f\"local[{NUM_THREADS}]\")\n",
+ " .config(\"spark.sql.shuffle.partitions\", f\"{NUM_THREADS * 3}\")\n",
+ " .config(\"spark.default.parallelism\", f\"{NUM_THREADS * 3}\")\n",
+ " .config(\"spark.driver.memory\", \"4G\")\n",
+ " .config(\"spark.executor.memory\", \"4G\")\n",
+ " .config(\"spark.driver.extraJavaOptions\", \"-XX:+UseG1GC\")\n",
+ " .config(\"spark.executor.extraJavaOptions\", \"-XX:+UseG1GC\")\n",
+ " .config(\"spark.local.dir\", SPARK_LOCAL_DIR)\n",
+ " .getOrCreate()\n",
+ ")\n",
+ "\n",
+ "spark.sparkContext.setLogLevel(\"ERROR\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "cellId": "9vf3sqixr4vgau073549pv"
+ },
+ "outputs": [],
+ "source": [
+ "K = 10 # number of iterations\n",
+ "NUM_ITER = 10\n",
+ "SEED = 1234\n",
+ "np.random.seed(SEED)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "ffl9l89trncxzwbk5zq7gn",
+ "execution_id": "cbbf5328-af84-4368-957e-3c000bd80332"
+ },
+ "source": [
+ "## Data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Load ContentWise in tabular form. Uncomment for the first run.\n",
+ "\n",
+ "This preprocessing is similat to preprocessing in old `ContentWise` class: \n",
+ "join interactions with impressions, binarize clicks, etc.\n",
+ "\n",
+ "ContentWise consists of following files:\n",
+ "1. interactions.csv.gz:\n",
+ " * `utc_ts_milliseconds` -- interaction timestamp \n",
+ " * `user_id` -- user id\n",
+ " * `item_id`, `series_id` -- video id, video series id. As long as only series were recommended, we threat 'series' as primary items\n",
+ " * `recommendation_id` -- key to match with recommendations\n",
+ " * `episode_number`, `series_length`, `item_type`, `interaction_type`, `vision_factor`, `explicit_rating` are ignored\n",
+ "\n",
+ "2. impressions-direct-link.csv.gz:\n",
+ " * `recommendation_id` -- impression id to match with responses, `-1` for unknown recommendation\n",
+ " * `recommendation_list_length`\n",
+ " * `recommended_series_list` -- string representation of python list of series ids\n",
+ " * `row_position` -- a position of recommendation slate on the site"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# cw_impr = \"data/ContentWiseImpressions/CW10M-CSV/impressions-direct-link.csv\"\n",
+ "# impressions = spark.read.option(\"header\", \"true\").csv(cw_impr)\n",
+ "# impressions = impressions.filter(col(\"recommendation_list_length\") == K)\n",
+ "# impressions = impressions.withColumn(\n",
+ "# \"tmp\", sf.regexp_replace(\"recommended_series_list\", r\"\\[\\s*\", \"\")\n",
+ "# )\n",
+ "# impressions = impressions.withColumn(\"tmp\", sf.regexp_replace(\"tmp\", r\"\\s*\\]\", \"\"))\n",
+ "# impressions = impressions.withColumn(\"tmp\", sf.regexp_replace(\"tmp\", r\"\\s+\", \" \"))\n",
+ "# impressions = impressions.withColumn(\"tmp\", sf.split(\"tmp\", \" \"))\n",
+ "# impressions = impressions.select(\n",
+ "# \"recommendation_id\", sf.posexplode(\"tmp\").alias(\"slate_pos\", \"item_id\")\n",
+ "# ).drop(\"tmp\", \"recommendation_list_length\", \"recommended_series_list\", \"row_position\")\n",
+ "# cw_inter = \"data/ContentWiseImpressions/CW10M-CSV/interactions.csv\"\n",
+ "# interactions = spark.read.option(\"header\", \"true\").csv(cw_inter)\n",
+ "# interactions = interactions.filter(col(\"recommendation_id\") != -1)\n",
+ "# interactions = interactions.drop(\n",
+ "# \"item_id\",\n",
+ "# \"episode_number\",\n",
+ "# \"series_length\",\n",
+ "# \"item_type\",\n",
+ "# \"interaction_type\",\n",
+ "# \"vision_factor\",\n",
+ "# \"explicit_rating\",\n",
+ "# )\n",
+ "# interactions = interactions.withColumnRenamed(\"series_id\", \"item_id\")\n",
+ "\n",
+ "# recommendation_metadata = interactions.groupBy(\"recommendation_id\").agg(\n",
+ "# sf.min(\"utc_ts_milliseconds\").alias(\"recommendation_timestamp\"),\n",
+ "# sf.first(\"user_id\").alias(\"user_id\"),\n",
+ "# )\n",
+ "# # click om item = first click on item\n",
+ "# interactions = interactions.drop(\"user_id\")\n",
+ "# interactions = interactions.groupBy(\"recommendation_id\", \"item_id\").agg(\n",
+ "# sf.min(\"utc_ts_milliseconds\").alias(\"response_timestamp\")\n",
+ "# )\n",
+ "# # add response\n",
+ "# interactions = interactions.withColumn(\"response\", sf.lit(1))\n",
+ "# content_wise_all = impressions.join(\n",
+ "# interactions, how=\"left\", on=[\"recommendation_id\", \"item_id\"]\n",
+ "# ).join(recommendation_metadata, on=\"recommendation_id\")\n",
+ "# content_wise_all = content_wise_all.withColumn(\n",
+ "# \"response\", sf.coalesce(\"response\", sf.lit(0))\n",
+ "# )\n",
+ "\n",
+ "# # split train-val-test by global time:\n",
+ "# total_cnt = content_wise_all.count()\n",
+ "# train_cnt = int(0.6 * total_cnt)\n",
+ "# test_cnt = int(0.2 * total_cnt)\n",
+ "# val_cnt = int(0.2 * total_cnt)\n",
+ "# sorted_df = content_wise_all.orderBy(\"recommendation_timestamp\")\n",
+ "# train = sorted_df.limit(train_cnt)\n",
+ "# val = sorted_df.subtract(train).limit(val_cnt)\n",
+ "# test = sorted_df.subtract(train).subtract(val)\n",
+ "# MAX_TIME = content_wise_all.agg(sf.max(\"recommendation_timestamp\")).collect()[0][0]\n",
+ "# MAX_TIME"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# def content_wise_to_simlog_format(df: \"DataFrame\"):\n",
+ "# \"\"\"Convert ContentWise dataset to math sim4rec log schema\"\"\"\n",
+ "# df = df.drop(\"response_timestamp\")\n",
+ "# df = df.withColumn(\"response_proba\", sf.col(\"response\").cast(\"float\"))\n",
+ "# df = df.withColumnRenamed(\"item_id\", \"item_idx\")\n",
+ "# df = df.withColumnRenamed(\"user_id\", \"user_idx\")\n",
+ "# # place all historical interactions BEFORE the simulated\n",
+ "# df = df.withColumn(\n",
+ "# \"__iter\",\n",
+ "# (sf.col(\"recommendation_timestamp\").cast(\"bigint\") - int(MAX_TIME)) / 1000,\n",
+ "# ).drop(\"recommendation_timestamp\", \"recommendation_id\")\n",
+ "# return df\n",
+ "\n",
+ "\n",
+ "# train = content_wise_to_simlog_format(train)\n",
+ "# test = content_wise_to_simlog_format(test)\n",
+ "# val = content_wise_to_simlog_format(val)\n",
+ "# val.show(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# from sim4rec.response.nn_response import SIM_LOG_SCHEMA\n",
+ "# print(SIM_LOG_SCHEMA, train.schema)\n",
+ "\n",
+ "# # cast types to match simlog schema\n",
+ "# train = train.withColumn(\"relevance\", 1 / (sf.col(\"slate_pos\") + 1))\n",
+ "# val = train.withColumn(\"relevance\", 1 / (sf.col(\"slate_pos\") + 1))\n",
+ "# test = train.withColumn(\"relevance\", 1 / (sf.col(\"slate_pos\") + 1))\n",
+ "\n",
+ "# for field in SIM_LOG_SCHEMA:\n",
+ "# train = train.withColumn(field.name, train[field.name].cast(field.dataType))\n",
+ "# val = val.withColumn(field.name, val[field.name].cast(field.dataType))\n",
+ "# test = test.withColumn(field.name, test[field.name].cast(field.dataType))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# # this takes some time\n",
+ "# !rm -rdf parquet && mkdir parquet\n",
+ "# train.write.partitionBy(\"user_idx\").parquet(\"parquet/train\")\n",
+ "# val.write.partitionBy(\"user_idx\").parquet(\"parquet/val\")\n",
+ "# test.write.partitionBy(\"user_idx\").parquet(\"parquet/test\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "# re-read:\n",
+ "train = spark.read.parquet(\"../parquet/train\")\n",
+ "val = spark.read.parquet(\"../parquet/val\")\n",
+ "test = spark.read.parquet(\"../parquet/test\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "+--------+---------+--------+--------------+--------+-------------------+--------+\n",
+ "|item_idx|slate_pos|response|response_proba| __iter| relevance|user_idx|\n",
+ "+--------+---------+--------+--------------+--------+-------------------+--------+\n",
+ "| 25508| 0| 0| 0.0|-8211853| 1.0| 35783|\n",
+ "| 9245| 8| 0| 0.0|-8211853| 0.1111111111111111| 35783|\n",
+ "| 5368| 6| 1| 1.0|-8211853|0.14285714285714285| 35783|\n",
+ "| 5939| 4| 0| 0.0|-8211853| 0.2| 35783|\n",
+ "| 10685| 5| 0| 0.0|-8211853|0.16666666666666666| 35783|\n",
+ "| 21058| 3| 0| 0.0|-8211853| 0.25| 35783|\n",
+ "| 5018| 9| 0| 0.0|-8211853| 0.1| 35783|\n",
+ "| 22613| 7| 0| 0.0|-8211853| 0.125| 35783|\n",
+ "| 17175| 2| 0| 0.0|-8211853| 0.3333333333333333| 35783|\n",
+ "| 7618| 1| 0| 0.0|-8211853| 0.5| 35783|\n",
+ "+--------+---------+--------+--------------+--------+-------------------+--------+\n",
+ "only showing top 10 rows\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "train.show(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "cellId": "zh9qtijcn5143mi4887od"
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "(2658, 19205)"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "users = [\n",
+ " [int(row[\"user_idx\"])] for row in train.select(\"user_idx\").distinct().collect()\n",
+ "]\n",
+ "NUM_USERS = len(users)\n",
+ "users = spark.createDataFrame(users, schema=[\"user_idx\"])\n",
+ "\n",
+ "items = [\n",
+ " [int(row[\"item_idx\"])] for row in train.select(\"item_idx\").distinct().collect()\n",
+ "]\n",
+ "NUM_ITEMS = len(items)\n",
+ "items = spark.createDataFrame(items, schema=[\"item_idx\"])\n",
+ "\n",
+ "NUM_ITEMS, NUM_USERS"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {
+ "cellId": "3btpzal8hblukqhq46asd"
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "2658"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "item_generator = RealDataGenerator(label=\"items_real\", seed=SEED)\n",
+ "user_generator = RealDataGenerator(label=\"users_real\", seed=SEED)\n",
+ "\n",
+ "item_generator.fit(items)\n",
+ "user_generator.fit(users)\n",
+ "\n",
+ "item_generator.generate(NUM_ITEMS)\n",
+ "user_generator.generate(NUM_USERS)\n",
+ "item_generator.getDataSize()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "1crcvslqi2qm4dnavh3obq",
+ "execution_id": "2c640f43-9dd5-445d-9511-d0d100fc830c"
+ },
+ "source": [
+ "# One iteration of simulation cycle step by step"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "q2oio9pylodwwu9qptdom",
+ "execution_id": "0f252faf-52c4-4a99-ac83-b425c14d055e"
+ },
+ "source": [
+ "## (1) Choise of users"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {
+ "cellId": "erkzmjzvo06nl5bok1qv5n"
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1964"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "user_generator.sample(0.1).count()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "tnbcus0l6hcbvoht2rnge",
+ "execution_id": "a45bc1e9-f284-4702-bfeb-d525f9349d20"
+ },
+ "source": [
+ "## (2) Choise of items\n",
+ "During the simulation cycle all 5276 items will be available at each iteration."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "4kfl2on9vg46431mkek4ot",
+ "execution_id": "85a06070-5f73-407a-ad84-ff781e7d04fb"
+ },
+ "source": [
+ "## (3) Initialization of recommender model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "p7qktnabe0pupwrpgo1vu",
+ "execution_id": "4f4957f4-cea9-47fe-9140-95dafb48e159"
+ },
+ "source": [
+ "### Baseline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {
+ "cellId": "kck71xz164nwlq1tlo81d"
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " user_idx | \n",
+ " item_idx | \n",
+ " relevance | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 232 | \n",
+ " 16330 | \n",
+ " 0.000376 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 232 | \n",
+ " 17915 | \n",
+ " 0.000376 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 23288 | \n",
+ " 17599 | \n",
+ " 0.000376 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 23288 | \n",
+ " 14627 | \n",
+ " 0.000376 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " user_idx item_idx relevance\n",
+ "0 232 16330 0.000376\n",
+ "1 232 17915 0.000376\n",
+ "2 23288 17599 0.000376\n",
+ "3 23288 14627 0.000376"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# RePlay model should be fitted on historic data before it can be refitted in cycle\n",
+ "# Let's assume we had one interaction for simplicity\n",
+ "model = UCB(sample=True, seed=SEED, exploration_coef=0.1)\n",
+ "model.fit(\n",
+ " log=users.limit(1).crossJoin(items.limit(1)).withColumn(\"relevance\", sf.lit(1))\n",
+ ")\n",
+ "pred = model.predict(log=None, users=users.limit(2), items=items, k=2)\n",
+ "pred.toPandas()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "7m11axprgbnc8wgrnr20km",
+ "execution_id": "1bf409d8-8df8-4ff6-a96d-eab7b07f54d8"
+ },
+ "source": [
+ "The response function in this tutorial is very simple. The response is binary, response == 1 means the user bought the item. \n",
+ "The probability of response is one tenth of the last digit of an `item_idx`. The response function is constant over time.\n",
+ "\n",
+ "Response function gets dataframe with columns `user_idx`, `item_idx`, `relevance`, and returns dataframe with columns `user_idx`, `item_idx`, `relevance`, `response`, adding the response column to the initial ones. If the initial dataframe had some other columns, these will also be returned."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Example how the response is generated for user-item pair"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## (4) Neural response function"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sim4rec.response import NNResponseEstimator, NNResponseTransformer\n",
+ "\n",
+ "proba_model = NNResponseEstimator(\n",
+ " outputCol=\"response_proba\",\n",
+ " log_dir=f\"{CHECKPOINT_DIR}/pipeline\",\n",
+ " model_name=\"SlatewiseTransformer\",\n",
+ " hist_data_dir=\"../parquet/train\",\n",
+ " val_data_dir=\"../parquet/val\",\n",
+ " batch_size=256,\n",
+ " lr=1e-3,\n",
+ " num_epochs=5,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'1.9.1+cu102'"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "torch.__version__"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "c92619a38c4448efbf86acaa2e3404b6",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "epoch: 0%| | 0/5 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "5aa3f610333a4184a1309dc23a2f7a4e",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "evaluate:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "metrics(rocauc=tensor(0.5021), f1=tensor(0.1555), accuracy=tensor(0.6724))\n"
+ ]
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "0b8abae4c59b445bba05faa1dd2d80ca",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "train epoch:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "13646cb019684e7fbfd8231ee19dca91",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "evaluate:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "metrics(rocauc=tensor(0.6201), f1=tensor(0.2110), accuracy=tensor(0.2747))\n"
+ ]
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "556abf1aec6145faa616a0120475ec5a",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "train epoch:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "5277b94fe96e44b983043bfd30168fe8",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "evaluate:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "metrics(rocauc=tensor(0.6472), f1=tensor(0.2158), accuracy=tensor(0.2727))\n"
+ ]
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "b0de39b1b337487e91956f124442ea69",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "train epoch:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "5b0847aae54e40cd83f1949604411b2d",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "evaluate:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "metrics(rocauc=tensor(0.7152), f1=tensor(0.2459), accuracy=tensor(0.8811))\n"
+ ]
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "b5eded98dde34ea5aa4413da59eb7f12",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "train epoch:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "88ed4271bd584c59bdd6816a5aa5663c",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "evaluate:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "metrics(rocauc=tensor(0.7275), f1=tensor(0.2512), accuracy=tensor(0.4530))\n"
+ ]
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "5044cb0b74e34474974c6e72b768e082",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "train epoch:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "71ff502c71fb432d8d745c8767f9cc76",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "evaluate:: 0%| | 0/76 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "metrics(rocauc=tensor(0.7352), f1=tensor(0.2665), accuracy=tensor(0.8777))\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Fit and train NN response function, save checkpoint to the disk\n",
+ "\n",
+ "proba_model = proba_model.fit(train)\n",
+ "!rm -rdf response_function_checkpoint\n",
+ "proba_model.save(\"response_function_checkpoint\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# reload saved response model\n",
+ "proba_model = NNResponseTransformer.load(\"response_function_checkpoint\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# create simlog dir (naturally it is created within the simulator pipeline)\n",
+ "!mkdir -p /root/notebooks/tmp/task_1_checkpoints/pipeline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "[Stage 4272:> (0 + 1) / 1]\r"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "+--------+--------+--------------------+-------------------+\n",
+ "|user_idx|item_idx| relevance| response_proba|\n",
+ "+--------+--------+--------------------+-------------------+\n",
+ "| 23288| 17599|3.762227238525207E-4|0.19280970096588135|\n",
+ "| 23288| 14627|3.762227238525207E-4| 0.1980724036693573|\n",
+ "| 232| 16330|3.762227238525207E-4| 0.1340920478105545|\n",
+ "| 232| 17915|3.762227238525207E-4|0.07575525343418121|\n",
+ "+--------+--------+--------------------+-------------------+\n",
+ "\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "test_response = proba_model.transform(pred)\n",
+ "test_response.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Pipelines work as well"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "br = BernoulliResponse(inputCol=\"response_proba\", outputCol=\"response\", seed=SEED)\n",
+ "response_pipeline = Pipeline(stages=[proba_model, br])\n",
+ "response_pipeline = response_pipeline.fit(items)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "test_response = response_pipeline.transform(pred)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " user_idx | \n",
+ " item_idx | \n",
+ " relevance | \n",
+ " response_proba | \n",
+ " response | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 23288 | \n",
+ " 17599 | \n",
+ " 0.000376 | \n",
+ " 0.192810 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 23288 | \n",
+ " 14627 | \n",
+ " 0.000376 | \n",
+ " 0.198072 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 232 | \n",
+ " 16330 | \n",
+ " 0.000376 | \n",
+ " 0.134092 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 232 | \n",
+ " 17915 | \n",
+ " 0.000376 | \n",
+ " 0.075755 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " user_idx item_idx relevance response_proba response\n",
+ "0 23288 17599 0.000376 0.192810 0\n",
+ "1 23288 14627 0.000376 0.198072 0\n",
+ "2 232 16330 0.000376 0.134092 0\n",
+ "3 232 17915 0.000376 0.075755 0"
+ ]
+ },
+ "execution_count": 28,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "test_response.toPandas()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "oklaxbiawagxloskdgy6g",
+ "execution_id": "418b174f-f4be-49fe-88aa-585826871197"
+ },
+ "source": [
+ "## (5) Fitting of new recommender model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "After receiving responses to recommendations, we can use this information to update the recommender model. To do this, we should rename column `response` to `relevance`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " user_idx | \n",
+ " item_idx | \n",
+ " relevance | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 23288 | \n",
+ " 17599 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 23288 | \n",
+ " 14627 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 232 | \n",
+ " 16330 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 232 | \n",
+ " 17915 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " user_idx item_idx relevance\n",
+ "0 23288 17599 0\n",
+ "1 23288 14627 0\n",
+ "2 232 16330 0\n",
+ "3 232 17915 0"
+ ]
+ },
+ "execution_count": 29,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "new_log = test_response.drop(\"relevance\", \"response_proba\").withColumnRenamed(\n",
+ " \"response\", \"relevance\"\n",
+ ")\n",
+ "new_log.limit(5).toPandas()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " item_idx | \n",
+ " relevance | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 16330 | \n",
+ " 0.37233 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 17915 | \n",
+ " 0.37233 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 14627 | \n",
+ " 0.37233 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 17599 | \n",
+ " 0.37233 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " item_idx relevance\n",
+ "0 16330 0.37233\n",
+ "1 17915 0.37233\n",
+ "2 14627 0.37233\n",
+ "3 17599 0.37233"
+ ]
+ },
+ "execution_count": 30,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "model.fit(log=new_log)\n",
+ "model.item_popularity.limit(5).toPandas()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "ytr06uktdlrtba7yym35z",
+ "execution_id": "875247d7-4576-4f2e-8524-57a90ec7b530"
+ },
+ "source": [
+ "## (6) Quality of recommendations"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "rlp6n6ghul6do1y9tnfs3",
+ "execution_id": "c66c5616-7b51-46fb-bf64-ff3aae3560a3"
+ },
+ "source": [
+ "Quality is the mean number of positive responses per user."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "metadata": {
+ "cellId": "ggmpn0ggz9nq4qt06ubae"
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "0.0"
+ ]
+ },
+ "execution_count": 31,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "calc_metric(test_response)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "o0o3kq6tjrs7tuvbdikavd",
+ "execution_id": "7c137458-8817-41ef-aa39-c255fe3286f6"
+ },
+ "source": [
+ "# Training the model in the simulator"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 32,
+ "metadata": {
+ "cellId": "kkg4h3xdwqhgpk4gs9y37m"
+ },
+ "outputs": [],
+ "source": [
+ "%%bash -s \"$CHECKPOINT_DIR\"\n",
+ "rm -rf $1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "wkff236bnjdemsw693fj6s",
+ "execution_id": "2f344684-ba2b-4d19-9079-527e6e2d7969"
+ },
+ "source": [
+ "## Simulator initialization"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "metadata": {
+ "cellId": "9eplt0wb7cnd273dkt5n6"
+ },
+ "outputs": [],
+ "source": [
+ "user_generator.initSeedSequence(SEED)\n",
+ "item_generator.initSeedSequence(SEED)\n",
+ "\n",
+ "sim = Simulator(\n",
+ " user_gen=user_generator,\n",
+ " item_gen=item_generator,\n",
+ " data_dir=f\"{CHECKPOINT_DIR}/pipeline\",\n",
+ " user_key_col=\"user_idx\",\n",
+ " item_key_col=\"item_idx\",\n",
+ " spark_session=spark,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "32xq7dw4q0uk4bwf04bzac",
+ "execution_id": "5a37dcac-ecb3-4c8a-b613-96059682e31d"
+ },
+ "source": [
+ "### Check that the format is correct"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "metadata": {
+ "cellId": "mz1tro3j75j8a8hcuvjvl7"
+ },
+ "outputs": [],
+ "source": [
+ "pred = model.predict(log=None, users=users.limit(10), items=items, k=K)\n",
+ "\n",
+ "assert pred.columns == [\"user_idx\", \"item_idx\", \"relevance\"]\n",
+ "assert (\n",
+ " pred.groupBy(\"user_idx\")\n",
+ " .agg(sf.countDistinct(\"item_idx\").alias(\"num_items\"))\n",
+ " .filter(sf.col(\"num_items\") == sf.lit(K))\n",
+ " .count()\n",
+ " == 10\n",
+ ")\n",
+ "assert (\n",
+ " pred.groupBy(\"user_idx\")\n",
+ " .agg(sf.count(\"item_idx\").alias(\"num_items\"))\n",
+ " .filter(sf.col(\"num_items\") == sf.lit(K))\n",
+ " .count()\n",
+ " == 10\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "log = sim.get_log(users)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "363j2r5xezoduowlgowzy8",
+ "execution_id": "23bcc021-9eb1-4d41-b46b-6a05442fd92e"
+ },
+ "source": [
+ "## Response function initialization"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "proba_model = NNResponseTransformer.load(\"response_function_checkpoint\")\n",
+ "br = BernoulliResponse(inputCol=\"response_proba\", outputCol=\"response\", seed=SEED)\n",
+ "response_pipeline = Pipeline(stages=[proba_model, br])\n",
+ "response_model = response_pipeline.fit(items)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "cellId": "1t5x6egzvjmz7yk9tc7gf",
+ "execution_id": "50e4dc71-1b47-4832-af9f-efcd08b5b47c"
+ },
+ "source": [
+ "## Simulation cycle"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 37,
+ "metadata": {
+ "cellId": "9xd6azbslgcdb0hsl7sm"
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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IoiPj29WFuL06dPo0qWLSBE5ttraWkgkN/5zLZVKodVqRYrIPnAGyEIWLlyI6dOnIy4uDoMHD8Z7772HmpoazJgxQ+zQHNKcOXOwfv16fPvtt1AqlSgqKgIAeHp6wsXFReToHItSqWy298rNzQ0+Pj7ckyWSF198EcOGDcObb76JSZMm4fDhw1i9ejVWr14tdmgOacKECfjHP/6BsLAwREVFIT09He+88w5mzpwpdmg2jcfgLWjlypX417/+haKiIsTExOD999/HkCFDxA7LIQmC0OL1tWvX4plnnrFsMNTM8OHDeQxeZNu3b0dCQgLOnDmDiIgILFy4EM8++6zYYTmkqqoqLF68GFu2bEFJSQmCgoIwefJkvPrqq3BychI7PJvFBIiIiIgcDvcAERERkcNhAkREREQOhwkQERERORwmQERERORwmAARERGRw2ECRERERA6HCRARERE5HCZARERE5HCYABGR6IYPH44FCxaIHcYNBEHA1q1bxQ6DiMyElaCJSHTl5eWQy+VQKpUIDw/HggULLJYQLVmyBFu3bkVGRsYN14uKiuDl5QWFQmGROIjIstgMlYhE5+3tbfJnNjQ03FafpM6dO5swGiKyNlwCIyLRGZbAhg8fjosXL+LFF1+EIAg3NK3du3cv7rrrLri4uCA0NBTz589HTU2N8f3h4eF44403MG3aNHh4eGDWrFkAgJdffhk9e/aEq6srunbtisWLF0OtVgMAEhMTsXTpUmRmZhpfLzExEUDzJbBjx47h3nvvhYuLC3x8fDBr1ixUV1cb3//MM8/goYcewttvv43AwED4+Phgzpw5xtciIuvCBIiIrMbmzZsREhKC119/HYWFhSgsLAQAnDt3Dvfddx8effRRHD16FBs3bsTevXsxd+7cGz7+7bffRnR0NNLT07F48WIAgFKpRGJiIrKzs/Gf//wHn3zyCd59910AwBNPPIGXXnoJUVFRxtd74oknmsVVU1ODsWPHwsvLCykpKfjqq6/wyy+/NHv9X3/9FefOncOvv/6KTz/9FImJicaEioisC5fAiMhqeHt7QyqVQqlU3rAEtXz5ckydOtW4L6hHjx54//33cc899+DDDz+Es7MzAODee+/FSy+9dMMzX3nlFeP/h4eH489//jM2bNiAv/71r3BxcYG7uztkMlmrS17r169HfX091q1bBzc3NwDAypUrMWHCBKxYsQIBAQEAAC8vL6xcuRJSqRSRkZEYP348du7ciWeffdYkXx8iMh0mQERk9TIzM3H06FF88cUXxms6nQ5arRY5OTno3bs3ACAuLq7Zx27cuBHvv/8+zp07h+rqajQ2NsLDw6Ndr3/ixAlER0cbkx8AiI+Ph1arxalTp4wJUFRUFKRSqfGewMBAHDt2rF2vRUSWwQSIiKxedXU1Zs+ejfnz5zd7X1hYmPH/r09QAODAgQOYOnUqli5dirFjx8LT0xMbNmzAv//9b7PEKZfLb3hbEARotVqzvBYR3R4mQERkVZycnKDRaG64NmDAAGRnZ6N79+7tetb+/fvRpUsX/P3vfzdeu3jx4i1f7/d69+6NxMRE1NTUGJOsffv2QSKRoFevXu2KiYisAzdBE5FVCQ8PR3JyMvLz81FWVgZAf5Jr//79mDt3LjIyMnDmzBl8++23zTYh/16PHj2Qm5uLDRs24Ny5c3j//fexZcuWZq+Xk5ODjIwMlJWVQaVSNXvO1KlT4ezsjOnTpyMrKwu//vor5s2bh6efftq4/EVEtoUJEBFZlddffx0XLlxAt27d4OfnBwDo378/du/ejdOnT+Ouu+5CbGwsXn31VQQFBbX6rIkTJ+LFF1/E3LlzERMTg/379xtPhxk8+uijuO+++zBixAj4+fnhyy+/bPYcV1dX/PzzzygvL8egQYPw2GOPYeTIkVi5cqXpPnEisihWgiYiIiKHwxkgIiIicjhMgIiIiMjhMAEiIiIih8MEiIiIiBwOEyAiIiJyOEyAiIiIyOEwASIiIiKHwwSIiIiIHA4TICIiInI4TICIiIjI4TABIiIiIofz/7Hu5ehDeFUtAAAAAElFTkSuQmCC",
+ "text/plain": [
+ "