Kaggle competition: Riiid Answer Correctness Prediction
<SOS> metric: AUC Kaggle data source: riiid-answer-correctness-prediction<count_missing_values>
import numpy as np
import pandas as pd
import lightgbm as lgb
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import roc_auc_score
from multiprocessing import cpu_count
from tqdm.notebook import tqdm
from memory_profiler import memory_usage
from cairosvg import svg2png
from PIL import Image
from io import BytesIO
from collections import deque
from glob import glob
from statistics import mean
import gc
import os
import sys
import re
import pickle
import math
data['LotFrontage'].isnull().sum()<categorify>
VERSION = 'V1G'
NUM_BOOST_ROUND = 5000
VERBOSE_EVAL = 10
METRICS = ['auc']
N_ROWS = 99271300
def get_index_np() :
return np.arange(N_ROWS )
features=['Electrical','KitchenQual','SaleType','Exterior2nd','Exterior1st','Alley','Fence', 'MiscFeature','FireplaceQu','GarageCond','GarageQual','GarageFinish','GarageType','BsmtCond','BsmtExposure','BsmtQual','BsmtFinType2','BsmtFinType1','MasVnrType']
for name in features:
data[name].fillna('Other',inplace=True )<count_missing_values>
def load_feature(feature, idxs=None, dtype=None):
file_path = f'/kaggle/input/riiid-answer-correctness-prediction-features-temp/FEATURES_{VERSION}/{feature}.npz'
if idxs is None and dtype is None:
return np.load(file_path, allow_pickle=True)['v']
elif idxs is not None and dtype is not None:
return np.load(file_path, allow_pickle=True)['v'][idxs].astype(dtype )
data[features].isnull().sum()<groupby>
for file_path in glob(f'/kaggle/input/riiid-answer-correctness-prediction-features-temp/FEATURES_{VERSION}/*.npz'):
print(re.findall('(?<=.\/ )([a-z_0-9]*)(.npz)', file_path)[0][0] )
data['MSZoning'] = data.groupby('MSSubClass')['MSZoning'].transform(lambda x: x.fillna(x.mode() [0])) 
<data_type_conversions>
given_features = [
'prior_question_elapsed_time',
'prior_question_had_explanation',
'bundle_id',
]
deduced_features = [
'mean_user_accuracy',
'mean_accuracy_diff',
'mean_user_content_accuracy',
'answered_correctly_user',
'answered_user',
'mean_user_accuracy_r10',
'mean_user_accuracy_r25',
'mean_user_accuracy_r100',
'mean_content_accuracy',
'content_id_pos_diff',
'content_count',
'part',
'mean_user_part_accuracy',
'answered_part_user',
'tag_1',
'tag_2',
'hmean_user_content_accuracy',
'last_interaction_elapsed_time_l1',
'last_interaction_elapsed_time_l2',
'last_interaction_elapsed_time_l3',
'attempt',
'lectures_seen',
'last_question_mean_acc_diff',
'user_part_answered_consecutive',
'mean_user_mean_content_acc_diff',
'last_correct_time_elapsed',
'last_incorrect_time_elapsed',
]
features = given_features + deduced_features
features_df_cols = [
'user_id', 'content_id', 'part', 'tags',
'tags_label', 'answered_user',
'answered_correctly_user', 'mean_user_accuracy', 'mean_content_accuracy',
]
target = 'answered_correctly'
categorical_feature = ['part', 'retry', 'prior_question_had_explanation', 'bundle_id', 'tag_1', 'tag_2']
categorical_feature_idxs = []
for v in categorical_feature:
try:
categorical_feature_idxs.append(features.index(v))
except:
pass
data['Functional']=data['Functional'].fillna('typ' )<categorify>
def get_train_val_idxs(TRAIN_SIZE, VAL_SIZE):
train_idxs = []
val_idxs = []
NEW_USER_FRAC = 1/4
np.random.seed(42)
 df = pd.DataFrame(index=get_index_np())
 for feature in ['user_id']:
