{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport tensorflow as tf\nfrom keras import layers, models\nfrom tqdm import tqdm\nimport joblib\nfrom sklearn.model_selection import KFold","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:30:40.034337Z","iopub.execute_input":"2024-12-02T13:30:40.035243Z","iopub.status.idle":"2024-12-02T13:30:40.039732Z","shell.execute_reply.started":"2024-12-02T13:30:40.035206Z","shell.execute_reply":"2024-12-02T13:30:40.038661Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BASE_PATH = \"/kaggle/input/hms-harmful-brain-activity-classification\"\nSPEC_DIR = \"/tmp/dataset/hms-hbac\"\nos.makedirs(SPEC_DIR + '/train_spectrograms', exist_ok=True)\nos.makedirs(SPEC_DIR + '/test_spectrograms', exist_ok=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:51:45.302096Z","iopub.execute_input":"2024-12-02T13:51:45.302837Z","iopub.status.idle":"2024-12-02T13:51:45.308471Z","shell.execute_reply.started":"2024-12-02T13:51:45.302797Z","shell.execute_reply":"2024-12-02T13:51:45.307328Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Train + Valid\ndf = pd.read_csv(f'{BASE_PATH}/train.csv')\ndf['eeg_path'] = f'{BASE_PATH}/train_eegs/'+df['eeg_id'].astype(str)+'.parquet'\ndf['spec_path'] = f'{BASE_PATH}/train_spectrograms/'+df['spectrogram_id'].astype(str)+'.parquet'\ndf['spec2_path'] = f'{SPEC_DIR}/train_spectrograms/'+df['spectrogram_id'].astype(str)+'.npy'\ndf['class_name'] = df.expert_consensus.copy()\ndf['class_label'] = df.expert_consensus.map(CFG.name2label)\ndisplay(df.head(2))\n\n# Test\ntest_df = pd.read_csv(f'{BASE_PATH}/test.csv')\ntest_df['eeg_path'] = \"/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/3911565283.parquet\"\ntest_df['spec_path'] = f'{BASE_PATH}/test_spectrograms/'+test_df['spectrogram_id'].astype(str)+'.parquet'\ntest_df['spec2_path'] = f'{SPEC_DIR}/test_spectrograms/'+test_df['spectrogram_id'].astype(str)+'.npy'\ndisplay(test_df.head(2))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:56:41.224221Z","iopub.execute_input":"2024-12-02T13:56:41.224661Z","iopub.status.idle":"2024-12-02T13:56:41.549791Z","shell.execute_reply.started":"2024-12-02T13:56:41.224623Z","shell.execute_reply":"2024-12-02T13:56:41.548638Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CFG:\n    verbose = 1  # Verbosity\n    seed = 42  # Random seed\n    preset = \"efficientnetv2_b2_imagenet\"  # Name of pretrained classifier\n    image_size = [400, 300]  # Input image size\n    epochs = 13 # Training epochs\n    batch_size = 64  # Batch size\n    lr_mode = \"cos\" # LR scheduler mode from one of \"cos\", \"step\", \"exp\"\n    drop_remainder = True  # Drop incomplete batches\n    num_classes = 6 # Number of classes in the dataset\n    fold = 0 # Which fold to set as validation data\n    class_names = ['Seizure', 'LPD', 'GPD', 'LRDA','GRDA', 'Other']\n    label2name = dict(enumerate(class_names))\n    name2label = {v:k for k, v in label2name.items()}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:51:47.432424Z","iopub.execute_input":"2024-12-02T13:51:47.433168Z","iopub.status.idle":"2024-12-02T13:51:47.477947Z","shell.execute_reply.started":"2024-12-02T13:51:47.433132Z","shell.execute_reply":"2024-12-02T13:51:47.476642Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_spec(spec_id, split=\"train\"):\n    \"\"\"\n    Processes and saves spectrogram data as a .npy file.\n    \"\"\"\n    spec_path = f\"{BASE_PATH}/{split}_spectrograms/{spec_id}.parquet\"\n    spec = pd.read_parquet(spec_path)\n    spec = spec.fillna(0).values[:, 1:].T  # Transpose for (Freq, Time)\n    spec = spec.astype(\"float32\")\n    np.save(f\"{SPEC_DIR}/{split}_spectrograms/{spec_id}.npy\", spec)\n\n# Parallel Process Train and Test Spectrograms\nspec_ids = df[\"spectrogram_id\"].unique()\n_ = joblib.Parallel(n_jobs=-1, backend=\"loky\")(\n    joblib.delayed(process_spec)(spec_id, \"train\")\n    for spec_id in tqdm(spec_ids, desc=\"Processing Train Spectrograms\", total=len(spec_ids))\n)\n\ntest_spec_ids = test_df[\"spectrogram_id\"].unique()\n_ = joblib.Parallel(n_jobs=-1, backend=\"loky\")(\n    joblib.delayed(process_spec)(spec_id, \"test\")\n    for spec_id in tqdm(test_spec_ids, desc=\"Processing Test Spectrograms\", total=len(test_spec_ids))\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:51:48.260168Z","iopub.execute_input":"2024-12-02T13:51:48.260664Z","iopub.status.idle":"2024-12-02T13:54:10.386969Z","shell.execute_reply.started":"2024-12-02T13:51:48.26062Z","shell.execute_reply":"2024-12-02T13:54:10.38569Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import StratifiedGroupKFold\n\nsgkf = StratifiedGroupKFold(n_splits=5, shuffle=True, random_state=CFG.seed)\n\ndf[\"fold\"] = -1\ndf.reset_index(drop=True, inplace=True)\nfor fold, (train_idx, valid_idx) in enumerate(\n    sgkf.split(df, y=df[\"class_label\"], groups=df[\"patient_id\"])\n):\n    df.loc[valid_idx, \"fold\"] = fold\ndf.groupby([\"fold\", \"class_name\"])[[\"eeg_id\"]].count().T","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:57:40.752717Z","iopub.execute_input":"2024-12-02T13:57:40.753597Z","iopub.status.idle":"2024-12-02T13:57:41.690796Z","shell.execute_reply.started":"2024-12-02T13:57:40.753538Z","shell.execute_reply":"2024-12-02T13:57:41.689689Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Sample from full data\nsample_df = df.groupby(\"spectrogram_id\").head(1).reset_index(drop=True)\ntrain_df = sample_df[sample_df.fold != CFG.fold]\nvalid_df = sample_df[sample_df.fold == CFG.fold]\nprint(f\"# Num Train: {len(train_df)} | Num Valid: {len(valid_df)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:59:06.678521Z","iopub.execute_input":"2024-12-02T13:59:06.679316Z","iopub.status.idle":"2024-12-02T13:59:06.705515Z","shell.execute_reply.started":"2024-12-02T13:59:06.679269Z","shell.execute_reply":"2024-12-02T13:59:06.7044Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_dataset(df, split):\n    spectrograms, eegs = [], []\n    for _, row in tqdm(df.iterrows(), desc=f\"Creating {split} Dataset\", total=len(df)):\n        # Load spectrogram\n        spec = np.load(row['spec2_path'])\n        spec = tf.image.resize(spec[..., None], (200, 150))\n        spec = tf.tile(spec, [1, 1, 3]) / 255.0  # Normalize and make 3-channel\n        spectrograms.append(spec)\n        \n        # Load EEG (Optional)\n        eeg = preprocess_eeg(row['eeg_id'], split)\n        \n        # Pad or truncate EEG to a fixed length\n        max_length = 5000  # Choose an appropriate max length based on your data\n        if eeg.shape[1] > max_length:\n            eeg = eeg[:, :max_length]\n        else:\n            eeg = np.pad(eeg, ((0, 0), (0, max_length - eeg.shape[1])), mode='constant')\n        \n        eegs.append(eeg)\n\n    # Convert to NumPy arrays to ensure uniform shape\n    spectrograms = np.array(spectrograms)\n    eegs = np.array(eegs)\n\n    # Create TensorFlow dataset\n    return tf.data.Dataset.from_tensor_slices((spectrograms, eegs))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:59:07.314852Z","iopub.execute_input":"2024-12-02T13:59:07.315247Z","iopub.status.idle":"2024-12-02T13:59:07.323031Z","shell.execute_reply.started":"2024-12-02T13:59:07.315213Z","shell.execute_reply":"2024-12-02T13:59:07.321949Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_ds = create_dataset(train_df, \"train\").batch(32)\nvalid_ds = create_dataset(valid_df, \"test\").batch(32)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:59:07.964822Z","iopub.execute_input":"2024-12-02T13:59:07.965226Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def build_encoder(input_shape, latent_dim):\n    inputs = layers.Input(shape=input_shape)\n    x = layers.Conv2D(32, (3, 3), activation='relu', strides=(2, 2), padding='same')(inputs)\n    x = layers.Conv2D(64, (3, 3), activation='relu', strides=(2, 2), padding='same')(x)\n    x = layers.Flatten()(x)\n    z_mean = layers.Dense(latent_dim, name=\"z_mean\")(x)\n    z_log_var = layers.Dense(latent_dim, name=\"z_log_var\")(x)\n    return models.Model(inputs, [z_mean, z_log_var], name=\"encoder\")\nclass Sampling(layers.Layer):\n    def call(self, inputs):\n        z_mean, z_log_var = inputs\n        epsilon = tf.random.normal(shape=tf.shape(z_mean))\n        return z_mean + tf.exp(0.5 * z_log_var) * epsilon","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:25:29.731464Z","iopub.execute_input":"2024-12-02T13:25:29.731971Z","iopub.status.idle":"2024-12-02T13:25:29.739295Z","shell.execute_reply.started":"2024-12-02T13:25:29.731921Z","shell.execute_reply":"2024-12-02T13:25:29.738365Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class VAE(models.Model):\n    def __init__(self, encoder, decoder, **kwargs):\n        super(VAE, self).__init__(**kwargs)\n        self.encoder = encoder\n        self.decoder = decoder\n\n    def call(self, inputs):\n        z_mean, z_log_var = self.encoder(inputs)\n        z = Sampling()([z_mean, z_log_var])\n        reconstructed = self.decoder(z)\n        kl_loss = -0.5 * tf.reduce_mean(z_log_var - tf.square(z_mean) - tf.exp(z_log_var) + 1)\n        self.add_loss(kl_loss)\n        return reconstructed","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:25:30.487645Z","iopub.execute_input":"2024-12-02T13:25:30.488023Z","iopub.status.idle":"2024-12-02T13:25:30.494051Z","shell.execute_reply.started":"2024-12-02T13:25:30.48799Z","shell.execute_reply":"2024-12-02T13:25:30.493023Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def build_decoder(latent_dim, output_shape):\n    latent_inputs = layers.Input(shape=(latent_dim,))\n    x = layers.Dense(100 * 75 * 64, activation='relu')(latent_inputs)\n    x = layers.Reshape((100, 75, 64))(x)\n    x = layers.Conv2DTranspose(64, (3, 3), activation='relu', strides=(2, 2), padding='same')(x)\n    x = layers.Conv2DTranspose(32, (3, 3), activation='relu', strides=(2, 2), padding='same')(x)\n    outputs = layers.Conv2DTranspose(3, (3, 3), activation='sigmoid', padding='same')(x)\n    return models.Model(latent_inputs, outputs, name=\"decoder\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:25:30.8188Z","iopub.execute_input":"2024-12-02T13:25:30.819636Z","iopub.status.idle":"2024-12-02T13:25:30.825969Z","shell.execute_reply.started":"2024-12-02T13:25:30.819568Z","shell.execute_reply":"2024-12-02T13:25:30.824825Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class VAE(models.Model):\n    def __init__(self, encoder, decoder, **kwargs):\n        super(VAE, self).__init__(**kwargs)\n        self.encoder = encoder\n        self.decoder = decoder\n\n    def call(self, inputs):\n        z_mean, z_log_var = self.encoder(inputs)\n        z = Sampling()([z_mean, z_log_var])\n        reconstructed = self.decoder(z)\n        kl_loss = -0.5 * tf.reduce_mean(z_log_var - tf.square(z_mean) - tf.exp(z_log_var) + 1)\n        self.add_loss(kl_loss)\n        return reconstructed","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:25:31.162231Z","iopub.execute_input":"2024-12-02T13:25:31.162997Z","iopub.status.idle":"2024-12-02T13:25:31.169255Z","shell.execute_reply.started":"2024-12-02T13:25:31.162957Z","shell.execute_reply":"2024-12-02T13:25:31.168018Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# VAE Configuration\ninput_shape = (400, 300, 3)  # Shape of spectrograms\nlatent_dim = 16\nencoder = build_encoder(input_shape, latent_dim)\ndecoder = build_decoder(latent_dim, input_shape)\nvae = VAE(encoder, decoder)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:25:31.530075Z","iopub.execute_input":"2024-12-02T13:25:31.531114Z","iopub.status.idle":"2024-12-02T13:25:31.633477Z","shell.execute_reply.started":"2024-12-02T13:25:31.531073Z","shell.execute_reply":"2024-12-02T13:25:31.632346Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"vae.compile(optimizer='adam', loss=tf.keras.losses.MeanSquaredError())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:25:32.437251Z","iopub.execute_input":"2024-12-02T13:25:32.4378Z","iopub.status.idle":"2024-12-02T13:25:32.452864Z","shell.execute_reply.started":"2024-12-02T13:25:32.437749Z","shell.execute_reply":"2024-12-02T13:25:32.451977Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class TQDMProgressBar(tf.keras.callbacks.Callback):\n    def on_epoch_end(self, epoch, logs=None):\n        logs = logs or {}\n        loss = logs.get('loss', 'N/A')\n        val_loss = logs.get('val_loss', 'N/A')\n        print(f\"Epoch {epoch + 1}: Loss = {loss}, Val Loss = {val_loss}\")\n\nprogress_bar = TQDMProgressBar()\nvae.fit(train_ds, validation_data=valid_ds, epochs=10, callbacks=[progress_bar])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T13:25:38.492466Z","iopub.execute_input":"2024-12-02T13:25:38.492941Z","iopub.status.idle":"2024-12-02T13:25:38.930073Z","shell.execute_reply.started":"2024-12-02T13:25:38.492907Z","shell.execute_reply":"2024-12-02T13:25:38.928663Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}