{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":45533,"databundleVersionId":5748852,"sourceType":"competition"}],"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:43:53.160125Z","iopub.execute_input":"2024-12-06T02:43:53.160472Z","iopub.status.idle":"2024-12-06T02:43:54.569166Z","shell.execute_reply.started":"2024-12-06T02:43:53.160422Z","shell.execute_reply":"2024-12-06T02:43:54.566921Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Preprocess","metadata":{}},{"cell_type":"code","source":"dtypes = {\n    'elapsed_time': 'int32',\n    'event_name': 'category',\n    'name': 'category',\n    'level': 'uint8',\n    'room_coor_x': 'float32',\n    'room_coor_y': 'float32',\n    'screen_coor_x': 'float32',\n    'screen_coor_y': 'float32',\n    'hover_duration': '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\nchunk_size = 100000\nchunks = pd.read_csv(\n    '/kaggle/input/predict-student-performance-from-game-play/train.csv',\n    dtype=dtypes,\n    chunksize=chunk_size,\n)\n\nchunk_list = []\nfor chunk in chunks:\n    chunk_list.append(chunk)\n\n\ndataset_df = pd.concat(chunk_list, axis=0, ignore_index=True)\nprint(f\"Original dataset shape: {dataset_df.shape}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:43:54.570857Z","iopub.execute_input":"2024-12-06T02:43:54.571913Z","iopub.status.idle":"2024-12-06T02:46:43.103589Z","shell.execute_reply.started":"2024-12-06T02:43:54.571864Z","shell.execute_reply":"2024-12-06T02:46:43.102246Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\n\ndef feature_engineer(dataset_df, label_encoders):\n    # Drop unnecessary columns\n    cols_to_drop = ['index', 'page', 'hover_duration']\n    dataset_df = dataset_df.drop(columns=cols_to_drop, errors='ignore')  # Avoid KeyError if a column is missing\n    \n    # Group by session_id and level_groupF\n    grouped_df = dataset_df.groupby(['session_id', 'level_group'], observed=True)\n    \n    numerical_cols = ['room_coor_x', 'room_coor_y', 'screen_coor_x', 'screen_coor_y']\n    categorical_cols = ['event_name', 'name', 'fqid', 'room_fqid', 'text_fqid', 'fullscreen', 'hq', 'music']\n    \n    # Add a new column for word count in 'text'\n    dataset_df['word_count'] = dataset_df['text'].apply(lambda x: len(str(x).split()))\n    \n    # Update the list of numerical columns to include 'word_count'\n    numerical_cols.append('word_count')\n    \n    aggregated_df = grouped_df.agg(\n        {**{col: 'mean' for col in numerical_cols}, **{col: 'first' for col in categorical_cols}}\n    ).reset_index()\n    \n    # Label encode categorical columns\n    for col in categorical_cols:\n        if col in label_encoders:\n            # Use existing LabelEncoder\n            le = label_encoders[col]\n        else:\n            # Create a new LabelEncoder\n            le = LabelEncoder()\n            label_encoders[col] = le\n        \n        # Fit-transform if new, transform only if existing\n        aggregated_df[col] = le.fit_transform(aggregated_df[col].astype(str))\n    \n    return aggregated_df, label_encoders","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:46:43.105912Z","iopub.execute_input":"2024-12-06T02:46:43.106288Z","iopub.status.idle":"2024-12-06T02:46:44.385656Z","shell.execute_reply.started":"2024-12-06T02:46:43.106254Z","shell.execute_reply":"2024-12-06T02:46:44.383838Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_encoder = {}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:46:44.387134Z","iopub.execute_input":"2024-12-06T02:46:44.387752Z","iopub.status.idle":"2024-12-06T02:46:44.393347Z","shell.execute_reply.started":"2024-12-06T02:46:44.387712Z","shell.execute_reply":"2024-12-06T02:46:44.392350Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset_df, label_encoders = feature_engineer(dataset_df, label_encoder)\n\nprint(dataset_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:46:44.395871Z","iopub.execute_input":"2024-12-06T02:46:44.397288Z","iopub.status.idle":"2024-12-06T02:47:17.439546Z","shell.execute_reply.started":"2024-12-06T02:46:44.397236Z","shell.execute_reply":"2024-12-06T02:47:17.436222Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Split dataset based on level_group\ngroup_0_4 = dataset_df[dataset_df['level_group'] == '0-4']\ngroup_5_12 = dataset_df[dataset_df['level_group'] == '5-12']\ngroup_13_22 = dataset_df[dataset_df['level_group'] == '13-22']\n\n# Drop level_group column\n\ngroup_0_4 = group_0_4.drop(columns='level_group')\ngroup_5_12 = group_5_12.drop(columns='level_group')\ngroup_13_22 = group_13_22.drop(columns='level_group')\n\n# Display the shapes of the subsets\nprint(f\"Group 0-4 shape: {group_0_4.shape}\")\nprint(f\"Group 5-12 shape: {group_5_12.shape}\")\nprint(f\"Group 13-22 shape: {group_13_22.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:17.443280Z","iopub.execute_input":"2024-12-06T02:47:17.447704Z","iopub.status.idle":"2024-12-06T02:47:17.527163Z","shell.execute_reply.started":"2024-12-06T02:47:17.447588Z","shell.execute_reply":"2024-12-06T02:47:17.524806Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/predict-student-performance-from-game-play/train_labels.csv')\n\n# Filtering based on session_id\ntrain_label_0_4 = df[df['session_id'].str.endswith(('_q1', '_q2', '_q3'))]\ntrain_label_5_12 = df[df['session_id'].str.contains('_q[4-9]|_q1[0-3]')]\ntrain_label_13_22 = df[df['session_id'].str.contains('_q1[4-8]')]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:17.530655Z","iopub.execute_input":"2024-12-06T02:47:17.531093Z","iopub.status.idle":"2024-12-06T02:47:19.194512Z","shell.execute_reply.started":"2024-12-06T02:47:17.531057Z","shell.execute_reply":"2024-12-06T02:47:19.192167Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def transform_table(df):\n    df = df.copy()\n    df[['session_id', 'question']] = df['session_id'].str.split('_', expand=True)\n    \n    pivot_df = df.pivot(index='session_id', columns='question', values='correct')\n    \n    pivot_df.reset_index(inplace=True)\n    \n    pivot_df.columns.name = None\n    pivot_df = pivot_df.rename(columns={col: f'{col}' for col in pivot_df.columns if col != 'session_id'})\n    \n    return pivot_df\n\n# Transform the table\ngroup_0_4_label = transform_table(train_label_0_4)\ngroup_5_12_label = transform_table(train_label_5_12)\ngroup_13_22_label = transform_table(train_label_13_22)\n\nprint(group_0_4_label.shape)\nprint(group_5_12_label.shape)\nprint(group_13_22_label.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:19.210143Z","iopub.execute_input":"2024-12-06T02:47:19.212367Z","iopub.status.idle":"2024-12-06T02:47:21.446461Z","shell.execute_reply.started":"2024-12-06T02:47:19.212117Z","shell.execute_reply":"2024-12-06T02:47:21.443339Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Feature Extraction","metadata":{}},{"cell_type":"markdown","source":"# Model ","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.ensemble import RandomForestClassifier\nimport joblib","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:21.450748Z","iopub.execute_input":"2024-12-06T02:47:21.457122Z","iopub.status.idle":"2024-12-06T02:47:21.979022Z","shell.execute_reply.started":"2024-12-06T02:47:21.456943Z","shell.execute_reply":"2024-12-06T02:47:21.977306Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def merge_data_with_labels(features_df, label_df):\n    features_df['session_id'] = features_df['session_id'].astype(str)\n    label_df['session_id'] = label_df['session_id'].astype(str)\n    # Merge data and label on session_id\n    merged_df = pd.merge(features_df, label_df, on='session_id', how='inner')\n    return merged_df\n\n# Prepare the data by splitting features and labels\ndef prepare_data(merged_df, label_columns):\n    drop_cols = list(label_columns)\n    drop_cols.append('session_id')\n    \n    X = merged_df.drop(columns=drop_cols)\n    y = merged_df.iloc[:, -len(label_columns):]\n    return X, y","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:21.981816Z","iopub.execute_input":"2024-12-06T02:47:21.983113Z","iopub.status.idle":"2024-12-06T02:47:21.992529Z","shell.execute_reply.started":"2024-12-06T02:47:21.983066Z","shell.execute_reply":"2024-12-06T02:47:21.990774Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Model Training function for multiple labels\ndef train_models_for_multiple_labels(X, y):\n    models = {}\n    for label_column in y.columns:\n        # Split the data into training and testing sets (80% train, 20% test)\n        X_train, X_test, y_train, y_test = train_test_split(X, y[label_column], test_size=0.2, random_state=42)\n\n        # Train a RandomForest Classifier\n        model = RandomForestClassifier(n_estimators=100, random_state=42)\n        model.fit(X_train, y_train)\n\n        # Evaluate the model (Optional)\n        print(f\"Model accuracy for {label_column}: {model.score(X_test, y_test)}\")\n\n        # Save the model\n        models[label_column] = model\n    return models","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:21.994422Z","iopub.execute_input":"2024-12-06T02:47:21.995008Z","iopub.status.idle":"2024-12-06T02:47:22.019722Z","shell.execute_reply.started":"2024-12-06T02:47:21.994800Z","shell.execute_reply":"2024-12-06T02:47:22.017310Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_columns_0_4 = group_0_4_label.columns[1:]\nlabel_columns_5_12 = group_5_12_label.columns[1:]\nlabel_columns_13_22 = group_13_22_label.columns[1:] ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:22.022009Z","iopub.execute_input":"2024-12-06T02:47:22.022557Z","iopub.status.idle":"2024-12-06T02:47:22.036357Z","shell.execute_reply.started":"2024-12-06T02:47:22.022512Z","shell.execute_reply":"2024-12-06T02:47:22.034919Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_0_4 = merge_data_with_labels(group_0_4, group_0_4_label)\nX_0_4, y_0_4 = prepare_data(merged_0_4, label_columns_0_4)\nmodels_0_4 = train_models_for_multiple_labels(X_0_4, y_0_4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:22.038691Z","iopub.execute_input":"2024-12-06T02:47:22.039096Z","iopub.status.idle":"2024-12-06T02:47:36.355833Z","shell.execute_reply.started":"2024-12-06T02:47:22.039060Z","shell.execute_reply":"2024-12-06T02:47:36.354235Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_5_12 = merge_data_with_labels(group_5_12, group_5_12_label)\nX_5_12, y_5_12 = prepare_data(merged_5_12, label_columns_5_12)\nmodels_5_12 = train_models_for_multiple_labels(X_5_12, y_5_12)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:47:36.357671Z","iopub.execute_input":"2024-12-06T02:47:36.358043Z","iopub.status.idle":"2024-12-06T02:48:28.776049Z","shell.execute_reply.started":"2024-12-06T02:47:36.358009Z","shell.execute_reply":"2024-12-06T02:48:28.774785Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_13_22 = merge_data_with_labels(group_13_22, group_13_22_label)\nX_13_22, y_13_22 = prepare_data(merged_13_22, label_columns_13_22)\nmodels_13_22 = train_models_for_multiple_labels(X_13_22, y_13_22)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:48:28.777681Z","iopub.execute_input":"2024-12-06T02:48:28.778327Z","iopub.status.idle":"2024-12-06T02:48:54.718384Z","shell.execute_reply.started":"2024-12-06T02:48:28.778286Z","shell.execute_reply":"2024-12-06T02:48:54.716770Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Test","metadata":{}},{"cell_type":"code","source":"models = {**models_0_4, **models_5_12, **models_13_22}\nprint(models)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:48:54.720411Z","iopub.execute_input":"2024-12-06T02:48:54.720810Z","iopub.status.idle":"2024-12-06T02:48:54.733949Z","shell.execute_reply.started":"2024-12-06T02:48:54.720779Z","shell.execute_reply":"2024-12-06T02:48:54.733162Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import jo_wilder_310\nenv = jo_wilder_310.make_env()\niter_test = env.iter_test() ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:48:54.735565Z","iopub.execute_input":"2024-12-06T02:48:54.735870Z","iopub.status.idle":"2024-12-06T02:48:54.771082Z","shell.execute_reply.started":"2024-12-06T02:48:54.735839Z","shell.execute_reply":"2024-12-06T02:48:54.769849Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define level groups\nlevel_group_list = ['0-4', '5-12', '13-22']\n\n# Iterate over test data from the Kaggle environment\nfor test, sample_submission in iter_test:\n    # Step 1: Perform feature engineering on the test set\n    test_df, _ = feature_engineer(test, label_encoders)  # Assuming feature_engineer now returns a tuple, use the first element\n\n    # Placeholder for predictions\n    results = []\n\n    # Access the single row in the DataFrame (since it's a one-row dataset)\n    row = test_df.iloc[0]\n\n    # Determine question range based on level group\n    index_offset = 0\n    if row['level_group'] == level_group_list[0]:  # Group '0-4'\n        questions_range = range(1, 4)  # Questions q1 to q3\n    elif row['level_group'] == level_group_list[1]:  # Group '5-12'\n        questions_range = range(4, 14)  # Questions q4 to q13\n    else:  # Group '13-22'\n        questions_range = range(14, 19)  # Questions q14 to q18\n\n    # Get predictions for the current level group\n    for i in questions_range:\n        model_key = f'q{i}'\n        model = models[model_key]  # Assumes `models` dictionary exists\n\n        # Prepare test data for prediction (drop unused columns)\n        features = row.drop(['session_id', 'level_group']).to_frame().T\n        \n        # Get the probabilities for class 1 (positive class)\n        probabilities = model.predict_proba(features)[:, 1]  # Probabilities for class 1 (positive class)\n        \n        # Convert probabilities to binary predictions (0 or 1) with a threshold\n        binary_prediction = (probabilities >= 0.625).astype(int)\n        \n        # Create session_id and correct prediction pair\n        session_id = f\"{row['session_id']}_q{i}\"\n        correct = binary_prediction[0]  # Get the single binary prediction\n        \n        # Append the prediction to results list\n        results.append({'session_id': session_id, 'correct': correct})\n\n    # Convert list of dicts to DataFrame at once\n    results_df = pd.DataFrame(results)\n    print(results_df)\n    # Update the sample_submission with predictions\n    sample_submission.update(results_df)\n\n    # Submit the predictions\n    env.predict(sample_submission)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:48:54.772555Z","iopub.execute_input":"2024-12-06T02:48:54.772870Z","iopub.status.idle":"2024-12-06T02:48:55.395624Z","shell.execute_reply.started":"2024-12-06T02:48:54.772841Z","shell.execute_reply":"2024-12-06T02:48:55.394289Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sub = pd.read_csv('submission.csv')\nsub","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:48:55.398237Z","iopub.execute_input":"2024-12-06T02:48:55.398625Z","iopub.status.idle":"2024-12-06T02:48:55.418346Z","shell.execute_reply.started":"2024-12-06T02:48:55.398591Z","shell.execute_reply":"2024-12-06T02:48:55.417443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ncategory_counts = sub['correct'].value_counts()\n\ncategory_counts.plot(kind='bar', color='red')\nplt.title(\"Correct Counts\")\nplt.xlabel(\"correct\")\nplt.ylabel(\"Count\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T02:48:55.419633Z","iopub.execute_input":"2024-12-06T02:48:55.419955Z","iopub.status.idle":"2024-12-06T02:48:55.667895Z","shell.execute_reply.started":"2024-12-06T02:48:55.419923Z","shell.execute_reply":"2024-12-06T02:48:55.666878Z"}},"outputs":[],"execution_count":null}]}