df[feature] = load_feature(feature)
 df['index'] = df.index.values.astype(np.uint32)
 user_id_index = df.groupby('user_id')['index'].apply(np.array)
 for indices in user_id_index.sample(user_id_index.size, random_state=42):
if len(train_idxs)> TRAIN_SIZE:
break
if len(val_idxs)< VAL_SIZE:
if np.random.rand() < NEW_USER_FRAC:
val_idxs += list(indices)
 else:
offset = np.random.randint(0, indices.size)
 train_idxs += list(indices[:offset])
 val_idxs += list(indices[offset:])
 else:
train_idxs += list(indices)
 train_idxs = np.array(train_idxs, dtype=np.uint32)
 val_idxs = np.array(val_idxs, dtype=np.uint32)
 return train_idxs, val_idxs
train_idxs, val_idxs = get_train_val_idxs(int(96.5e6), 2.5e6)
 print(f'len train_idxs: {len(train_idxs)}, len validation_idxs: {len(val_idxs)}' )
zero=['GarageArea','GarageYrBlt','MasVnrArea','BsmtHalfBath','BsmtHalfBath','BsmtFullBath','BsmtFinSF1','BsmtFinSF2','BsmtUnfSF','TotalBsmtSF','GarageCars']
for name in zero:
data[name].fillna(0,inplace=True )<count_missing_values>
def make_x_y(train_idxs, val_idxs):
X_train = np.ndarray(shape=(len(train_idxs), len(features)) , dtype=np.float32)
 X_val = np.ndarray(shape=(len(val_idxs), len(features)) , dtype=np.float32)
 for idx, feature in enumerate(tqdm(features)) :
X_train[:,idx] = load_feature(feature, train_idxs, np.float32)
 X_val[:,idx] = load_feature(feature, val_idxs, np.float32)
 y_train = load_feature(target, train_idxs, np.int8)
 y_val = load_feature(target, val_idxs, np.int8)
 return X_train, y_train, X_val, y_val
X_train, y_train, X_val, y_val = make_x_y(train_idxs, val_idxs )
data.isnull().sum().sum()<feature_engineering>
display(pd.DataFrame(X_train[:25], columns=features))
data.loc[data['MSSubClass']==60, 'MSSubClass']=0
data.loc[(data['MSSubClass']==20)|(data['MSSubClass']==120), 'MSSubClass']=1
data.loc[data['MSSubClass']==75, 'MSSubClass']=2
data.loc[(data['MSSubClass']==40)|(data['MSSubClass']==70)|(data['MSSubClass']==80), 'MSSubClass']=3
data.loc[(data['MSSubClass']==50)|(data['MSSubClass']==85)|(data['MSSubClass']==90)|(data['MSSubClass']==160)|(data['MSSubClass']==190), 'MSSubClass']=4
data.loc[(data['MSSubClass']==30)|(data['MSSubClass']==45)|(data['MSSubClass']==180), 'MSSubClass']=5
data.loc[(data['MSSubClass']==150), 'MSSubClass']=6<categorify>
train_data = lgb.Dataset(
 data = X_train,
label = y_train,
categorical_feature = None, 
)
 val_data = lgb.Dataset(
 data = X_val,
label = y_val,
categorical_feature = None,
)
def dummies(d):
dummies_df=pd.DataFrame()
object_features = d.select_dtypes(include='object' ).columns
for name in object_features:
dummies = pd.get_dummies(d[name], drop_first=False)
 dummies = dummies.add_prefix("{}_".format(name))
dummies_df=pd.concat([dummies_df,dummies],axis=1)
 return dummies_df<categorify>
del X_train, y_train, X_val, y_val, train_idxs, val_idxs
gc.collect()
dummies_data=dummies(data)
 dummies_data.shape<drop_column>
lgbm_params = {
'objective': 'binary',
'metric': METRICS,
'num_leaves': 200,
'learning_rate': 0.1,
}
data=data.drop(columns=object_features,axis=1)
 data.columns<concatenate>
