{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Introduction","metadata":{}},{"cell_type":"markdown","source":"**Item Embedding with Word2Vec**\n\nI refer to [this kernel](https://www.kaggle.com/code/radek1/word2vec-how-to-training-and-submission) :) Thanks to [RADEK OSMULSKI](https://www.kaggle.com/radek1)\n","metadata":{}},{"cell_type":"markdown","source":"## Setup","metadata":{}},{"cell_type":"code","source":"!pip install -q --no-cache-dir polars","metadata":{"execution":{"iopub.status.busy":"2023-01-17T04:42:11.050322Z","iopub.execute_input":"2023-01-17T04:42:11.051270Z","iopub.status.idle":"2023-01-17T04:42:24.340310Z","shell.execute_reply.started":"2023-01-17T04:42:11.051220Z","shell.execute_reply":"2023-01-17T04:42:24.338611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"GLOBAL_SEED = 42\n\nimport os\nos.environ['PYTHONHASHSEED'] = str(GLOBAL_SEED)\nimport sys\nfrom multiprocessing import cpu_count\nimport gc\nfrom tqdm import tqdm\nimport datetime\n\nimport polars as pl\nimport pandas as pd\nimport numpy as np\nfrom collections import Counter\n\nfrom annoy import AnnoyIndex\nfrom gensim.test.utils import common_texts\nfrom gensim.models import Word2Vec","metadata":{"execution":{"iopub.status.busy":"2023-01-17T04:42:24.343662Z","iopub.execute_input":"2023-01-17T04:42:24.344233Z","iopub.status.idle":"2023-01-17T04:42:24.351715Z","shell.execute_reply.started":"2023-01-17T04:42:24.344179Z","shell.execute_reply":"2023-01-17T04:42:24.350690Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed=42):\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    # python random\n    rnd.seed(seed)\n    # numpy random\n    np_rnd.seed(seed)\n    # tf random\n    try:\n        tf_rnd.set_seed(seed)\n    except:\n        pass\n    # RAPIDS random\n    try:\n        cupy.random.seed(seed)\n    except:\n        pass\n    # pytorch random\n    try:\n        torch.manual_seed(seed)\n        torch.cuda.manual_seed(seed)\n        torch.backends.cudnn.deterministic = True\n    except:\n        pass","metadata":{"execution":{"iopub.status.busy":"2023-01-17T04:42:24.353873Z","iopub.execute_input":"2023-01-17T04:42:24.354397Z","iopub.status.idle":"2023-01-17T04:42:24.370777Z","shell.execute_reply.started":"2023-01-17T04:42:24.354344Z","shell.execute_reply":"2023-01-17T04:42:24.369368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CFG:\n    debug = False\n    embed_dim = 32\n    tz = datetime.timezone.utc\n    ts_zero = datetime.datetime(1970, 1, 1, tzinfo=tz)\n    contentType_mapper = pd.Series([\"clicks\", \"carts\", \"orders\"], index=[0, 1, 2])\n    target_weight = (0.1, 0.3, 0.6)\n    \n    w2v_type = {\n        \"CBOW\": 0,\n        \"SkipGram\": 1\n    }","metadata":{"execution":{"iopub.status.busy":"2023-01-17T04:42:24.374318Z","iopub.execute_input":"2023-01-17T04:42:24.375228Z","iopub.status.idle":"2023-01-17T04:42:24.384223Z","shell.execute_reply.started":"2023-01-17T04:42:24.375174Z","shell.execute_reply":"2023-01-17T04:42:24.382789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Preprocessing","metadata":{}},{"cell_type":"code","source":"sentences_df = pl.concat([pl.read_parquet('../input/otto-full-optimized-memory-footprint/train.parquet'), pl.read_parquet('../input/otto-full-optimized-memory-footprint/test.parquet')])\nsentences_df = sentences_df[[\"session\", \"aid\"]].groupby(\"session\").agg([\n    pl.col(\"aid\").list()\n])\nsentences_df = sentences_df[\"aid\"].to_list()[:1000] if CFG.debug else sentences_df[\"aid\"].to_list()","metadata":{"execution":{"iopub.status.busy":"2023-01-17T04:42:24.385874Z","iopub.execute_input":"2023-01-17T04:42:24.386215Z","iopub.status.idle":"2023-01-17T04:43:15.480453Z","shell.execute_reply.started":"2023-01-17T04:42:24.386186Z","shell.execute_reply":"2023-01-17T04:43:15.479287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sentences_df[:1]","metadata":{"execution":{"iopub.status.busy":"2023-01-17T04:43:15.481858Z","iopub.execute_input":"2023-01-17T04:43:15.482217Z","iopub.status.idle":"2023-01-17T04:43:15.490178Z","shell.execute_reply.started":"2023-01-17T04:43:15.482186Z","shell.execute_reply":"2023-01-17T04:43:15.489042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training a word2vec model","metadata":{}},{"cell_type":"code","source":"%%time\n\nw2vec = Word2Vec(sentences=sentences_df, sg=CFG.w2v_type[\"CBOW\"], vector_size=CFG.embed_dim, window=2, min_count=1, compute_loss=True, seed=42, workers=cpu_count())","metadata":{"execution":{"iopub.status.busy":"2023-01-17T04:43:15.492649Z","iopub.execute_input":"2023-01-17T04:43:15.493237Z","iopub.status.idle":"2023-01-17T04:59:57.212698Z","shell.execute_reply.started":"2023-01-17T04:43:15.493187Z","shell.execute_reply":"2023-01-17T04:59:57.211349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"w2vec.save(\"./word2vec.model\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del sentences_df; gc.collect()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Building Searcher with Spotify Annoy (Approximate Nearest Neighbors Oh Yeah) ","metadata":{}},{"cell_type":"code","source":"%%time\n\nntrees = 100\n\nsearcher = AnnoyIndex(CFG.embed_dim, 'euclidean')\nsearcher.set_seed(GLOBAL_SEED)\n\n# Add items\nfor idx, value in enumerate(np.argsort(w2vec.wv.index_to_key)):\n    searcher.add_item(idx, w2vec.wv.vectors[value])\n\n# Building tree\nsearcher.build(ntrees)\n\n# Savling searcher\nsearcher.save(\"./searcher.ann\")","metadata":{"execution":{"iopub.status.busy":"2023-01-17T04:59:57.214323Z","iopub.execute_input":"2023-01-17T04:59:57.214952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference","metadata":{}},{"cell_type":"code","source":"test = pd.read_parquet('../input/otto-full-optimized-memory-footprint/test.parquet')\nsession_types = ['clicks', 'carts', 'orders']\ntest_session_AIDs = test.reset_index(drop=True).groupby('session')['aid'].apply(list)\ntest_session_types = test.reset_index(drop=True).groupby('session')['type'].apply(list)\ndel test; gc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_aids = 20\n\noutput = {\n    \"session\": [],\n    \"type\": [],\n    \"rec\": [],\n    \"score\": [],\n}\n\nfor SESS, AIDs, types in tqdm(zip(test_session_AIDs.index, test_session_AIDs.values, test_session_types.values), total=len(test_session_AIDs.index)):\n    # Get more co-visitation items order > cart > click\n    # If you want to analyze & get the items with details, you may need more RAM & CPU resources\n    candidates = []\n    for aid in AIDs[::-1]:\n        candidates += searcher.get_nns_by_item(aid, 21)[1:]\n    if len(candidates) == 0: candidates = AIDs.copy()\n\n    candidates = Counter(candidates)\n    rec, score = zip(*candidates.most_common(n_aids))\n    \n    output[\"session\"].extend([SESS] * 3)\n    output[\"type\"].extend([0, 1, 2])\n    output[\"rec\"].extend([\" \".join(pd.Series(rec, dtype=\"str\").values)] * 3)\n    output[\"score\"].extend([\" \".join(pd.Series(score, dtype=\"str\").values)] * 3)\n\noutput = pd.DataFrame(output).set_index([\"session\", \"type\"])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output.reset_index().to_parquet(\"./raw_output.parquet\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Submission","metadata":{}},{"cell_type":"code","source":"output[\"session_type\"] = [str(i[0]) + \"_\" + str(CFG.contentType_mapper[i[1]]) for i in output.index]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(\"/kaggle/input/otto-recommender-system/sample_submission.csv\")\nsubmission = submission.set_index(\"session_type\")\nsubmission.loc[output[\"session_type\"].values, \"labels\"] = output[\"rec\"].values\nsubmission = submission.reset_index()\nsubmission.to_csv(\"./submission.csv\", index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}