{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":45533,"databundleVersionId":5748852,"sourceType":"competition"},{"sourceId":5005978,"sourceType":"datasetVersion","datasetId":2902225},{"sourceId":5675701,"sourceType":"datasetVersion","datasetId":3244175},{"sourceId":7188996,"sourceType":"datasetVersion","datasetId":4154551}],"dockerImageVersionId":30407,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd, numpy as np\nfrom catboost import CatBoostClassifier\nfrom sklearn.model_selection import GridSearchCV\nimport pickle\nimport sys\nimport random\nimport time\n\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import xgboost as xgb\nfrom catboost import CatBoostRegressor\nimport numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import KFold\nfrom sklearn.metrics import mean_squared_error, accuracy_score, roc_auc_score, f1_score\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.patches as mpatches\nimport seaborn as sns\nimport optuna","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUM_TRIES = 100\nLOAD_MODELS = False\nMODEL_NAME = 'catboost'\nTHRESHOLD = 0.63","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def reduce_mem_usage(df):\n    start_mem = df.memory_usage().sum() / 1024**2\n    print(f'Memory usage of dataframe is {start_mem:.2f} MB')\n    for col in df.columns:\n        if df[col].dtype == 'object':\n            df[col] = df[col].astype('category')\n        elif df[col].dtype == 'int':\n            int_types = [np.int8, np.int16, np.int32, np.int64]\n            for int_type in int_types:\n                if df[col].min() >= np.iinfo(int_type).min and df[col].max() <= np.iinfo(int_type).max:\n                    df[col] = df[col].astype(int_type)\n                    break\n        elif df[col].dtype == 'float':\n            float_types = [np.float16, np.float32, np.float64]\n            for float_type in float_types:\n                if df[col].min() >= np.finfo(float_type).min and df[col].max() <= np.finfo(float_type).max:\n                    df[col] = df[col].astype(float_type)\n                    break\n    mem_usage = df.memory_usage().sum() / 1024**2 \n    print(f\"Memory usage became: {mem_usage:.2f} MB\")\n    return df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtypes = {\n    'session_id':'int', \n    'elapsed_time':np.int32,\n    'event_name':'category',\n    'name':'category',\n    'level':np.int32,\n    'page':'category',\n    'room_coor_x':np.float32,\n    'room_coor_y':np.float32,\n    'screen_coor_x':np.float32,\n    'screen_coor_y':np.float32,\n    'hover_duration':np.float32,\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","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Read data, reduce memory consumption","metadata":{}},{"cell_type":"code","source":"# %%time\n# train_full = pd.read_csv('/kaggle/input/predict-student-performance-from-game-play/train.csv', dtype=dtypes)\n# train_full = reduce_mem_usage(train_full)\n# train_full","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_full = pd.read_csv('/kaggle/input/predict-student-performance-from-game-play/test.csv', dtype=dtypes)\ntest_full = reduce_mem_usage(test_full)\ntest_full","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_full.describe()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_full.info()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# label_full = pd.read_csv('/kaggle/input/predict-student-performance-from-game-play/train_labels.csv')\n# label_full","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feature_df = pd.read_csv('/kaggle/input/featur/feature_sort.csv', dtype=dtypes)\nfeature_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"These features are used to categorized and arranged to be convenient in masking and create some new feature","metadata":{}},{"cell_type":"code","source":"feature_df.describe()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feature_df.info()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feature_df[0:1].to_dict()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feature_df[100:101].to_dict()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We split the data into each question for each session","metadata":{}},{"cell_type":"code","source":"feature_df[200:201].to_dict()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feature_df[1000:1001].to_dict()","metadata":{"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:]) )\ntargets","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Feature Engineer","metadata":{"papermill":{"duration":0.005196,"end_time":"2023-02-07T01:00:59.092865","exception":false,"start_time":"2023-02-07T01:00:59.087669","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"In general, we reduce the size of the data by aggregate all the feature into data, each row represent the feature of each session. We also seperate the data into segments according to the level","metadata":{}},{"cell_type":"markdown","source":"- Find the delta time between each record in each session\n- Fill na with zero since we use different function (first record will be nan)\n- Clip the delta time to make sure remove noise\n- Shift the data upward","metadata":{}},{"cell_type":"code","source":"def delt_time_def(df):\n    df.sort_values(by=['session_id', 'elapsed_time'], inplace=True)\n    df['d_time'] = df['elapsed_time'].diff(1)\n    df['d_time'].fillna(0, inplace=True)\n    df['delt_time'] = df['d_time'].clip(0, 103000)\n    df['delt_time_next'] = df['delt_time'].shift(-1)\n    return df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Add some column to the training data. Group by for each session id, then calculcate different quantiles of d_time feature of each events. Also calculate the mean, std of hover duration.\n- Further more, we split the session id into year, month, day ","metadata":{}},{"cell_type":"code","source":"def feature_engineer(train, kol_f):\n    global kol_col, kol_col_max\n    kol_col = 9\n    kol_col_max = 11 + kol_f * 2 # set the number of columns\n    col = [i for i in range(0, kol_col_max)]\n    new_train = pd.DataFrame(index=train['session_id'].unique(), columns=col, dtype=np.float16)  \n    new_train[10] = new_train.index # \"session_id\"    \n\n    new_train[0] = train.groupby(['session_id'])['d_time'].quantile(q=0.3)\n    new_train[1] = train.groupby(['session_id'])['d_time'].quantile(q=0.8)\n    new_train[2] = train.groupby(['session_id'])['d_time'].quantile(q=0.5)\n    new_train[3] = train.groupby(['session_id'])['d_time'].quantile(q=0.65)\n    \n    new_train[4] = train.groupby(['session_id'])['hover_duration'].agg('mean')\n    new_train[5] = train.groupby(['session_id'])['hover_duration'].agg('std')    \n    \n    new_train[6] = new_train[10].apply(lambda x: int(str(x)[:2])).astype(np.uint8) # \"year\"\n    new_train[7] = new_train[10].apply(lambda x: int(str(x)[2:4]) + 1).astype(np.uint8) # \"month\"\n    new_train[8] = new_train[10].apply(lambda x: int(str(x)[4:6])).astype(np.uint8) # \"day\"\n    new_train[9] = new_train[10].apply(lambda x: int(str(x)[6:8])).astype(np.uint8)\\\n                                + new_train[10].apply(lambda x: int(str(x)[8:10])).astype(np.uint8) / 60\n    \n    new_train[10] = 0\n    \n    new_train = new_train.fillna(-1)\n    \n    return new_train","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Add new feature, which are some statistics: sum, mean, count base on some available feature. Since we aggregate all the feature field into a line, we must masking the data to calculate the feature, for example, delt_time correctly\n- kol_col == 1: aggregate base on session id\n- kol_col == 0: directly calculate the statistics","metadata":{}},{"cell_type":"code","source":"def feature_next_t(row_f, new_train, train, gran_1, gran_2, i):\n    global kol_col\n    kol_col +=1\n    col1 = row_f['col1']\n    val1 = row_f['val1']\n    maska = (train[col1] == val1)\n    \n    if row_f['kol_col'] == 1:       \n        new_train[kol_col] = train[maska].groupby(['session_id'])['delt_time_next'].sum()\n        if gran_1:\n            kol_col +=1\n            new_train[kol_col] = train[maska].groupby(['session_id'])['delt_time'].mean()\n        if gran_2:\n            kol_col +=1\n            new_train[kol_col] = train[maska].groupby(['session_id'])['index'].count()  \n            \n    elif row_f['kol_col'] == 2: # masking different\n        col2 = row_f['col2']\n        val2 = row_f['val2']\n        maska = maska & (train[col2] == val2)        \n        new_train[kol_col] = train[maska].groupby(['session_id'])['delt_time_next'].sum()\n        if gran_1:\n            kol_col +=1\n            new_train[kol_col] = train[maska].groupby(['session_id'])['delt_time'].mean()\n        if gran_2:\n            kol_col +=1\n            new_train[kol_col] = train[maska].groupby(['session_id'])['index'].count()\n    return new_train\n\ndef feature_next_t_otvet(row_f, new_train, train, gran_1, gran_2, i):\n    global kol_col\n    kol_col +=1\n    col1 = row_f['col1']\n    val1 = row_f['val1']\n    maska = (train[col1] == val1)\n    \n    if row_f['kol_col'] == 1:      \n        new_train[kol_col] = train[maska]['delt_time_next'].sum()\n        if gran_1:\n            kol_col +=1\n            new_train[kol_col] = train[maska]['delt_time'].mean()\n        if gran_2:\n            kol_col +=1\n            new_train[kol_col] = train[maska]['index'].count() \n            \n    elif row_f['kol_col'] == 2: \n        col2 = row_f['col2']\n        val2 = row_f['val2']\n        maska = maska & (train[col2] == val2)        \n        new_train[kol_col] = train[maska]['delt_time_next'].sum()\n        if gran_1:\n            kol_col +=1\n            new_train[kol_col] = train[maska]['delt_time'].mean()\n        if gran_2:\n            kol_col +=1\n            new_train[kol_col] = train[maska]['index'].count()\n    return new_train\n\n\n\ndef feature_quest_otvet(new_train, train, quest, kol_f):\n    global kol_col\n    kol_col = 9\n    g1 = 0.7 \n    g2 = 0.3 \n\n    feature_q = feature_df[feature_df['quest'] == quest].copy()\n    feature_q.reset_index(drop=True, inplace=True)\n    \n    gran1 = round(kol_f * g1)\n    gran2 = round(kol_f * g2)    \n    for i in range(0, kol_f):         \n        row_f = feature_q.loc[i]\n        new_train = feature_next_t_otvet(row_f, new_train, train, i < gran1, i <  gran2, i) \n    col = [i for i in range(0,kol_col+1)]\n    return new_train[col]\n\n\ndef feature_engineer_new(new_train, train, feature_q, kol_f):\n    g1 = 0.7 \n    g2 = 0.3 \n    gran1 = round(kol_f * g1)\n    gran2 = round(kol_f * g2)    \n    for i in range(0, kol_f): \n        row_f = feature_q.loc[i]       \n        new_train = feature_next_t(row_f, new_train, train, i < gran1, i <  gran2, i)         \n    return new_train\n\n\n# interface\n\ndef feature_quest(new_train, train, quest, kol_f):\n    global kol_col\n    kol_col = 9\n    feature_q = feature_df[feature_df['quest'] == quest].copy()\n    feature_q.reset_index(drop=True, inplace=True)\n    new_train = feature_engineer_new(new_train, train, feature_q, kol_f)\n    col = [i for i in range(0,kol_col+1)]\n    return new_train[col]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = {}\nbest_threshold = 0.63","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list_kol_f = {\n    1:140,3:110,\n    4:110, 5:220, 6:120, 7:110, 8:110, 9:100, 10:120, 11:120,\n    14: 110, 15:160, 16:105, 17:140             \n}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Searching for Best Parameters","metadata":{}},{"cell_type":"markdown","source":"We use Optuna to choose the hyperparameters","metadata":{}},{"cell_type":"code","source":"def get_trial(trial):\n#     params_range = {\n#         'tree_method':'hist',  # this parameter means using the GPU when training our model to speedup the training process\n# #         'lambda': trial.suggest_float('lambda', 1e-3, 10.0, log=True),\n# #         'alpha': trial.suggest_float('alpha', 1e-3, 10.0, log=True),\n# #         'colsample_bytree': trial.suggest_float('colsample_bytree', 0.3, 1.0),\n# #         'subsample': trial.suggest_float('subsample', 0.4, 1.0),\n#         'learning_rate': trial.suggest_float('learning_rate', 1e-6, 1e-3, log=True),\n#         'n_estimators': trial.suggest_int('n_estimators', 10, 200),\n#         'max_depth': trial.suggest_int('max_depth', 5, 10),\n#         'random_state': trial.suggest_categorical('random_state', [42]),\n# #         'min_child_weight': trial.suggest_int('min_child_weight', 1, 300),\n# #         'early_stopping_rounds': 15,\n# #         'objective': 'binary:logistic',\n\n#     }\n    \n    params_range = {\n        'learning_rate': trial.suggest_float('learning_rate', 1e-4, 1e-1),\n        'depth': trial.suggest_int('depth', 1, 10),\n        'iterations': trial.suggest_int('iterations', 20, 500),\n        \n#         'l2_leaf_reg': trial.suggest_float('l2_leaf_reg', 1, 10),\n#         'bagging_temperature': trial.suggest_float('bagging_temperature', 0, 1),\n\n    }\n    return params_range #params_range_catboost # params_range_xgboost","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list_best_hyperparams = {}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load model for each session - also seperate by level to reduce the size","metadata":{}},{"cell_type":"code","source":"%%time\n\nif not LOAD_MODELS:\n    df0_4 = pd.read_csv('/kaggle/input/featur/train_0_4t.csv', dtype=dtypes) \n\n    print('leng', len(df0_4))\n\n    kol_lvl = (df0_4 .groupby(['session_id'])['level'].agg('nunique') < 5)\n    list_session = kol_lvl[kol_lvl].index\n    df0_4  = df0_4 [~df0_4 ['session_id'].isin(list_session)]\n    df0_4 = delt_time_def(df0_4)\n\n    quests_0_4 = [1, 3] \n    # list_kol_f = {1:140,3:110}\n\n    kol_quest = len(quests_0_4)\n    # ITERATE THRU QUESTIONS\n    for q in quests_0_4:\n        print('### quest ', q, end='')\n        new_train = feature_engineer(df0_4, list_kol_f[q])\n        train_x = feature_quest(new_train, df0_4, q, list_kol_f[q])\n        print (' ---- ', 'train_q.shape = ', train_x.shape)\n        \n\n        # TRAIN DATA\n        train_users = train_x.index.values\n        train_y = targets.loc[targets.q==q].set_index('session').loc[train_users]\n        \n#         train_x[train_x.columns] = train_x[train_x.columns].apply(pd.to_numeric, errors='coerce')\n#         train_x = train_x.fillna(train_x.median()) \n\n        def objective(trial, data=train_x.astype('float32'), target=train_y['correct'].astype('int')):\n\n            training_set, validation_set, training_label, validation_label = train_test_split(\n                data, \n                target, \n                test_size=0.2,\n                random_state=42\n            )\n            param = get_trial(trial)\n    #         model = xgb.XGBClassifier(**param)  \n            model = CatBoostClassifier(**param)\n\n            model.fit(\n                training_set,\n                training_label,\n                eval_set=[(validation_set, validation_label)],\n                verbose=20\n            )\n\n            preds = model.predict_proba(validation_set)[:, 1]\n            print(preds)\n            preds = np.array(preds > THRESHOLD).astype(int)\n\n            acc = accuracy_score(validation_label, preds)\n            roc_auc = roc_auc_score(validation_label, preds)\n            f1 = f1_score(validation_label, preds)\n            \n            print('accuracy', acc)\n            print('roc_auc', roc_auc)\n            print('f1_score', f1)\n            \n            return roc_auc\n\n        study = optuna.create_study(direction='maximize')\n        study.optimize(objective, n_trials=NUM_TRIES)\n\n\n        print('Number of finished trials:', len(study.trials))\n        print('Best trial:', study.best_trial.params)\n\n        list_best_hyperparams[f'{q}'] = study.best_trial.params\n\n    del df0_4","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list_best_hyperparams","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if not LOAD_MODELS:\n\n    df5_12 = pd.read_csv('/kaggle/input/featur/train_5_12t.csv', dtype=dtypes)\n    print('leng', len(df5_12))\n\n    kol_lvl = (df5_12.groupby(['session_id'])['level'].agg('nunique') < 8)\n    list_session = kol_lvl[kol_lvl].index\n    df5_12 = df5_12[~df5_12['session_id'].isin(list_session)]\n    df5_12 = delt_time_def(df5_12)\n    quests_5_12 = [4, 5, 6, 7, 8, 9, 10, 11] \n\n    # list_kol_f = {4:110, 5:220, 6:120, 7:110, 8:110, 9:100, 10:120, 11:120}\n\n    kol_quest = len(quests_5_12)\n    # ITERATE THRU QUESTIONS\n    for q in quests_5_12:\n        print('### quest ', q, end='')\n        new_train = feature_engineer(df5_12, list_kol_f[q])\n        train_x = feature_quest(new_train, df5_12, q, list_kol_f[q])\n        print (' ---- ', 'train_q.shape = ', train_x.shape)\n\n        # TRAIN DATA\n        train_users = train_x.index.values\n        train_y = targets.loc[targets.q==q].set_index('session').loc[train_users]\n\n#         train_x[train_x.columns] = train_x[train_x.columns].apply(pd.to_numeric, errors='coerce')\n#         train_x = train_x.fillna(train_x.median()) \n\n        CBC = CatBoostClassifier()\n\n        def objective(trial, data=train_x.astype('float32'), target=train_y['correct'].astype('int')):\n\n            training_set, validation_set, training_label, validation_label = train_test_split(\n                data, \n                target, \n                test_size=0.2,\n                random_state=42\n            )\n            param = get_trial(trial)\n            model = CatBoostClassifier(**param)\n\n            model.fit(\n                training_set,\n                training_label,\n                eval_set=[(validation_set, validation_label)],\n                verbose=20\n            )\n\n            preds = model.predict_proba(validation_set)[:, 1]\n            print(preds)\n            preds = np.array(preds > THRESHOLD).astype(int)\n\n            acc = accuracy_score(validation_label, preds)\n            roc_auc = roc_auc_score(validation_label, preds)\n            f1 = f1_score(validation_label, preds)\n            \n            print('accuracy', acc)\n            print('roc_auc', roc_auc)\n            print('f1_score', f1)\n            \n            return roc_auc\n\n        study = optuna.create_study(direction='maximize')\n        study.optimize(objective, n_trials=NUM_TRIES)\n\n\n        print('Number of finished trials:', len(study.trials))\n        print('Best trial:', study.best_trial.params)\n\n        list_best_hyperparams[f'{q}'] = study.best_trial.params\n\n\n    del df5_12","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if not LOAD_MODELS:\n    df13_22 = pd.read_csv('/kaggle/input/featur/train_13_22t.csv', dtype=dtypes) \n    print('leng', len(df13_22))\n\n    kol_lvl = (df13_22 .groupby(['session_id'])['level'].agg('nunique') < 10)\n    list_session = kol_lvl[kol_lvl].index\n    df13_22  = df13_22 [~df13_22 ['session_id'].isin(list_session)]\n    df13_22 = delt_time_def(df13_22)\n\n    quests_13_22 = [14, 15, 16, 17] \n    # list_kol_f = {14: 110, 15:160, 16:105, 17:140}\n\n    kol_quest = len(quests_13_22)\n    # ITERATE THRU QUESTIONS\n    for q in quests_13_22:\n        print('### quest ', q, end='')\n        new_train = feature_engineer(df13_22, list_kol_f[q])\n        train_x = feature_quest(new_train, df13_22, q, list_kol_f[q])\n        print (' ---- ', 'train_q.shape = ', train_x.shape)\n\n        # TRAIN DATA\n        train_users = train_x.index.values\n        train_y = targets.loc[targets.q==q].set_index('session').loc[train_users]\n\n#         train_x[train_x.columns] = train_x[train_x.columns].apply(pd.to_numeric, errors='coerce')\n#         train_x = train_x.fillna(train_x.median()) \n\n        CBC = CatBoostClassifier()\n\n        def objective(trial, data=train_x.astype('float32'), target=train_y['correct'].astype('int')):\n\n            training_set, validation_set, training_label, validation_label = train_test_split(\n                data, \n                target, \n                test_size=0.2,\n                random_state=42\n            )\n            param = get_trial(trial)\n            model = CatBoostClassifier(**param)\n\n            model.fit(\n                training_set,\n                training_label,\n                eval_set=[(validation_set, validation_label)],\n                verbose=20\n            )\n\n            preds = model.predict_proba(validation_set)[:, 1]\n            print(preds)\n            preds = np.array(preds > THRESHOLD).astype(int)\n\n            acc = accuracy_score(validation_label, preds)\n            roc_auc = roc_auc_score(validation_label, preds)\n            f1 = f1_score(validation_label, preds)\n            \n            print('accuracy', acc)\n            print('roc_auc', roc_auc)\n            print('f1_score', f1)\n            \n            return roc_auc\n\n        study = optuna.create_study(direction='maximize')\n        study.optimize(objective, n_trials=NUM_TRIES)\n\n\n        print('Number of finished trials:', len(study.trials))\n        print('Best trial:', study.best_trial.params)\n\n        list_best_hyperparams[f'{q}'] = study.best_trial.params\n\n\n    del df13_22","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create model with best parameters","metadata":{}},{"cell_type":"code","source":"list_best_hyperparams","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_model(old_train, quests, models, list_kol_f):\n    \n    kol_quest = len(quests)\n    # ITERATE THRU QUESTIONS\n    print(quests)\n    for q in quests:\n        print('### quest ', q, end='')\n        new_train = feature_engineer(old_train, list_kol_f[q])\n        train_x = feature_quest(new_train, old_train, q, list_kol_f[q])\n        print (' ---- ', 'train_q.shape = ', train_x.shape)\n           \n        # TRAIN DATA\n        train_users = train_x.index.values\n        train_y = targets.loc[targets.q==q].set_index('session').loc[train_users]\n\n        # TRAIN MODEL \n        if not LOAD_MODELS:\n            model = CatBoostClassifier(**list_best_hyperparams[f'{q}'])  \n            model.fit(train_x.astype('float32'), train_y['correct'], verbose=False)\n            model.save_model(f'{MODEL_NAME}_{q}')\n        else:\n            model = CatBoostClassifier()\n            model.load_model(f'/kaggle/input/gameplay-prediction/{MODEL_NAME}_{q}')\n\n        # SAVE MODEL, PREDICT VALID OOF\n        models[f'{q}'] = model\n\n    return models","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load models for each quests. We only use session that play a lot, which sastify some number of played level","metadata":{}},{"cell_type":"code","source":"models = {}\n\nlist_kol_f = {\n    1:140,3:110,\n    4:120, 5:220, 6:130, 7:110, 8:110, 9:100, 10:140, 11:120,\n    14: 160, 15:160, 16:130, 17:140             \n}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df0_4 = pd.read_csv('/kaggle/input/featur/train_0_4t.csv', dtype=dtypes) \nkol_lvl = (df0_4 .groupby(['session_id'])['level'].agg('nunique') < 5)\nlist_session = kol_lvl[kol_lvl].index\ndf0_4  = df0_4 [~df0_4 ['session_id'].isin(list_session)]\ndf0_4 = delt_time_def(df0_4)\n\nquests_0_4 = [1, 3] \n# list_kol_f = {1:140,3:110}\n\nmodels = create_model(df0_4, quests_0_4, models, list_kol_f)\ndel df0_4","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df5_12 = pd.read_csv('/kaggle/input/featur/train_5_12t.csv', dtype=dtypes)\nkol_lvl = (df5_12.groupby(['session_id'])['level'].agg('nunique') < 8)\nlist_session = kol_lvl[kol_lvl].index\ndf5_12 = df5_12[~df5_12['session_id'].isin(list_session)]\ndf5_12 = delt_time_def(df5_12)\nquests_5_12 = [4, 5, 6, 7, 8, 9, 10, 11] \n\n# list_kol_f = {4:110, 5:220, 6:120, 7:110, 8:110, 9:100, 10:120, 11:120}\n\nmodels = create_model(df5_12, quests_5_12, models, list_kol_f)\ndel df5_12","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df13_22 = pd.read_csv('/kaggle/input/featur/train_13_22t.csv', dtype=dtypes) \nkol_lvl = (df13_22 .groupby(['session_id'])['level'].agg('nunique') < 10)\nlist_session = kol_lvl[kol_lvl].index\ndf13_22  = df13_22 [~df13_22 ['session_id'].isin(list_session)]\ndf13_22 = delt_time_def(df13_22)\n\nquests_13_22 = [14, 15, 16, 17] \n# list_kol_f = {14: 110, 15:160, 16:105, 17:140}\n\nmodels = create_model(df13_22, quests_13_22, models, list_kol_f)\ndel df13_22 ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(models)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Infer Test Data**","metadata":{}},{"cell_type":"code","source":"import jo_wilder\n\ntry:\n    jo_wilder.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.make_env()\niter_test = env.iter_test()    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Split the data into segment, using suitable model to predict on the engineered feature","metadata":{}},{"cell_type":"code","source":"%%time\ng_end4 = 0\ng_end5 = 0\n\nlist_q = {'0-4':quests_0_4, '5-12':quests_5_12, '13-22':quests_13_22}\nfor (test, sam_sub) in iter_test:\n    sam_sub['question'] = [int(label.split('_')[1][1:]) for label in sam_sub['session_id']]    \n    grp = test.level_group.values[0]   \n    sam_sub['correct'] = 1\n    sam_sub.loc[sam_sub.question.isin([5, 8, 10, 13, 15]), 'correct'] = 0  \n    old_train = delt_time_def(test[test.level_group == grp])\n       \n    for q in list_q[grp]:\n        \n        start4 = time.time()\n        new_train = feature_engineer(old_train, list_kol_f[q])\n        new_train = feature_quest_otvet(new_train, old_train, q, list_kol_f[q])\n        \n        end4 = time.time() - start4\n        g_end4 += end4\n        \n        start5 = time.time()        \n        \n        clf = models[f'{q}']\n        p = clf.predict_proba(new_train.astype('float32'))[:,1]        \n        \n        end5 = time.time() - start5\n        g_end5 += end5\n             \n        \n        mask = sam_sub.question == q \n        x = int(p[0] > THRESHOLD)\n        sam_sub.loc[mask,'correct'] = x      \n        \n    convert_dict = {\n        'correct': int,\n    }\n    \n    sam_sub.fillna(1)        \n    sam_sub = sam_sub[['session_id', 'correct']].astype(convert_dict)\n    print(sam_sub)\n    env.predict(sam_sub)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA submission.csv","metadata":{"papermill":{"duration":0.011427,"end_time":"2023-02-07T01:02:45.502331","exception":false,"start_time":"2023-02-07T01:02:45.490904","status":"completed"},"tags":[]}},{"cell_type":"code","source":"df = pd.read_csv('submission.csv')\nprint(df.shape)\ndf.head(60)","metadata":{"papermill":{"duration":0.027432,"end_time":"2023-02-07T01:02:45.541022","exception":false,"start_time":"2023-02-07T01:02:45.51359","status":"completed"},"tags":[],"trusted":true},"execution_count":null,"outputs":[]}]}