%%time
def train() :
evals_result = {}
model = lgb.train(
 params = lgbm_params,
train_set = train_data,
valid_sets = [val_data],
num_boost_round = NUM_BOOST_ROUND,
verbose_eval = VERBOSE_EVAL,
evals_result = evals_result,
early_stopping_rounds = 10,
categorical_feature = categorical_feature_idxs,
feature_name = features, 
)
 model.save_model(f'model_{VERSION}_{NUM_BOOST_ROUND}.lgb')
 return model, evals_result
model, evals_result = train()
final_data=pd.concat([data,dummies_data],axis=1)
 final_data.shape<prepare_x_and_y>
def show_feature_importances(model, importance_type, max_num_features=10**10):
feature_importances = pd.DataFrame()
feature_importances['feature'] = features
feature_importances['value'] = pd.DataFrame(model.feature_importance(importance_type))
feature_importances = feature_importances.sort_values(by='value', ascending=False)
 feature_importances.to_csv(f'feature_importances_{importance_type}.csv')
 feature_importances = feature_importances[:max_num_features]
plt.figure(figsize=(18, 8))
plt.xlim([0, feature_importances.value.max() *1.1])
 plt.title(f'Feature {importance_type}', fontsize=18);
sns.barplot(data=feature_importances, x='value', y='feature', palette='rocket');
for idx, v in enumerate(feature_importances.value):
plt.text(v, idx, " {:.2e}".format(v))
show_feature_importances(model, 'gain')
 show_feature_importances(model, 'split' )
X=train_data
y=train.loc[:,'SalePrice']<import_modules>
del train_data, val_data
gc.collect()
from sklearn.linear_model import Ridge, RidgeCV, LassoCV, ElasticNet<train_on_grid>
def get_features_questions_df() :
features_questions_df = pd.DataFrame(index=get_index_np())
 cols = [
'content_id',
'part',
'tag_1',
'tag_2',
'content_count',
'mean_content_id_pos',
'bundle_id',
]
for feature in tqdm(cols):
features_questions_df[feature] = load_feature(feature)
 features_questions_df.drop_duplicates(subset='content_id', inplace=True)
 features_questions_df.sort_values('content_id', inplace=True)
 features_questions_df.reset_index(drop=True, inplace=True)
 return features_questions_df
features_questions_df = get_features_questions_df()
print(f'features_questions_df, rows: {features_questions_df.shape[0]}')
 display(features_questions_df.head() )
model_las_cv = LassoCV(alphas=(0.0001, 0.0005, 0.001, 0.01, 0.05, 0.1, 0.3, 1, 3, 5, 10))
model_las_cv.fit(X,y)
 las_cv_preds=model_las_cv.predict(test_data )<train_on_grid>
def get_state() :
features_df = pd.DataFrame(index=get_index_np())
 cols = [
'user_id', 'content_id', 'answered_correctly','lectures_seen',
'mean_user_accuracy', 'mean_content_accuracy',
'last_correct_time_elapsed', 'last_incorrect_time_elapsed', 'part', 'user_part_answered_consecutive',
'timestamp', 'last_interaction_elapsed_time_l1', 'last_interaction_elapsed_time_l2', 'last_interaction_elapsed_time_l3',
]
for f in tqdm(cols):
features_df[f] = load_feature(f)
 last_features = features_df.groupby('user_id')[[
'timestamp', 'lectures_seen', 'mean_content_accuracy', 'part', 'user_part_answered_consecutive',
'last_correct_time_elapsed', 'last_incorrect_time_elapsed',
'last_interaction_elapsed_time_l1', 'last_interaction_elapsed_time_l2', 'last_interaction_elapsed_time_l3',
]].last()
last_correct_features = features_df.groupby(['user_id', 'answered_correctly'])['timestamp'].last()
features_df.drop([
'timestamp', 'last_interaction_elapsed_time_l1', 'last_interaction_elapsed_time_l2', 'last_interaction_elapsed_time_l3',
'last_correct_time_elapsed', 'last_incorrect_time_elapsed', 'user_part_answered_consecutive',
], axis=1, inplace=True)
 features_df_grouped_by_user = features_df[['user_id', 'answered_correctly']].groupby('user_id')['answered_correctly']
