Kaggle competition: Riiid Answer Correctness Prediction
<SOS> metric: AUC Kaggle data source: riiid-answer-correctness-prediction<import_modules>
import gc
import json
import pandas as pd
from pathlib import Path
import sqlite3
import riiideducation
import time
import xgboost as xgb
from keras.layers import Dense
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dropout
from keras.layers import Activation<load_from_csv>
env = riiideducation.make_env()
iter_test = env.iter_test()
train_df = pd.read_csv('/kaggle/input/digit-recognizer/train.csv')
 train_df.head()<load_from_csv>
PATH = Path('.. /input/riiid-submission' )
test_df = pd.read_csv('/kaggle/input/digit-recognizer/test.csv')
 test_df.head()<prepare_x_and_y>
model = xgb.Booster(model_file=PATH/'model.xgb')
 print('model loaded' )
columns = train_df.columns
X = train_df[columns[columns != 'label']]
y = train_df['label']<split>
dtypes = {
'answered_correctly': 'int8',
'answered_correctly_content_id_cumsum': 'int16',
'answered_correctly_content_id_cumsum_pct': 'int16',
'answered_correctly_cumsum': 'int16',
'answered_correctly_cumsum_pct': 'int8',
'answered_correctly_cumsum_upto': 'int8',
'answered_correctly_rollsum': 'int8',
'answered_correctly_rollsum_pct': 'int8',
'answered_incorrectly': 'int8',
'answered_incorrectly_content_id_cumsum': 'int16',
'answered_incorrectly_cumsum': 'int16',
'answered_incorrectly_rollsum': 'int8',
'bundle_id': 'uint16',
'content_id': 'int16',
'content_type_id': 'int8',
'correct_answer': 'uint8',
'lecture_id': 'uint16',
'lectures_cumcount': 'int16',
'part': 'uint8',
'part_correct_pct': 'uint8',
'prior_question_elapsed_time': 'float32',
'prior_question_elapsed_time_rollavg': 'float32',
'prior_question_had_explanation': 'bool',
'question_id': 'uint16',
'question_id_correct_pct': 'uint8',
'row_id': 'int64',
'tag': 'uint8',
'tag__0': 'uint8',
'tag__0_correct_pct': 'uint8',
'tags': 'str',
'task_container_id': 'int16',
'task_container_id_orig': 'int16',
'timestamp': 'int64',
'type_of': 'str',
'user_answer': 'int8',
'user_id': 'int32'
}
batch_cols_all = [
'user_id',
'content_id',
'row_id',
'task_container_id',
'timestamp',
'prior_question_elapsed_time',
'prior_question_had_explanation'
]
batch_cols_prior = [
'user_id',
'content_id',
'content_type_id'
]
with open(PATH/'columns.json')as cj:
test_cols = json.load(cj)
 batch_cols = ['user_id', 'content_id', 'row_id'] + [c for c in batch_cols_all if c in test_cols]
print('test_cols:')
 _ = list(map(print, test_cols))
dtypes_test = {k: v for k,v in dtypes.items() if k in test_cols}
dtypes_test = {**dtypes_test, **{'user_id': 'int32', 'content_id': 'int16'}}
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.1, random_state = 4 )<data_type_conversions>
df_users_content = pd.read_pickle(PATH/'df_users_content.pkl')
 df_users_content.head()
X_train = X_train.values.reshape(X_train.shape[0], 28, 28, 1 ).astype('float32')
 X_test = X_test.values.reshape(X_test.shape[0], 28, 28, 1 ).astype('float32' )<normalization>
df_users = df_users_content[['user_id', 'answered_correctly', 'answered_incorrectly']].groupby('user_id' ).sum().reset_index()
df_users = df_users.astype({'user_id': 'int32', 'answered_correctly': 'int16', 'answered_incorrectly': 'int16'})
 df_users.head()
X_train = X_train / 255
X_test = X_test / 255<categorify>
df_questions = pd.read_pickle(PATH/'df_questions.pkl')
 df_questions.head()
y_train = to_categorical(y_train)
 y_test = to_categorical(y_test)
 num_classes = y_test.shape[1]<choose_model_class>
%%time
chunk_size = 20000
total = len(df_users_content)
 n_chunks =(total // chunk_size + 1)
 i = 0
while i < n_chunks:
df_users_content.iloc[i * chunk_size:(i + 1)* chunk_size].to_sql('users_content', conn, method='multi', if_exists='append', index=False)
 i += 1
conn.execute('CREATE UNIQUE INDEX users_content_index ON users_content(user_id, content_id)')
 del df_users_content
gc.collect()
def convolutional_model() :
ADAMAX = optimizers.Adamax(lr = 0.002, beta_1 = 0.9, beta_2 = 0.999)
 model = Sequential()
model.add(Conv2D(32,(4, 4), activation = 'relu', input_shape =(28, 28, 1)))
 model.add(Conv2D(64,(3, 3), activation = 'relu'))
model.add(MaxPooling2D(pool_size =(2, 2), strides =(2, 2)))
 model.add(BatchNormalization(axis = -1))
model.add(Dropout(0.2))
model.add(Conv2D(128,(3, 3), activation = 'relu'))
model.add(MaxPooling2D(pool_size =(2, 2), strides =(2, 2)))
 model.add(BatchNormalization(axis = -1))
model.add(Dropout(0.2))
model.add(Conv2D(128,(2, 2), activation = 'relu'))
model.add(Conv2D(256,(2, 2), activation = 'relu'))
model.add(MaxPooling2D(pool_size =(2, 2), strides =(2, 2)))
 model.add(BatchNormalization(axis = -1))
model.add(Dropout(0.2))
model.add(Flatten())
 model.add(Dense(256, activation = 'relu'))
model.add(BatchNormalization())
 model.add(Dense(128, activation = 'relu'))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation = 'softmax'))
