{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport gc\n# neural nets\nimport tensorflow as tf\nimport tensorflow.keras.models as M\nimport tensorflow.keras.layers as L\n# riiid\nimport riiideducation\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Garbage collect \n### Just run me every now and then to avoid overuse of resources!! "},{"metadata":{"trusted":true},"cell_type":"code","source":"gc.collect()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Globals"},{"metadata":{"trusted":true},"cell_type":"code","source":"INPUT_DIR = '/kaggle/input/riiid-test-answer-prediction/'\nTRAIN_FILE = os.path.join(INPUT_DIR,'train.csv')\nTEST_FILE = os.path.join(INPUT_DIR,'test.csv')\nQUES_FILE = os.path.join(INPUT_DIR,'questions.csv')\nLEC_FILE = os.path.join(INPUT_DIR,'lectures.csv')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Read Dataset"},{"metadata":{},"cell_type":"markdown","source":"## Training Set"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"tr = pd.read_csv(TRAIN_FILE,\n                   usecols=[1, 2, 3, 4, 7, 8, 9],\n                   dtype={'timestamp': 'int64',\n                          'user_id': 'int32',\n                          'content_id': 'int16',\n                          'content_type_id': 'int8',\n                          'answered_correctly':'int8',\n                          'prior_question_elapsed_time': 'float32',\n                          'prior_question_had_explanation': 'boolean'}\n                   )\n\ntr.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Convert to Pickle"},{"metadata":{"trusted":true},"cell_type":"code","source":"def ds_to_pickle(ds, ds_file, pkl_file):\n    ds.to_pickle(pkl_file)\n    print(\"Saving to pkl file to save some space and time, take a look at some stats:\")\n    print(\"train.csv:\", os.stat(ds_file).st_size * 1e-6)\n    print(\"train.pkl:\", os.stat(pkl_file).st_size * 1e-6)\n    del ds\n    return pd.read_pickle('tr.pkl')\n    \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tr = ds_to_pickle(tr, TRAIN_FILE, 'tr.pkl')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tr.info()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# EDA"},{"metadata":{},"cell_type":"markdown","source":"## Num Users"},{"metadata":{"trusted":true},"cell_type":"code","source":"total_num_users = tr.user_id.unique().size\nunique_user_ids = list(tr.user_id.unique())\nprint('Total num users:', total_num_users)\nprint('Sneak peek of the list of all unique user ids... \\\n        \\nMin:', min(unique_user_ids), '\\nMax:', max(unique_user_ids),\n        '\\nFirst 10 user IDs:', unique_user_ids[:10])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Total number of Questions"},{"metadata":{"trusted":true},"cell_type":"code","source":"total_num_ques = tr.loc[tr.content_type_id==0].content_id.unique().size\nunique_ques = list(tr.loc[tr.content_type_id==0].content_id.unique())\nprint('Total num ques:',total_num_ques)\nprint('Sneak peek of unique ques:', '\\nMin:',min(unique_ques), '\\nMax:',max(unique_ques),\\\n       '\\nFirst 10 Ques:',unique_ques[:10])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Reduce the Dataset by user_ids that answered very few questions"},{"metadata":{},"cell_type":"markdown","source":"## How many questions did each user answer?"},{"metadata":{"trusted":true},"cell_type":"code","source":"num_ques_per_user = pd.DataFrame({\"user_id\":list(tr.loc[tr.content_type_id==0].user_id.unique()), \\\n                                 \"num_ques_answered\":list(tr.loc[tr.content_type_id==0].user_id.value_counts())}, \n                                 )\nnum_ques_answered = num_ques_per_user.sort_values('num_ques_answered')['num_ques_answered'].\\\n                                                    to_frame(name='num_ques_answered')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(num_ques_answered.min(), num_ques_answered.max())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- We have number of questions answered by a user ranging from 1 to 17609\n  - take only user_id s that answered > 100 questions"},{"metadata":{},"cell_type":"markdown","source":"## Take off these Users from tr"},{"metadata":{"trusted":true},"cell_type":"code","source":"def remove_user_by_num_ques_ans(num_ques_ans_thresh=100, tr=None):\n    num_ques_ans_filtered = num_ques_answered.loc[num_ques_answered.num_ques_answered > num_ques_ans_thresh].\\\n                                            rename(columns=\\\n                                            {'num_ques_answered':'num_ques_answered_gt_'+str(num_ques_ans_thresh)})\n    num_ques_per_user_gt_thresh = num_ques_per_user.loc[num_ques_per_user.num_ques_answered > num_ques_ans_thresh].\\\n                                                rename(columns={'num_ques_answered':'num_ques_answered_gt'+str(num_ques_ans_thresh)})\n    new_tr = tr[tr['user_id'].isin(list(num_ques_per_user_gt_thresh['user_id']))]\n    print(new_tr)\n    return num_ques_per_user_gt_thresh, new_tr","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"num_ques_answered_gt_100, tr_user_ques_gt_100 = remove_user_by_num_ques_ans(100, tr=tr)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"new_num_rows = len(tr_user_ques_gt_100.index)\nold_num_rows = len(tr.index)\n\nprint('Old rows:', old_num_rows, '\\nNew rows:', new_num_rows, \\\n      '\\nReduced to:', new_num_rows*100/old_num_rows,'% of original dataset size')\nprint('That\\'s a 70% reduction, YAY!')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tr_user_ques_gt_100.to_pickle('tr_user_ans_gt_100_ques.pkl')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tr.info()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tr_user_ques_gt_100.info()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del tr","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tr = tr_user_ques_gt_100","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Pre-process Dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\npiv1 = tr.loc[tr.answered_correctly!=-1].groupby(\"content_id\")[\"answered_correctly\"].mean().reset_index()\npiv1.columns = [\"content_id\", \"content_emb\"]\n\npiv3 = tr.loc[tr.answered_correctly!=-1].groupby(\"user_id\")[\"answered_correctly\"].mean().reset_index()\npiv3.columns = [\"user_id\", \"user_emb\"]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TIME_MEAN = tr.prior_question_elapsed_time.median()\nTIME_MIN = tr.prior_question_elapsed_time.min()\nTIME_MAX = tr.prior_question_elapsed_time.max()\nprint(TIME_MEAN,TIME_MAX, TIME_MIN)\nmap_prior = {True:1, False:0}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def preprocess(df):\n#     print('before merging:\\n',df[:10])\n    df = df.merge(piv1, how=\"left\", on=\"content_id\")\n#     print('merged piv1:\\n',df[:10])\n    df[\"content_emb\"] = df[\"content_emb\"].fillna(0.5)\n    df = df.merge(piv3, how=\"left\", on=\"user_id\")\n    df[\"user_emb\"] = df[\"user_emb\"].fillna(0.5)\n    df[\"prior_question_elapsed_time\"] = df[\"prior_question_elapsed_time\"].fillna(TIME_MEAN)\n    df[\"duration\"] = (df[\"prior_question_elapsed_time\"] - TIME_MIN) / (TIME_MAX - TIME_MIN)\n    df[\"prior_answer\"] = df[\"prior_question_had_explanation\"].map(map_prior)\n    df[\"prior_answer\"] = df[\"prior_answer\"].fillna(0.5)\n    return df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\ntr_preprocessed = preprocess(tr)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"FE = [\"content_emb\",  \"user_emb\", \"duration\", \"prior_answer\"]\nTARGET = \"answered_correctly\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x = tr_preprocessed.loc[tr_preprocessed.answered_correctly!=-1, FE].values\ny = tr_preprocessed.loc[tr_preprocessed.answered_correctly!=-1, TARGET].values","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Build and Train a Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"# detect and init the TPU\ntpu = tf.distribute.cluster_resolver.TPUClusterResolver()\ntf.config.experimental_connect_to_cluster(tpu)\ntf.tpu.experimental.initialize_tpu_system(tpu)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# instantiate a distribution strategy\ntpu_strategy = tf.distribute.experimental.TPUStrategy(tpu)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# instantiating the model in the strategy scope creates the model on the TPU\nwith tpu_strategy.scope():\n    def make_ann(n_in):\n        inp = L.Input(shape=(n_in,), name=\"inp\")\n        d1 = L.Dense(100, activation=\"relu\", name=\"d1\")(inp)\n        d2 = L.Dense(100, activation=\"relu\", name=\"d2\")(d1)\n        preds = L.Dense(1, activation=\"sigmoid\", name=\"preds\")(d2)\n\n        model = M.Model(inp, preds, name=\"ANN\")\n        model.compile(loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"])\n        return model\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"net = make_ann(x.shape[1])\nprint(net.summary())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"net.fit(x, y, validation_split=0.2, batch_size=30_000, epochs=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"net.save('min_100_ques_50_epochs.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}