mean_user_accuracy = features_df_grouped_by_user.mean().values.astype(np.float32)
 answered_correctly_user = features_df_grouped_by_user.sum().values.astype(np.uint16)
 answered_user = features_df_grouped_by_user.count().values.astype(np.uint16)
 last_questions_answered_100 = features_df.groupby('user_id')[['user_id', 'answered_correctly']].tail(100 ).groupby('user_id')['answered_correctly'].apply(np.array ).apply(np.flip)
 mean_content_accuracy_sum = features_df.groupby('user_id')['mean_content_accuracy'].sum().values
mean_accuracy_diff_sum =(features_df.groupby('user_id')['mean_user_accuracy'].sum() - features_df.groupby('user_id')['mean_content_accuracy'].sum() ).values
user_part_features = features_df.groupby(['user_id', 'part'])['answered_correctly'].agg(['count', 'sum'] ).reset_index().astype({'user_id': int, 'part': int})
 del features_df_grouped_by_user, features_df
gc.collect()
with open('/kaggle/input/riiid-answer-correctness-prediction-features/state.pkl', 'rb')as state_pickle_file:
state = pickle.load(state_pickle_file)
 for idx, user_id in tqdm(enumerate(state.keys()), total=len(state)) :
state[user_id]['mean_user_accuracy'] = mean_user_accuracy[idx]
state[user_id]['answered_correctly_user'] = answered_correctly_user[idx]
state[user_id]['answered_user'] = answered_user[idx]
state[user_id]['mean_content_accuracy_sum'] = mean_content_accuracy_sum[idx]
state[user_id]['mean_accuracy_diff_sum'] = mean_accuracy_diff_sum[idx]
state[user_id]['lectures_seen'] = last_features.loc[user_id, 'lectures_seen']
state[user_id]['timestamp'] = last_features.loc[user_id, 'timestamp']
state[user_id]['last_mean_content_accuracy'] = last_features.loc[user_id, 'mean_content_accuracy']
state[user_id]['last_part'] = last_features.loc[user_id, 'part']
state[user_id]['user_part_answered_consecutive'] = last_features.loc[user_id, 'user_part_answered_consecutive']
state[user_id]['last_correct_timestamp'] = last_correct_features.loc[user_id, True] if(user_id, True)in last_correct_features else np.nan
state[user_id]['last_incorrect_timestamp'] = last_correct_features.loc[user_id, False] if(user_id, False)in last_correct_features else np.nan
state[user_id]['last_interaction_elapsed_time_l1'] = last_features.loc[user_id, 'last_interaction_elapsed_time_l1']
state[user_id]['last_interaction_elapsed_time_l2'] = last_features.loc[user_id, 'last_interaction_elapsed_time_l2']
state[user_id]['last_interaction_elapsed_time_l3'] = last_features.loc[user_id, 'last_interaction_elapsed_time_l3']
state[user_id]['mean_user_accuracy_r10'] = deque(last_questions_answered_100[user_id][:10], maxlen=10)
 state[user_id]['mean_user_accuracy_r25'] = deque(last_questions_answered_100[user_id][:25], maxlen=25)
 state[user_id]['mean_user_accuracy_r100'] = deque(last_questions_answered_100[user_id], maxlen=100)
 for idx,(user_id, part, part_count, part_sum)in tqdm(user_part_features.iterrows() , total=user_part_features.index.size):
state[user_id][f'part_{part}_count'] = part_count
state[user_id][f'part_{part}_sum'] = part_sum
return state
state = get_state()
gc.collect()
model_ridge_cv = RidgeCV(alphas=(0.01, 0.05, 0.1, 0.3, 1, 3, 5, 10))
model_ridge_cv.fit(X, y)
 ridge_cv_preds=model_ridge_cv.predict(test_data )<train_model>
