{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# default_exp datasets.session"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Sample Session dataset\n",
    "> Small sample of session dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#hide\n",
    "from nbdev.showdoc import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "from typing import List, Optional, Callable, Union, Any, Tuple\n",
    "\n",
    "import os\n",
    "import os.path as osp\n",
    "from collections.abc import Sequence\n",
    "import sys\n",
    "import csv\n",
    "import pickle\n",
    "import math\n",
    "import operator\n",
    "\n",
    "import numpy as np\n",
    "from datetime import timezone, datetime, timedelta\n",
    "import time\n",
    "\n",
    "from recohut.datasets.base import SessionDatasetv2\n",
    "from recohut.utils.common_utils import download_url"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "class SampleSessionDataset(SessionDatasetv2):\n",
    "    url = 'https://github.com/RecoHut-Datasets/sample_session/raw/v1/sample_train-item-views.csv'\n",
    "\n",
    "    def __init__(self, root, column_names={'SESSION_ID':'session_id',\n",
    "                                        'ITEM_ID': 'item_id',\n",
    "                                        'TIMEFRAME': 'timeframe',\n",
    "                                        'EVENT_DATE': 'eventdate'}):\n",
    "        super().__init__(root, column_names)\n",
    "\n",
    "    @property\n",
    "    def raw_file_names(self) -> str:\n",
    "        return 'sample_train-item-views.csv'\n",
    "\n",
    "    def download(self):\n",
    "        path = download_url(self.url, self.raw_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Downloading https://github.com/RecoHut-Datasets/sample_session/raw/v1/sample_train-item-views.csv\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-- Reading data\n",
      "Splitting date 1464134400.0\n",
      "469\n",
      "47\n",
      "[('2671', 1451952000.0), ('1211', 1452384000.0), ('3780', 1452384000.0)]\n",
      "[('1864', 1464220800.0), ('1867', 1464220800.0), ('1868', 1464220800.0)]\n",
      "-- Splitting train set and test set\n",
      "310\n",
      "1205\n",
      "99\n",
      "[[1, 2], [1], [4]] [1451952000.0, 1451952000.0, 1452384000.0] [3, 2, 5]\n",
      "[[282], [281, 308], [281]] [1464220800.0, 1464220800.0, 1464220800.0] [282, 281, 308]\n",
      "avg length:  3.5669291338582676\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Processing...\n",
      "Done!\n"
     ]
    }
   ],
   "source": [
    "ds = SampleSessionDataset(root='/content/samplesession')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#exporti\n",
    "def data_masks(all_usr_pois, item_tail):\n",
    "    us_lens = [len(upois) for upois in all_usr_pois]\n",
    "    len_max = max(us_lens)\n",
    "    us_pois = [upois + item_tail * (len_max - le) for upois, le in zip(all_usr_pois, us_lens)]\n",
    "    us_msks = [[1] * le + [0] * (len_max - le) for le in us_lens]\n",
    "    return us_pois, us_msks, len_max"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#exporti\n",
    "def split_validation(train_set, valid_portion):\n",
    "    train_set_x, train_set_y = train_set\n",
    "    n_samples = len(train_set_x)\n",
    "    sidx = np.arange(n_samples, dtype='int32')\n",
    "    np.random.shuffle(sidx)\n",
    "    n_train = int(np.round(n_samples * (1. - valid_portion)))\n",
    "    valid_set_x = [train_set_x[s] for s in sidx[n_train:]]\n",
    "    valid_set_y = [train_set_y[s] for s in sidx[n_train:]]\n",
    "    train_set_x = [train_set_x[s] for s in sidx[:n_train]]\n",
    "    train_set_y = [train_set_y[s] for s in sidx[:n_train]]\n",
    "\n",
    "    return (train_set_x, train_set_y), (valid_set_x, valid_set_y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "class GraphData():\n",
    "    def __init__(self, data, shuffle=False, graph=None):\n",
    "        inputs = data[0]\n",
    "        inputs, mask, len_max = data_masks(inputs, [0])\n",
    "        self.inputs = np.asarray(inputs)\n",
    "        self.mask = np.asarray(mask)\n",
    "        self.len_max = len_max\n",
    "        self.targets = np.asarray(data[1])\n",
    "        self.length = len(inputs)\n",
    "        self.shuffle = shuffle\n",
    "        self.graph = graph\n",
    "\n",
    "    def generate_batch(self, batch_size):\n",
    "        if self.shuffle:\n",
    "            shuffled_arg = np.arange(self.length)\n",
    "            np.random.shuffle(shuffled_arg)\n",
    "            self.inputs = self.inputs[shuffled_arg]\n",
    "            self.mask = self.mask[shuffled_arg]\n",
    "            self.targets = self.targets[shuffled_arg]\n",
    "        n_batch = int(self.length / batch_size)\n",
    "        if self.length % batch_size != 0:\n",
    "            n_batch += 1\n",
    "        slices = np.split(np.arange(n_batch * batch_size), n_batch)\n",
    "        slices[-1] = slices[-1][:(self.length - batch_size * (n_batch - 1))]\n",
    "        return slices\n",
    "\n",
    "    def get_slice(self, i):\n",
    "        inputs, mask, targets = self.inputs[i], self.mask[i], self.targets[i]\n",
    "        items, n_node, A, alias_inputs = [], [], [], []\n",
    "        for u_input in inputs:\n",
    "            n_node.append(len(np.unique(u_input)))\n",
    "        max_n_node = np.max(n_node)\n",
    "        for u_input in inputs:\n",
    "            node = np.unique(u_input)\n",
    "            items.append(node.tolist() + (max_n_node - len(node)) * [0])\n",
    "            u_A = np.zeros((max_n_node, max_n_node))\n",
    "            for i in np.arange(len(u_input) - 1):\n",
    "                if u_input[i + 1] == 0:\n",
    "                    break\n",
    "                u = np.where(node == u_input[i])[0][0]\n",
    "                v = np.where(node == u_input[i + 1])[0][0]\n",
    "                u_A[u][v] = 1\n",
    "            u_sum_in = np.sum(u_A, 0)\n",
    "            u_sum_in[np.where(u_sum_in == 0)] = 1\n",
    "            u_A_in = np.divide(u_A, u_sum_in)\n",
    "            u_sum_out = np.sum(u_A, 1)\n",
    "            u_sum_out[np.where(u_sum_out == 0)] = 1\n",
    "            u_A_out = np.divide(u_A.transpose(), u_sum_out)\n",
    "            u_A = np.concatenate([u_A_in, u_A_out]).transpose()\n",
    "            A.append(u_A)\n",
    "            alias_inputs.append([np.where(node == i)[0][0] for i in u_input])\n",
    "        return alias_inputs, A, items, mask, targets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[1, 2], [1], [4], [6], [8, 9], [8], [10, 11, 11], [10, 11], [10], [12]]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data = pickle.load(open('/content/sample/processed/train.txt', 'rb'))\n",
    "train_data[0][:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1205"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(train_data[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_data, valid_data = split_validation(train_data, valid_portion=0.1)\n",
    "test_data = valid_data\n",
    "\n",
    "train_data = GraphData(train_data, shuffle=True)\n",
    "test_data = GraphData(test_data, shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),\n",
       " array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),\n",
       " array([20, 21, 22, 23, 24, 25, 26, 27, 28, 29]),\n",
       " array([30, 31, 32, 33, 34, 35, 36, 37, 38, 39]),\n",
       " array([40, 41, 42, 43, 44, 45, 46, 47, 48, 49])]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data.generate_batch(10)[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Author: Sparsh A.\n",
      "\n",
      "Last updated: 2021-12-22 18:50:17\n",
      "\n",
      "recohut: 0.0.6\n",
      "\n",
      "Compiler    : GCC 7.5.0\n",
      "OS          : Linux\n",
      "Release     : 5.4.144+\n",
      "Machine     : x86_64\n",
      "Processor   : x86_64\n",
      "CPU cores   : 2\n",
      "Architecture: 64bit\n",
      "\n",
      "csv    : 1.0\n",
      "sys    : 3.7.12 (default, Sep 10 2021, 00:21:48) \n",
      "[GCC 7.5.0]\n",
      "IPython: 5.5.0\n",
      "numpy  : 1.19.5\n",
      "\n"
     ]
    }
   ],
   "source": [
    "#hide\n",
    "%reload_ext watermark\n",
    "%watermark -a \"Sparsh A.\" -m -iv -u -t -d -p recohut"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
