{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":30648,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<a href=\"https://www.kaggle.com/code/yujansaya/harmful-brain-activity?scriptVersionId=161975137\" target=\"_blank\"><img align=\"left\" alt=\"Kaggle\" title=\"Open in Kaggle\" src=\"https://kaggle.com/static/images/open-in-kaggle.svg\"></a>","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport random\nimport matplotlib.pyplot as plt, gc\nimport joblib  # to pipeline files reading and transforming\nfrom tqdm.notebook import tqdm  # progress bar\nimport keras_cv\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         #print()\n#         os.path.join(dirname, filename)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-02-21T16:30:17.731073Z","iopub.execute_input":"2024-02-21T16:30:17.731357Z","iopub.status.idle":"2024-02-21T16:30:37.071468Z","shell.execute_reply.started":"2024-02-21T16:30:17.731331Z","shell.execute_reply":"2024-02-21T16:30:37.070711Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install tensorflow[and-cuda]","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:30:37.073333Z","iopub.execute_input":"2024-02-21T16:30:37.074067Z","iopub.status.idle":"2024-02-21T16:32:38.426154Z","shell.execute_reply.started":"2024-02-21T16:30:37.074034Z","shell.execute_reply":"2024-02-21T16:32:38.424987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:32:38.4294Z","iopub.execute_input":"2024-02-21T16:32:38.42975Z","iopub.status.idle":"2024-02-21T16:32:38.434523Z","shell.execute_reply.started":"2024-02-21T16:32:38.429721Z","shell.execute_reply":"2024-02-21T16:32:38.43367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BASE_PATH = \"/kaggle/input/hms-harmful-brain-activity-classification\"\n\nSPEC_DIR = \"/kaggle/working\"\nos.makedirs(f'{SPEC_DIR}/train', exist_ok=True)\nos.makedirs(f'{SPEC_DIR}/test', exist_ok=True)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:32:38.436875Z","iopub.execute_input":"2024-02-21T16:32:38.437132Z","iopub.status.idle":"2024-02-21T16:32:38.448003Z","shell.execute_reply.started":"2024-02-21T16:32:38.43711Z","shell.execute_reply":"2024-02-21T16:32:38.447226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_classes = 6\nimage_size = [200, 600]\nclass_names = ['Seizure', 'LPD', 'GPD', 'LRDA','GRDA', 'Other']\nlabel2name = dict(enumerate(class_names))\nname2label = {v:k for k, v in label2name.items()}\nbatch_size = 64\nLOSS = tf.keras.losses.KLDivergence()","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:32:38.449133Z","iopub.execute_input":"2024-02-21T16:32:38.449415Z","iopub.status.idle":"2024-02-21T16:32:38.458705Z","shell.execute_reply.started":"2024-02-21T16:32:38.449392Z","shell.execute_reply":"2024-02-21T16:32:38.457878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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/'+df['spectrogram_id'].astype(str)+'.npy'\ndf['eeg_to_spec'] = f'{SPEC_DIR}/train/'+df['eeg_id'].astype(str)+'.npy'\ndf['class_name'] = df.expert_consensus.copy()\ndf['class_label'] = df.expert_consensus.map(name2label)\ndisplay(df.head(2))\n\n# Test\ntest_df = pd.read_csv(f'{BASE_PATH}/test.csv')\ntest_df['eeg_path'] = f'{BASE_PATH}/test_eegs/'+test_df['eeg_id'].astype(str)+'.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/'+test_df['spectrogram_id'].astype(str)+'.npy'\ntest_df['eeg_to_spec'] = f'{SPEC_DIR}/test/'+test_df['eeg_id'].astype(str)+'.npy'\ndisplay(test_df.head(2))","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:32:38.459843Z","iopub.execute_input":"2024-02-21T16:32:38.460419Z","iopub.status.idle":"2024-02-21T16:32:39.079464Z","shell.execute_reply.started":"2024-02-21T16:32:38.460389Z","shell.execute_reply":"2024-02-21T16:32:39.078603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import librosa\n\nNAMES = ['LL','LP','RP','RR']\n\nFEATS = [['Fp1','F7','T3','T5','O1'],\n         ['Fp1','F3','C3','P3','O1'],\n         ['Fp2','F8','T4','T6','O2'],\n         ['Fp2','F4','C4','P4','O2']]\n\n\ndef spectrogram_from_eeg(eeg_id, split, display=False,):\n    \n    # LOAD MIDDLE 50 SECONDS OF EEG SERIES\n    #eeg_path = f\"{BASE_PATH}/{split}_eegs/{eeg_id}.parquet\"\n    PATH = f'/kaggle/input/hms-harmful-brain-activity-classification/{split}_eegs/'\n    eeg = pd.read_parquet(f'{PATH}{eeg_id}.parquet')\n    \n    middle = (len(eeg)-10_000)//2\n    eeg = eeg.iloc[middle:middle+10_000]\n    \n    # VARIABLE TO HOLD SPECTROGRAM\n    img = np.zeros((150, 200, 4),dtype='float32')\n    \n    #if display: plt.figure(figsize=(10,7))\n    signals = []\n    for k in range(4):\n        COLS = FEATS[k]\n        \n        for kk in range(4):\n        \n            # COMPUTE PAIR DIFFERENCES\n            x = eeg[COLS[kk]].values - eeg[COLS[kk+1]].values\n\n            # FILL NANS\n            m = np.nanmean(x)\n            if np.isnan(x).mean()<1: x = np.nan_to_num(x,nan=m)\n            else: x[:] = 0\n\n            # DENOISE\n#             if USE_WAVELET:\n#                 x = denoise(x, wavelet=USE_WAVELET)\n            signals.append(x)\n\n            # RAW SPECTROGRAM\n            mel_spec = librosa.feature.melspectrogram(y=x, sr=200, hop_length=len(x)//200, \n                  n_fft=1024, n_mels=150, fmin=0, fmax=20, win_length=150)\n\n            # LOG TRANSFORM\n            width = (mel_spec.shape[1]//10)*10\n            mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max).astype(np.float32)[:,:width]\n\n            # STANDARDIZE TO -1 TO 1\n            mel_spec_db = (mel_spec_db+40)/40 \n            img[:,:,k] += mel_spec_db\n                \n        # AVERAGE THE 4 MONTAGE DIFFERENCES\n        img[:,:,k] /= 4.0\n        \n#         if display:\n#             plt.subplot(2,2,k+1)\n#             plt.imshow(img[:,:,k],aspect='auto',origin='lower')\n#             plt.title(f'EEG {eeg_id} - Spectrogram {NAMES[k]}')\n            \n#     if display: \n#         plt.show()\n#         plt.figure(figsize=(10,5))\n#         offset = 0\n#         for k in range(4):\n#             if k>0: offset -= signals[3-k].min()\n#             plt.plot(range(10_000),signals[k]+offset,label=NAMES[3-k])\n#             offset += signals[3-k].max()\n#         plt.legend()\n#         plt.title(f'EEG {eeg_id} Signals')\n#         plt.show()\n#         print(); print('#'*25); print()\n#         plt.close() \n    #np.save(f'{SPEC_DIR}/{split}/{eeg_id}',img)\n    return {eeg_id: img}","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:32:39.080827Z","iopub.execute_input":"2024-02-21T16:32:39.081459Z","iopub.status.idle":"2024-02-21T16:32:39.103717Z","shell.execute_reply.started":"2024-02-21T16:32:39.081425Z","shell.execute_reply":"2024-02-21T16:32:39.102932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nDISPLAY = 4\nEEG_IDS = df.eeg_id.unique()\nEEG_IDS_TEST = test_df.eeg_id.unique()\n\n#train eegs\neegs = joblib.Parallel(n_jobs=-1, backend=\"loky\")(\n    joblib.delayed(spectrogram_from_eeg)(eeg_id, \"train\")\n    for eeg_id in tqdm(EEG_IDS, total=len(EEG_IDS))\n)\nall_eegs = {k: v for d in eegs for k, v in d.items()}\n\n#test eegs\n# _ = joblib.Parallel(n_jobs=-1, backend=\"loky\")(\n#     joblib.delayed(spectrogram_from_eeg)(eeg_id, \"test\")\n#     for eeg_id in tqdm(EEG_IDS_TEST, total=len(EEG_IDS_TEST))\n# )","metadata":{"_kg_hide-input":false,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-02-21T16:37:55.260344Z","iopub.execute_input":"2024-02-21T16:37:55.261459Z","iopub.status.idle":"2024-02-21T16:52:16.981712Z","shell.execute_reply.started":"2024-02-21T16:37:55.261424Z","shell.execute_reply":"2024-02-21T16:52:16.980615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.save('eeg_specs',all_eegs)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:52:35.567534Z","iopub.execute_input":"2024-02-21T16:52:35.568173Z","iopub.status.idle":"2024-02-21T16:53:03.652441Z","shell.execute_reply.started":"2024-02-21T16:52:35.568131Z","shell.execute_reply":"2024-02-21T16:53:03.651272Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define a function to process a single eeg_id\ndef process_spec(spec_id, split=\"train\"):\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 # fill NaN values with 0, transpose for (Time, Freq) -> (Freq, Time)\n    spec = spec.astype(\"float32\")\n    #np.save(f\"{SPEC_DIR}/{split}/{spec_id}.npy\", spec)\n    return {spec_id: spec}\n\n# Get unique spec_ids of train and valid data\nspec_ids = df[\"spectrogram_id\"].unique()\n\n# Parallelize the processing using joblib for training data\nspecs = joblib.Parallel(n_jobs=-1, backend=\"loky\")(\n    joblib.delayed(process_spec)(spec_id, \"train\")\n    for spec_id in tqdm(spec_ids, total=len(spec_ids))\n)\nall_specs = {k: v for d in specs for k, v in d.items()}\n\n# Get unique spec_ids of test data\n# test_spec_ids = test_df[\"spectrogram_id\"].unique()\n\n# # Parallelize the processing using joblib for test data\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, total=len(test_spec_ids))\n# )","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:53:20.663909Z","iopub.execute_input":"2024-02-21T16:53:20.664645Z","iopub.status.idle":"2024-02-21T16:56:17.597895Z","shell.execute_reply.started":"2024-02-21T16:53:20.664614Z","shell.execute_reply":"2024-02-21T16:56:17.59673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.save('kaggle_specs',all_specs)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:56:40.417501Z","iopub.execute_input":"2024-02-21T16:56:40.418203Z","iopub.status.idle":"2024-02-21T16:57:09.727828Z","shell.execute_reply.started":"2024-02-21T16:56:40.418167Z","shell.execute_reply":"2024-02-21T16:57:09.726028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_augmenter(dim=image_size):\n    augmenters = [\n        keras_cv.layers.MixUp(alpha=2.0),\n        keras_cv.layers.RandomCutout(height_factor=(1.0, 1.0),\n                                     width_factor=(0.06, 0.1)), # freq-masking\n        keras_cv.layers.RandomCutout(height_factor=(0.06, 0.1),\n                                     width_factor=(1.0, 1.0)), # time-masking\n    ]\n    \n    def augment(img, label):\n        data = {\"images\":img, \"labels\":label}\n        for augmenter in augmenters:\n            if tf.random.uniform([]) < 0.5:\n                data = augmenter(data, training=True)\n        return data[\"images\"], data[\"labels\"]\n    \n    return augment\n\n\ndef build_decoder(with_labels=True, target_size=image_size, dtype=32):\n    def decode_signal(path, path_eeg, offset=None):\n        # Read .npy files and process the signal\n        file_bytes = tf.io.read_file(path)\n        sig = tf.io.decode_raw(file_bytes, tf.float32)\n        sig = sig[1024//dtype:]  # Remove header tag\n        sig = tf.reshape(sig, [200, -1])\n        \n        #Extract labeled subsample from full spectrogram using \"offset\"\n        if offset is not None: \n            #offset = offset // 2  # Only odd values are given\n            sig = sig[:, offset:offset+600]\n            \n            # Pad spectrogram to ensure the same input shape of [400, 300]\n            pad_size = tf.math.maximum(0, 600 - tf.shape(sig)[1])\n            sig = tf.pad(sig, [[0, 0], [0, pad_size]])\n            sig = tf.reshape(sig, [200, 600])\n        \n        # Log spectrogram \n        sig = tf.clip_by_value(sig, tf.math.exp(-4.0), tf.math.exp(8.0)) # avoid 0 in log\n        sig = tf.math.log(sig)\n        \n        # Normalize spectrogram\n        sig -= tf.math.reduce_mean(sig)\n        sig /= tf.math.reduce_std(sig) + 1e-6\n        \n        # Adding our eeg_spectogram\n        file_eeg = tf.io.read_file(path_eeg)\n        eeg = tf.io.decode_raw(file_eeg, tf.float32)\n        eeg = eeg[1024//dtype:]\n        eeg = tf.transpose(eeg)\n        eeg = tf.reshape(eeg, [200, -1])\n        \n        sig = tf.concat([sig, eeg], axis = 0)\n        \n        # Mono channel to 3 channels to use \"ImageNet\" weights\n        sig = tf.tile(sig[..., None], [1, 1, 3])\n        return sig\n    \n    def decode_label(label):\n        label = tf.one_hot(label, num_classes)\n        label = tf.cast(label, tf.float32)\n        label = tf.reshape(label, [num_classes])\n        return label\n    \n    def decode_with_labels(path, path_eeg, offset=None, label=None):\n        sig = decode_signal(path, path_eeg, offset)\n        label = decode_label(label)\n        return (sig, label)\n    \n    return decode_with_labels if with_labels else decode_signal\n\n\ndef build_dataset(paths, paths_eeg, offsets=None, labels=None, batch_size=32, cache=True,\n                  decode_fn=None, augment_fn=None,\n                  augment=False, repeat=True, shuffle=1024, \n                  cache_dir=\"\", drop_remainder=False):\n    if cache_dir != \"\" and cache is True:\n        os.makedirs(cache_dir, exist_ok=True)\n    \n    if decode_fn is None:\n        decode_fn = build_decoder(labels is not None)\n    \n    if augment_fn is None:\n        augment_fn = build_augmenter()\n    \n    AUTO = tf.data.experimental.AUTOTUNE\n    slices = (paths, paths_eeg, offsets) if labels is None else (paths, paths_eeg, offsets, labels)\n    \n    ds = tf.data.Dataset.from_tensor_slices(slices)\n    ds = ds.map(decode_fn, num_parallel_calls=AUTO)\n    ds = ds.cache(cache_dir) if cache else ds\n    ds = ds.repeat() if repeat else ds\n    if shuffle: \n        ds = ds.shuffle(shuffle, seed=42)\n        opt = tf.data.Options()\n        opt.experimental_deterministic = False\n        ds = ds.with_options(opt)\n    ds = ds.batch(batch_size, drop_remainder=drop_remainder)\n    ds = ds.map(augment_fn, num_parallel_calls=AUTO) if augment else ds\n    ds = ds.prefetch(AUTO)\n    return ds","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:57:09.732007Z","iopub.execute_input":"2024-02-21T16:57:09.7325Z","iopub.status.idle":"2024-02-21T16:57:09.778927Z","shell.execute_reply.started":"2024-02-21T16:57:09.732439Z","shell.execute_reply":"2024-02-21T16:57:09.77692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import StratifiedGroupKFold\n\nsgkf = StratifiedGroupKFold(n_splits=5, shuffle=True, random_state=42)\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":{"execution":{"iopub.status.busy":"2024-02-21T16:57:09.781435Z","iopub.execute_input":"2024-02-21T16:57:09.782206Z","iopub.status.idle":"2024-02-21T16:57:11.433405Z","shell.execute_reply.started":"2024-02-21T16:57:09.782167Z","shell.execute_reply":"2024-02-21T16:57:11.432535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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 != 0]\nvalid_df = sample_df[sample_df.fold == 0]\nprint(f\"# Num Train: {len(train_df)} | Num Valid: {len(valid_df)}\")\n\n# Train\ntrain_paths = train_df.spec2_path.values\ntrain_eeg_paths = train_df.eeg_to_spec\ntrain_offsets = train_df.spectrogram_label_offset_seconds.values.astype(int)\ntrain_labels = train_df.class_label.values\ntrain_ds = build_dataset(train_paths,train_eeg_paths, train_offsets, train_labels, batch_size=batch_size,\n                         repeat=True, shuffle=True, augment=True, cache=True)\n\n# Valid\nvalid_paths = valid_df.spec2_path.values \nvalid_eeg_paths = valid_df.eeg_to_spec\nvalid_offsets = valid_df.spectrogram_label_offset_seconds.values.astype(int)\nvalid_labels = valid_df.class_label.values\nvalid_ds = build_dataset(valid_paths, valid_eeg_paths, valid_offsets, valid_labels, batch_size=batch_size,\n                         repeat=False, shuffle=False, augment=False, cache=True)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:57:11.435963Z","iopub.execute_input":"2024-02-21T16:57:11.43653Z","iopub.status.idle":"2024-02-21T16:57:22.286113Z","shell.execute_reply.started":"2024-02-21T16:57:11.436503Z","shell.execute_reply":"2024-02-21T16:57:22.285095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imgs, tars = next(iter(train_ds))\n\nnum_imgs = 1\nplt.figure(figsize=(16, 20))\nfor i in range(num_imgs):\n    #plt.subplot(1, 4, i + 1)\n    img = imgs[i].numpy()[...,0]  # Adjust as per your image data format\n    img -= img.min()\n    img /= img.max() + 1e-4\n    tar = label2name[np.argmax(tars[i].numpy())]\n    plt.imshow(img)\n    plt.title(f\"Target: {tar}\")\n    plt.axis('off')\n    \n#plt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:57:46.022781Z","iopub.execute_input":"2024-02-21T16:57:46.023627Z","iopub.status.idle":"2024-02-21T16:57:46.301824Z","shell.execute_reply.started":"2024-02-21T16:57:46.023586Z","shell.execute_reply":"2024-02-21T16:57:46.300541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math\n\ndef get_lr_callback(batch_size=8, mode='cos', epochs=5, plot=False):\n    lr_start, lr_max, lr_min = 5e-5, 6e-6 * batch_size, 1e-5\n    lr_ramp_ep, lr_sus_ep, lr_decay = 3, 0, 0.75\n\n    def lrfn(epoch):  # Learning rate update function\n        if epoch < lr_ramp_ep: lr = (lr_max - lr_start) / lr_ramp_ep * epoch + lr_start\n        elif epoch < lr_ramp_ep + lr_sus_ep: lr = lr_max\n        elif mode == 'exp': lr = (lr_max - lr_min) * lr_decay**(epoch - lr_ramp_ep - lr_sus_ep) + lr_min\n        elif mode == 'step': lr = lr_max * lr_decay**((epoch - lr_ramp_ep - lr_sus_ep) // 2)\n        elif mode == 'cos':\n            decay_total_epochs, decay_epoch_index = epochs - lr_ramp_ep - lr_sus_ep + 3, epoch - lr_ramp_ep - lr_sus_ep\n            phase = math.pi * decay_epoch_index / decay_total_epochs\n            lr = (lr_max - lr_min) * 0.5 * (1 + math.cos(phase)) + lr_min\n        return lr\n\n    if plot:  # Plot lr curve if plot is True\n        plt.figure(figsize=(10, 5))\n        plt.plot(np.arange(epochs), [lrfn(epoch) for epoch in np.arange(epochs)], marker='o')\n        plt.xlabel('epoch'); plt.ylabel('lr')\n        plt.title('LR Scheduler')\n        plt.show()\n\n    return tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=False)  # Create lr callback\n\nlr_cb = get_lr_callback(64, mode='cos', plot=True)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:59:39.876845Z","iopub.execute_input":"2024-02-21T16:59:39.877729Z","iopub.status.idle":"2024-02-21T16:59:40.168246Z","shell.execute_reply.started":"2024-02-21T16:59:39.877699Z","shell.execute_reply":"2024-02-21T16:59:40.167342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications.efficientnet_v2 import EfficientNetV2L","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:59:44.831557Z","iopub.execute_input":"2024-02-21T16:59:44.8319Z","iopub.status.idle":"2024-02-21T16:59:44.844694Z","shell.execute_reply.started":"2024-02-21T16:59:44.831874Z","shell.execute_reply":"2024-02-21T16:59:44.843869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#base_model = EfficientNetV2M(input_shape = (480, 480, 3), include_top = True, weights = 'imagenet')","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:59:46.508469Z","iopub.execute_input":"2024-02-21T16:59:46.508838Z","iopub.status.idle":"2024-02-21T16:59:46.513056Z","shell.execute_reply.started":"2024-02-21T16:59:46.508808Z","shell.execute_reply":"2024-02-21T16:59:46.512029Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model = EfficientNetV2L(input_shape = (400, 600, 3), include_top = False, weights = 'imagenet')","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:59:46.792141Z","iopub.execute_input":"2024-02-21T16:59:46.792553Z","iopub.status.idle":"2024-02-21T17:01:07.351669Z","shell.execute_reply.started":"2024-02-21T16:59:46.792519Z","shell.execute_reply":"2024-02-21T17:01:07.350795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for layer in base_model.layers:\n    layer.trainable = False","metadata":{"execution":{"iopub.status.busy":"2024-02-21T17:02:12.331862Z","iopub.execute_input":"2024-02-21T17:02:12.33223Z","iopub.status.idle":"2024-02-21T17:02:12.376977Z","shell.execute_reply.started":"2024-02-21T17:02:12.332203Z","shell.execute_reply":"2024-02-21T17:02:12.376074Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x = base_model.output\nx = tf.keras.layers.Flatten()(x)\nx = tf.keras.layers.Dense(32, activation=\"relu\")(x)\nx = tf.keras.layers.Dropout(0.1)(x)\n\n# Add a final sigmoid layer with 1 node for classification output\npredictions = tf.keras.layers.Dense(6, activation=\"softmax\")(x)\nmodel_final = tf.keras.models.Model(inputs = base_model.input, outputs = predictions)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T17:02:13.332156Z","iopub.execute_input":"2024-02-21T17:02:13.333115Z","iopub.status.idle":"2024-02-21T17:02:13.475651Z","shell.execute_reply.started":"2024-02-21T17:02:13.333079Z","shell.execute_reply":"2024-02-21T17:02:13.474694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_final.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),\n              loss=LOSS, metrics = [LOSS])","metadata":{"execution":{"iopub.status.busy":"2024-02-21T17:02:14.92163Z","iopub.execute_input":"2024-02-21T17:02:14.921979Z","iopub.status.idle":"2024-02-21T17:02:14.965584Z","shell.execute_reply.started":"2024-02-21T17:02:14.921953Z","shell.execute_reply":"2024-02-21T17:02:14.964795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ckpt_cb = tf.keras.callbacks.ModelCheckpoint(\"best_model.keras\",\n                                         monitor='val_loss',\n                                         save_best_only=True,\n                                         save_weights_only=False,\n                                         mode='min')","metadata":{"execution":{"iopub.status.busy":"2024-02-21T17:02:18.942142Z","iopub.execute_input":"2024-02-21T17:02:18.942554Z","iopub.status.idle":"2024-02-21T17:02:18.947972Z","shell.execute_reply.started":"2024-02-21T17:02:18.942525Z","shell.execute_reply":"2024-02-21T17:02:18.946947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model_final.fit(\n    train_ds, \n    epochs=5,\n    callbacks=[ckpt_cb, lr_cb], \n    steps_per_epoch=len(train_df)//64,\n    validation_data=valid_ds, \n    verbose=1\n)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T17:02:20.470239Z","iopub.execute_input":"2024-02-21T17:02:20.471107Z","iopub.status.idle":"2024-02-21T17:02:52.088351Z","shell.execute_reply.started":"2024-02-21T17:02:20.471073Z","shell.execute_reply":"2024-02-21T17:02:52.087159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predictions","metadata":{}},{"cell_type":"code","source":"test_paths = test_df.spec2_path.values\ntest_eeg_paths = test_df.eeg_to_spec\ntest_ds = build_dataset(test_paths, test_eeg_paths, batch_size=min(CFG.batch_size, len(test_df)),\n                         repeat=False, shuffle=False, cache=False, augment=False)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:36:51.578331Z","iopub.status.idle":"2024-02-21T16:36:51.578678Z","shell.execute_reply.started":"2024-02-21T16:36:51.57851Z","shell.execute_reply":"2024-02-21T16:36:51.578527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = model_final.predict(test_ds)","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:36:51.579809Z","iopub.status.idle":"2024-02-21T16:36:51.580138Z","shell.execute_reply.started":"2024-02-21T16:36:51.579977Z","shell.execute_reply":"2024-02-21T16:36:51.579991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_df = test_df[[\"eeg_id\"]].copy()\ntarget_cols = [x.lower()+'_vote' for x in class_names]\npred_df[target_cols] = preds.tolist()\n\nsub_df = pd.read_csv(f'{BASE_PATH}/sample_submission.csv')\nsub_df = sub_df[[\"eeg_id\"]].copy()\nsub_df = sub_df.merge(pred_df, on=\"eeg_id\", how=\"left\")\nsub_df.to_csv(\"submission.csv\", index=False)\nsub_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-02-21T16:36:51.581185Z","iopub.status.idle":"2024-02-21T16:36:51.581541Z","shell.execute_reply.started":"2024-02-21T16:36:51.581353Z","shell.execute_reply":"2024-02-21T16:36:51.581367Z"},"trusted":true},"execution_count":null,"outputs":[]}]}