def get_new_user(row):
return {
'mean_user_accuracy': 0.680,
'answered_correctly_user': 0,
'answered_user': 0,
'user_content_attempts': dict() ,
'lectures_seen': 0,
'timestamp': row['timestamp'],
'last_mean_content_accuracy': 0,
'last_part': int(row['part']),
'user_part_answered_consecutive': 0,
'last_correct_timestamp': np.nan,
'last_incorrect_timestamp': np.nan,
'last_interaction_elapsed_time_l1': 0,
'last_interaction_elapsed_time_l2': 0,
'last_interaction_elapsed_time_l3': 0,
'mean_user_accuracy_r10': deque([], maxlen=10),
'mean_user_accuracy_r25': deque([], maxlen=25),
'mean_user_accuracy_r100': deque([], maxlen=100),
'mean_accuracy_diff_sum': 0,
'mean_content_accuracy_sum': 0,
}
def get_user_data_dict() :
return {
'mean_user_accuracy': [],
'answered_correctly_user': [],
'answered_user': [],
'lectures_seen': [],
'last_interaction_elapsed_time_l1': [],
'last_interaction_elapsed_time_l2': [],
'last_interaction_elapsed_time_l3': [],
'mean_user_accuracy_r10': [],
'mean_user_accuracy_r25': [],
'mean_user_accuracy_r100': [],
'mean_user_part_accuracy': [],
'answered_part_user': [],
'mean_accuracy_diff': [],
'mean_user_content_accuracy': [],
'last_question_mean_acc_diff': [],
'user_part_answered_consecutive': [],
'mean_user_mean_content_acc_diff': [],
'last_correct_time_elapsed': [],
'last_incorrect_time_elapsed': [],
}
model_ridge = Ridge(alpha=10, solver='auto')
 model_ridge.fit(X, y)
 ridge_preds=model_ridge.predict(test_data )<train_on_grid>
lectures = pd.read_csv('/kaggle/input/riiid-test-answer-prediction/lectures.csv', dtype={ 'tag': np.uint8 })[['lecture_id', 'tag']]
content_id2tag = pd.Series(lectures['tag'].values, index=lectures['lecture_id'].values)
 def get_user_data(state, test_df):
user_data = get_user_data_dict()
part_first_question_mean_accuracy_dict = {1: 0.75, 2: 0.60, 3: 0.49, 4: 0.41, 5: 0.52, 6: 0.51, 7: 0.47}
cols = ['user_id', 'content_id', 'content_type_id', 'timestamp', 'part', 'mean_content_accuracy']
for idx,(user_id, content_id, is_lecture, timestamp, part, mean_content_accuracy)in test_df[cols].iterrows() :
if is_lecture:
state[user_id]['lectures_seen'] += 1
for key in user_data.keys() :
user_data[key].append(0)
 else:
part = int(part)
 state[user_id]['last_interaction_elapsed_time_l3'] = state[user_id]['last_interaction_elapsed_time_l2']
state[user_id]['last_interaction_elapsed_time_l2'] = state[user_id]['last_interaction_elapsed_time_l1']
if timestamp != state[user_id]['timestamp']:
state[user_id]['last_interaction_elapsed_time_l1'] = timestamp - state[user_id]['timestamp']
state[user_id]['timestamp'] = timestamp
cols = [
'mean_user_accuracy', 'answered_correctly_user', 'answered_user', 'lectures_seen',
'last_interaction_elapsed_time_l1', 'last_interaction_elapsed_time_l2', 'last_interaction_elapsed_time_l3',
]
for feature in cols:
user_data[feature].append(state[user_id][feature])
 if state[user_id]['answered_user'] > 0:
user_data['mean_accuracy_diff'].append(state[user_id]['mean_accuracy_diff_sum'] / state[user_id]['answered_user'])
 user_data['mean_user_content_accuracy'].append(state[user_id]['mean_content_accuracy_sum'] / state[user_id]['answered_user'])
 user_data['mean_user_accuracy_r10'].append(np.array(state[user_id]['mean_user_accuracy_r10'] ).mean())
 user_data['mean_user_accuracy_r25'].append(np.array(state[user_id]['mean_user_accuracy_r25'] ).mean())
 user_data['mean_user_accuracy_r100'].append(np.array(state[user_id]['mean_user_accuracy_r100'] ).mean())
 else:
