{"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":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport pickle\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#need to update train_#_content.csv","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load processed data","metadata":{}},{"cell_type":"code","source":"content_df=pd.read_csv('/kaggle/input/riiid-contents/content_new.csv')\ncontent_df=content_df[['content_id','part','type_of_encoding','tag_ids','content_accuracy']]\n#use for embedding layers\ncontent_ids = content_df.content_id.max() + 2\npart_ids = content_df.part.max() +1\ntypes = content_df.type_of_encoding.max() + 1\ntag_ids = content_df.tag_ids.max() + 1\ntask_container_ids = 10001","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# pd.read_csv('/kaggle/input/riiid-content`s/train_2_new(jjin).csv', nrows=10**6)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtype = {\n    'answered_correctly': 'int8',\n    'user_id': 'int32',\n    'content_id': 'int16',\n    'content_type_id': 'int8',\n#     'task_container_id': 'int16',\n    'prior_question_elapsed_time': 'float32',\n#     'prior_question_had_explanation': 'int8',\n    'part': 'int8',\n    'tag_ids': 'int16',\n#     'type_of_encoding': 'int8',\n    'content_accuracy': 'float16',\n}\n\n#Load Train data\ndf = pd.read_csv(\n    '/kaggle/input/riiid-contents/train_2_new(jjin).csv',\n    usecols=dtype.keys(),\n    dtype=dtype,\n    nrows=2*10**6\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = {uid: u.drop(columns='user_id') for uid, u in df.groupby('user_id')}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Load Train data\ndf2 = pd.read_csv(\n    '/kaggle/input/riiid-contents/train_1_new(jjin).csv',\n    usecols=dtype.keys(),\n    dtype=dtype,\n    nrows=2*10**5\n)\ndf2 = {uid: u.drop(columns='user_id') for uid, u in df2.groupby('user_id')}\n# df.update(df2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(df)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# #Load Train data\n# df2 = pd.read_csv(\n#     '/kaggle/input/riiid-contents/train_3_new(jjin).csv',\n#     usecols=dtype.keys(),\n#     dtype=dtype,\n# #     nrows=3*10**6\n# )\n# df2 = {uid: u.drop(columns='user_id') for uid, u in df2.groupby('user_id')}\n# print(len(df2))\n# df.update(df2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(df)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for k in df.keys():\n    v = df[k]\n    if len(v)>2000:\n        df[k]=df[k][:2000]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for k in df2.keys():\n    v = df2[k]\n    if len(v)>2000:\n        df2[k]=df2[k][:2000]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# just some stuff I ctrl C ctrl V from StackOverflow (with little changes)\n# [1,2,3,4] --- w = 2 --[[1,2], [2,3], [3,4]] but 2D to 3D\ndef rolling_window(a, w):\n    s0, s1 = a.strides\n    m, n = a.shape\n    return np.lib.stride_tricks.as_strided(\n        a, \n        shape=(m-w+1, w, n), \n        strides=(s0, s0, s1)\n    )\n\n\ndef make_time_series(x, windows_size):\n  x = np.pad(x, [[ windows_size-1, 0], [0, 0]], constant_values=0)\n  x = rolling_window(x, windows_size)\n  return x\n\n\ndef add_features_to_user(user):\n    # We add one to the column in order to have zeros as padding values\n    # Start Of Sentence (SOS) token will be 3. \n    user['answered_correctly'] = user['answered_correctly'].shift(fill_value=2)+1\n    return user","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RiidSequence(tf.keras.utils.Sequence):\n\n  def __init__(self, \n               users, \n               windows_size,\n               batch_size=64,\n               start=0,\n               end=None):\n    self.users = users # {'user_id': user_df, ...} Dictionary\n    self.windows_size = windows_size\n    # to convert indices to our keys\n    self.mapper = dict(zip(range(len(users)), users.keys()))\n    # start and end to easy generate training and validation\n    self.start = start\n    self.end = end if end else len(users)\n    # To know where the answered_correctly_column is\n    self.answered_correctly_index = list(self.user_example().columns).index('answered_correctly')\n    \n    ## user dict for feature \n#     self.user_history={}\n        \n  def __len__(self):\n    return self.end-self.start\n\n  # get df from dict and generate numpy\n  def __getitem__(self, idx):\n    uid = self.mapper[idx+self.start]\n    user = self.users[uid].copy()\n    y = user['answered_correctly'].to_numpy().copy()\n    x = add_features_to_user(user)\n    return make_time_series(x, self.windows_size), y\n\n  \n  def user_example(self):\n    \"\"\"Just to check what we have till' now.\"\"\"\n    uid = self.mapper[self.start]\n    return add_features_to_user(self.users[uid].copy())\n\n\n\n  # INFERENCE PART    \n  def get_user_for_inference(self, user_row):\n    \"\"\"Picks a new user row and concats it to previous interactions \n    if it was already stored.\n    \n    Maybe the biggest trick in the notebook is here. We reuse the user_id column to \n    insert the answered_correctly SOS token because we previously placed the column \n    there on purpose.\n    \n    After it, we roll that column and then crop it if it was bigger than the window\n    size, making the SOS token disapear if out of the sequence.\n    \n    If the sequence if shorter than the window size, then we pad it.\n    \"\"\"\n    \n    uid = user_row[self.answered_correctly_index]\n    \n    user_row[self.answered_correctly_index] = 2 # SOS token\n    user_row = user_row[np.newaxis, ...]\n    \n    if uid in self.users:\n      x = np.concatenate([self.users[uid], user_row])\n      # same as in training, we need to add one!!!\n      x[:, self.answered_correctly_index] = np.roll(x[:, self.answered_correctly_index], 1) + 1\n    else:\n      x = user_row\n     \n    if x.shape[0] < self.windows_size:\n      return np.pad(x, [[self.windows_size-x.shape[0], 0], [0, 0]])\n    elif x.shape[0] > self.windows_size:\n      return x[-self.windows_size:]\n    else:\n      return x\n\n  def update_user(self, uid, user):\n    \"\"\"Concat the new user's interactions to the old ones if already stored.\"\"\"\n    if uid in self.users:\n      self.users[uid] = \\\n        np.concatenate([self.users[uid], user])[-self.windows_size:]\n    else:\n      self.users[uid] = user","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"RiidSequence(df, 64).user_example().head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# x, y = RiidSequence(df, 4)[2]\n# x.shape, y.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# POSITION ENCODING\n\ndef get_angles(pos, i, d_model):\n  angle_rates = 1 / np.power(10000, (2 * (i//2)) / np.float32(d_model))\n  return pos * angle_rates\n\n\ndef positional_encoding(position, d_model):\n  angle_rads = get_angles(np.arange(position)[:, np.newaxis],\n                          np.arange(d_model)[np.newaxis, :],\n                          d_model)\n  angle_rads[:, 0::2] = np.sin(angle_rads[:, 0::2])\n  angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])\n\n  pos_encoding = angle_rads[np.newaxis, ...]\n\n  return tf.cast(pos_encoding, dtype=tf.float32)\n\n# NN THINGS\ndef scaled_dot_product_attention(q, k, v, mask):\n  matmul_qk = tf.matmul(q, k, transpose_b=True)\n  dk = tf.cast(tf.shape(k)[-1], tf.float32)\n  scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)\n  if mask is not None:\n    scaled_attention_logits += (mask * -1e9)  \n  attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)\n  output = tf.matmul(attention_weights, v)\n  return output, attention_weights\n\n    \nclass MultiHeadAttention(tf.keras.layers.Layer):\n  def __init__(self, d_model, num_heads):\n    super(MultiHeadAttention, self).__init__()\n    self.num_heads = num_heads\n    self.d_model = d_model\n    \n    assert d_model % self.num_heads == 0\n    \n    self.depth = d_model // self.num_heads\n    \n    self.wq = tf.keras.layers.Dense(d_model)\n    self.wk = tf.keras.layers.Dense(d_model)\n    self.wv = tf.keras.layers.Dense(d_model)\n    \n    self.dense = tf.keras.layers.Dense(d_model)\n\n  def split_heads(self, x, batch_size):\n    x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))\n    return tf.transpose(x, perm=[0, 2, 1, 3])\n\n  def call(self, v, k, q, mask):\n    batch_size = tf.shape(q)[0]\n    q = self.wq(q)\n    k = self.wk(k)\n    v = self.wv(v)\n\n    q = self.split_heads(q, batch_size)\n    k = self.split_heads(k, batch_size)\n    v = self.split_heads(v, batch_size)\n\n    scaled_attention, attention_weights = scaled_dot_product_attention(\n        q, k, v, mask)\n\n    scaled_attention = tf.transpose(scaled_attention, perm=[0, 2, 1, 3])\n\n    concat_attention = tf.reshape(scaled_attention, \n                                  (batch_size, -1, self.d_model))\n\n    output = self.dense(concat_attention)\n\n    return output, attention_weights\n\n\ndef point_wise_feed_forward_network(d_model, dff):\n  return tf.keras.Sequential([\n      tf.keras.layers.Dense(dff, activation='relu'),\n      tf.keras.layers.Dense(d_model)\n  ])\n\n\nclass EncoderLayer(tf.keras.layers.Layer):\n  def __init__(self, d_model, num_heads, dff, rate=0.1):\n    super(EncoderLayer, self).__init__()\n\n    self.mha = MultiHeadAttention(d_model, num_heads)\n    self.ffn = point_wise_feed_forward_network(d_model, dff)\n\n    self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)\n    self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)\n\n    self.dropout1 = tf.keras.layers.Dropout(rate)\n    self.dropout2 = tf.keras.layers.Dropout(rate)\n\n  def call(self, x, training, mask):\n\n    attn_output, _ = self.mha(x, x, x, mask) \n    attn_output = self.dropout1(attn_output, training=training)\n    out1 = self.layernorm1(x + attn_output) \n\n    ffn_output = self.ffn(out1)\n    ffn_output = self.dropout2(ffn_output, training=training)\n    out2 = self.layernorm2(out1 + ffn_output) \n\n    return out2","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_padding_mask(seqs):\n  # We mask only those vectors of the sequence in which we have all zeroes \n  # (this is more scalable for some situations).\n  mask = tf.cast(tf.reduce_all(tf.math.equal(seqs, 0), axis=-1), tf.float32)\n  return mask[:, tf.newaxis, tf.newaxis, :]  # (batch_size, 1, 1, seq_len)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"columns = list(RiidSequence(df, 64).user_example().columns)\ncolumns","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[list(df.keys())[0]]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_series_model(\n        n_features,\n        content_ids,\n        task_container_ids,\n        part_ids,\n        windows_size=64,\n        d_model=24,\n        num_heads=4,\n        n_encoder_layers = 2\n    ):\n    # Input\n    inputs = tf.keras.Input(shape=(windows_size, n_features), name='inputs')\n    mask = create_padding_mask(inputs)\n    pos_enc = positional_encoding(windows_size, d_model)    \n    \n    # Divide branches\n    content_id = inputs[..., 0]\n#     content_type_id = inputs[..., 1] ## ADD\n#     task_container_id = inputs[..., 2]\n    answered_correctly = inputs[..., 1]\n    elapsed_time = inputs[..., 2]\n#     had_explanation = inputs[..., 5] ## ADD\n    part = inputs[..., 3]\n    tag_id = inputs[..., 4]\n#     type_of = inputs[..., 8]\n    acc = inputs[..., 5]\n    \n    acc = tf.expand_dims(acc, axis=-1, name=None)\n    elapsed_time = tf.expand_dims(elapsed_time, axis=-1, name=None)\n    \n     # Create embeddings\n    content_embeddings = tf.keras.layers.Embedding(content_ids, d_model)(content_id)\n#     content_type_embeddings = tf.keras.layers.Embedding(3, d_model)(content_type_id) ## ADD\n#     task_embeddings = tf.keras.layers.Embedding(task_container_ids, d_model)(task_container_id)\n    answered_correctly_embeddings = tf.keras.layers.Embedding(4, d_model)(answered_correctly)\n#     had_explanation_embeddings = tf.keras.layers.Embedding(3, d_model)(had_explanation) ## ADD\n    \n    tag_id_embeddings = tf.keras.layers.Embedding(tag_ids, d_model)(tag_id)\n#     type_of_embeddings = tf.keras.layers.Embedding(types, d_model)(type_of)\n    \n    # Continuous! Only a learnable layer for it.\n#     elapsed_time_embeddings = tf.keras.layers.Dense(d_model, use_bias=False)(elapsed_time)\n    part_embeddings = tf.keras.layers.Embedding(part_ids, d_model)(part)\n#     acc_embeddings = tf.keras.layers.Dense(d_model, use_bias=False)(acc)\n    \n    \n    # Add embeddings\n    x = tf.keras.layers.Add()([\n        pos_enc,\n        content_embeddings,\n#         content_type_embeddings, ## ADD\n#         task_embeddings,\n        answered_correctly_embeddings,\n#         had_explanation_embeddings, ## ADD\n#         elapsed_time_embeddings,\n        part_embeddings,\n        tag_id_embeddings,## ADD\n#         type_of_embeddings,## ADD\n#         acc_embeddings, ## ADD\n        \n    ])\n\n    for _ in range(n_encoder_layers):\n        x = EncoderLayer(d_model=d_model, num_heads=num_heads, dff=d_model*4, rate=0.1)(x, mask=mask)\n    \n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x)\n    acc1 = tf.keras.layers.GlobalAveragePooling1D()(acc)\n    et1 = tf.keras.layers.GlobalAveragePooling1D()(elapsed_time)\n    \n    x2 = tf.keras.layers.GlobalMaxPooling1D()(x)\n    acc2 = tf.keras.layers.GlobalMaxPool1D()(acc)\n    et1 = tf.keras.layers.GlobalMaxPool1D()(elapsed_time)\n    \n    \n    x1 = tf.concat([x1,acc1], axis=-1, name='concat')\n    x2 = tf.concat([x2,acc2], axis=-1, name='concat2')\n#     print(x.shape)\n    x1 = tf.keras.layers.Dropout(0.4)(x1)\n    x1 = tf.keras.layers.Dense(4, activation='relu')(x1)\n    \n    x2 = tf.keras.layers.Dropout(0.4)(x2)\n    x2 = tf.keras.layers.Dense(4, activation='relu')(x2)\n    \n    x = tf.concat([x1,x2], axis=-1)\n#     print(x.shape)\n    output = tf.keras.layers.Dense(1, activation='sigmoid', name='output')(x)\n    return tf.keras.Model(inputs, output, name='model')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_idx = int(len(df)*0.99)\nwindows_size = 64\nepochs = 5\npatience = 2\nd_model = 16\nnum_heads = 4\nn_encoder_layers = 2","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s_train = RiidSequence(df, windows_size, start=0, end=train_idx)\n# s_val = RiidSequence(df, windows_size, start=train_idx)\ns_val = RiidSequence(df2, windows_size)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s_train[0][0][0].shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_features = s_train[0][0].shape[-1]\n\ntf.keras.backend.clear_session()\nmodel = get_series_model(\n        n_features,\n        content_ids,\n        task_container_ids,\n        part_ids,\n        windows_size=windows_size,\n        d_model=d_model,\n        num_heads=num_heads,\n        n_encoder_layers=n_encoder_layers\n    )\n\noptimizer = tf.keras.optimizers.Adam(\n            learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-07,\n)\n\nmodel.compile(\n    optimizer= optimizer, \n    loss='binary_crossentropy', \n    metrics=[tf.keras.metrics.AUC(name='AUC'), tf.keras.metrics.BinaryAccuracy(name='acc')]\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# tf.keras.utils.plot_model(model)\nimport gc\ngc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.fit(\n    s_train,\n    validation_data=s_val,\n    epochs=epochs,\n#     workers=32,\n    shuffle=True,\n#     use_multiprocessing=True,\n    callbacks=tf.keras.callbacks.EarlyStopping(patience=patience, monitor='val_AUC', mode='max', restore_best_weights=True),\n    verbose=1\n)\nmodel.save_weights('model_2.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model.load_weights('/kaggle/input/weight/model_2.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prediction","metadata":{}},{"cell_type":"code","source":"import gc\n# del s_val\n# del s_train\ngc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"content_df.columns","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"columns","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# answered_correctly  --> user_id\ncolumns[columns.index('answered_correctly')] = 'user_id'\ncolumns = ['content_id'] + [c for c in columns if c not in content_df.columns] + ['row_id'] \ncolumns","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import riiideducation\n\nenv = riiideducation.make_env()\niter_test = env.iter_test()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#prepare for processing test data\nwith open('/kaggle/input/riiid-contents/lecture_id.pickle', 'rb') as handle:\n    lecture_id = pickle.load(handle)\n\n\n# max_elaped = max(df['prior_question_elapsed_time'])\n# max_elaped = 30000    \n    \n# Function for testset preprocess\ndef preprocess_dataset(df, content_df, lecture_id):\n    \n    # dataset content_id switch\n    def change_lecture_id(x):\n        content_id, lecture = x[0], x[1]\n        if content_id in lecture_id and lecture==1:\n            return lecture_id[content_id]\n        else:\n            return content_id\n        \n    df = df.fillna(0)    \n    df.prior_question_had_explanation = df.prior_question_had_explanation.apply(int) \n    # lecture_id switch axis=1\n    df[['content_id']] = df[['content_id','content_type_id']].apply(change_lecture_id,axis=1)\n#     df.answered_correctly.replace({-1: 1}, inplace=True)\n    \n    #fill nan & normalize\n    df['prior_question_elapsed_time'] = df['prior_question_elapsed_time'].astype(np.float32)/max(df['prior_question_elapsed_time'])\n    \n    # dataset-content_id merge\n    df = pd.merge(df,content_df[['content_id', 'part', 'tag_ids', 'type_of_encoding']], on='content_id')\n    \n    return df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for test_, sample_prediction in iter_test:\n    \n    try:\n        prior_correct = eval(test['prior_group_answers_correct'].iloc[0]) #이전 그룹의 정답여부 \n        prior_correct = [a for a in prior_correct if a != -1] # -1 이 아닌경우만\n    except:\n        prior_correct = []\n    \n    # Add prior correct to test and update stored users\n    if prior_correct:\n        prior_test.insert(s_train.answered_correctly_index, 'answered_correctly', prior_correct)\n        for uid, user in prior_test.groupby('user_id'):\n            s_train.update_user(uid, user.drop(columns='user_id').to_numpy())    \n\n    test = test_.loc[\n        test_['content_type_id'] == 0,\n        columns\n    ]\n    \n    # Add global features\n    test = preprocess_dataset(test, content_df, lecture_id)\n\n    # Save test for later\n    prior_test = test.drop(columns='row_id').copy()\n\n    # Make x\n    x = np.apply_along_axis(\n        s_train.get_user_for_inference,\n        1,\n        test.drop(columns='row_id').to_numpy()\n    )\n    \n    # Predict\n    test['answered_correctly'] = model.predict(x, batch_size=x.shape[0])\n    env.predict(test.loc[test['content_type_id'] == 0, ['row_id', 'answered_correctly']])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.loc[test['content_type_id'] == 0, ['row_id', 'answered_correctly']]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_.columns","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"columns","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = test_.loc[\n    test_['content_type_id'] == 0,\n    columns\n]\ntest","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preprocess_dataset(test, content_df, lecture_id)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.drop(columns='row_id')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"    content_id = inputs[..., 0]\n    content_type_id = inputs[..., 1] ## ADD\n    task_container_id = inputs[..., 2]\n    answered_correctly = inputs[..., 3]\n    elapsed_time = inputs[..., 4]\n    had_explanation = inputs[..., 5] ## ADD\n    part = inputs[..., 6]\n    \n    tag_id = inputs[..., 7]\n    type_of = inputs[..., 8]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = test_[columns]\n\n# Add global features\ntest = preprocess_dataset(test, content_df, lecture_id)\n\n# Save test for later\nprior_test = test.drop(columns='row_id').copy()\n\n# Make x\nx = np.apply_along_axis(\n    s_train.get_user_for_inference,\n    1,\n    test.drop(columns=['row_id']).to_numpy()\n)\n\n# Predict\nprint(x.shape)\ntest['answered_correctly'] = model.predict(x, batch_size=x.shape[0])\nenv.predict(test.loc[test['content_type_id'] == 0, ['row_id', 'answered_correctly']])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result = test.loc[test['content_type_id'] == 0, ['row_id', 'answered_correctly']]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result['answered_correctly'] = (result['answered_correctly'] + result['answered_correctly']*1.4)/2\nresult","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}