model.compile(optimizer = ADAMAX, loss = 'categorical_crossentropy', metrics = ['accuracy'])
 return model<define_variables>
%%time
pd.read_sql('SELECT * from users_content LIMIT 5', conn )
gen = ImageDataGenerator(rotation_range = 12, width_shift_range = 0.1, shear_range = 0.1,
height_shift_range = 0.1, zoom_range = 0.1, fill_mode = 'nearest', horizontal_flip = False,
vertical_flip = False, featurewise_center = False,
samplewise_center = False, featurewise_std_normalization = False,
samplewise_std_normalization = False)
 test_gen = ImageDataGenerator()
train_generator = gen.flow(X_train, y_train, batch_size = 32)
 test_generator = test_gen.flow(X_test, y_test, batch_size = 32 )<choose_model_class>
%%time
chunk_size = 20000
total = len(df_users)
 n_chunks =(total // chunk_size + 1)
 i = 0
while i < n_chunks:
df_users.iloc[i * chunk_size:(i + 1)* chunk_size].to_sql('users', conn, method='multi', if_exists='append', index=False)
 i += 1
_ = conn.execute('CREATE UNIQUE INDEX users_index ON users(user_id)')
 del df_users
gc.collect()
reduce_lr = ReduceLROnPlateau(monitor = 'val_accuracy', patience = 3, verbose = 1, factor = 0.4, min_lr = 0.00002,
mode = 'auto', cooldown = 0 )<train_model>
%%time
pd.read_sql('SELECT * from users LIMIT 5', conn )
model = convolutional_model()
epochs = 80
history = model.fit_generator(train_generator, steps_per_epoch = 40000//16, epochs = epochs,
validation_data = test_generator, validation_steps = 10000//8, verbose = 1,
callbacks=[reduce_lr])
 scores = model.evaluate(X_test, y_test, verbose = 0)
 print("Accuracy: {}
Error: {}".format(scores[1], 100-scores[1]*100))
plot_loss_accuracy(history )<predict_on_test>
%%time
q_cols = [
'question_id',
'part',
'tag__0',
'part_correct_pct',
'tag__0_correct_pct',
'question_id_correct_pct'
]
df_questions[q_cols].to_sql('questions', conn, method='multi', index=False)
 _ = conn.execute('CREATE UNIQUE INDEX question_id_index ON questions(question_id)')
 del df_questions
gc.collect()
test_data = test_df.values.reshape(test_df.shape[0], 28, 28, 1 ).astype('float32')
 test_data = test_data / 255
Y_pred = model.predict(test_data )<prepare_output>
%%time
pd.read_sql('SELECT * from questions LIMIT 5', conn )
Y_pred = np.argmax(Y_pred,axis = 1)
 Y_pred = pd.Series(Y_pred, name = "Label" )<create_dataframe>
db_size = pd.read_sql('SELECT page_count * page_size as size FROM pragma_page_count() , pragma_page_size() ', conn)['size'][0]
print(f'Total size of database is: {db_size/1e9:0.3f} GB' )
submission_df = pd.DataFrame({
"ImageId": pd.Series(range(1, len(Y_pred)+1)) ,
"Label": pd.Series(Y_pred)} )<save_to_csv>
def select_state(batch_cols, records):
return f
submission_df.to_csv('/kaggle/working/Submission.csv', index = False )<import_modules>
def update_state(df):
def get_select_params(r):
values_uc = f'({r.user_id}, {r.content_id}, {r.answered_correctly}, {1-r.answered_correctly})'
values_u = f'({r.user_id}, {r.answered_correctly}, {1-r.answered_correctly})'
return values_uc, values_u
values = df.apply(get_select_params, axis=1, result_type='expand')
 return f
<load_from_csv><EOS> 
%%time
df_batch_prior = None
counter = 0
for test_batch in iter_test:
counter += 1
if df_batch_prior is not None:
answers = eval(test_batch[0]['prior_group_answers_correct'].iloc[0])
 df_batch_prior['answered_correctly'] = answers
cursor.executescript(update_state(df_batch_prior[df_batch_prior.content_type_id == 0]))
if not counter % 100:
conn.commit()
df_batch_prior = test_batch[0][batch_cols_prior].astype({k: dtypes[k] for k in batch_cols_prior})
 df_batch = test_batch[0][test_batch[0].content_type_id == 0]
records = df_batch[batch_cols].fillna(0 ).to_records(index=False)
 df_batch = pd.read_sql(select_state(batch_cols, records), conn)
 predictions = model.predict(xgb.DMatrix(df_batch[test_cols]))
df_batch['answered_correctly'] = predictions
env.predict(df_batch[['row_id', 'answered_correctly']] )