user_data['mean_accuracy_diff'].append(0)
 user_data['mean_user_content_accuracy'].append(0)
 user_data['mean_user_accuracy_r10'].append(0.68)
 user_data['mean_user_accuracy_r25'].append(0.68)
 user_data['mean_user_accuracy_r100'].append(0.68)
 if state[user_id]['last_mean_content_accuracy'] != 0:
user_data['last_question_mean_acc_diff'].append(mean_content_accuracy - state[user_id]['last_mean_content_accuracy'])
 else:
user_data['last_question_mean_acc_diff'].append(0)
 state[user_id]['last_mean_content_accuracy'] = mean_content_accuracy
if f'part_{part}_count' in state[user_id]:
if state[user_id][f'part_{part}_sum'] == 0:
user_data['mean_user_part_accuracy'].append(0)
 else:
user_data['mean_user_part_accuracy'].append(state[user_id][f'part_{part}_sum'] / state[user_id][f'part_{part}_count'])
 user_data['answered_part_user'].append(state[user_id][f'part_{part}_count'])
 else:
state[user_id][f'part_{part}_sum'] = 0
state[user_id][f'part_{part}_count'] = 0
user_data['mean_user_part_accuracy'].append(part_first_question_mean_accuracy_dict[part])
 user_data['answered_part_user'].append(0)
 if part == state[user_id]['last_part']:
state[user_id]['user_part_answered_consecutive'] += 1
else:
state[user_id]['last_part'] = part
state[user_id]['user_part_answered_consecutive'] = 0
user_data['user_part_answered_consecutive'].append(state[user_id]['user_part_answered_consecutive'])
 user_data['mean_user_mean_content_acc_diff'].append(mean_content_accuracy - state[user_id]['mean_user_accuracy'])
 user_data['last_correct_time_elapsed'].append(timestamp - state[user_id]['last_correct_timestamp'])
 user_data['last_incorrect_time_elapsed'].append(timestamp - state[user_id]['last_incorrect_timestamp'])
 return user_data
model_en = ElasticNet(random_state=1, alpha=0.00065, max_iter=3000)
 model_en.fit(X, y)
 en_preds=model_en.predict(test_data )<import_modules>
def add_new_users(test_df):
for idx, row in test_df.iterrows() :
if not row['user_id'] in state:
state[row['user_id']] = get_new_user(row )
import xgboost as xgb<choose_model_class>
def add_attempt_retry(test_df):
attempt = []
for user_id, content_id in test_df[['user_id', 'content_id']].itertuples(name=None, index=False):
if content_id in state[user_id]['user_content_attempts']:
state[user_id]['user_content_attempts'][content_id] += 1
else:
state[user_id]['user_content_attempts'][content_id] = 0
attempt.append(state[user_id]['user_content_attempts'][content_id])
 test_df['attempt'] = attempt
test_df['retry'] = test_df['attempt'] > 0
model_xgb = xgb.XGBRegressor(learning_rate=0.01,n_estimators=3460,
max_depth=3, min_child_weight=0,
gamma=0, subsample=0.7,
colsample_bytree=0.7,
objective='reg:linear', nthread=-1,
scale_pos_weight=1, seed=27,
reg_alpha=0.00006)
 model_xgb.fit(X, y)
 xgb_preds=model_xgb.predict(test_data )<import_modules>
with open('/kaggle/input/riiid-answer-correctness-prediction-features/mean_content_accuracy_cases_dict.pickle', 'rb')as f:
mean_content_accuracy_cases_dict = pickle.load(f)
 def add_mean_content_accuracy(test_df):
mean_content_accuracy = []
for key in test_df[['content_id', 'prior_question_had_explanation', 'retry']].itertuples(name=None, index=False):
if key in mean_content_accuracy_cases_dict:
mean_content_accuracy.append(mean_content_accuracy_cases_dict[key])
 else:
mean_content_accuracy.append(0)
 test_df['mean_content_accuracy'] = mean_content_accuracy
