{"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":"code","source":"# import shutil\n# try:\n#     src_dir = '/kaggle/input/sacremoses'\n#     dest_dir = '/kaggle/working/sacremoses'\n\n#     shutil.copytree(src_dir, dest_dir)\n\n#     src_dir = '/kaggle/input/pytorch-transformers-120'\n#     dest_dir = '/kaggle/working/pytorch-transformers-120'\n\n#     shutil.copytree(src_dir, dest_dir)\n\n#     !pip install ../working/sacremoses/sacremoses-master/\n#     !pip install pytorch-transformers --no-index --find-links=file:///kaggle/working/pytorch-transformers-120/pytorch-transformers\n# except:\n#     print('Did copy!')","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:17:53.665867Z","iopub.execute_input":"2023-06-19T03:17:53.666269Z","iopub.status.idle":"2023-06-19T03:17:53.670962Z","shell.execute_reply.started":"2023-06-19T03:17:53.666239Z","shell.execute_reply":"2023-06-19T03:17:53.670008Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os, sys, torch, gc, time, random\nimport numpy as np\nimport pandas as pd\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader, Dataset\nfrom transformers import LlamaConfig, LlamaModel\n\nimport warnings\nwarnings.filterwarnings(action='ignore')","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:17:53.672328Z","iopub.execute_input":"2023-06-19T03:17:53.672628Z","iopub.status.idle":"2023-06-19T03:17:53.688233Z","shell.execute_reply.started":"2023-06-19T03:17:53.672602Z","shell.execute_reply":"2023-06-19T03:17:53.687032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Models","metadata":{}},{"cell_type":"code","source":"class TransfomerModel(nn.Module):\n    def __init__(self, cfg):\n        super(TransfomerModel, self).__init__()\n        self.cfg = cfg\n        cate_col_size = len(cfg.cate_cols)\n        cont_col_size = len(cfg.cont_cols)\n        self.cate_emb = nn.Embedding(cfg.total_cate_size, cfg.emb_size, padding_idx=0)\n        self.cate_proj = nn.Sequential(\n            nn.Linear(cfg.emb_size*cate_col_size, cfg.hidden_size//2),\n            nn.LayerNorm(cfg.hidden_size//2),\n        )        \n        self.cont_emb = nn.Sequential(                \n            nn.Linear(cont_col_size, cfg.hidden_size//2),\n            nn.LayerNorm(cfg.hidden_size//2),\n        )\n        \n        self.config = LlamaConfig( \n            3, # not used\n            hidden_size=cfg.hidden_size,\n            num_hidden_layers=cfg.nlayers,\n            num_attention_heads=cfg.nheads,\n            intermediate_size=cfg.hidden_size,\n            hidden_dropout_prob=cfg.dropout,\n            attention_probs_dropout_prob=cfg.dropout,\n        )\n        self.encoder = LlamaModel(self.config)        \n        \n        def get_reg():\n            return nn.Sequential(\n            nn.Linear(cfg.hidden_size, cfg.hidden_size),\n            nn.LayerNorm(cfg.hidden_size),\n            nn.Dropout(cfg.dropout),\n            nn.ReLU(),\n            nn.Linear(cfg.hidden_size, cfg.hidden_size),\n            nn.LayerNorm(cfg.hidden_size),\n            nn.Dropout(cfg.dropout),\n            nn.ReLU(),\n            nn.Linear(cfg.hidden_size, cfg.target_size),            \n        )        \n        self.reg_layer = get_reg()\n        \n    def forward(self, cate_x, cont_x, mask):        \n        batch_size = cate_x.size(0)\n        \n        cate_emb = self.cate_emb(cate_x).view(batch_size, self.cfg.seq_len, -1)\n        cate_emb = self.cate_proj(cate_emb)     \n        cont_emb = self.cont_emb(cont_x)\n             \n        seq_emb = torch.cat([cate_emb, cont_emb], 2)\n        \n        encoded_layers = self.encoder(inputs_embeds=seq_emb, attention_mask=mask)\n        sequence_output = encoded_layers[0]\n        sequence_output = sequence_output[:, -1]\n        \n        pred_y = self.reg_layer(sequence_output)\n        return pred_y","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:17:53.689949Z","iopub.execute_input":"2023-06-19T03:17:53.690305Z","iopub.status.idle":"2023-06-19T03:17:53.706468Z","shell.execute_reply.started":"2023-06-19T03:17:53.690274Z","shell.execute_reply":"2023-06-19T03:17:53.705620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BowlDataset(Dataset):\n    def __init__(self, cfg, model_lv_type, df, sample_indices):\n        self.cfg = cfg\n        self.sample_indices = sample_indices\n        self.seq_len = cfg.seq_len\n        self.model_lv_type = model_lv_type\n\n        self.cate_cols = self.cfg.cate_cols\n        self.cont_cols = self.cfg.cont_cols\n\n        self.cate_df = df[self.cate_cols]\n        self.cont_df = np.sign(df[self.cont_cols]) * np.log(np.abs(df[self.cont_cols]) + 1)\n\n    def __getitem__(self, idx):\n        indices = self.sample_indices[idx]\n        \n        seq_len = min(self.seq_len, len(indices))     \n                   \n        tmp_cate_x = torch.LongTensor(self.cate_df.iloc[indices].values)\n        cate_x = torch.LongTensor(self.seq_len, len(self.cate_cols)).zero_()\n        cate_x[-seq_len:] = tmp_cate_x[-seq_len:]        \n        \n        tmp_cont_x = torch.FloatTensor(self.cont_df.iloc[indices].values)\n        tmp_cont_x[-1] = 0\n        cont_x = torch.FloatTensor(self.seq_len, len(self.cont_cols)).zero_()\n        cont_x[-seq_len:] = tmp_cont_x[-seq_len:]\n        \n        mask = torch.ByteTensor(self.seq_len).zero_()\n        mask[-seq_len:] = 1\n        \n        target = 0\n        \n        return cate_x, cont_x, mask, target\n    \n        \n\n    def __len__(self):\n        return len(self.sample_indices)\n","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:17:53.708107Z","iopub.execute_input":"2023-06-19T03:17:53.708968Z","iopub.status.idle":"2023-06-19T03:17:53.724432Z","shell.execute_reply.started":"2023-06-19T03:17:53.708932Z","shell.execute_reply":"2023-06-19T03:17:53.723394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load models","metadata":{}},{"cell_type":"code","source":"base_model_path_list_04 = [\n            ['bowl.pt', [\n                [1.0, os.path.join('/kaggle/input/psp-seqtf-llama/', 'b-64_a-LLamaModel_e-100_h-500_d-0.2_l-2_hd-10_s-7_len-256_aug-0.5_da-04_k-0.pt')],            \n            ]],\n        ]\nbase_model_path_list_512 = [\n            ['bowl.pt', [\n                [1.0, os.path.join('/kaggle/input/psp-seqtf-llama/', 'b-32_a-LLamaModel_e-100_h-500_d-0.2_l-2_hd-10_s-7_len-528_aug-0.5_da-512_k-3.pt')],            \n            ]],\n        ]\nbase_model_path_list_1322 = [\n            ['bowl.pt', [\n                [1.0, os.path.join('/kaggle/input/psp-seqtf-llama/', 'b-16_a-LLamaModel_e-100_h-500_d-0.2_l-2_hd-10_s-7_len-808_aug-0.5_da-1322_k-0.pt')],            \n            ]],\n        ]\n\nclass CFG:\n    learning_rate=1.0e-4\n    batch_size=32\n    num_workers=4\n    dropout=0.2\n    emb_size=100\n    hidden_size=500\n    nlayers=2\n    nheads=10\n    seq_len=100\n    device='cpu'\n    seed=7\n\nlevel_mapper={\n    '0-4': '0to4',\n    '5-12': '5to12',\n    '13-22': '13to22'\n}\n\nTARGET_COLS = {\n    '0to4': ['1', '2', '3'],\n    '5to12': ['4', '5', '6', '7', '8', '9', '10', '11', '12', '13'],\n    '13to22': ['14', '15', '16', '17', '18'],\n}\n\nENCODERS = {    \n    'LLamaModel':TransfomerModel,\n}\n\nCATS = ['event_name', 'level', 'fqid', 'room_fqid', 'text', 'name', 'text_fqid']\nNUMS = ['elapsed_time', 'room_coor_x', 'room_coor_y', 'page',\n        'screen_coor_x', 'screen_coor_y', 'hover_duration']","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:17:53.725714Z","iopub.execute_input":"2023-06-19T03:17:53.726165Z","iopub.status.idle":"2023-06-19T03:17:53.742015Z","shell.execute_reply.started":"2023-06-19T03:17:53.726103Z","shell.execute_reply":"2023-06-19T03:17:53.741198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model(CFG, base_model_path_list, cate_size, cate_cols, cont_cols, current_lv):\n    models = []\n    \n    CFG.target_size = len(TARGET_COLS[current_lv])\n    CFG.total_cate_size = cate_size\n    CFG.cate_cols = cate_cols\n    CFG.cont_cols = cont_cols\n        \n    for _, base_model_paths in base_model_path_list:\n        for model_w, base_model_path in base_model_paths:\n            path = base_model_path.split('/')[-1]\n            path = path.replace('bowl_', '')\n            cfg_dict = dict([tok.split('-') for tok in path.split('_')])\n            CFG.encoder = cfg_dict['a']\n            CFG.seq_len = 256 #int(cfg_dict['len'])\n            CFG.emb_size = int(cfg_dict['e'])\n            CFG.hidden_size = int(cfg_dict['h'])\n            CFG.nlayers = int(cfg_dict['l'])\n            CFG.nheads = int(cfg_dict['hd'])\n            CFG.seed = int(cfg_dict['s'])\n            CFG.data_seed = int(cfg_dict['s'])\n                        \n            for k in range(5):\n                model = ENCODERS[CFG.encoder](CFG)\n                checkpoint = torch.load(base_model_path.replace('k-0', f'k-{k}'), map_location=CFG.device)        \n                model.load_state_dict(checkpoint['state_dict'])\n                model.to(CFG.device) \n                print(\"=> loaded checkpoint '{}' (epoch {})\".format(base_model_path.replace('k-0', f'k-{k}'), checkpoint['epoch']))   \n\n                models.append(model)\n\n                del model \n                \n    return models\n\nmodels04 = get_model(CFG, base_model_path_list_04, 191, CATS, NUMS, '0to4')\nmodels512 = get_model(CFG, base_model_path_list_512, 390, CATS, NUMS, '5to12')\nmodels1322 = get_model(CFG, base_model_path_list_1322, 477, CATS, NUMS, '13to22')","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:17:53.784265Z","iopub.execute_input":"2023-06-19T03:17:53.785403Z","iopub.status.idle":"2023-06-19T03:17:57.154929Z","shell.execute_reply.started":"2023-06-19T03:17:53.785366Z","shell.execute_reply":"2023-06-19T03:17:57.153962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mp04, _, _, _ = torch.load('/kaggle/input/psp-seqtf-llama/info04.pt')\nmp512, _, _, _ = torch.load('/kaggle/input/psp-seqtf-llama/info512.pt')\nmp1322, _, _, _ = torch.load('/kaggle/input/psp-seqtf-llama/info1322.pt')\n\ndel _\n\n# load mappers\nmp = {\n    '0to4': mp04,\n    '5to12': mp512,\n    '13to22': mp1322\n}\n\ncoef04 = [\n    [0.31894719, 0.53980624, 0.53314472],\n    [0.33481867, 0.56520423, 0.53378786],\n    [0.32016032, 0.54647527, 0.54948131],\n    [0.3260431 , 0.57259159, 0.51717821],\n    [0.37217078, 0.55600566, 0.52749486]\n]\ncoef512= [\n    [0.59428402, 0.47315996, 0.59096675, 0.5118662 , 0.51113613,\n       0.5354509 , 0.38436716, 0.50396677, 0.49056115, 0.20276313],\n    [0.54810286, 0.48500724, 0.5786955 , 0.52030383, 0.44546623,\n       0.59834199, 0.40508055, 0.47606891, 0.46118339, 0.2871894 ],\n    [0.59112511, 0.46303488, 0.64459857, 0.50373546, 0.41980164,\n       0.59434941, 0.37472922, 0.51129721, 0.57696454, 0.21568142],\n    [0.62735126, 0.46626628, 0.60258133, 0.51851509, 0.51376069,\n       0.5485605 , 0.43093066, 0.49605786, 0.43983651, 0.25182025],\n    [0.59859971, 0.43354179, 0.46588917, 0.52270312, 0.49677891,\n       0.54871605, 0.41409055, 0.51430292, 0.59089701, 0.23687914]\n]\ncoef1322 = [\n    [0.51613567, 0.32316362, 0.49835094, 0.49992666, 0.61999241],\n    [0.5305848 , 0.41168854, 0.49471133, 0.51798015, 0.52445352],\n    [0.43206006, 0.32272994, 0.55063945, 0.47782677, 0.60325316],\n    [0.43732881, 0.26527522, 0.47688687, 0.41755   , 0.67626059],\n    [0.10248128, 0.31985864, 0.48933056, 0.40519788, 0.56127087]\n]","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:21:27.506632Z","iopub.execute_input":"2023-06-19T03:21:27.507046Z","iopub.status.idle":"2023-06-19T03:21:27.533184Z","shell.execute_reply.started":"2023-06-19T03:21:27.507000Z","shell.execute_reply":"2023-06-19T03:21:27.532243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data pipeline","metadata":{}},{"cell_type":"code","source":"CATS = ['event_name', 'level', 'fqid', 'room_fqid', 'text', 'name', 'text_fqid']\nNUMS = ['elapsed_time', 'room_coor_x', 'room_coor_y', 'page',\n        'screen_coor_x', 'screen_coor_y', 'hover_duration']","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:21:30.261220Z","iopub.execute_input":"2023-06-19T03:21:30.261589Z","iopub.status.idle":"2023-06-19T03:21:30.266959Z","shell.execute_reply.started":"2023-06-19T03:21:30.261562Z","shell.execute_reply":"2023-06-19T03:21:30.266043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess(df1, mappers_dict):    \n    # Define the data types and columns\n    dtypes = {\n        'session_id': np.int64,\n        'elapsed_time': np.int32,\n        'event_name': 'category',\n        'name': 'category',\n        'level': 'category',\n        'page': np.float64,\n        'room_coor_x': np.float64,\n        'room_coor_y': np.float64,\n        'screen_coor_x': np.float64,\n        'screen_coor_y': np.float64,\n        'hover_duration': np.float64,\n        'text': 'category',\n        'fqid': 'category',\n        'room_fqid': 'category',\n        'text_fqid': 'category',\n        'fullscreen': 'category',\n        'hq': 'category',\n        'music': 'category',\n        'level_group': 'category'\n    }\n\n    use_cols = [\n        'session_id', 'index', 'elapsed_time', 'event_name', 'name', 'level', 'page', 'room_coor_x', 'room_coor_y',\n        'screen_coor_x', 'screen_coor_y', 'hover_duration', 'text', 'fqid', 'room_fqid', 'text_fqid', 'level_group'\n    ]\n    \n    # Create a new DataFrame with selected columns and data types\n    df = pd.DataFrame()\n    for col in use_cols:\n        df[col] = df1[col].astype(dtypes.get(col, 'object'))\n\n    # Optionally, you can reset the index of the new DataFrame\n    df = df.reset_index(drop=True) \n    \n    df['elapsed_time'] //= 1000\n    df['hover_duration'] //= 1000\n    \n    for col in CATS:\n        if 0 not in df[col].unique():\n            df[col] = df[col].cat.add_categories(0)  \n        df[col] = df[col].map(mappers_dict[col]).fillna(0).astype(np.int64)            \n        df[col] = df[col]\n    \n    # Fill missing values in numeric columns\n    df[NUMS] = df[NUMS].fillna(-1)\n    \n    # Group session indices\n    sample_indices = []\n    df_groups = df.groupby('session_id').groups\n    for inst_idx, indices in enumerate(df_groups.values()):\n        sample_indices.append(indices.tolist())\n    \n    return df, sample_indices\n","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:21:32.724444Z","iopub.execute_input":"2023-06-19T03:21:32.724824Z","iopub.status.idle":"2023-06-19T03:21:32.737549Z","shell.execute_reply.started":"2023-06-19T03:21:32.724794Z","shell.execute_reply":"2023-06-19T03:21:32.736603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Infering","metadata":{}},{"cell_type":"code","source":"from scipy.stats import mode\n\ndef hard_voting(predictions):\n    majority_votes = mode(predictions)[0][0]\n    return majority_votes\n\ndef validate(valid_loader, model):\n    model.eval()\n    predictions = [model(cate_x.to(CFG.device), cont_x.to(CFG.device), mask.to(CFG.device)).sigmoid().detach().cpu().numpy()\n                   for cate_x, cont_x, mask, y in valid_loader]\n    predictions = np.concatenate(predictions)\n    return predictions\n\ndef infer(model, coef, cfg, model_lv_type, df, sample_indices):\n    predictions = [validate(DataLoader(BowlDataset(cfg, model_lv_type, df, sample_indices), batch_size=CFG.batch_size, shuffle=False,\n                                       num_workers=CFG.num_workers, pin_memory=True), model[k])\n                   for k in range(5)]\n    predictions = np.array(predictions)\n    \n    for k in range(len(coef)):\n        predictions[k][0] = (predictions[k][0] >= coef[k]).astype(np.int64)\n    \n    majority_votes = hard_voting(predictions.astype(np.int64))\n    return majority_votes\n    \ndef main(df, mp):\n    df_lv = df.level_group.values[0]\n    current_lv = level_mapper[df_lv] \n    df1, sample_indices = preprocess(df, mp[current_lv])   \n    \n    df = df.reset_index()\n    \n    if current_lv == '0to4':   \n        preds = infer(models04, coef04, CFG, current_lv, df1, sample_indices)\n        return preds[0].astype(np.int64)\n    elif current_lv == '5to12':\n        preds = infer(models512, coef512, CFG, current_lv, df1, sample_indices)\n        return preds[0].astype(np.int64)\n    else:\n        preds = infer(models1322, coef1322, CFG, current_lv, df1, sample_indices)\n        return preds[0].astype(np.int64)","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:21:42.431584Z","iopub.execute_input":"2023-06-19T03:21:42.431972Z","iopub.status.idle":"2023-06-19T03:21:42.735455Z","shell.execute_reply.started":"2023-06-19T03:21:42.431943Z","shell.execute_reply":"2023-06-19T03:21:42.734317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submit","metadata":{}},{"cell_type":"code","source":"import jo_wilder_310\ntry:\n    jo_wilder_310.make_env.__called__ = False\n    env.__called__ = False\n    type(env)._state = type(type(env)._state).__dict__['INIT']\nexcept:\n    pass\n\nenv = jo_wilder_310.make_env()\niter_test = env.iter_test() ","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:21:46.158734Z","iopub.execute_input":"2023-06-19T03:21:46.159392Z","iopub.status.idle":"2023-06-19T03:21:46.185404Z","shell.execute_reply.started":"2023-06-19T03:21:46.159360Z","shell.execute_reply":"2023-06-19T03:21:46.184530Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for test, sample_submission in iter_test:\n    test = test.sort_values('index').reset_index(drop=True)\n\n    sample_submission['question'] = [int(label.split('_')[1][1:]) for label in sample_submission['session_id']]\n    sample_submission = sample_submission.sort_values('question').reset_index(drop=True)\n\n    preds = main(test, mp)\n\n    sample_submission['correct'] = preds\n\n    env.predict(sample_submission[['session_id', 'correct']])","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:21:50.543796Z","iopub.execute_input":"2023-06-19T03:21:50.544380Z","iopub.status.idle":"2023-06-19T03:22:21.850310Z","shell.execute_reply.started":"2023-06-19T03:21:50.544350Z","shell.execute_reply":"2023-06-19T03:22:21.848833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('submission.csv')\nprint( df.shape )\ndf.head(50)","metadata":{"execution":{"iopub.status.busy":"2023-06-19T03:22:21.852912Z","iopub.execute_input":"2023-06-19T03:22:21.853322Z","iopub.status.idle":"2023-06-19T03:22:21.884493Z","shell.execute_reply.started":"2023-06-19T03:22:21.853282Z","shell.execute_reply":"2023-06-19T03:22:21.883561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def validate(valid_loader, model):\n#     model.eval()        \n#     predictions = []\n    \n#     for step, (cate_x, cont_x, mask, y) in enumerate(valid_loader):        \n#         cate_x, cont_x, mask = cate_x.to(CFG.device), cont_x.to(CFG.device), mask.to(CFG.device)       \n#         with torch.no_grad():        \n#             pred = model(cate_x, cont_x, mask)\n            \n#         pred = pred.sigmoid()\n        \n#         predictions.append(pred.detach().cpu())\n\n#     predictions = torch.cat(predictions).numpy()    \n#     return predictions","metadata":{"execution":{"iopub.status.busy":"2023-06-11T19:12:07.400628Z","iopub.execute_input":"2023-06-11T19:12:07.401156Z","iopub.status.idle":"2023-06-11T19:12:07.404936Z","shell.execute_reply.started":"2023-06-11T19:12:07.401128Z","shell.execute_reply":"2023-06-11T19:12:07.404099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def preprocess(df1, mappers_dict):    \n    \n#     # Drop columns\n#     df.drop(['fullscreen', 'hq', 'music'], axis=1, inplace=True)\n    \n#     # Convert numeric columns\n# #     df[NUMS] = df[NUMS].astype(np.float64)\n# #     df['session_id'] = df['session_id'].astype(np.int64)\n#     df['elapsed_time'] //= 1000\n#     df['hover_duration'] //= 1000\n    \n#     # Convert categorical columns\n# #     for col in CATS:\n# #         if col in df.columns:\n# #             df[col] = df[col].astype('category')\n    \n#     # Categorize columns\n    \n#     for col in CATS:\n#         if 0 not in df[col].unique():\n#             df[col] = df[col].cat.add_categories(0)  \n#         df[col] = df[col].map(mappers_dict[col]).fillna(0).astype(np.int64)            \n#         df[col] = df[col]\n    \n#     # Fill missing values in numeric columns\n#     df[NUMS] = df[NUMS].fillna(-1)\n    \n#     # Group session indices\n#     sample_indices = []\n#     df_groups = df.groupby('session_id').groups\n#     for inst_idx, indices in enumerate(df_groups.values()):\n#         sample_indices.append(indices.tolist())\n    \n#     return df, sample_indices\n","metadata":{"execution":{"iopub.status.busy":"2023-06-11T19:12:07.406211Z","iopub.execute_input":"2023-06-11T19:12:07.406772Z","iopub.status.idle":"2023-06-11T19:12:07.42285Z","shell.execute_reply.started":"2023-06-11T19:12:07.406744Z","shell.execute_reply":"2023-06-11T19:12:07.421821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}