{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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)\n\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        (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":{"iopub.status.busy":"2025-07-11T16:53:58.804529Z","iopub.execute_input":"2025-07-11T16:53:58.804798Z","iopub.status.idle":"2025-07-11T16:54:44.673535Z","shell.execute_reply.started":"2025-07-11T16:53:58.804778Z","shell.execute_reply":"2025-07-11T16:54:44.67274Z"}},"outputs":[],"execution_count":1},{"cell_type":"code","source":"pip install pdf2image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T16:54:44.674746Z","iopub.execute_input":"2025-07-11T16:54:44.675189Z","iopub.status.idle":"2025-07-11T16:54:49.67484Z","shell.execute_reply.started":"2025-07-11T16:54:44.675163Z","shell.execute_reply":"2025-07-11T16:54:49.674093Z"}},"outputs":[{"name":"stdout","text":"Requirement already satisfied: pdf2image in /usr/local/lib/python3.11/dist-packages (1.17.0)\nRequirement already satisfied: pillow in /usr/local/lib/python3.11/dist-packages (from pdf2image) (11.2.1)\nNote: you may need to restart the kernel to use updated packages.\n","output_type":"stream"}],"execution_count":2},{"cell_type":"code","source":"!pip install pyspark","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T16:54:49.675882Z","iopub.execute_input":"2025-07-11T16:54:49.676116Z","iopub.status.idle":"2025-07-11T16:54:52.660801Z","shell.execute_reply.started":"2025-07-11T16:54:49.67608Z","shell.execute_reply":"2025-07-11T16:54:52.660093Z"}},"outputs":[{"name":"stdout","text":"Requirement already satisfied: pyspark in /usr/local/lib/python3.11/dist-packages (3.5.1)\nRequirement already satisfied: py4j==0.10.9.7 in /usr/local/lib/python3.11/dist-packages (from pyspark) (0.10.9.7)\n","output_type":"stream"}],"execution_count":3},{"cell_type":"code","source":"from pyspark.sql import SparkSession\n\nspark = SparkSession.builder \\\n    .appName(\"EEG_EDA\") \\\n    .getOrCreate()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T16:54:52.66274Z","iopub.execute_input":"2025-07-11T16:54:52.663045Z","iopub.status.idle":"2025-07-11T16:55:01.179488Z","shell.execute_reply.started":"2025-07-11T16:54:52.663021Z","shell.execute_reply":"2025-07-11T16:55:01.178832Z"}},"outputs":[{"name":"stderr","text":"Setting default log level to \"WARN\".\nTo adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).\n25/07/11 16:54:58 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable\n","output_type":"stream"}],"execution_count":4},{"cell_type":"code","source":"spark","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T16:55:01.180535Z","iopub.execute_input":"2025-07-11T16:55:01.181165Z","iopub.status.idle":"2025-07-11T16:55:02.934411Z","shell.execute_reply.started":"2025-07-11T16:55:01.181129Z","shell.execute_reply":"2025-07-11T16:55:02.933708Z"}},"outputs":[{"execution_count":5,"output_type":"execute_result","data":{"text/plain":"<pyspark.sql.session.SparkSession at 0x7dcafb7590d0>","text/html":"\n            <div>\n                <p><b>SparkSession - in-memory</b></p>\n                \n        <div>\n            <p><b>SparkContext</b></p>\n\n            <p><a href=\"http://993e92f23488:4040\">Spark UI</a></p>\n\n            <dl>\n              <dt>Version</dt>\n                <dd><code>v3.5.1</code></dd>\n              <dt>Master</dt>\n                <dd><code>local[*]</code></dd>\n              <dt>AppName</dt>\n                <dd><code>EEG_EDA</code></dd>\n            </dl>\n        </div>\n        \n            </div>\n        "},"metadata":{}}],"execution_count":5},{"cell_type":"code","source":"import os\n\nbase_dir = \"/kaggle/input/hms-harmful-brain-activity-classification\"\ntrain_eeg_dir = os.path.join(base_dir, \"train_eegs\")\ntrain_spec_dir = os.path.join(base_dir, \"train_spectrograms\")\n\neeg_parquet_files = sorted([f for f in os.listdir(train_eeg_dir) if f.endswith(\".parquet\")])\nspec_parquet_files = sorted([f for f in os.listdir(train_spec_dir) if f.endswith(\".parquet\")])\n\nprint(\"Total EEG files:\", len(eeg_parquet_files))\nprint(\"Total Spectrogram files:\", len(spec_parquet_files))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T16:55:02.935314Z","iopub.execute_input":"2025-07-11T16:55:02.935704Z","iopub.status.idle":"2025-07-11T16:55:02.970323Z","shell.execute_reply.started":"2025-07-11T16:55:02.935675Z","shell.execute_reply":"2025-07-11T16:55:02.969652Z"}},"outputs":[{"name":"stdout","text":"Total EEG files: 17300\nTotal Spectrogram files: 11138\n","output_type":"stream"}],"execution_count":6},{"cell_type":"code","source":"# from pyspark.sql import SparkSession\nfrom pyspark.sql.functions import input_file_name, regexp_extract\n\n# spark = SparkSession.builder.getOrCreate()\n\n# 1. Load train.csv (labels)\ndf_labels = spark.read.option(\"header\", True).csv(\"/kaggle/input/hms-harmful-brain-activity-classification/train.csv\")\n\n# 2. Load ALL EEG files and extract eeg_id from filename\ndf_eeg = (\n    spark.read.parquet(\"/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/*.parquet\")\n    .withColumn(\"file_path\", input_file_name())\n    .withColumn(\"eeg_id\", regexp_extract(\"file_path\", r\"(\\d+)\\.parquet\", 1).cast(\"long\"))\n)\n\n# 3. Load ALL spectrogram files and extract spectrogram_id from filename\ndf_spec = (\n    spark.read.parquet(\"/kaggle/input/hms-harmful-brain-activity-classification/train_spectrograms/*.parquet\")\n    .withColumn(\"file_path\", input_file_name())\n    .withColumn(\"spectrogram_id\", regexp_extract(\"file_path\", r\"(\\d+)\\.parquet\", 1).cast(\"long\"))\n)\n\n# 4. Join all together on ids\ndf_joined = (\n    df_labels\n    .join(df_eeg, on=\"eeg_id\", how=\"left\")\n    .join(df_spec, on=\"spectrogram_id\", how=\"left\")\n)\n\ndf_joined.printSchema()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T16:55:02.971172Z","iopub.execute_input":"2025-07-11T16:55:02.97142Z","iopub.status.idle":"2025-07-11T16:56:26.416596Z","shell.execute_reply.started":"2025-07-11T16:55:02.971398Z","shell.execute_reply":"2025-07-11T16:56:26.415721Z"}},"outputs":[{"name":"stderr","text":"                                                                                \r","output_type":"stream"},{"name":"stdout","text":"root\n |-- spectrogram_id: string (nullable = true)\n |-- eeg_id: string (nullable = true)\n |-- eeg_sub_id: string (nullable = true)\n |-- eeg_label_offset_seconds: string (nullable = true)\n |-- spectrogram_sub_id: string (nullable = true)\n |-- spectrogram_label_offset_seconds: string (nullable = true)\n |-- label_id: string (nullable = true)\n |-- patient_id: string (nullable = true)\n |-- expert_consensus: string (nullable = true)\n |-- seizure_vote: string (nullable = true)\n |-- lpd_vote: string (nullable = true)\n |-- gpd_vote: string (nullable = true)\n |-- lrda_vote: string (nullable = true)\n |-- grda_vote: string (nullable = true)\n |-- other_vote: string (nullable = true)\n |-- Fp1: float (nullable = true)\n |-- F3: float (nullable = true)\n |-- C3: float (nullable = true)\n |-- P3: float (nullable = true)\n |-- F7: float (nullable = true)\n |-- T3: float (nullable = true)\n |-- T5: float (nullable = true)\n |-- O1: float (nullable = true)\n |-- Fz: float (nullable = true)\n |-- Cz: float (nullable = true)\n |-- Pz: float (nullable = true)\n |-- Fp2: float (nullable = true)\n |-- F4: float (nullable = true)\n |-- C4: float (nullable = true)\n |-- P4: float (nullable = true)\n |-- F8: float (nullable = true)\n |-- T4: float (nullable = true)\n |-- T6: float (nullable = true)\n |-- O2: float (nullable = true)\n |-- EKG: float (nullable = true)\n |-- file_path: string (nullable = true)\n |-- time: long (nullable = true)\n |-- LL_0.59: float (nullable = true)\n |-- LL_0.78: float (nullable = true)\n |-- LL_0.98: float (nullable = true)\n |-- LL_1.17: float (nullable = true)\n |-- LL_1.37: float (nullable = true)\n |-- LL_1.56: float (nullable = true)\n |-- LL_1.76: float (nullable = true)\n |-- LL_1.95: float (nullable = true)\n |-- LL_2.15: float (nullable = true)\n |-- LL_2.34: float (nullable = true)\n |-- LL_2.54: float (nullable = true)\n |-- LL_2.73: float (nullable = true)\n |-- LL_2.93: float (nullable = true)\n |-- LL_3.13: float (nullable = true)\n |-- LL_3.32: float (nullable = true)\n |-- LL_3.52: float (nullable = true)\n |-- LL_3.71: float (nullable = true)\n |-- LL_3.91: float (nullable = true)\n |-- LL_4.1: float (nullable = true)\n |-- LL_4.3: float (nullable = true)\n |-- LL_4.49: float (nullable = true)\n |-- LL_4.69: float (nullable = true)\n |-- LL_4.88: float (nullable = true)\n |-- LL_5.08: float (nullable = true)\n |-- LL_5.27: float (nullable = true)\n |-- LL_5.47: float (nullable = true)\n |-- LL_5.66: float (nullable = true)\n |-- LL_5.86: float (nullable = true)\n |-- LL_6.05: float (nullable = true)\n |-- LL_6.25: float (nullable = true)\n |-- LL_6.45: float (nullable = true)\n |-- LL_6.64: float (nullable = true)\n |-- LL_6.84: float (nullable = true)\n |-- LL_7.03: float (nullable = true)\n |-- LL_7.23: float (nullable = true)\n |-- LL_7.42: float (nullable = true)\n |-- LL_7.62: float (nullable = true)\n |-- LL_7.81: float (nullable = true)\n |-- LL_8.01: float (nullable = true)\n |-- LL_8.2: float (nullable = true)\n |-- LL_8.4: float (nullable = true)\n |-- LL_8.59: float (nullable = true)\n |-- LL_8.79: float (nullable = true)\n |-- LL_8.98: float (nullable = true)\n |-- LL_9.18: float (nullable = true)\n |-- LL_9.38: float (nullable = true)\n |-- LL_9.57: float (nullable = true)\n |-- LL_9.77: float (nullable = true)\n |-- LL_9.96: float (nullable = true)\n |-- LL_10.16: float (nullable = true)\n |-- LL_10.35: float (nullable = true)\n |-- LL_10.55: float (nullable = true)\n |-- LL_10.74: float (nullable = true)\n |-- LL_10.94: float (nullable = true)\n |-- LL_11.13: float (nullable = true)\n |-- LL_11.33: float (nullable = true)\n |-- LL_11.52: float (nullable = true)\n |-- LL_11.72: float (nullable = true)\n |-- LL_11.91: float (nullable = true)\n |-- LL_12.11: float (nullable = true)\n |-- LL_12.3: float (nullable = true)\n |-- LL_12.5: float (nullable = true)\n |-- LL_12.7: float (nullable = true)\n |-- LL_12.89: float (nullable = true)\n |-- LL_13.09: float (nullable = true)\n |-- LL_13.28: float (nullable = true)\n |-- LL_13.48: float (nullable = true)\n |-- LL_13.67: float (nullable = true)\n |-- LL_13.87: float (nullable = true)\n |-- LL_14.06: float (nullable = true)\n |-- LL_14.26: float (nullable = true)\n |-- LL_14.45: float (nullable = true)\n |-- LL_14.65: float (nullable = true)\n |-- LL_14.84: float (nullable = true)\n |-- LL_15.04: float (nullable = true)\n |-- LL_15.23: float (nullable = true)\n |-- LL_15.43: float (nullable = true)\n |-- LL_15.63: float (nullable = true)\n |-- LL_15.82: float (nullable = true)\n |-- LL_16.02: float (nullable = true)\n |-- LL_16.21: float (nullable = true)\n |-- LL_16.41: float (nullable = true)\n |-- LL_16.6: float (nullable = true)\n |-- LL_16.8: float (nullable = true)\n |-- LL_16.99: float (nullable = true)\n |-- LL_17.19: float (nullable = true)\n |-- LL_17.38: float (nullable = true)\n |-- LL_17.58: float (nullable = true)\n |-- LL_17.77: float (nullable = true)\n |-- LL_17.97: float (nullable = true)\n |-- LL_18.16: float (nullable = true)\n |-- LL_18.36: float (nullable = true)\n |-- LL_18.55: float (nullable = true)\n |-- LL_18.75: float (nullable = true)\n |-- LL_18.95: float (nullable = true)\n |-- LL_19.14: float (nullable = true)\n |-- LL_19.34: float (nullable = true)\n |-- LL_19.53: float (nullable = true)\n |-- LL_19.73: float (nullable = true)\n |-- LL_19.92: float (nullable = true)\n |-- RL_0.59: float (nullable = true)\n |-- RL_0.78: float (nullable = true)\n |-- RL_0.98: float (nullable = true)\n |-- RL_1.17: float (nullable = true)\n |-- RL_1.37: float (nullable = true)\n |-- RL_1.56: float (nullable = true)\n |-- RL_1.76: float (nullable = true)\n |-- RL_1.95: float (nullable = true)\n |-- RL_2.15: float (nullable = true)\n |-- RL_2.34: float (nullable = true)\n |-- RL_2.54: float (nullable = true)\n |-- RL_2.73: float (nullable = true)\n |-- RL_2.93: float (nullable = true)\n |-- RL_3.13: float (nullable = true)\n |-- RL_3.32: float (nullable = true)\n |-- RL_3.52: float (nullable = true)\n |-- RL_3.71: float (nullable = true)\n |-- RL_3.91: float (nullable = true)\n |-- RL_4.1: float (nullable = true)\n |-- RL_4.3: float (nullable = true)\n |-- RL_4.49: float (nullable = true)\n |-- RL_4.69: float (nullable = true)\n |-- RL_4.88: float (nullable = true)\n |-- RL_5.08: float (nullable = true)\n |-- RL_5.27: float (nullable = true)\n |-- RL_5.47: float (nullable = true)\n |-- RL_5.66: float (nullable = true)\n |-- RL_5.86: float (nullable = true)\n |-- RL_6.05: float (nullable = true)\n |-- RL_6.25: float (nullable = true)\n |-- RL_6.45: float (nullable = true)\n |-- RL_6.64: float (nullable = true)\n |-- RL_6.84: float (nullable = true)\n |-- RL_7.03: float (nullable = true)\n |-- RL_7.23: float (nullable = true)\n |-- RL_7.42: float (nullable = true)\n |-- RL_7.62: float (nullable = true)\n |-- RL_7.81: float (nullable = true)\n |-- RL_8.01: float (nullable = true)\n |-- RL_8.2: float (nullable = true)\n |-- RL_8.4: float (nullable = true)\n |-- RL_8.59: float (nullable = true)\n |-- RL_8.79: float (nullable = true)\n |-- RL_8.98: float (nullable = true)\n |-- RL_9.18: float (nullable = true)\n |-- RL_9.38: float (nullable = true)\n |-- RL_9.57: float (nullable = true)\n |-- RL_9.77: float (nullable = true)\n |-- RL_9.96: float (nullable = true)\n |-- RL_10.16: float (nullable = true)\n |-- RL_10.35: float (nullable = true)\n |-- RL_10.55: float (nullable = true)\n |-- RL_10.74: float (nullable = true)\n |-- RL_10.94: float (nullable = true)\n |-- RL_11.13: float (nullable = true)\n |-- RL_11.33: float (nullable = true)\n |-- RL_11.52: float (nullable = true)\n |-- RL_11.72: float (nullable = true)\n |-- RL_11.91: float (nullable = true)\n |-- RL_12.11: float (nullable = true)\n |-- RL_12.3: float (nullable = true)\n |-- RL_12.5: float (nullable = true)\n |-- RL_12.7: float (nullable = true)\n |-- RL_12.89: float (nullable = true)\n |-- RL_13.09: float (nullable = true)\n |-- RL_13.28: float (nullable = true)\n |-- RL_13.48: float (nullable = true)\n |-- RL_13.67: float (nullable = true)\n |-- RL_13.87: float (nullable = true)\n |-- RL_14.06: float (nullable = true)\n |-- RL_14.26: float (nullable = true)\n |-- RL_14.45: float (nullable = true)\n |-- RL_14.65: float (nullable = true)\n |-- RL_14.84: float (nullable = true)\n |-- RL_15.04: float (nullable = true)\n |-- RL_15.23: float (nullable = true)\n |-- RL_15.43: float (nullable = true)\n |-- RL_15.63: float (nullable = true)\n |-- RL_15.82: float (nullable = true)\n |-- RL_16.02: float (nullable = true)\n |-- RL_16.21: float (nullable = true)\n |-- RL_16.41: float (nullable = true)\n |-- RL_16.6: float (nullable = true)\n |-- RL_16.8: float (nullable = true)\n |-- RL_16.99: float (nullable = true)\n |-- RL_17.19: float (nullable = true)\n |-- RL_17.38: float (nullable = true)\n |-- RL_17.58: float (nullable = true)\n |-- RL_17.77: float (nullable = true)\n |-- RL_17.97: float (nullable = true)\n |-- RL_18.16: float (nullable = true)\n |-- RL_18.36: float (nullable = true)\n |-- RL_18.55: float (nullable = true)\n |-- RL_18.75: float (nullable = true)\n |-- RL_18.95: float (nullable = true)\n |-- RL_19.14: float (nullable = true)\n |-- RL_19.34: float (nullable = true)\n |-- RL_19.53: float (nullable = true)\n |-- RL_19.73: float (nullable = true)\n |-- RL_19.92: float (nullable = true)\n |-- LP_0.59: float (nullable = true)\n |-- LP_0.78: float (nullable = true)\n |-- LP_0.98: float (nullable = true)\n |-- LP_1.17: float (nullable = true)\n |-- LP_1.37: float (nullable = true)\n |-- LP_1.56: float (nullable = true)\n |-- LP_1.76: float (nullable = true)\n |-- LP_1.95: float (nullable = true)\n |-- LP_2.15: float (nullable = true)\n |-- LP_2.34: float (nullable = true)\n |-- LP_2.54: float (nullable = true)\n |-- LP_2.73: float (nullable = true)\n |-- LP_2.93: float (nullable = true)\n |-- LP_3.13: float (nullable = true)\n |-- LP_3.32: float (nullable = true)\n |-- LP_3.52: float (nullable = true)\n |-- LP_3.71: float (nullable = true)\n |-- LP_3.91: float (nullable = true)\n |-- LP_4.1: float (nullable = true)\n |-- LP_4.3: float (nullable = true)\n |-- LP_4.49: float (nullable = true)\n |-- LP_4.69: float (nullable = true)\n |-- LP_4.88: float (nullable = true)\n |-- LP_5.08: float (nullable = true)\n |-- LP_5.27: float (nullable = true)\n |-- LP_5.47: float (nullable = true)\n |-- LP_5.66: float (nullable = true)\n |-- LP_5.86: float (nullable = true)\n |-- LP_6.05: float (nullable = true)\n |-- LP_6.25: float (nullable = true)\n |-- LP_6.45: float (nullable = true)\n |-- LP_6.64: float (nullable = true)\n |-- LP_6.84: float (nullable = true)\n |-- LP_7.03: float (nullable = true)\n |-- LP_7.23: float (nullable = true)\n |-- LP_7.42: float (nullable = true)\n |-- LP_7.62: float (nullable = true)\n |-- LP_7.81: float (nullable = true)\n |-- LP_8.01: float (nullable = true)\n |-- LP_8.2: float (nullable = true)\n |-- LP_8.4: float (nullable = true)\n |-- LP_8.59: float (nullable = true)\n |-- LP_8.79: float (nullable = true)\n |-- LP_8.98: float (nullable = true)\n |-- LP_9.18: float (nullable = true)\n |-- LP_9.38: float (nullable = true)\n |-- LP_9.57: float (nullable = true)\n |-- LP_9.77: float (nullable = true)\n |-- LP_9.96: float (nullable = true)\n |-- LP_10.16: float (nullable = true)\n |-- LP_10.35: float (nullable = true)\n |-- LP_10.55: float (nullable = true)\n |-- LP_10.74: float (nullable = true)\n |-- LP_10.94: float (nullable = true)\n |-- LP_11.13: float (nullable = true)\n |-- LP_11.33: float (nullable = true)\n |-- LP_11.52: float (nullable = true)\n |-- LP_11.72: float (nullable = true)\n |-- LP_11.91: float (nullable = true)\n |-- LP_12.11: float (nullable = true)\n |-- LP_12.3: float (nullable = true)\n |-- LP_12.5: float (nullable = true)\n |-- LP_12.7: float (nullable = true)\n |-- LP_12.89: float (nullable = true)\n |-- LP_13.09: float (nullable = true)\n |-- LP_13.28: float (nullable = true)\n |-- LP_13.48: float (nullable = true)\n |-- LP_13.67: float (nullable = true)\n |-- LP_13.87: float (nullable = true)\n |-- LP_14.06: float (nullable = true)\n |-- LP_14.26: float (nullable = true)\n |-- LP_14.45: float (nullable = true)\n |-- LP_14.65: float (nullable = true)\n |-- LP_14.84: float (nullable = true)\n |-- LP_15.04: float (nullable = true)\n |-- LP_15.23: float (nullable = true)\n |-- LP_15.43: float (nullable = true)\n |-- LP_15.63: float (nullable = true)\n |-- LP_15.82: float (nullable = true)\n |-- LP_16.02: float (nullable = true)\n |-- LP_16.21: float (nullable = true)\n |-- LP_16.41: float (nullable = true)\n |-- LP_16.6: float (nullable = true)\n |-- LP_16.8: float (nullable = true)\n |-- LP_16.99: float (nullable = true)\n |-- LP_17.19: float (nullable = true)\n |-- LP_17.38: float (nullable = true)\n |-- LP_17.58: float (nullable = true)\n |-- LP_17.77: float (nullable = true)\n |-- LP_17.97: float (nullable = true)\n |-- LP_18.16: float (nullable = true)\n |-- LP_18.36: float (nullable = true)\n |-- LP_18.55: float (nullable = true)\n |-- LP_18.75: float (nullable = true)\n |-- LP_18.95: float (nullable = true)\n |-- LP_19.14: float (nullable = true)\n |-- LP_19.34: float (nullable = true)\n |-- LP_19.53: float (nullable = true)\n |-- LP_19.73: float (nullable = true)\n |-- LP_19.92: float (nullable = true)\n |-- RP_0.59: float (nullable = true)\n |-- RP_0.78: float (nullable = true)\n |-- RP_0.98: float (nullable = true)\n |-- RP_1.17: float (nullable = true)\n |-- RP_1.37: float (nullable = true)\n |-- RP_1.56: float (nullable = true)\n |-- RP_1.76: float (nullable = true)\n |-- RP_1.95: float (nullable = true)\n |-- RP_2.15: float (nullable = true)\n |-- RP_2.34: float (nullable = true)\n |-- RP_2.54: float (nullable = true)\n |-- RP_2.73: float (nullable = true)\n |-- RP_2.93: float (nullable = true)\n |-- RP_3.13: float (nullable = true)\n |-- RP_3.32: float (nullable = true)\n |-- RP_3.52: float (nullable = true)\n |-- RP_3.71: float (nullable = true)\n |-- RP_3.91: float (nullable = true)\n |-- RP_4.1: float (nullable = true)\n |-- RP_4.3: float (nullable = true)\n |-- RP_4.49: float (nullable = true)\n |-- RP_4.69: float (nullable = true)\n |-- RP_4.88: float (nullable = true)\n |-- RP_5.08: float (nullable = true)\n |-- RP_5.27: float (nullable = true)\n |-- RP_5.47: float (nullable = true)\n |-- RP_5.66: float (nullable = true)\n |-- RP_5.86: float (nullable = true)\n |-- RP_6.05: float (nullable = true)\n |-- RP_6.25: float (nullable = true)\n |-- RP_6.45: float (nullable = true)\n |-- RP_6.64: float (nullable = true)\n |-- RP_6.84: float (nullable = true)\n |-- RP_7.03: float (nullable = true)\n |-- RP_7.23: float (nullable = true)\n |-- RP_7.42: float (nullable = true)\n |-- RP_7.62: float (nullable = true)\n |-- RP_7.81: float (nullable = true)\n |-- RP_8.01: float (nullable = true)\n |-- RP_8.2: float (nullable = true)\n |-- RP_8.4: float (nullable = true)\n |-- RP_8.59: float (nullable = true)\n |-- RP_8.79: float (nullable = true)\n |-- RP_8.98: float (nullable = true)\n |-- RP_9.18: float (nullable = true)\n |-- RP_9.38: float (nullable = true)\n |-- RP_9.57: float (nullable = true)\n |-- RP_9.77: float (nullable = true)\n |-- RP_9.96: float (nullable = true)\n |-- RP_10.16: float (nullable = true)\n |-- RP_10.35: float (nullable = true)\n |-- RP_10.55: float (nullable = true)\n |-- RP_10.74: float (nullable = true)\n |-- RP_10.94: float (nullable = true)\n |-- RP_11.13: float (nullable = true)\n |-- RP_11.33: float (nullable = true)\n |-- RP_11.52: float (nullable = true)\n |-- RP_11.72: float (nullable = true)\n |-- RP_11.91: float (nullable = true)\n |-- RP_12.11: float (nullable = true)\n |-- RP_12.3: float (nullable = true)\n |-- RP_12.5: float (nullable = true)\n |-- RP_12.7: float (nullable = true)\n |-- RP_12.89: float (nullable = true)\n |-- RP_13.09: float (nullable = true)\n |-- RP_13.28: float (nullable = true)\n |-- RP_13.48: float (nullable = true)\n |-- RP_13.67: float (nullable = true)\n |-- RP_13.87: float (nullable = true)\n |-- RP_14.06: float (nullable = true)\n |-- RP_14.26: float (nullable = true)\n |-- RP_14.45: float (nullable = true)\n |-- RP_14.65: float (nullable = true)\n |-- RP_14.84: float (nullable = true)\n |-- RP_15.04: float (nullable = true)\n |-- RP_15.23: float (nullable = true)\n |-- RP_15.43: float (nullable = true)\n |-- RP_15.63: float (nullable = true)\n |-- RP_15.82: float (nullable = true)\n |-- RP_16.02: float (nullable = true)\n |-- RP_16.21: float (nullable = true)\n |-- RP_16.41: float (nullable = true)\n |-- RP_16.6: float (nullable = true)\n |-- RP_16.8: float (nullable = true)\n |-- RP_16.99: float (nullable = true)\n |-- RP_17.19: float (nullable = true)\n |-- RP_17.38: float (nullable = true)\n |-- RP_17.58: float (nullable = true)\n |-- RP_17.77: float (nullable = true)\n |-- RP_17.97: float (nullable = true)\n |-- RP_18.16: float (nullable = true)\n |-- RP_18.36: float (nullable = true)\n |-- RP_18.55: float (nullable = true)\n |-- RP_18.75: float (nullable = true)\n |-- RP_18.95: float (nullable = true)\n |-- RP_19.14: float (nullable = true)\n |-- RP_19.34: float (nullable = true)\n |-- RP_19.53: float (nullable = true)\n |-- RP_19.73: float (nullable = true)\n |-- RP_19.92: float (nullable = true)\n |-- file_path: string (nullable = true)\n\n","output_type":"stream"}],"execution_count":7},{"cell_type":"code","source":"# ✅ Define EEG and label columns\neeg_channels = ['Fp1', 'F3', 'C3', 'P3', 'F7', 'T3', 'T5', 'O1', 'Fz', 'Cz', \n                'Pz', 'Fp2', 'F4', 'C4', 'P4', 'F8', 'T4', 'T6', 'O2', 'EKG']\nlabel_columns = ['seizure_vote', 'lpd_vote', 'gpd_vote', 'lrda_vote', 'grda_vote', 'other_vote']\n\ndf_sampled = df_joined.limit(5000)  # You can reduce further if needed (e.g., 10_000)\n\n# ✅ Step 1: Select only needed columns\ndf_selected = df_sampled.select(eeg_channels + label_columns)\n\n# ✅ Step 2: Drop rows with null values\ndf_filtered = df_selected.dropna()\n\n# ✅ Step 3: Take a fixed number of rows (e.g., 20,000)\n# Much safer than sampling in constrained environments like Kaggle\n\n# ✅ Optional: Cache to speed up reuse (if needed)\ndf_filtered.cache()\n\n# ✅ Step 4: Convert to pandas (should now fit in RAM)\ndf_pandas = df_filtered.toPandas()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T16:59:25.9585Z","iopub.execute_input":"2025-07-11T16:59:25.958873Z","iopub.status.idle":"2025-07-11T17:38:47.59836Z","shell.execute_reply.started":"2025-07-11T16:59:25.958818Z","shell.execute_reply":"2025-07-11T17:38:47.597415Z"}},"outputs":[{"name":"stderr","text":"Exception in thread \"serve-DataFrame\" java.net.SocketTimeoutException: Accept timed out\n\tat java.base/java.net.PlainSocketImpl.socketAccept(Native Method)\n\tat java.base/java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:474)\n\tat java.base/java.net.ServerSocket.implAccept(ServerSocket.java:565)\n\tat java.base/java.net.ServerSocket.accept(ServerSocket.java:533)\n\tat org.apache.spark.security.SocketAuthServer$$anon$1.run(SocketAuthServer.scala:65)\n","output_type":"stream"}],"execution_count":9},{"cell_type":"code","source":"df_pandas.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T17:39:16.164752Z","iopub.execute_input":"2025-07-11T17:39:16.165028Z","iopub.status.idle":"2025-07-11T17:39:16.222421Z","shell.execute_reply.started":"2025-07-11T17:39:16.16501Z","shell.execute_reply":"2025-07-11T17:39:16.221858Z"}},"outputs":[{"execution_count":10,"output_type":"execute_result","data":{"text/plain":"          Fp1          F3          C3          P3          F7          T3  \\\n0 -295.679993 -286.559998 -281.079987 -257.200012 -217.190002 -285.410004   \n1 -295.679993 -286.559998 -281.079987 -257.200012 -217.190002 -285.410004   \n2 -295.679993 -286.559998 -281.079987 -257.200012 -217.190002 -285.410004   \n3 -295.679993 -286.559998 -281.079987 -257.200012 -217.190002 -285.410004   \n4 -295.679993 -286.559998 -281.079987 -257.200012 -217.190002 -285.410004   \n\n           T5          O1          Fz          Cz  ...          T4      T6  \\\n0 -298.450012 -267.970001 -294.140015 -285.779999  ... -292.790009 -246.25   \n1 -298.450012 -267.970001 -294.140015 -285.779999  ... -292.790009 -246.25   \n2 -298.450012 -267.970001 -294.140015 -285.779999  ... -292.790009 -246.25   \n3 -298.450012 -267.970001 -294.140015 -285.779999  ... -292.790009 -246.25   \n4 -298.450012 -267.970001 -294.140015 -285.779999  ... -292.790009 -246.25   \n\n           O2        EKG  seizure_vote  lpd_vote  gpd_vote  lrda_vote  \\\n0 -220.779999  27.059999             0         1         0          0   \n1 -220.779999  27.059999             0         1         0          0   \n2 -220.779999  27.059999             0         1         0          0   \n3 -220.779999  27.059999             0         1         0          0   \n4 -220.779999  27.059999             0         1         0          0   \n\n   grda_vote  other_vote  \n0          0           4  \n1          0           4  \n2          0           4  \n3          0           4  \n4          0           4  \n\n[5 rows x 26 columns]","text/html":"<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Fp1</th>\n      <th>F3</th>\n      <th>C3</th>\n      <th>P3</th>\n      <th>F7</th>\n      <th>T3</th>\n      <th>T5</th>\n      <th>O1</th>\n      <th>Fz</th>\n      <th>Cz</th>\n      <th>...</th>\n      <th>T4</th>\n      <th>T6</th>\n      <th>O2</th>\n      <th>EKG</th>\n      <th>seizure_vote</th>\n      <th>lpd_vote</th>\n      <th>gpd_vote</th>\n      <th>lrda_vote</th>\n      <th>grda_vote</th>\n      <th>other_vote</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>-295.679993</td>\n      <td>-286.559998</td>\n      <td>-281.079987</td>\n      <td>-257.200012</td>\n      <td>-217.190002</td>\n      <td>-285.410004</td>\n      <td>-298.450012</td>\n      <td>-267.970001</td>\n      <td>-294.140015</td>\n      <td>-285.779999</td>\n      <td>...</td>\n      <td>-292.790009</td>\n      <td>-246.25</td>\n      <td>-220.779999</td>\n      <td>27.059999</td>\n      <td>0</td>\n      <td>1</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>-295.679993</td>\n      <td>-286.559998</td>\n      <td>-281.079987</td>\n      <td>-257.200012</td>\n      <td>-217.190002</td>\n      <td>-285.410004</td>\n      <td>-298.450012</td>\n      <td>-267.970001</td>\n      <td>-294.140015</td>\n      <td>-285.779999</td>\n      <td>...</td>\n      <td>-292.790009</td>\n      <td>-246.25</td>\n      <td>-220.779999</td>\n      <td>27.059999</td>\n      <td>0</td>\n      <td>1</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>-295.679993</td>\n      <td>-286.559998</td>\n      <td>-281.079987</td>\n      <td>-257.200012</td>\n      <td>-217.190002</td>\n      <td>-285.410004</td>\n      <td>-298.450012</td>\n      <td>-267.970001</td>\n      <td>-294.140015</td>\n      <td>-285.779999</td>\n      <td>...</td>\n      <td>-292.790009</td>\n      <td>-246.25</td>\n      <td>-220.779999</td>\n      <td>27.059999</td>\n      <td>0</td>\n      <td>1</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>-295.679993</td>\n      <td>-286.559998</td>\n      <td>-281.079987</td>\n      <td>-257.200012</td>\n      <td>-217.190002</td>\n      <td>-285.410004</td>\n      <td>-298.450012</td>\n      <td>-267.970001</td>\n      <td>-294.140015</td>\n      <td>-285.779999</td>\n      <td>...</td>\n      <td>-292.790009</td>\n      <td>-246.25</td>\n      <td>-220.779999</td>\n      <td>27.059999</td>\n      <td>0</td>\n      <td>1</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>-295.679993</td>\n      <td>-286.559998</td>\n      <td>-281.079987</td>\n      <td>-257.200012</td>\n      <td>-217.190002</td>\n      <td>-285.410004</td>\n      <td>-298.450012</td>\n      <td>-267.970001</td>\n      <td>-294.140015</td>\n      <td>-285.779999</td>\n      <td>...</td>\n      <td>-292.790009</td>\n      <td>-246.25</td>\n      <td>-220.779999</td>\n      <td>27.059999</td>\n      <td>0</td>\n      <td>1</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>4</td>\n    </tr>\n  </tbody>\n</table>\n<p>5 rows × 26 columns</p>\n</div>"},"metadata":{}}],"execution_count":10},{"cell_type":"code","source":"import tensorflow as tf\nimport numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\n\n# ✅ 1. Confirm GPU availability\ngpus = tf.config.list_physical_devices('GPU')\nif gpus:\n    print(f\"✅ GPU detected: {gpus}\")\n    strategy = tf.distribute.MirroredStrategy()\nelse:\n    print(\"⚠️ No GPU detected, using default strategy.\")\n    strategy = tf.distribute.get_strategy()\n\n# ✅ 2. Use the already cleaned pandas DataFrame\n# (Assumes df_pandas is already defined from Spark)\ndf_clean = df_pandas.copy()\n\n# ✅ 3. Define EEG and label columns\neeg_channels = ['Fp1', 'F3', 'C3', 'P3', 'F7', 'T3', 'T5', 'O1', \n                'Fz', 'Cz', 'Pz', 'Fp2', 'F4', 'C4', 'P4', \n                'F8', 'T4', 'T6', 'O2', 'EKG']\nlabel_columns = ['seizure_vote', 'lpd_vote', 'gpd_vote', 'lrda_vote', 'grda_vote', 'other_vote']\n\n# ✅ 4. Extract EEG data and labels as numpy arrays\neeg_array = df_clean[eeg_channels].values.astype(np.float32)\nlabels_array = df_clean[label_columns].values.astype(np.float32)\n\n# ✅ 5. Chunk EEG data and corresponding labels\nCHUNK_SIZE = 100  # Smaller for safety on Kaggle\nchunks = []\nchunk_labels = []\n\nfor i in range(0, len(eeg_array) - CHUNK_SIZE, CHUNK_SIZE):\n    eeg_chunk = eeg_array[i:i+CHUNK_SIZE]\n    label_chunk = labels_array[i:i+CHUNK_SIZE]\n\n    if eeg_chunk.shape[0] == CHUNK_SIZE:\n        chunks.append(eeg_chunk)\n        chunk_labels.append(label_chunk.mean(axis=0))  # average label votes\n\nX = np.array(chunks)  # shape: (num_chunks, CHUNK_SIZE, 20)\ny = np.array(chunk_labels)  # shape: (num_chunks, 6)\n\nprint(f\"✅ Final input shape: {X.shape}, Labels shape: {y.shape}\")\n\n# ✅ 6. Train-test split\nX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)\n\n# ✅ 7. Build the LSTM model\nn_classes = 6\n\nwith strategy.scope():\n    model = tf.keras.Sequential([\n        tf.keras.layers.Input(shape=(CHUNK_SIZE, len(eeg_channels))),\n        tf.keras.layers.LSTM(64),\n        tf.keras.layers.Dense(64, activation='relu'),\n        tf.keras.layers.Dense(n_classes, activation='sigmoid')  # multi-label\n    ])\n    \n    model.compile(optimizer='adam',\n                  loss='binary_crossentropy',\n                  metrics=['accuracy'])\n\n# ✅ 8. Train the model\nmodel.fit(X_train, y_train, epochs=5, batch_size=32, validation_data=(X_val, y_val))\n\n# ✅ 9. Evaluate\nloss, accuracy = model.evaluate(X_val, y_val)\nprint(f\"\\n🎯 Validation Accuracy: {accuracy:.4f}\")\n\n# ✅ 10. Classification report\ny_pred = model.predict(X_val)\ny_pred_classes = (y_pred > 0.5).astype(int)\n\nprint(\"\\n📊 Classification Report:\")\nprint(classification_report(y_val, y_pred_classes, target_names=label_columns))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T17:43:57.66194Z","iopub.execute_input":"2025-07-11T17:43:57.662234Z","iopub.status.idle":"2025-07-11T17:44:34.188868Z","shell.execute_reply.started":"2025-07-11T17:43:57.662211Z","shell.execute_reply":"2025-07-11T17:44:34.187972Z"}},"outputs":[{"name":"stderr","text":"2025-07-11 17:44:01.192108: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\nWARNING: All log messages before absl::InitializeLog() is called are written to STDERR\nE0000 00:00:1752255841.564072      36 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\nE0000 00:00:1752255841.670783      36 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n","output_type":"stream"},{"name":"stdout","text":"✅ GPU detected: [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU'), PhysicalDevice(name='/physical_device:GPU:1', device_type='GPU')]\n✅ Final input shape: (49, 100, 20), Labels shape: (49, 6)\n","output_type":"stream"},{"name":"stderr","text":"I0000 00:00:1752255861.214331      36 gpu_device.cc:2022] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 13942 MB memory:  -> device: 0, name: Tesla T4, pci bus id: 0000:00:04.0, compute capability: 7.5\nI0000 00:00:1752255861.215057      36 gpu_device.cc:2022] Created device /job:localhost/replica:0/task:0/device:GPU:1 with 13942 MB memory:  -> device: 1, name: Tesla T4, pci bus id: 0000:00:05.0, compute capability: 7.5\n","output_type":"stream"},{"name":"stdout","text":"Epoch 1/5\n","output_type":"stream"},{"name":"stderr","text":"I0000 00:00:1752255866.668176    1700 cuda_dnn.cc:529] Loaded cuDNN version 90300\nI0000 00:00:1752255866.735123    1701 cuda_dnn.cc:529] Loaded cuDNN version 90300\n","output_type":"stream"},{"name":"stdout","text":"\u001b[1m2/2\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 1s/step - accuracy: 0.1929 - loss: 0.7790 - val_accuracy: 1.0000 - val_loss: 0.5334\nEpoch 2/5\n\u001b[1m2/2\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 581ms/step - accuracy: 1.0000 - loss: 0.5353 - val_accuracy: 1.0000 - val_loss: 0.3323\nEpoch 3/5\n\u001b[1m2/2\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 562ms/step - accuracy: 1.0000 - loss: 0.3438 - val_accuracy: 1.0000 - val_loss: 0.2465\nEpoch 4/5\n\u001b[1m2/2\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 873ms/step - accuracy: 1.0000 - loss: 0.2531 - val_accuracy: 1.0000 - val_loss: 0.1112\nEpoch 5/5\n\u001b[1m2/2\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 577ms/step - accuracy: 1.0000 - loss: 0.1075 - val_accuracy: 1.0000 - val_loss: -0.0702\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 282ms/step - accuracy: 1.0000 - loss: -0.0702\n\n🎯 Validation Accuracy: 1.0000\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 561ms/step\n\n📊 Classification Report:\n","output_type":"stream"},{"traceback":["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m","\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)","\u001b[0;32m/tmp/ipykernel_36/3478932562.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     76\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     77\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"\\n📊 Classification Report:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 78\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mclassification_report\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my_val\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_pred_classes\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget_names\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlabel_columns\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m","\u001b[0;32m/usr/local/lib/python3.11/dist-packages/sklearn/metrics/_classification.py\u001b[0m in \u001b[0;36mclassification_report\u001b[0;34m(y_true, y_pred, labels, target_names, sample_weight, digits, output_dict, zero_division)\u001b[0m\n\u001b[1;32m   2308\u001b[0m     \"\"\"\n\u001b[1;32m   2309\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2310\u001b[0;31m     \u001b[0my_type\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_true\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_pred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_check_targets\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my_true\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_pred\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   2311\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2312\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mlabels\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;32m/usr/local/lib/python3.11/dist-packages/sklearn/metrics/_classification.py\u001b[0m in \u001b[0;36m_check_targets\u001b[0;34m(y_true, y_pred)\u001b[0m\n\u001b[1;32m     93\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     94\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my_type\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 95\u001b[0;31m         raise ValueError(\n\u001b[0m\u001b[1;32m     96\u001b[0m             \"Classification metrics can't handle a mix of {0} and {1} targets\".format(\n\u001b[1;32m     97\u001b[0m                 \u001b[0mtype_true\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtype_pred\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;31mValueError\u001b[0m: Classification metrics can't handle a mix of multiclass-multioutput and multilabel-indicator targets"],"ename":"ValueError","evalue":"Classification metrics can't handle a mix of multiclass-multioutput and multilabel-indicator targets","output_type":"error"}],"execution_count":11},{"cell_type":"code","source":"# ✅ 10. Classification report\ny_pred = model.predict(X_val)\ny_pred_classes = (y_pred > 0.5).astype(int)\ny_true_classes = (y_val > 0.5).astype(int)  # convert to binary as well\n\nprint(\"\\n📊 Classification Report:\")\nprint(classification_report(y_true_classes, y_pred_classes, target_names=label_columns))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T17:47:42.888346Z","iopub.execute_input":"2025-07-11T17:47:42.889073Z","iopub.status.idle":"2025-07-11T17:47:43.234629Z","shell.execute_reply.started":"2025-07-11T17:47:42.889047Z","shell.execute_reply":"2025-07-11T17:47:43.233906Z"}},"outputs":[{"name":"stdout","text":"\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 261ms/step\n\n📊 Classification Report:\n              precision    recall  f1-score   support\n\nseizure_vote       0.00      0.00      0.00         0\n    lpd_vote       0.00      0.00      0.00        10\n    gpd_vote       0.00      0.00      0.00         0\n   lrda_vote       0.00      0.00      0.00         0\n   grda_vote       0.00      0.00      0.00         0\n  other_vote       1.00      1.00      1.00        10\n\n   micro avg       1.00      0.50      0.67        20\n   macro avg       0.17      0.17      0.17        20\nweighted avg       0.50      0.50      0.50        20\n samples avg       1.00      0.50      0.67        20\n\n","output_type":"stream"}],"execution_count":14},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T17:48:49.452736Z","iopub.execute_input":"2025-07-11T17:48:49.453647Z","iopub.status.idle":"2025-07-11T17:48:49.457079Z","shell.execute_reply.started":"2025-07-11T17:48:49.453619Z","shell.execute_reply":"2025-07-11T17:48:49.456373Z"}},"outputs":[],"execution_count":15},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nlabel_counts = (y > 0.5).sum(axis=0)  # binary count of each label\nplt.bar(label_columns, label_counts)\nplt.title(\"Label Distribution\")\nplt.xticks(rotation=45)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-11T19:32:10.937096Z","iopub.execute_input":"2025-07-11T19:32:10.937695Z","iopub.status.idle":"2025-07-11T19:32:11.077324Z","shell.execute_reply.started":"2025-07-11T19:32:10.937672Z","shell.execute_reply":"2025-07-11T19:32:11.076641Z"}},"outputs":[{"output_type":"display_data","data":{"text/plain":"<Figure size 640x480 with 1 Axes>","image/png":"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\n"},"metadata":{}}],"execution_count":18},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}