{"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":"[An essay for a PSPFGP comepetition.](https://www.kaggle.com/competitions/predict-student-performance-from-game-play/discussion/425798)\n\n1. [PSPFGP_NN_dataset](https://www.kaggle.com/code/dongyk/pspfgp-nn-dataset)\n2. [PSPFGP_NN_Pretrain](https://www.kaggle.com/code/dongyk/pspfgp-nn-pretrain)\n3. [PSPFGP_NN_Train](https://www.kaggle.com/code/dongyk/pspfgp-nn-train)\n4. [PSPFGP_NN_Inference](https://www.kaggle.com/code/dongyk/pspfgp-nn-inference)","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport pickle\nimport tensorflow as tf","metadata":{"execution":{"iopub.status.busy":"2023-07-20T10:08:16.690505Z","iopub.execute_input":"2023-07-20T10:08:16.690900Z","iopub.status.idle":"2023-07-20T10:08:27.464861Z","shell.execute_reply.started":"2023-07-20T10:08:16.690861Z","shell.execute_reply":"2023-07-20T10:08:27.463373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CAT_FEATURES = ['coded_event_name_name', 'coded_room_fqid', 'coded_text', 'coded_fqid']\nNUM_FEATURES = ['elapsed_time_diff']\nFEATURES = NUM_FEATURES + CAT_FEATURES\n\nNN_PATH = '/kaggle/input/pspfgp-nn-4'\nLENGTHS = {'0-4':600, '5-12':1400, '13-22':2000}\nLEVEL_GROUPS = ['0-4', '5-12', '13-22']\nN_FOLDS = 5","metadata":{"execution":{"iopub.status.busy":"2023-07-20T10:08:54.655104Z","iopub.execute_input":"2023-07-20T10:08:54.655484Z","iopub.status.idle":"2023-07-20T10:08:54.662136Z","shell.execute_reply.started":"2023-07-20T10:08:54.655453Z","shell.execute_reply":"2023-07-20T10:08:54.661092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"VERSION = 4\nCODE_VERSION = f'PSPFGP_NN_code_{VERSION}'\nTHR_VERSION = f'PSPFGP_NN_thr_{VERSION}'\nprint(CODE_VERSION)\nprint(THR_VERSION)\n\nCODE, CODE_LEN = pickle.load(open(f'{NN_PATH}/{CODE_VERSION}.pkl', 'rb'))\nTHR = pickle.load(open(f'{NN_PATH}/{THR_VERSION}.pkl', 'rb'))","metadata":{"execution":{"iopub.status.busy":"2023-07-20T10:08:55.724577Z","iopub.execute_input":"2023-07-20T10:08:55.724976Z","iopub.status.idle":"2023-07-20T10:08:55.744533Z","shell.execute_reply.started":"2023-07-20T10:08:55.724945Z","shell.execute_reply":"2023-07-20T10:08:55.743680Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model():\n    def __init__(self):\n        self.models, self.info = self.build()\n    \n    def build(self):\n        models = {}\n        info = {}\n        for lvgp in LEVEL_GROUPS:\n            models[lvgp] = {}\n            models[lvgp]['convnet'] = {}\n            models[lvgp]['head'] = {}\n            info[lvgp] = {}\n            info[lvgp]['input_details'] = {}\n            info[lvgp]['input_details']['convnet'] = {}\n            info[lvgp]['input_details']['head'] = {}\n            info[lvgp]['output_details'] = {}\n            info[lvgp]['output_details']['convnet'] = {}\n            info[lvgp]['output_details']['head'] = {}\n            for f in range(N_FOLDS):\n                convnet_interpreter = tf.lite.Interpreter(model_path=f\"{NN_PATH}/convnet_f{f}_{lvgp.replace('-', '_')}.tflite\")\n                convnet_interpreter.allocate_tensors()\n                models[lvgp]['convnet'][f] = convnet_interpreter\n                input_details = convnet_interpreter.get_input_details()\n                output_details = convnet_interpreter.get_output_details()\n                info[lvgp]['input_details']['convnet'][f] = {feat: input_detail for input_detail in input_details for feat in FEATURES if feat in input_detail['name']}\n                info[lvgp]['output_details']['convnet'][f] = output_details[0]\n\n                head_interpreter = tf.lite.Interpreter(model_path=f\"{NN_PATH}/head_f{f}_{lvgp.replace('-', '_')}.tflite\")\n                head_interpreter.allocate_tensors()\n                models[lvgp]['head'][f] = head_interpreter\n                input_details = head_interpreter.get_input_details()\n                output_details = head_interpreter.get_output_details()\n                info[lvgp]['input_details']['head'][f] = input_details[0]\n                info[lvgp]['output_details']['head'][f] = output_details[0]\n                \n        return models, info\n    \n    def predict(self, x: dict, level_group):\n        convnet_interpreter = self.models[level_group]['convnet']\n        head_interpreter = self.models[level_group]['head']\n        convnet_input_details = self.info[level_group]['input_details']['convnet']\n        convnet_output_details = self.info[level_group]['output_details']['convnet']\n        head_input_details = self.info[level_group]['input_details']['head']\n        head_output_details = self.info[level_group]['output_details']['head']\n        if level_group == '0-4':\n            self.convnet_output = {}\n            self.convnet_output['0-4'] = {}\n            self.convnet_output['5-12'] = {}\n        preds = []\n            \n        for f in range(N_FOLDS):\n            for feat in FEATURES:\n                convnet_interpreter[f].set_tensor(convnet_input_details[f][feat]['index'], x[feat])\n            convnet_interpreter[f].invoke()\n            convnet_output = convnet_interpreter[f].get_tensor(convnet_output_details[f]['index'])\n            if level_group != '13-22':\n                self.convnet_output[level_group][f] = convnet_output\n            \n            if level_group == '5-12':\n                convnet_output = np.concatenate([self.convnet_output['0-4'][f], convnet_output], axis=1)\n            if level_group == '13-22':\n                convnet_output = np.concatenate([self.convnet_output['0-4'][f], self.convnet_output['5-12'][f], convnet_output], axis=1)\n            head_interpreter[f].set_tensor(head_input_details[f]['index'], convnet_output)\n            head_interpreter[f].invoke()\n            head_output = head_interpreter[f].get_tensor(head_output_details[f]['index'])\n            pred = (head_output > THR[f'f{f}']).astype('int')\n            preds.append(pred)\n        \n        return (np.mean(preds, axis=0) > 0.5).astype('int')","metadata":{"execution":{"iopub.status.busy":"2023-07-20T10:08:57.479155Z","iopub.execute_input":"2023-07-20T10:08:57.479941Z","iopub.status.idle":"2023-07-20T10:08:57.501722Z","shell.execute_reply.started":"2023-07-20T10:08:57.479906Z","shell.execute_reply":"2023-07-20T10:08:57.500492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def engineer_nn(x: pd.DataFrame, level_group):\n\n    x['elapsed_time_diff'] = (- x['elapsed_time'].diff(-1)).fillna(0).abs().clip(0, 60000) / 60000\n    x['event_name_name'] = x['event_name'] + '_' +  x['name']\n    coded_cats = CODE[level_group]\n    for cat in coded_cats:\n        x[cat] = x[cat[6:]].fillna('None').map(coded_cats[cat]).fillna(0)\n    \n    length = LENGTHS[level_group]\n    length_x = len(x)\n    X = {}\n    for feat in FEATURES:\n        seq = np.concatenate([x[feat].values, [0] * (length - length_x)]) if length_x < length else x[feat].values[:length]\n        seq = seq.T[np.newaxis, :]\n        seq = seq.astype('float32')\n        X[feat] = seq\n        \n    return X","metadata":{"execution":{"iopub.status.busy":"2023-07-20T10:08:58.572804Z","iopub.execute_input":"2023-07-20T10:08:58.573196Z","iopub.status.idle":"2023-07-20T10:08:58.583039Z","shell.execute_reply.started":"2023-07-20T10:08:58.573165Z","shell.execute_reply":"2023-07-20T10:08:58.582034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Model()","metadata":{"execution":{"iopub.status.busy":"2023-07-20T10:09:00.269840Z","iopub.execute_input":"2023-07-20T10:09:00.270272Z","iopub.status.idle":"2023-07-20T10:09:00.637069Z","shell.execute_reply.started":"2023-07-20T10:09:00.270239Z","shell.execute_reply":"2023-07-20T10:09:00.635601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import jo_wilder_310\n#jo_wilder_310.make_env.func_dict['__called__'] = False\nenv = jo_wilder_310.make_env()\niter_test = env.iter_test()","metadata":{"execution":{"iopub.status.busy":"2023-07-20T10:09:01.822042Z","iopub.execute_input":"2023-07-20T10:09:01.823273Z","iopub.status.idle":"2023-07-20T10:09:01.861394Z","shell.execute_reply.started":"2023-07-20T10:09:01.823225Z","shell.execute_reply":"2023-07-20T10:09:01.860274Z"},"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    lvgp = test['level_group'].values[0]\n    X = engineer_nn(test, lvgp)\n    preds = model.predict(X, lvgp)\n    sample_submission['question'] = sample_submission['session_id'].apply(lambda x: int(x.split('_')[1][1:]))\n    sample_submission = sample_submission.sort_values('question')\n    sample_submission['correct'] = np.squeeze(preds)\n    \n    #display(sample_submission)\n    \n    env.predict(sample_submission[['session_id', 'correct']])","metadata":{"execution":{"iopub.status.busy":"2023-07-20T10:09:02.747343Z","iopub.execute_input":"2023-07-20T10:09:02.748795Z","iopub.status.idle":"2023-07-20T10:09:03.018306Z","shell.execute_reply.started":"2023-07-20T10:09:02.748740Z","shell.execute_reply":"2023-07-20T10:09:03.017236Z"},"trusted":true},"execution_count":null,"outputs":[]}]}