{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":38760,"databundleVersionId":4493939,"sourceType":"competition"},{"sourceId":4461402,"sourceType":"datasetVersion","datasetId":2611514},{"sourceId":4474043,"sourceType":"datasetVersion","datasetId":2601572}],"dockerImageVersionId":31154,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install recbole","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:24:36.506260Z","iopub.execute_input":"2025-11-14T08:24:36.506718Z","iopub.status.idle":"2025-11-14T08:25:55.092830Z","shell.execute_reply.started":"2025-11-14T08:24:36.506696Z","shell.execute_reply":"2025-11-14T08:25:55.092129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tqdm\nimport polars as pl\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport random\nimport os \nimport h5py\nimport sys\nimport gc\n\nfrom matplotlib import pyplot as plt\nimport pyarrow.parquet as pq","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:25:55.094420Z","iopub.execute_input":"2025-11-14T08:25:55.094667Z","iopub.status.idle":"2025-11-14T08:25:56.753624Z","shell.execute_reply.started":"2025-11-14T08:25:55.094647Z","shell.execute_reply":"2025-11-14T08:25:56.753077Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"file_path = '/kaggle/input/otto-full-optimized-memory-footprint/train.parquet'\ndf = pl.read_parquet(file_path)\nprint(df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:25:56.754276Z","iopub.execute_input":"2025-11-14T08:25:56.754645Z","iopub.status.idle":"2025-11-14T08:26:25.248440Z","shell.execute_reply.started":"2025-11-14T08:25:56.754623Z","shell.execute_reply":"2025-11-14T08:26:25.247798Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pl.read_parquet('/kaggle/input/otto-train-and-test-data-for-local-validation/test.parquet')\ntest = pl.read_parquet('/kaggle/input/otto-full-optimized-memory-footprint/test.parquet')\n\ndf = pl.concat([train, test])\n\ndf = df.sort(['session', 'aid', 'ts'])\ndf = df.with_columns((pl.col('ts') * 1e9).alias('ts'))\ndf = df.rename({'session': 'session:token', 'aid': 'aid:token', 'ts': 'ts:float'})","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:26:25.249172Z","iopub.execute_input":"2025-11-14T08:26:25.249435Z","iopub.status.idle":"2025-11-14T08:26:28.256707Z","shell.execute_reply.started":"2025-11-14T08:26:25.249414Z","shell.execute_reply":"2025-11-14T08:26:28.255875Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(df.columns)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:26:28.258619Z","iopub.execute_input":"2025-11-14T08:26:28.258849Z","iopub.status.idle":"2025-11-14T08:26:28.262591Z","shell.execute_reply.started":"2025-11-14T08:26:28.258828Z","shell.execute_reply":"2025-11-14T08:26:28.261872Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!mkdir -p /kaggle/working/recbox_data\ndf[['session:token', 'aid:token', 'ts:float']].write_csv('/kaggle/working/recbox_data/recbox_data.inter', separator='\\t')\n\ndel df, train, test\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:26:28.263360Z","iopub.execute_input":"2025-11-14T08:26:28.263618Z","iopub.status.idle":"2025-11-14T08:26:31.008375Z","shell.execute_reply.started":"2025-11-14T08:26:28.263594Z","shell.execute_reply":"2025-11-14T08:26:31.007558Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import logging\nfrom logging import getLogger\nimport typing\nfrom typing_extensions import Literal\ntyping.Literal = Literal\nfrom recbole.config import Config\nfrom recbole.data import create_dataset, data_preparation\nfrom recbole.model.sequential_recommender import SASRec\nfrom recbole.trainer import Trainer\nfrom recbole.utils import init_seed, init_logger\n\nfrom recbole.utils.case_study import full_sort_topk","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:26:31.009319Z","iopub.execute_input":"2025-11-14T08:26:31.009575Z","iopub.status.idle":"2025-11-14T08:26:47.069781Z","shell.execute_reply.started":"2025-11-14T08:26:31.009556Z","shell.execute_reply":"2025-11-14T08:26:47.069231Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"MAX_ITEM = 50  # SASRec thường cần chuỗi dài hơn một chút so với GRU4Rec\n\nparameter_dict = {\n    # === Data ===\n    'data_path': '/kaggle/working/',\n    'USER_ID_FIELD': 'session',\n    'ITEM_ID_FIELD': 'aid',\n    'TIME_FIELD': 'ts',\n    'user_inter_num_interval': \"[5,Inf)\",\n    'item_inter_num_interval': \"[5,Inf)\",\n    'load_col': {'inter': ['session', 'aid', 'ts']},\n\n    # === Model training ===\n    'epochs': 10,                     # SASRec thường cần nhiều epoch hơn GRU4Rec\n    'stopping_step': 3,\n    'train_batch_size': 256,          # có thể tăng lên nếu GPU đủ mạnh\n    'eval_batch_size': 1024,\n    'train_neg_sample_args': None,   # sử dụng full-sort evaluation\n    'learning_rate': 0.001,\n\n    # === Sequence handling ===\n    'MAX_ITEM_LIST_LENGTH': MAX_ITEM,\n    'MAX_SEQ_LENGTH': MAX_ITEM,       # SASRec cần tham số này\n    'hidden_size': 64,                # embedding dimension\n    'num_heads': 2,                   # số head trong self-attention\n    'num_layers': 2,                  # số layer Transformer\n    'hidden_dropout_prob': 0.2,       # dropout cho feed-forward\n    'attn_dropout_prob': 0.2,         # dropout cho attention\n\n    # === Evaluation ===\n    'eval_args': {\n        'split': {'RS': [9, 1, 0]},\n        'group_by': 'user',\n        'order': 'TO',\n        'mode': 'full'\n    },\n\n    # === Optimization ===\n    'loss_type': 'CE',               # có thể thử 'CE' (Cross Entropy)\n\n    # === Save model to Kaggle working directory ===\n    'checkpoint_dir': '/kaggle/working/',   # folder lưu model\n    'save_best': True,                       # lưu model tốt nhất\n}\n\n# === Initialize config ===\nconfig = Config(model='SASRec', dataset='recbox_data', config_dict=parameter_dict)\n\n# === Initialize random seed and logger ===\ninit_seed(config['seed'], config['reproducibility'])\ninit_logger(config)\nlogger = getLogger()\n\n# === Create handler để log ra màn hình ===\nc_handler = logging.StreamHandler()\nc_handler.setLevel(logging.INFO)\nlogger.addHandler(c_handler)\n\n# === Print config để kiểm tra ===\nlogger.info(config)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:26:47.070556Z","iopub.execute_input":"2025-11-14T08:26:47.071155Z","iopub.status.idle":"2025-11-14T08:26:47.502820Z","execution_failed":"2025-11-14T11:25:10.682Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset = create_dataset(config)\nlogger.info(dataset)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:26:47.503505Z","iopub.execute_input":"2025-11-14T08:26:47.503796Z","iopub.status.idle":"2025-11-14T08:29:04.571010Z","shell.execute_reply.started":"2025-11-14T08:26:47.503778Z","shell.execute_reply":"2025-11-14T08:29:04.570428Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# dataset splitting\ntrain_data, valid_data, test_data = data_preparation(config, dataset)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:29:04.571779Z","iopub.execute_input":"2025-11-14T08:29:04.572076Z","iopub.status.idle":"2025-11-14T08:31:50.517700Z","shell.execute_reply.started":"2025-11-14T08:29:04.572054Z","shell.execute_reply":"2025-11-14T08:31:50.517182Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = SASRec(config, train_data.dataset).to(config['device'])\nlogger.info(model)\n\n# trainer loading and initialization\ntrainer = Trainer(config, model)\n\n# model training\nbest_valid_score, best_valid_result = trainer.fit(train_data, valid_data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T08:31:50.518428Z","iopub.execute_input":"2025-11-14T08:31:50.518730Z","execution_failed":"2025-11-14T11:25:10.682Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import gc\ndel trainer, train_data, valid_data, test_data","metadata":{"trusted":true,"execution":{"execution_failed":"2025-11-14T11:25:10.682Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"gc.collect()","metadata":{"trusted":true,"execution":{"execution_failed":"2025-11-14T11:25:10.682Z"}},"outputs":[],"execution_count":null}]}