{"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 pandas as pd\nimport numpy as np\n\nimport gc\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2023-06-22T20:18:28.261504Z","iopub.execute_input":"2023-06-22T20:18:28.262199Z","iopub.status.idle":"2023-06-22T20:18:28.267903Z","shell.execute_reply.started":"2023-06-22T20:18:28.262169Z","shell.execute_reply":"2023-06-22T20:18:28.265565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Credits to [this notebook](https://www.kaggle.com/code/kimtaehun/lightgbm-baseline-with-aggregated-log-data/notebook) for the engineering part\n\nCredits to [this notebook](https://www.kaggle.com/code/cdeotte/xgboost-baseline-0-680) for the memory optimization part","metadata":{}},{"cell_type":"code","source":"CATS = ['event_name', 'fqid', 'room_fqid', 'text']\nNUMS = ['elapsed_time','level','page','room_coor_x', 'room_coor_y', \n        'screen_coor_x', 'screen_coor_y', 'hover_duration']\n\n# https://www.kaggle.com/code/kimtaehun/lightgbm-baseline-with-aggregated-log-data\nEVENTS = ['navigate_click','person_click','cutscene_click','object_click',\n          'map_hover','notification_click','map_click','observation_click',\n          'checkpoint']","metadata":{"execution":{"iopub.status.busy":"2023-06-22T20:18:28.269853Z","iopub.execute_input":"2023-06-22T20:18:28.270397Z","iopub.status.idle":"2023-06-22T20:18:28.280883Z","shell.execute_reply.started":"2023-06-22T20:18:28.270370Z","shell.execute_reply":"2023-06-22T20:18:28.279610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def feature_engineer(train):\n    \n    dfs = []\n    for c in CATS:\n        tmp = train.groupby(['session_id','level_group'])[c].agg('nunique')\n        tmp.name = tmp.name + '_nunique'\n        dfs.append(tmp)\n    for c in NUMS:\n        tmp = train.groupby(['session_id','level_group'])[c].agg('mean')\n        tmp.name = tmp.name + '_mean'\n        dfs.append(tmp)\n    for c in NUMS:\n        tmp = train.groupby(['session_id','level_group'])[c].agg('std')\n        tmp.name = tmp.name + '_std'\n        dfs.append(tmp)\n    for c in EVENTS: \n        train[c] = (train.event_name == c).astype('int8')\n    for c in EVENTS + ['elapsed_time']:\n        tmp = train.groupby(['session_id','level_group'])[c].agg('sum')\n        tmp.name = tmp.name + '_sum'\n        dfs.append(tmp)\n    train = train.drop(EVENTS,axis=1)\n        \n    df = pd.concat(dfs,axis=1)\n    df = df.fillna(-1)\n    df = df.reset_index()\n    df = df.set_index('session_id')\n    return df","metadata":{"execution":{"iopub.status.busy":"2023-06-22T20:18:28.282625Z","iopub.execute_input":"2023-06-22T20:18:28.282935Z","iopub.status.idle":"2023-06-22T20:18:28.292161Z","shell.execute_reply.started":"2023-06-22T20:18:28.282908Z","shell.execute_reply":"2023-06-22T20:18:28.290825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# READ USER ID ONLY\ntmp = pd.read_csv(\"/kaggle/input/predict-student-performance-from-game-play/train.csv\",usecols=[0])\ntmp = tmp.groupby('session_id').session_id.agg('count')\n\n# COMPUTE READS AND SKIPS\nPIECES = 10\nCHUNK = int( np.ceil(len(tmp)/PIECES) )\n\nreads = []\nskips = [0]\nfor k in range(PIECES):\n    a = k*CHUNK\n    b = (k+1)*CHUNK\n    if b>len(tmp): b=len(tmp)\n    r = tmp.iloc[a:b].sum()\n    reads.append(r)\n    skips.append(skips[-1]+r)\n    \nprint(f'To avoid memory error, we will read train in {PIECES} pieces of sizes:')\nprint(reads)","metadata":{"execution":{"iopub.status.busy":"2023-06-22T20:18:28.293459Z","iopub.execute_input":"2023-06-22T20:18:28.293701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\n# PROCESS TRAIN DATA IN PIECES\nall_pieces = []\nprint(f'Processing train as {PIECES} pieces to avoid memory error... ')\nfor k in range(PIECES):\n    print(k,', ',end='')\n    SKIPS = 0\n    if k>0: SKIPS = range(1,skips[k]+1)\n    train = pd.read_csv('/kaggle/input/predict-student-performance-from-game-play/train.csv',\n                        nrows=reads[k], skiprows=SKIPS)\n    df = feature_engineer(train)\n    all_pieces.append(df)\n    \n# CONCATENATE ALL PIECES\nprint('\\n')\ndel train; gc.collect()\ndf = pd.concat(all_pieces, axis=0)\nprint('Shape of all train data after feature engineering:', df.shape )\ndf.head()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"targets = pd.read_csv('/kaggle/input/predict-student-performance-from-game-play/train_labels.csv')\ntargets['session'] = targets.session_id.apply(lambda x: int(x.split('_')[0]) )\ntargets['q'] = targets.session_id.apply(lambda x: int(x.split('_')[-1][1:]) )\nprint( targets.shape )\ntargets.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"FEATURES = [c for c in df.columns if c != 'level_group']","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from matplotlib import pyplot as plt\n\nfrom sklearn import metrics, tree\nfrom sklearn.tree import DecisionTreeClassifier, plot_tree\nfrom sklearn.model_selection import train_test_split\n\n\nmodels = {}\n\nfor q in range(1, 18+1):\n    \n    if q <= 3: grp = '0-4'\n    elif q <= 13: grp = '5-12'\n    elif q <= 22: grp = '13-22'\n    \n    df_subset = df[df[\"level_group\"]==grp]\n    \n    X = df_subset[FEATURES]\n    y = targets.loc[targets.q==q]['correct']\n\n    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n        \n    model = DecisionTreeClassifier(max_depth=4)\n\n    model.fit(X_train, y_train)\n    \n    models[q] = model\n    \n    y_pred = model.predict(X_test)\n\n    accuracy = metrics.f1_score(y_test, y_pred)\n    print(f\"Question {q}: %.2f%%\" % (accuracy * 100.0))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(150,100))\n_ = tree.plot_tree(models[1], \n                   feature_names=X_train.columns,  \n                   class_names=['0', '1'],\n                   filled=True,\n                   #max_depth=2\n                  )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import jo_wilder_310\nenv = jo_wilder_310.make_env()\niter_test = env.iter_test()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for (test, sample_submission) in iter_test:\n    test = test.sort_values(by = 'index')\n    sample_submission['q'] = sample_submission.session_id.apply(lambda x: x.split(\"_q\")[1]).astype(int)\n    sample_submission = sample_submission.sort_values(by = 'q')\n    sample_submission.drop('q',axis=1,inplace=True)\n    \n    X_clean = feature_engineer(test)\n    \n    num_models = sample_submission.session_id.apply(lambda x: int(x.split('_q')[1])).to_list()\n        \n    \n    for i, num_model in enumerate(num_models):\n        sample_submission['correct'][i] = models[num_model].predict(X_clean[FEATURES])\n    \n    env.predict(sample_submission)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"! head submission.csv","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}