{"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":"# Using GPU - Part 2\n## Making a Submission using CPU\n\nThis is Part 2 of the implementation of Chris's idea to use GPU Kaggle notebook for feature engineering during training and then CPU for inference from [here][1]. \n\nPart 1 Notebook is used to for feature engineering and training XGBoost using GPU. Check it out [here][2].\n\n**Version Updates:**\n\n**Version 2 -**\n\nIn the previous version I was loading the models in the Kaggle API's Inference Loop, which was slow as the notebook was reading the models 198,000 times (11k users and for 18 questions) from the disk. Thanks @cdeotte for pointing this out. \n\nI've now updated the notebook. Now the models are loaded outside before Kaggle's API, so the notebook reads the models 18 times from the disk ONCE.\n\n**Version 6 -**\nChanged the structure of the notebook and added features with the help of [this][3] amazing notebook by @takanashihumbert\n\n**Version7 -**\nMade changes in the infer loop according to the changes made in the Kaggle API.\n\n[1]: https://www.kaggle.com/competitions/predict-student-performance-from-game-play/discussion/386218\n[2]: https://www.kaggle.com/code/shashwatraman/gpu-xgb-baseline-using-rapids-cudf-train\n[3]: https://www.kaggle.com/code/takanashihumbert/magic-bingo-train-part-lb-0-687","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport gc\nimport pickle\nfrom sklearn.model_selection import KFold, GroupKFold\nfrom xgboost import XGBClassifier\nfrom sklearn.metrics import f1_score\nfrom tqdm.notebook import tqdm\nfrom collections import defaultdict\nimport warnings\nfrom itertools import combinations\n\nwarnings.filterwarnings('ignore')\npd.set_option(\"display.max_columns\", None)\npd.set_option(\"display.max_rows\", 200)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-03-31T16:54:09.094558Z","iopub.execute_input":"2023-03-31T16:54:09.094944Z","iopub.status.idle":"2023-03-31T16:54:10.254798Z","shell.execute_reply.started":"2023-03-31T16:54:09.094911Z","shell.execute_reply":"2023-03-31T16:54:10.253633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CATS = ['event_name','name','fqid','room_fqid','text_fqid']\n\nNUMS = ['page', 'room_coor_x','room_coor_y','screen_coor_x','screen_coor_y','hover_duration','time_diff']\n\nEVENTS = ['cutscene_click', 'person_click', 'navigate_click',\n       'observation_click', 'notification_click', 'object_click',\n       'object_hover', 'map_hover', 'map_click', 'checkpoint',\n       'notebook_click']\n\nNAMES = ['basic', 'undefined', 'close', 'open', 'prev', 'next']","metadata":{"execution":{"iopub.status.busy":"2023-03-31T16:54:10.256611Z","iopub.execute_input":"2023-03-31T16:54:10.256970Z","iopub.status.idle":"2023-03-31T16:54:10.263435Z","shell.execute_reply.started":"2023-03-31T16:54:10.256937Z","shell.execute_reply":"2023-03-31T16:54:10.262192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def feature_engineer(x, grp):\n    \n    x['time_diff'] = x['elapsed_time'] - x.groupby('session_id')['elapsed_time'].shift(1)\n    mask = x['time_diff'] < 0\n    x.loc[mask,'time_diff'] = 0\n    \n    x['elapsed_time'] = x['elapsed_time'] / 1000\n    x['time_diff'] = x['time_diff'] / 1000\n    \n    #session duration\n    df_final = x.groupby('session_id')['index'].agg('count')\n    df_final.name = 'num_events'\n    df_final = df_final.reset_index()\n    df_final = df_final.set_index('session_id')\n    \n    #Bingo Features\n    if grp == '5-12':\n        \n        df_final['logbingo-logbook'] = x[(x['fqid']=='logbook.page.bingo')&(x['event_name']=='object_click')].groupby('session_id')['index'].agg('first') - x[x['fqid']=='logbook'].groupby('session_id')['index'].agg('first')\n        df_final['readerbingo-reader'] = x[(x['fqid']=='reader.paper2.bingo')&(x['event_name']=='object_click')].groupby('session_id')['index'].agg('first') - x[x['fqid']=='reader'].groupby('session_id')['index'].agg('first')\n        df_final['jourbingo-journalspic'] = x[(x['fqid']=='journals.pic_2.bingo')&(x['event_name']=='object_click')].groupby('session_id')['index'].agg('first') - x[x['fqid']=='journals.pic_0.next'].groupby('session_id')['index'].agg('first')\n        \n        df_final['logbingo-logbook_time'] = x[(x['fqid']=='logbook.page.bingo')&(x['event_name']=='object_click')].groupby('session_id')['elapsed_time'].agg('first') - x[x['fqid']=='logbook'].groupby('session_id')['elapsed_time'].agg('first')\n        df_final['readerbingo-reader_time'] = x[(x['fqid']=='reader.paper2.bingo')&(x['event_name']=='object_click')].groupby('session_id')['elapsed_time'].agg('first') - x[x['fqid']=='reader'].groupby('session_id')['elapsed_time'].agg('first')\n        df_final['jourbingo-journalspic_time'] = x[(x['fqid']=='journals.pic_2.bingo')&(x['event_name']=='object_click')].groupby('session_id')['elapsed_time'].agg('first') - x[x['fqid']=='journals.pic_0.next'].groupby('session_id')['elapsed_time'].agg('first')\n        \n    if grp=='13-22':\n        \n        df_final['readerbingo-reader_flag'] = x[(x['fqid']=='reader_flag.paper2.bingo')&(x['event_name']=='object_click')].groupby('session_id')['index'].agg('first') - x[x['fqid']=='reader_flag'].groupby('session_id')['index'].agg('first')\n        df_final['journalbingo-journals_flag'] = x[(x['fqid']=='journals_flag.pic_0.bingo')&(x['event_name']=='object_click')].groupby('session_id')['index'].agg('first') - x[x['fqid']=='journals_flag'].groupby('session_id')['index'].agg('first')\n        \n        df_final['readerbingo-reader_flag_time'] = x[(x['fqid']=='reader_flag.paper2.bingo')&(x['event_name']=='object_click')].groupby('session_id')['elapsed_time'].agg('first') - x[x['fqid']=='reader_flag'].groupby('session_id')['elapsed_time'].agg('first')\n        df_final['journalbingo-journals_flag_time'] = x[(x['fqid']=='journals_flag.pic_0.bingo')&(x['event_name']=='object_click')].groupby('session_id')['elapsed_time'].agg('first') - x[x['fqid']=='journals_flag'].groupby('session_id')['elapsed_time'].agg('first')\n        \n    df_final['first_elapsed_time'] = x.groupby('session_id')['elapsed_time'].agg('first')\n    df_final['elapsed_time'] = x.groupby('session_id')['elapsed_time'].agg('last') - df_final['first_elapsed_time']\n    \n    for c in CATS:\n        df_final[f'{c}_nuniques'] = x.groupby('session_id')[c].agg('nunique')\n    \n    for c in NUMS:\n        df_final[f'{c}_mean'] = x.groupby('session_id')[c].agg('mean')\n        df_final[f'{c}_min'] = x.groupby('session_id')[c].agg('min')\n        df_final[f'{c}_max'] = x.groupby('session_id')[c].agg('max')\n        \n    for c in EVENTS:\n        x[c] = (x.event_name == c).astype('int8')\n    for c in EVENTS:\n        df_final[f'{c}_sum'] = x.groupby('session_id')[c].agg('sum')\n    x.drop(EVENTS, axis=1, inplace=True)\n    \n    for c in EVENTS:\n        df_final[f'{c}_time_mean'] = x[x['event_name']==c].groupby('session_id')['time_diff'].mean()\n        df_final[f'{c}_time_min'] = x[x['event_name']==c].groupby('session_id')['time_diff'].min()\n        df_final[f'{c}_time_max'] = x[x['event_name']==c].groupby('session_id')['time_diff'].max()\n    \n    for c in NAMES:\n        x[c] = (x.name == c).astype('int8')\n    for c in NAMES:\n        df_final[f'{c}_sum'] = x.groupby('session_id')[c].agg('sum')\n    x.drop(NAMES, axis=1, inplace=True)\n    \n    for c in NAMES:\n        df_final[f'{c}_time_mean'] = x[x['name']==c].groupby('session_id')['time_diff'].mean()\n        df_final[f'{c}_time_min'] = x[x['name']==c].groupby('session_id')['time_diff'].min()\n        df_final[f'{c}_time_max'] = x[x['name']==c].groupby('session_id')['time_diff'].max()\n\n    return df_final","metadata":{"execution":{"iopub.status.busy":"2023-03-31T16:54:10.264724Z","iopub.execute_input":"2023-03-31T16:54:10.265552Z","iopub.status.idle":"2023-03-31T16:54:10.295077Z","shell.execute_reply.started":"2023-03-31T16:54:10.265507Z","shell.execute_reply":"2023-03-31T16:54:10.293953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f_read = open('/kaggle/input/gpu-xgb-baseline-using-rapids-cudf-train/importance_dict.pkl', 'rb')\nimportance_dict = pickle.load(f_read)\nf_read.close()","metadata":{"execution":{"iopub.status.busy":"2023-03-31T16:54:10.296516Z","iopub.execute_input":"2023-03-31T16:54:10.297217Z","iopub.status.idle":"2023-03-31T16:54:10.316675Z","shell.execute_reply.started":"2023-03-31T16:54:10.297166Z","shell.execute_reply":"2023-03-31T16:54:10.315423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Loading the models\nQUESTION_MODELS = []\nfor t in range(1,19):\n    clf = XGBClassifier()\n    clf.load_model(f'../input/gpu-xgb-baseline-using-rapids-cudf-train/XGB_question{t}.xgb')\n    QUESTION_MODELS.append( clf )","metadata":{"execution":{"iopub.status.busy":"2023-03-31T16:54:10.319402Z","iopub.execute_input":"2023-03-31T16:54:10.320167Z","iopub.status.idle":"2023-03-31T16:54:10.666147Z","shell.execute_reply.started":"2023-03-31T16:54:10.320103Z","shell.execute_reply":"2023-03-31T16:54:10.664299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Infer Test Data","metadata":{}},{"cell_type":"code","source":"# IMPORT KAGGLE API\nimport jo_wilder\nenv = jo_wilder.make_env()\niter_test = env.iter_test()","metadata":{"execution":{"iopub.status.busy":"2023-03-31T16:54:10.671010Z","iopub.execute_input":"2023-03-31T16:54:10.671420Z","iopub.status.idle":"2023-03-31T16:54:10.700444Z","shell.execute_reply.started":"2023-03-31T16:54:10.671376Z","shell.execute_reply":"2023-03-31T16:54:10.699197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"limits = {'0-4':(1,4), '5-12':(4,14),'13-22':(14,19)}\nbest_threshold = 0.625\n\nhistorical_meta = defaultdict(list)\n\nfor (test, sample_submission) in iter_test:\n    \n    grp = test.level_group.values[0]\n    session_id = test.session_id.values[0]\n    \n    df = feature_engineer(test, grp)\n    \n    a,b = limits[grp]\n    for t in range(a,b):\n        FEATURES = importance_dict[str(t)]\n        \n        clf = QUESTION_MODELS[t-1]\n        p = clf.predict_proba(df[FEATURES].astype('float32'))[0,1]\n        mask = sample_submission.session_id.str.contains(f'q{t}')\n        sample_submission.loc[mask,'correct'] = int(p.item()>best_threshold)\n    \n    env.predict(sample_submission)","metadata":{"execution":{"iopub.status.busy":"2023-03-31T16:54:10.702002Z","iopub.execute_input":"2023-03-31T16:54:10.702376Z","iopub.status.idle":"2023-03-31T16:54:11.486838Z","shell.execute_reply.started":"2023-03-31T16:54:10.702339Z","shell.execute_reply":"2023-03-31T16:54:11.485832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## EDA submission.csv","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/working/submission.csv')\nprint(df.shape)\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-03-31T16:54:11.488077Z","iopub.execute_input":"2023-03-31T16:54:11.488421Z","iopub.status.idle":"2023-03-31T16:54:11.519688Z","shell.execute_reply.started":"2023-03-31T16:54:11.488389Z","shell.execute_reply":"2023-03-31T16:54:11.518113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(df.correct.mean())","metadata":{"execution":{"iopub.status.busy":"2023-03-31T16:54:11.520990Z","iopub.execute_input":"2023-03-31T16:54:11.521605Z","iopub.status.idle":"2023-03-31T16:54:11.528167Z","shell.execute_reply.started":"2023-03-31T16:54:11.521567Z","shell.execute_reply":"2023-03-31T16:54:11.527186Z"},"trusted":true},"execution_count":null,"outputs":[]}]}