from sklearn.ensemble import GradientBoostingRegressor<choose_model_class>
for(content_id, prior_question_had_explanation, retry), mean_content_accuracy in mean_content_accuracy_cases_dict.items() :
if content_id == 6116:
print(f'content_id {content_id}, prior_question_had_explanation: {prior_question_had_explanation}, retry: {retry}, mean_content_accuracy: {mean_content_accuracy}' )
model_gbr = GradientBoostingRegressor(n_estimators=3000,
learning_rate=0.05,
max_depth=4,
max_features='sqrt',
min_samples_leaf=15,
min_samples_split=10,
loss='huber',
random_state =42)
 model_gbr.fit(X, y)
 gbr_preds=model_gbr.predict(test_data )<import_modules>
def update_user_data(state, prev_test_df):
for idx, row in prev_test_df.iterrows() :
if not row['content_type_id']:
answered_correctly = row['answered_correctly']
user_id = row['user_id']
part = int(row['part'])
 state[user_id]['answered_correctly_user'] += answered_correctly
state[user_id]['answered_user'] += 1
state[user_id]['mean_user_accuracy'] = state[user_id]['answered_correctly_user'] / state[user_id]['answered_user']
state[user_id]['mean_user_accuracy_r10'].appendleft(answered_correctly)
 state[user_id]['mean_user_accuracy_r25'].appendleft(answered_correctly)
 state[user_id]['mean_user_accuracy_r100'].appendleft(answered_correctly)
 state[user_id][f'part_{part}_sum'] += answered_correctly
state[user_id][f'part_{part}_count'] += 1
state[user_id]['mean_accuracy_diff_sum'] += row['mean_user_accuracy'] - row['mean_content_accuracy']
state[user_id]['mean_content_accuracy_sum'] += row['mean_content_accuracy']
if answered_correctly:
state[user_id]['last_correct_timestamp'] = row['timestamp']
else:
state[user_id]['last_incorrect_timestamp'] = row['timestamp']
from lightgbm import LGBMRegressor<choose_model_class>
env = riiideducation.make_env()
iter_test = env.iter_test()
model_lgbm = LGBMRegressor(objective='regression',
num_leaves=4,
learning_rate=0.01,
n_estimators=5000,
max_bin=200,
bagging_fraction=0.75,
bagging_freq=5,
bagging_seed=7,
feature_fraction=0.2,
feature_fraction_seed=7,
verbose=-1, 
)
 model_lgbm.fit(X, y)
 lgbm_preds=model_lgbm.predict(test_data )<define_variables>
pd.options.display.max_columns = 99
prev_test_df = None
for idx,(test_df, _)in tqdm(enumerate(iter_test)) :
if prev_test_df is not None:
prev_test_df['answered_correctly'] = eval(test_df['prior_group_answers_correct'].iloc[0])
 update_user_data(state, prev_test_df)
 if idx < 4:
display(test_df)
 display(prev_test_df)
 test_df['prior_question_had_explanation'] = test_df['prior_question_had_explanation'].fillna(value = False ).astype(bool)
 test_df['prior_question_elapsed_time'].fillna(23916, inplace=True)
 test_df = features_questions_df.merge(test_df, how='right', on='content_id')
 add_new_users(test_df)
 add_attempt_retry(test_df)
 add_mean_content_accuracy(test_df)
 user_data = get_user_data(state, test_df)
 for feature, values in user_data.items() :
test_df[feature] = values
test_df['hmean_user_content_accuracy'] = 2 *(
(test_df['mean_user_accuracy'] * test_df['mean_content_accuracy'])/ 
(test_df['mean_user_accuracy'] + test_df['mean_content_accuracy'])
)
 test_df['content_id_pos_diff'] =(test_df['answered_user'] - test_df['mean_content_id_pos'] ).values.astype(np.int16)
 test_df['answered_correctly'] = model.predict(test_df[features])
 env.predict(test_df.loc[test_df['content_type_id'] == 0, ['row_id', 'answered_correctly']])
 prev_test_df = test_df.copy()
<prepare_output><EOS> 
submission = pd.read_csv('./submission.csv' )