{"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":"! pip install /kaggle/input/treelite-240/treelite-2.4.0-py3-none-manylinux2014_x86_64.whl --disable-pip-version-check","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:57:33.429409Z","iopub.execute_input":"2023-06-28T12:57:33.430075Z","iopub.status.idle":"2023-06-28T12:57:47.837189Z","shell.execute_reply.started":"2023-06-28T12:57:33.430024Z","shell.execute_reply":"2023-06-28T12:57:47.835181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"! pip install /kaggle/input/treelite-240/treelite_runtime-2.4.0-py3-none-manylinux2014_x86_64.whl --disable-pip-version-check","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:57:47.838963Z","iopub.execute_input":"2023-06-28T12:57:47.839397Z","iopub.status.idle":"2023-06-28T12:58:02.46391Z","shell.execute_reply.started":"2023-06-28T12:57:47.839357Z","shell.execute_reply":"2023-06-28T12:58:02.462575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PATH = \"/kaggle/input\"\nTHRESHOLD = 0.625\nEXPIT = True\nLEVEL_GROUPS = ['0-4', '5-12', '13-22']\nLENGTHS = {'0-4': 600, '5-12': 1400, '13-22': 2000}\nDISCRETE_FEATURES = ['room_fqid', 'event_name_name', 'text', 'fqid', 'coor_x', 'coor_y', 'page']\nCONTINUOUS_FEATURES = ['duration', 'hover_duration']\nFEATURES = DISCRETE_FEATURES + CONTINUOUS_FEATURES\nFEATURES_5 = ['room_fqid', 'event_name_name', 'text', 'fqid', 'duration']","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:02.465456Z","iopub.execute_input":"2023-06-28T12:58:02.465907Z","iopub.status.idle":"2023-06-28T12:58:02.474971Z","shell.execute_reply.started":"2023-06-28T12:58:02.465848Z","shell.execute_reply":"2023-06-28T12:58:02.473911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MODELS = [\n    {\n        'path': f'{PATH}/cpmp-predict-student-xgb-10-folds/pspfgp-46-xgb-bags-10-folds',\n        'n_bags': 4,\n        'n_seeds': 1,\n        'n_folds': 10,\n        'weight': 0.5,\n    }, {\n        'path': f'{PATH}/pspfgp-49-dataset/pspfgp-46-nn-simple-head',\n        'n_bags': 1,\n        'n_seeds': 4,\n        'n_folds': 5,\n        'weight': 0.15,\n    }, {\n        'path': f'{PATH}/pspfgp-49-dataset/pspfgp-47-nn-simple-head',\n        'n_bags': 1,\n        'n_seeds': 4,\n        'n_folds': 5,\n        'weight': 0.2,\n    }, {\n        'path': f'{PATH}/pspfgp-49-dataset/pspfgp-48-nn-simple-head',\n        'n_bags': 1,\n        'n_seeds': 4,\n        'n_folds': 5,\n        'weight': 0.15,\n    },\n]","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:02.478265Z","iopub.execute_input":"2023-06-28T12:58:02.478606Z","iopub.status.idle":"2023-06-28T12:58:02.494092Z","shell.execute_reply.started":"2023-06-28T12:58:02.478573Z","shell.execute_reply":"2023-06-28T12:58:02.492667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport pickle\nimport polars as pl\nimport re\nif EXPIT:\n    from scipy.special import expit, logit\nimport tensorflow as tf\nimport treelite\nimport treelite_runtime\nfrom xgboost import XGBClassifier","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:02.495976Z","iopub.execute_input":"2023-06-28T12:58:02.496346Z","iopub.status.idle":"2023-06-28T12:58:06.749142Z","shell.execute_reply.started":"2023-06-28T12:58:02.496313Z","shell.execute_reply":"2023-06-28T12:58:06.747525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import jo_wilder\nenv = jo_wilder.make_env()\niter_test = env.iter_test()","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.751277Z","iopub.execute_input":"2023-06-28T12:58:06.75207Z","iopub.status.idle":"2023-06-28T12:58:06.761601Z","shell.execute_reply.started":"2023-06-28T12:58:06.752028Z","shell.execute_reply":"2023-06-28T12:58:06.760656Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_levels(level_group, within_level_group=True):\n    level_group_split = level_group.split(\"-\")\n    level_group_min = int(level_group_split[0]) if within_level_group else 0\n    level_group_max = int(level_group_split[1])\n    return [i for i in range(level_group_min, level_group_max + 1)]","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.76304Z","iopub.execute_input":"2023-06-28T12:58:06.763764Z","iopub.status.idle":"2023-06-28T12:58:06.771308Z","shell.execute_reply.started":"2023-06-28T12:58:06.763723Z","shell.execute_reply":"2023-06-28T12:58:06.770137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_questions(level_group):\n    return ([1, 2, 3] if level_group == '0-4' \n            else [4, 5, 6, 7, 8, 9, 10, 11, 12, 13] if level_group == '5-12' \n            else [14, 15, 16, 17, 18])","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.7729Z","iopub.execute_input":"2023-06-28T12:58:06.773249Z","iopub.status.idle":"2023-06-28T12:58:06.789437Z","shell.execute_reply.started":"2023-06-28T12:58:06.773215Z","shell.execute_reply":"2023-06-28T12:58:06.788299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def clean_feature_name(feature_name):\n    return re.sub('[^A-Za-z0-9_]', '_', str(feature_name))","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.790711Z","iopub.execute_input":"2023-06-28T12:58:06.791919Z","iopub.status.idle":"2023-06-28T12:58:06.80453Z","shell.execute_reply.started":"2023-06-28T12:58:06.791873Z","shell.execute_reply":"2023-06-28T12:58:06.802687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AggsBuilder:\n    def __init__(self, collections):\n        self.collections = collections\n        self.aggs = []\n        \n    def doc(self):\n        to_exclude = ['collections', 'aggs']\n        return [el for el in dir(self) if '__' not in el and el not in to_exclude]\n        \n    def collect(self):\n        aggs = self.aggs\n        self.aggs = []\n        return aggs\n    \n    def clear(self):\n        self.aggs = []\n        \n    def add(self, *aggregations):\n        self.aggs.extend([*aggregations])\n        \n    def add_durations(self, level_group):\n        fqids = self.collections[level_group]['fqids']\n        room_fqids = self.collections[level_group]['room_fqids']\n        event_name_names = self.collections[level_group]['event_name_names']\n        texts = self.collections[level_group]['texts']\n        levels = get_levels(level_group)\n        activities = self.collections[level_group]['activities']\n        pages = self.collections[level_group]['pages']\n        \n        text_root = pl.col('duration').filter(~pl.col('text').is_null())\n        \n        self.add(pl.col('duration').drop_nulls().sum()\n                 .alias(f'level_group_{level_group}_duration_sum'))\n        \n        self.add(*[pl.col('duration').filter(pl.col('room_fqid') == r).sum()\n                   .alias(f'level_group_{level_group}_room_fqid_{r}_duration_sum') for r in room_fqids])\n        \n        self.add(*[pl.col('duration').filter(pl.col('fqid') == f).sum()\n                   .alias(f'level_group_{level_group}_fqid_{f}_duration_sum') for f in fqids])\n        \n        self.add(*[pl.col('duration').filter(pl.col('text') == t).sum()\n                   .alias(f'level_group_{level_group}_text_{t}_duration_sum') for t in texts])\n        \n        self.add(*[pl.col('duration').filter(pl.col('fqid').str.contains(f)).sum()\n                   .alias(f'level_group_{level_group}_activity_{f}_duration_sum') for f in activities])\n        \n        self.add(*[pl.col('hover_duration').filter(pl.col('fqid').str.contains(f)).sum()\n                   .alias(f'level_group_{level_group}_fqid_{f}_hover_duration_sum') for f in fqids])\n\n        self.add(*[pl.col('duration').filter(pl.col('event_name_name') == e).sum()\n                   .alias(f'level_group_{level_group}_event_name_name_{e}_duration_sum') \n                   for e in event_name_names])\n\n        self.add(*[pl.col('duration').filter((pl.col('level') == l) & (pl.col('event_name_name') == e)).sum()\n                   .alias(f'level_{l}_event_name_name_{e}_duration_sum') \n                   for e in event_name_names for l in levels])\n\n        self.add(*[pl.col('duration').filter((pl.col('room_fqid') == r) & (pl.col('event_name_name') == e)).sum()\n                   .alias(f'level_group_{level_group}_room_fqid_{r}_event_name_name_{e}_duration_sum') \n                   for e in event_name_names for r in room_fqids])\n        \n        self.add(*[(pl.col('elapsed_time').filter(pl.col('fqid').str.contains(f)).max() - \n                    pl.col('elapsed_time').filter(pl.col('fqid').str.contains(f)).min())\n                   .alias(f'level_group_{level_group}_activity_{f}_elapsed_time_diff') for f in activities])\n        \n        self.add(*[pl.col('prev_duration').filter(pl.col('fqid') == f).sum()\n                   .alias(f'level_group_{level_group}_fqid_{f}_prev_duration_sum') for f in fqids])\n        \n        self.add(*[pl.col('prev_duration').filter(pl.col('text') == t).sum()\n                   .alias(f'level_group_{level_group}_text_{t}_prev_duration_sum') for t in texts])\n        \n        self.add(*[pl.col('prev_duration').filter(pl.col('fqid').str.contains(f)).sum()\n                   .alias(f'level_group_{level_group}_activity_{f}_prev_duration_sum') for f in activities])\n\n        return self\n    \n    def add_counts(self, level_group):\n        fqids = self.collections[level_group]['fqids']\n        room_fqids = self.collections[level_group]['room_fqids']\n        event_name_names = self.collections[level_group]['event_name_names']\n        texts = self.collections[level_group]['texts']\n        levels = get_levels(level_group)\n        activities = self.collections[level_group]['activities']\n        pages = self.collections[level_group]['pages']\n        text_fqids = self.collections[level_group]['text_fqids']\n        \n        self.add(pl.col('index').count()\n                 .alias(f'level_group_{level_group}_cnt'))\n        \n        self.add(*[pl.col('index').filter(pl.col('room_fqid') == r).count()\n                   .alias(f'level_group_{level_group}_room_fqid_{r}_cnt') for r in room_fqids])\n        \n        self.add(*[pl.col('index').filter(pl.col('fqid').str.contains(f)).count()\n                   .alias(f'level_group_{level_group}_activity_{f}_cnt') for f in activities])\n        \n        self.add(*[pl.col('index').filter(pl.col('level') == l).count()\n                   .alias(f'level_{l}_cnt') for l in levels])\n        \n        self.add(*[pl.col('index').filter(pl.col('fqid') == f).count()\n                   .alias(f'level_group_{level_group}_fqid_{f}_cnt') for f in fqids])\n        \n        self.add(*[pl.col('index').filter(pl.col('text_fqid') == t).count()\n                   .alias(f'level_group_{level_group}_text_fqid_{t}_cnt') for t in text_fqids])\n        \n        self.add(*[pl.col('index').filter(pl.col('page') == p).count()\n                   .alias(f'level_group_{level_group}_page_{p}_cnt') for p in pages])\n        \n        self.add(*[pl.col('index').filter(pl.col('event_name_name') == e).count()\n                   .alias(f'level_group_{level_group}_event_name_name_{e}_cnt') for e in event_name_names])\n        \n        self.add(*[pl.col('index').filter((pl.col('event_name_name') == e) & (pl.col('level') == l)).count()\n                   .alias(f'level_group_{level_group}_level_{l}_event_name_name_{e}_cnt') \n                   for e in event_name_names for l in levels])\n        \n        self.add(*[pl.col('index').filter((pl.col('event_name_name') == e) & (pl.col('room_fqid') == r)).count()\n                   .alias(f'level_group_{level_group}_room_fqid_{r}_event_name_name_{e}_cnt') \n                   for e in event_name_names for r in room_fqids])\n        \n        return self\n    \n    def add_mouse(self, level_group):\n        filter_condition = (pl.col('event_name') == 'object_click') & (pl.col('name') == 'basic')\n        activities = self.collections[level_group]['activities']\n        \n        self.add(*[pl.col('room_coor_x').filter(filter_condition & pl.col('fqid').str.contains(f)).mean()\n                   .alias(f'level_group_{level_group}_{f}_room_coor_x_mean') for f in activities])\n        self.add(*[pl.col('room_coor_x').filter(filter_condition & pl.col('fqid').str.contains(f)).std()\n                   .alias(f'level_group_{level_group}_{f}_room_coor_x_std') for f in activities])\n        self.add(*[pl.col('room_coor_x').filter(filter_condition & pl.col('fqid').str.contains(f)).mean()\n                   .alias(f'level_group_{level_group}_{f}_room_coor_y_mean') for f in activities])\n        self.add(*[pl.col('room_coor_x').filter(filter_condition & pl.col('fqid').str.contains(f)).std()\n                   .alias(f'level_group_{level_group}_{f}_room_coor_y_std') for f in activities])\n        \n        return self\n        \n    def add_notebook(self, level_group):\n        self.add(*[pl.col('duration').filter((pl.col('level') == l) & \n                                             ((pl.col('event_name') == 'notebook_click') & \n                                              (pl.col('name') != 'close'))).sum()\n                   .alias(f'level_{l}_notebook_duration_sum') for l in get_levels(level_group)])\n        return self\n\n    def add_globals(self, level_group):\n        return self","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.80635Z","iopub.execute_input":"2023-06-28T12:58:06.807621Z","iopub.status.idle":"2023-06-28T12:58:06.866562Z","shell.execute_reply.started":"2023-06-28T12:58:06.807572Z","shell.execute_reply":"2023-06-28T12:58:06.865213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def engineer_gbdt(x_raw, session_data, level_group, aggs_builder):\n    aggs = (\n        aggs_builder\n            .add_durations(level_group)\n            .add_counts(level_group)\n            .add_mouse(level_group)\n            .add_notebook(level_group)\n            .collect()\n    )\n    columns = [((pl.col('elapsed_time').shift(-1) - pl.col('elapsed_time')).fill_null(0)\n                .over(['session_id', 'level_group'])\n                .alias('duration')),\n               ((pl.col('elapsed_time').shift(1) - pl.col('elapsed_time')).fill_null(0)\n                .over(['session_id', 'level_group'])\n                .alias('prev_duration'))]\n    x_lg = (pl.from_pandas(x_raw)\n            .lazy().drop(['fullscreen', 'hq', 'music']).with_columns(columns)\n            .groupby('session_id', maintain_order=True).agg(aggs)\n            .sort('session_id').collect().to_pandas())\n    x_lg.columns = [clean_feature_name(c) for c in x_lg.columns]\n    \n    x_lg = x_lg.fillna(-999999)\n        \n    if level_group == '0-4':\n        return x_lg\n    \n    return pd.concat([session_data, x_lg.drop(['session_id'], axis=1)], axis=1)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.868282Z","iopub.execute_input":"2023-06-28T12:58:06.868878Z","iopub.status.idle":"2023-06-28T12:58:06.882307Z","shell.execute_reply.started":"2023-06-28T12:58:06.868839Z","shell.execute_reply":"2023-06-28T12:58:06.88091Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_sequence(df, n_features, length):\n    return (np.vstack([df.values, np.zeros((length - len(df), n_features))]) \n            if len(df) < length else df[:length].values)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.884132Z","iopub.execute_input":"2023-06-28T12:58:06.884523Z","iopub.status.idle":"2023-06-28T12:58:06.903469Z","shell.execute_reply.started":"2023-06-28T12:58:06.884487Z","shell.execute_reply":"2023-06-28T12:58:06.902025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def engineer_nn(x, length, tokenizer_map, features):\n    x['coor_x'] = (((np.clip(x['room_coor_x'], -2000, 2000) + 2000) / 4000).fillna(0) * 50).astype(int)\n    x['coor_y'] = (((np.clip(x['room_coor_y'], -1000, 1000) + 1000) / 2000).fillna(0) * 50).astype(int)\n\n    next_elapsed_time = x['elapsed_time'].shift(-1)\n    x['duration'] = next_elapsed_time - x['elapsed_time']\n    x['duration'] = x['duration'].fillna(60000)\n    x['duration'] = np.clip(x['duration'], 0, 60000) / 60000\n    \n    x['hover_duration'] = x['hover_duration'].fillna(0)\n    x['hover_duration'] = np.clip(x['hover_duration'], 0, 60000) / 60000\n    \n    for feature in DISCRETE_FEATURES:\n        if feature in features:\n            encoder = {value: token for token, value in enumerate(tokenizer_map[feature]['encode'])}\n            x[feature] = np.where(~x[feature].isin(tokenizer_map[feature]['encode']), np.nan, x[feature])\n            x[feature] = x[feature].map(encoder)\n            x[feature] = x[feature].fillna(0)\n    \n    x = build_sequence(x[features], len(features), length)\n    x = x.T\n    x = x.astype(np.float32)\n    x = np.expand_dims(x, axis=1)\n    \n    return x","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.907952Z","iopub.execute_input":"2023-06-28T12:58:06.908411Z","iopub.status.idle":"2023-06-28T12:58:06.928775Z","shell.execute_reply.started":"2023-06-28T12:58:06.908351Z","shell.execute_reply":"2023-06-28T12:58:06.927213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model:\n    def __init__(self, path, n_bags, n_seeds, n_folds, weight):\n        self.path = path\n        self.type = path.split('/')[-1].split('-')[2]\n        self.n_bags = n_bags\n        self.n_seeds = n_seeds\n        self.n_folds = n_folds\n        self.weight = weight\n        self.models = {}\n        self.build()\n        \n    def build(self):\n        if self.type == 'xgb' or self.type == 'lgb':\n            self.features = pickle.load(open(f'{self.path}/features.pkl', 'rb'))\n            for q in range(1, 18 + 1):\n                for b in range(self.n_bags):\n                    for f in range(self.n_folds):\n                        for s in range(self.n_seeds):\n                            path = f'{self.path}/q{q}b{b}f{f}s{s}'\n                            if self.type == 'xgb':\n                                model = treelite.Model.load(f'{path}.xgb', model_format='xgboost')\n                            elif self.type == 'lgb':\n                                model = treelite.Model.load(f'{path}.lgb', model_format='lightgbm')\n                            self.models[path.split('/')[-1]] = model\n            \n        elif self.type == 'convnet' or self.type == 'nn':\n            self.embeddings = {}\n            self.info = {}\n            for level_group in LEVEL_GROUPS:\n                self.models[level_group] = {}\n                self.info[level_group] = {}\n                for s in range(self.n_seeds):\n                    self.models[level_group][s] = {}\n                    self.info[level_group][s] = {}\n                    for f in range(self.n_folds):\n                        suffix = f'_{level_group.replace(\"-\", \"_\")}_b0f{f}'\n                        convnet_interpreter = tf.lite.Interpreter(model_path=f'{self.path}-s{s}/convnet{suffix}.tflite')\n                        convnet_interpreter.allocate_tensors()\n                        head_interpreter = tf.lite.Interpreter(model_path=f'{self.path}-s{s}/head{suffix}.tflite')\n                        head_interpreter.allocate_tensors()\n                        self.models[level_group][s][f'f{f}'] = {}\n                        self.info[level_group][s]['input_details']  = {}\n                        self.info[level_group][s]['output_details']  = {}\n                        self.models[level_group][s][f'f{f}']['convnet'] = convnet_interpreter\n                        self.models[level_group][s][f'f{f}']['head'] = head_interpreter\n                        input_details = convnet_interpreter.get_input_details()\n                        output_details = convnet_interpreter.get_output_details()\n                        self.info[level_group][s]['input_details']['convnet'] = input_details\n                        self.info[level_group][s]['output_details']['convnet'] = output_details\n                        self.info[level_group][s]['features'] = [\n                            (input_detail['name']\n                             .replace('serving_default_input_', '')\n                             .replace(f\"_{level_group.replace('-', '_')}:0\", '')) \n                            for input_detail in self.info[level_group][s]['input_details']['convnet']]\n                        self.info[level_group][s]['input_details']['head'] = head_interpreter.get_input_details()\n                        self.info[level_group][s]['output_details']['head'] = head_interpreter.get_output_details()            \n        \n    def predict(self, session_id, level_group, x_gbdt, x_nn):\n        if self.type == 'xgb' or self.type == 'lgb':\n            preds = []\n            for q in get_questions(level_group):\n                question_preds = []\n                for b in range(self.n_bags):\n                    for f in range(self.n_folds):\n                        for s in range(self.n_seeds):\n                            model_name = f'q{q}b{b}f{f}s{s}'\n                            data = x_gbdt[self.features[f'q{q}']].astype(np.float32).values\n                            pred = treelite.gtil.predict(self.models[model_name], data=data)\n                            question_preds.append(pred)\n                question_preds = expit(np.mean(logit(question_preds))) if EXPIT else np.mean(question_preds)\n                preds.append(question_preds)\n            preds = np.array(preds)\n            return preds\n        \n        elif self.type == 'convnet' or self.type == 'nn':\n            feature_map = {f: i for i, f in enumerate(FEATURES_5 if '48' in model.path else FEATURES)}\n            \n            if level_group == '0-4':\n                self.embeddings[session_id] = {}\n                for l in LEVEL_GROUPS:\n                    self.embeddings[session_id][l] = {}\n                    for s in range(self.n_seeds):\n                        self.embeddings[session_id][l][s] = {}\n                    \n            preds = []\n            for b in range(self.n_bags):\n                for f in range(self.n_folds):\n                    fold_preds = []\n                    for s in range(self.n_seeds):\n                        x = x_nn.astype(np.float32)\n                        convnet_interpreter = self.models[level_group][s][f'f{f}']['convnet']\n                        features = self.info[level_group][s]['features']\n                        input_details = self.info[level_group][s]['input_details']['convnet']\n                        output_details = self.info[level_group][s]['output_details']['convnet']  \n                        for i, feature in enumerate(features):\n                            convnet_interpreter.set_tensor(input_details[i]['index'], x[feature_map[feature]])\n                        convnet_interpreter.invoke()\n                        x = convnet_interpreter.get_tensor(output_details[0]['index'])\n\n                        if level_group != '13-22':\n                            self.embeddings[session_id][level_group][s][f'f{f}'] = x\n                        if level_group == '5-12':\n                            x = np.concatenate([self.embeddings[session_id]['0-4'][s][f'f{f}'], x], axis=1)\n                        elif level_group == '13-22':\n                            emb_04 = self.embeddings[session_id]['0-4'][s][f'f{f}']\n                            emb_512 = self.embeddings[session_id]['5-12'][s][f'f{f}']\n                            x = np.concatenate([emb_04, emb_512, x], axis=1)\n\n                        head_interpreter = self.models[level_group][s][f'f{f}']['head']\n                        input_details = self.info[level_group][s]['input_details']['head']\n                        output_details = self.info[level_group][s]['output_details']['head']  \n                        head_interpreter.set_tensor(input_details[0]['index'], x)\n                        head_interpreter.invoke()\n                        p = head_interpreter.get_tensor(output_details[0]['index'])\n                        fold_preds.append(p)\n                    fold_preds = np.mean(fold_preds, axis=0)[0]\n                    preds.append(fold_preds)\n                preds = np.mean(preds, axis=0)\n                return preds","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.930519Z","iopub.execute_input":"2023-06-28T12:58:06.930898Z","iopub.status.idle":"2023-06-28T12:58:06.980301Z","shell.execute_reply.started":"2023-06-28T12:58:06.93086Z","shell.execute_reply":"2023-06-28T12:58:06.979178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = [Model(m['path'], m['n_bags'], m['n_seeds'], m['n_folds'], m['weight']) for m in MODELS]\naggs_builder = AggsBuilder(pickle.load(open(f'{PATH}/pspfgp-49-dataset/collections.pkl', 'rb')))\ntokenizer_map = pickle.load(open(f'{PATH}/pspfgp-49-dataset/tokenizer_map.pkl', 'rb'))\ngbdt_data = {}","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:06.982302Z","iopub.execute_input":"2023-06-28T12:58:06.983453Z","iopub.status.idle":"2023-06-28T12:58:38.585719Z","shell.execute_reply.started":"2023-06-28T12:58:06.9834Z","shell.execute_reply":"2023-06-28T12:58:38.583919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for test, sample_submission in iter_test:\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    session_id = test.iloc[0]['session_id']\n    level_group = test.iloc[0]['level_group']\n    \n    if level_group == '0-4':\n        gbdt_data[session_id] = None\n        \n    test = test.sort_values('index').reset_index(drop=True)\n    test['event_name_name'] = test['event_name'] + '_' + test['name']\n    \n    x_gbdt = engineer_gbdt(test, gbdt_data[session_id], level_group, aggs_builder)\n    x_nn = engineer_nn(test, LENGTHS[level_group], tokenizer_map, FEATURES)\n    x_nn_5 = engineer_nn(test, LENGTHS[level_group], tokenizer_map, FEATURES_5)\n    \n    if level_group == '0-4' or level_group == '5-12':\n        gbdt_data[session_id] = x_gbdt\n    \n    preds = []\n    for model in models:\n        p = model.predict(session_id, level_group, x_gbdt, x_nn_5 if '48' in model.path else x_nn)\n        w = model.weight\n        preds.append(w * p)\n    preds = np.sum(preds, axis=0)\n    \n    sample_submission['correct'] = 1 * (preds > THRESHOLD)\n    \n    env.predict(sample_submission[['session_id', 'correct']])","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:58:38.587689Z","iopub.execute_input":"2023-06-28T12:58:38.588137Z","iopub.status.idle":"2023-06-28T12:59:02.064218Z","shell.execute_reply.started":"2023-06-28T12:58:38.588096Z","shell.execute_reply":"2023-06-28T12:59:02.062743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"! head -n 55 submission.csv","metadata":{"execution":{"iopub.status.busy":"2023-06-28T12:59:02.066111Z","iopub.execute_input":"2023-06-28T12:59:02.066959Z","iopub.status.idle":"2023-06-28T12:59:03.313142Z","shell.execute_reply.started":"2023-06-28T12:59:02.066912Z","shell.execute_reply":"2023-06-28T12:59:03.310936Z"},"trusted":true},"execution_count":null,"outputs":[]}]}