{"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"},{"sourceId":7392733,"sourceType":"datasetVersion","datasetId":4297749},{"sourceId":7465251,"sourceType":"datasetVersion","datasetId":4317718},{"sourceId":7772394,"sourceType":"datasetVersion","datasetId":4547084}],"dockerImageVersionId":30646,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# <div style=\"padding: 25px;color:white;margin:10;font-size:60%;text-align:left;display:fill;border-radius:10px;background-color:#FFFFFF;overflow:hidden;background-color:#A51C30\"><b><span style='color:#FFFFFF'>1 |</span></b> <b>GPUs Setting</b></div>","metadata":{}},{"cell_type":"code","source":"VER = 1\n\nimport os\nimport gc\nimport ctypes\nimport random\n\nimport numpy as np, pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport tensorflow as tf\nprint('tensorflow version:',tf.__version__)\n\n# CUDA 0,1\nos.environ['CUDA_VISIBLE_DEVICES'] = '0,1'\n\n# gpu strategy\ngpus = tf.config.list_physical_devices('GPU')\nif len(gpus) <= 1:\n    strategy = tf.distribute.OneDeviceStrategy(device='/gpu:0')\n    print(f'Using {len(gpus)} gpus')\nelse: \n    strategy = tf.distribute.MirroredStrategy()\n    print(f'Using {len(gpus)} gpus')\n    \n# warning filtering\nimport warnings\nwarnings.filterwarnings('ignore')\n\nLOAD_MODELS_FROM = None","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:39:59.850879Z","iopub.execute_input":"2024-03-06T06:39:59.851232Z","iopub.status.idle":"2024-03-06T06:40:24.365280Z","shell.execute_reply.started":"2024-03-06T06:39:59.851203Z","shell.execute_reply":"2024-03-06T06:40:24.364376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Seed**","metadata":{}},{"cell_type":"code","source":"SEED = 2024\n\ndef seed_everything():\n    np.random.seed(SEED)\n    random.seed(SEED)\n    os.environ[\"PYTHONHASHSEED\"] = str(SEED)\n    \nseed_everything()","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:40:24.366824Z","iopub.execute_input":"2024-03-06T06:40:24.367353Z","iopub.status.idle":"2024-03-06T06:40:24.372597Z","shell.execute_reply.started":"2024-03-06T06:40:24.367327Z","shell.execute_reply":"2024-03-06T06:40:24.371680Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# mixed_preicision\n# Helps memeory effectively \n\nMIX=True\n\nif MIX: \n    tf.config.optimizer.set_experimental_options({'auto_mixed_precision':True})\n    print(\"Mixed Precision Enabled\")\nelse:\n    print(\"Using Full Precision\")","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:40:24.373675Z","iopub.execute_input":"2024-03-06T06:40:24.374046Z","iopub.status.idle":"2024-03-06T06:40:24.385648Z","shell.execute_reply.started":"2024-03-06T06:40:24.374011Z","shell.execute_reply":"2024-03-06T06:40:24.384873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Clean Memory**","metadata":{}},{"cell_type":"code","source":"def clean_memory():\n    # malloc_trim: 현재 사용되지 않는 메모리를 시스템에서 다시 반환함0\n    ctypes.CDLL('libc.so.6').malloc_trim(0)\n    gc.collect()\nclean_memory()","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:40:24.387876Z","iopub.execute_input":"2024-03-06T06:40:24.388181Z","iopub.status.idle":"2024-03-06T06:40:24.598771Z","shell.execute_reply.started":"2024-03-06T06:40:24.388146Z","shell.execute_reply":"2024-03-06T06:40:24.597768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <div style=\"padding: 25px;color:white;margin:10;font-size:60%;text-align:left;display:fill;border-radius:10px;background-color:#FFFFFF;overflow:hidden;background-color:#A51C30\"><b><span style='color:#FFFFFF'>3 |</span></b> <b>Load Train Data</b></div>","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/train.csv\")\nprint('train shape: ',train.shape)\ndisplay(train.head())","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:40:24.600152Z","iopub.execute_input":"2024-03-06T06:40:24.600466Z","iopub.status.idle":"2024-03-06T06:40:24.903287Z","shell.execute_reply.started":"2024-03-06T06:40:24.600432Z","shell.execute_reply":"2024-03-06T06:40:24.902362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### <b><span style='color:#A51C30'> 3.1 </span> Raw EEG Signals</b>","metadata":{}},{"cell_type":"code","source":"df = pd.read_parquet('/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/1000913311.parquet')\nFEATS = df.columns\nprint(f'There are {len(FEATS)} raw eeg features')\nprint(list(FEATS))","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:40:24.904462Z","iopub.execute_input":"2024-03-06T06:40:24.904743Z","iopub.status.idle":"2024-03-06T06:40:25.210784Z","shell.execute_reply.started":"2024-03-06T06:40:24.904720Z","shell.execute_reply":"2024-03-06T06:40:25.209825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('We will use the follwing subset of 10 raw eeg features:')\nFEATS = ['Fp1','T3','C3','O1','Fp2','C4','T4','O2']\nFEAT2IDX = {x:y for x,y in zip(FEATS, range(len(FEATS)))}\nprint(FEATS)","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:40:25.212091Z","iopub.execute_input":"2024-03-06T06:40:25.212379Z","iopub.status.idle":"2024-03-06T06:40:25.218194Z","shell.execute_reply.started":"2024-03-06T06:40:25.212354Z","shell.execute_reply":"2024-03-06T06:40:25.217173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def eeg_from_parquet(parquet_path, display=False):\n    \n    # 특정 electrode만 추출하기\n    eeg = pd.read_parquet(parquet_path, columns=FEATS)\n    rows = len(eeg)\n    offset = (rows-10000)//2\n    # eeg의 구간: 50초\n    eeg = eeg.iloc[offset:offset+10_000]\n    \n    if display:\n        plt.figure(figsize=(10,5))\n        offset = 0\n        \n    # CONVERT TO NUMPY\n    data = np.zeros((10_000, len(FEATS)))\n    for j,col in enumerate(FEATS):\n        \n        # FILL NAN\n        x = eeg[col].values.astype('float32')\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        data[:,j] = x    \n        \n        if display: \n            if j!=0: offset += x.max()\n            plt.plot(range(10_000), x-offset, label=col)\n            offset -= x.min()\n            \n    if display:\n        plt.legend()\n        name = parquet_path.split('/')[-1]\n        name = name.split('.')[0]\n        plt.title(f'EEG {name}', size=16)\n        plt.show()\n        \n    return data    ","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:40:25.219347Z","iopub.execute_input":"2024-03-06T06:40:25.219619Z","iopub.status.idle":"2024-03-06T06:40:25.230309Z","shell.execute_reply.started":"2024-03-06T06:40:25.219596Z","shell.execute_reply":"2024-03-06T06:40:25.229386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nCREATE_EEGS = False\nall_eegs = {}\nDISPLAY = 4\nEEG_IDS = train.eeg_id.unique()\nPATH = '/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/'\n\nfor i, eeg_id in enumerate(EEG_IDS):\n    if (i%100==0)&(i!=0): print(i, ', ', end='')\n        \n    data = eeg_from_parquet(f'{PATH}{eeg_id}.parquet', display=i<DISPLAY) \n    all_eegs[eeg_id] = data\n    \n    if i==DISPLAY:\n        if CREATE_EEGS:\n            print(f'processing {train.eeg_id.nunique()} eeg parquets... ', end='')\n        else:\n            print(f'Reading {len(EEG_IDS)} eeg Numpys from disk.')\n            \n            break\n            \nall_eegs = np.load('/kaggle/input/brain-eegs/eegs.npy',allow_pickle=True).item()  ","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:40:25.231529Z","iopub.execute_input":"2024-03-06T06:40:25.231778Z","iopub.status.idle":"2024-03-06T06:42:13.755803Z","shell.execute_reply.started":"2024-03-06T06:40:25.231757Z","shell.execute_reply":"2024-03-06T06:42:13.754811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### <b><span style='color:#A51C30'> 3.2 </span> Deduplicate Train EEG Id</b>","metadata":{}},{"cell_type":"code","source":"# LOAD TRAIN \ndf = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')\nTARGETS = df.columns[-6:]\nTARS = {'Seizure':0, 'LPD':1, 'GPD':2, 'LRDA':3, 'GRDA':4, 'Other':5}\nTARS2 = {x:y for y,x in TARS.items()}\n\ntrain = df.groupby('eeg_id')[['patient_id']].agg('first')\n\ntmp = df.groupby('eeg_id')[TARGETS].agg('sum')\nfor t in TARGETS:\n    train[t] = tmp[t].values\n    \ny_data = train[TARGETS].values\ny_data = y_data / y_data.sum(axis=1,keepdims=True)\ntrain[TARGETS] = y_data\n\ntmp = df.groupby('eeg_id')[['expert_consensus']].agg('first')\ntrain['target'] = tmp\n\ndf['total_evaluators'] = df[['seizure_vote', 'lpd_vote', 'gpd_vote', 'lrda_vote', 'grda_vote', 'other_vote']].sum(axis=1)\ntmp = df.groupby('eeg_id')['total_evaluators'].agg('first')\ntrain['total_evaluators'] = tmp\n\ntrain = train.reset_index()\ntrain = train.loc[train.eeg_id.isin(EEG_IDS)]\nprint('Train Data with unique eeg_id shape:', train.shape )\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:13.760164Z","iopub.execute_input":"2024-03-06T06:42:13.760472Z","iopub.status.idle":"2024-03-06T06:42:14.069719Z","shell.execute_reply.started":"2024-03-06T06:42:13.760446Z","shell.execute_reply":"2024-03-06T06:42:14.068848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12,6))\nsns.histplot(data=train, x='total_evaluators', bins='auto')\nplt.xlabel('total_evaluators')\nplt.ylabel('count')\nplt.title('Distribution of total evaluators')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:14.071038Z","iopub.execute_input":"2024-03-06T06:42:14.071459Z","iopub.status.idle":"2024-03-06T06:42:14.362203Z","shell.execute_reply.started":"2024-03-06T06:42:14.071427Z","shell.execute_reply":"2024-03-06T06:42:14.361203Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### <b><span style='color:#A51C30'> 3.3 </span> Butter Low-Pass Filter</b>","metadata":{}},{"cell_type":"code","source":"from scipy.signal import butter, lfilter\n\ndef butter_lowpass_filter(data, cutoff_freq=20, sampling_rate=200, order=4):\n    nyquist = 0.5 * sampling_rate\n    normal_cutoff = cutoff_freq / nyquist\n    b, a = butter(order, normal_cutoff, btype='low', analog=False)\n    filtered_data = lfilter(b, a, data, axis=0)\n    return filtered_data","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:14.364133Z","iopub.execute_input":"2024-03-06T06:42:14.364420Z","iopub.status.idle":"2024-03-06T06:42:14.464622Z","shell.execute_reply.started":"2024-03-06T06:42:14.364396Z","shell.execute_reply":"2024-03-06T06:42:14.463684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <div style=\"padding: 25px;color:white;margin:10;font-size:60%;text-align:left;display:fill;border-radius:10px;background-color:#FFFFFF;overflow:hidden;background-color:#A51C30\"><b><span style='color:#FFFFFF'>4 |</span></b> <b>Data Loader</b></div>","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\n\nclass DataGenerator(tf.keras.utils.Sequence):\n    # Constructor(init method)\n    def __init__(self,data, batch_size=32, shuffle=True, eegs=all_eegs, augment=False,\n               mode='train'):\n        \n        self.data = data\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.eegs = eegs\n        self.augment = augment\n        self.mode = mode\n        self.on_epoch_end()\n        \n    def __len__(self):\n        ct = int(np.ceil(len(self.data)/self.batch_size))\n        return ct\n        \n    def __getitem__(self, index):\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n        X, y = self.__data_generation(indexes)\n        if self.augment: X = self.__augment_batch(X)\n        \n        return X, y\n        \n    def on_epoch_end(self):\n        self.indexes = np.arange(len(self.data))\n        if self.shuffle: np.random.shuffle(self.indexes)\n        \n    def __data_generation(self, indexes):\n        X = np.zeros((len(indexes),10_000,8), dtype='float32')\n        y = np.zeros((len(indexes),6),dtype='float32')\n        \n        sample = np.zeros((10_000, X.shape[-1]))\n        for j,i in enumerate(indexes):\n            row = self.data.iloc[i]\n            data = self.eegs[row.eeg_id] \n            \n            # FEATURE ENGINEER\n            sample[:,0] = data[:,FEAT2IDX['Fp1']] - data[:,FEAT2IDX['T3']]\n            sample[:,1] = data[:,FEAT2IDX['T3']] - data[:,FEAT2IDX['O1']]\n            \n            sample[:,2] = data[:,FEAT2IDX['Fp1']] - data[:,FEAT2IDX['C3']]\n            sample[:,3] = data[:,FEAT2IDX['C3']] - data[:,FEAT2IDX['O1']]\n            \n            sample[:,4] = data[:,FEAT2IDX['Fp2']] - data[:,FEAT2IDX['C4']]\n            sample[:,5] = data[:,FEAT2IDX['C4']] - data[:,FEAT2IDX['O2']]\n            \n            sample[:,6] = data[:,FEAT2IDX['Fp2']] - data[:,FEAT2IDX['T4']]\n            sample[:,7] = data[:,FEAT2IDX['T4']] - data[:,FEAT2IDX['O2']]\n            \n            \n            # crop scaling\n            sample = np.clip(sample, -1024,1024)\n\n            \n            # standarization: (x-mean)/std\n            # The mean of all the raw data: 0\n            # The std of all the raw data: 32\n            sample = np.nan_to_num(sample,nan=0) / 32.0\n            \n            # BUTTER LOW-PASS FILTER[0~30Hz]\n            sample = butter_lowpass_filter(sample)\n            \n            # Wavelet Filtering[db6]\n        \n            X[j,] = sample\n            if self.mode!= 'test':\n                y[j] = row[TARGETS]\n                \n    \n        return X,y\n    \n    def __middle_crop(self, sample):\n        crop_size = 1500 # 50s -> 15s(Zoom in Effect) \n        return sample[5000-crop_size:5000+crop_size]\n\n    def __resize(self, sample):\n        middle_sample = self.__middle_crop(sample)  \n        if np.random.rand() < 0.4:\n            resized_sample = np.resize(middle_sample, (10_000,8))\n        else:\n            resized_sample = sample\n        \n        return resized_sample\n    \n    def __augment_batch(self, sample_batch):\n        for i in range(sample_batch.shape[0]):\n            sample_batch[i, ] = self.__resize(sample_batch[i, ])\n        return sample_batch\n    ","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:44:17.320179Z","iopub.execute_input":"2024-03-06T06:44:17.320613Z","iopub.status.idle":"2024-03-06T06:44:17.340952Z","shell.execute_reply.started":"2024-03-06T06:44:17.320571Z","shell.execute_reply":"2024-03-06T06:44:17.339664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <div style=\"padding: 25px;color:white;margin:10;font-size:60%;text-align:left;display:fill;border-radius:10px;background-color:#FFFFFF;overflow:hidden;background-color:#A51C30\"><b><span style='color:#FFFFFF'>5 |</span></b> <b>Build WaveNet Model</b></div>","metadata":{}},{"cell_type":"code","source":"# TRAIN SCHEDULE\n\ndef lrfn(epoch):\n    return [1e-3,1e-3,1e-4,1e-4,1e-5][epoch]\nLR = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=True)\nEPOCHS = 5","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:14.699592Z","iopub.execute_input":"2024-03-06T06:42:14.699872Z","iopub.status.idle":"2024-03-06T06:42:14.704898Z","shell.execute_reply.started":"2024-03-06T06:42:14.699848Z","shell.execute_reply":"2024-03-06T06:42:14.704035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### <b><span style='color:#A51C30'> 5.1 </span> Wave_Block </b>","metadata":{}},{"cell_type":"markdown","source":"![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F16438831%2F57a7deab91934b33bf8bc3c334a16512%2Fw.PNG?generation=1708167117378209&alt=media)","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.layers import Input, Dense, Multiply, Add, Conv1D, Concatenate,AveragePooling1D, Bidirectional, LSTM\n\n\ndef wave_block(x, filters, kernel_size, n):\n    # dilation_rates: Convultion Layer 매개변수 중 하나\n    # Convultion filter의 간격을 조절하는 역할\n    dilation_rates = [2**i for i in range(n)]\n    # Convultion 1D Layer\n    x = Conv1D(filters = filters,\n              kernel_size = 1,\n              padding = 'same')(x)\n    res_x = x # 잔차 진행\n    # Activation Function: tanh, sigm\n    for dilation_rate in dilation_rates:\n        tanh_out = Conv1D(filters = filters, \n                         kernel_size = kernel_size,\n                         padding = 'same',\n                         activation = 'tanh',\n                         dilation_rate = dilation_rate)(x)\n        \n        sigm_out = Conv1D(filters = filters,\n                         kernel_size = kernel_size,\n                         padding = 'same',\n                         activation = 'sigmoid',\n                         dilation_rate = dilation_rate)(x)\n        # Multiply: 두 텐서의 요소를 곱하는 Layer\n        x = Multiply()([tanh_out, sigm_out])\n        x = Conv1D(filters=filters,\n                  kernel_size = 1,\n                  padding = 'same')(x)\n        # Add: 두 텐서의 요소를 더하는 layer \n        res_x = Add()([res_x, x])\n        \n    return res_x    \n        ","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:14.707287Z","iopub.execute_input":"2024-03-06T06:42:14.707566Z","iopub.status.idle":"2024-03-06T06:42:14.727914Z","shell.execute_reply.started":"2024-03-06T06:42:14.707543Z","shell.execute_reply":"2024-03-06T06:42:14.727031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### <b><span style='color:#A51C30'> 5.2 </span> Wave Net + Transformer Architecture </b>","metadata":{}},{"cell_type":"code","source":"def build_model():\n        \n    # INPUT \n    inp = tf.keras.Input(shape=(2_000,8))\n    \n    ############\n    # FEATURE EXTRACTION SUB MODEL\n    \"Dilated Inception CNN\"\n    inp2 = tf.keras.Input(shape=(2_000,1))\n    x = wave_block(inp2, 8, 2, 12)\n    x = wave_block(x, 16, 4, 8)\n    x = wave_block(x, 32, 6, 4)\n    x = wave_block(x, 64, 8, 1)\n    model2 = tf.keras.Model(inputs=inp2, outputs=x)\n    ###########\n    \n    # LEFT TEMPORAL CHAIN\n    x1 = model2(inp[:,:,0:1])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model2(inp[:,:,1:2])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z1 = tf.keras.layers.Average()([x1,x2])\n    \n    # LEFT PARASAGITTAL CHAIN\n    x1 = model2(inp[:,:,2:3])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model2(inp[:,:,3:4])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z2 = tf.keras.layers.Average()([x1,x2])\n    \n    # RIGHT PARASAGITTAL CHAIN\n    x1 = model2(inp[:,:,4:5])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model2(inp[:,:,5:6])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z3 = tf.keras.layers.Average()([x1,x2])\n    \n    # RIGHT TEMPORAL CHAIN\n    x1 = model2(inp[:,:,6:7])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model2(inp[:,:,7:8])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z4 = tf.keras.layers.Average()([x1,x2])\n    \n    # COMBINE CHAINS\n    y = tf.keras.layers.Concatenate()([z1,z2,z3,z4])\n    y = tf.keras.layers.Dense(64, activation='relu')(y)\n    y = tf.keras.layers.Dense(6,activation='softmax', dtype='float32')(y)\n    \n    # COMPILE MODEL\n    model = tf.keras.Model(inputs=inp, outputs=y)\n    opt = tf.keras.optimizers.Adam(learning_rate = 1e-3)\n    loss = tf.keras.losses.KLDivergence()\n    model.compile(loss=loss, optimizer = opt)\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:14.729095Z","iopub.execute_input":"2024-03-06T06:42:14.729360Z","iopub.status.idle":"2024-03-06T06:42:14.746602Z","shell.execute_reply.started":"2024-03-06T06:42:14.729338Z","shell.execute_reply":"2024-03-06T06:42:14.745852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <div style=\"padding: 25px;color:white;margin:10;font-size:60%;text-align:left;display:fill;border-radius:10px;background-color:#FFFFFF;overflow:hidden;background-color:#A51C30\"><b><span style='color:#FFFFFF'>6 |</span></b> <b>Cross Validation</b></div>","metadata":{}},{"cell_type":"markdown","source":"### <b><span style='color:#A51C30'> 6.1 </span> Train GroupKFold</b>","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv('/kaggle/input/labeled-wavenet/labeled_train.csv')\ndisplay(train)","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:14.747622Z","iopub.execute_input":"2024-03-06T06:42:14.747863Z","iopub.status.idle":"2024-03-06T06:42:14.864458Z","shell.execute_reply.started":"2024-03-06T06:42:14.747842Z","shell.execute_reply":"2024-03-06T06:42:14.863368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_MODEL = True      \nFOLDS_TO_TRAIN = 5\n\nfrom sklearn.model_selection import GroupKFold\nimport tensorflow.keras.backend as K, gc \n\nall_oof = [] ; all_true = [] \n\ngkf = GroupKFold(n_splits=5)\nfor i, (train_idx, valid_idx) in enumerate(gkf.split(train, train.target, train.patient_id)):\n    \n    # 진행상태 확인하기 \n    print('#'*25)\n    print(f'### Fold {i+1}')\n    print(f'### train size {len(train_idx)}, valid size {len(valid_idx)}')\n    print('#'*25)  \n          \n    # split train & valid       \n    train_gen = DataGenerator(train.iloc[train_idx], shuffle=True, batch_size=32, augment=True)\n    valid_gen = DataGenerator(train.iloc[valid_idx], shuffle=False, batch_size=64)\n    \n    # model 정의\n    # WaveNet Model은 이미 function으로 정함\n    K.clear_session()\n    with strategy.scope():\n        model = build_model()     \n          \n    # moodel fit\n    if TRAIN_MODEL:      \n        model.fit(train_gen, verbose=1,\n               validation_data = valid_gen, \n              epochs=EPOCHS, callbacks = [LR])  \n    # model save\n    # save_weights는 tf.keras에서 지원하는 기능\n        model.save_weights(f'WaveNet_{VER}_fold{i}.h5')\n    else:\n        model.load_weights(f'{LOAD_MODELS_FROM}WaveNet_{VER}_fold{i}.h5')\n            \n    # model predict\n    oof = model.predict(valid_gen, verbose=False) \n    all_oof.append(oof)\n    all_true.append(train.iloc[valid_idx][TARGETS].values)\n                           \n    if i == FOLDS_TO_TRAIN-1: break     \n                           \nall_oof = np.concatenate(all_oof)\nall_true = np.concatenate(all_true)","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:44:23.522528Z","iopub.execute_input":"2024-03-06T06:44:23.522897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del oof, train_gen, valid_gen\nclean_memory()","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:26.421456Z","iopub.status.idle":"2024-03-06T06:42:26.421767Z","shell.execute_reply.started":"2024-03-06T06:42:26.421613Z","shell.execute_reply":"2024-03-06T06:42:26.421625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### <b><span style='color:#A51C30'> 6.2 </span> CV Score</b>","metadata":{}},{"cell_type":"code","source":"import sys\nsys.path.append('/kaggle/input/kaggle-kl-div')\nfrom kaggle_kl_div import score\n\noof = pd.DataFrame(all_oof.copy())\noof['id'] = np.arange(len(oof))\n\ntrue = pd.DataFrame(all_true.copy())\ntrue['id'] = np.arange(len(true))\n\ncv = score(solution=true, submission=oof, row_id_column_name='id')\nprint('CV Score with WaveNet Raw EEG =',cv)","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:26.423236Z","iopub.status.idle":"2024-03-06T06:42:26.423572Z","shell.execute_reply.started":"2024-03-06T06:42:26.423402Z","shell.execute_reply":"2024-03-06T06:42:26.423416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <div style=\"padding: 25px;color:white;margin:10;font-size:60%;text-align:left;display:fill;border-radius:10px;background-color:#FFFFFF;overflow:hidden;background-color:#A51C30\"><b><span style='color:#FFFFFF'>7 |</span></b> <b>Submit to Kaggle LB</b></div>","metadata":{}},{"cell_type":"code","source":"del all_eegs, train; gc.collect()\ntest = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/test.csv')\nprint('Test shape:',test.shape)\ntest.head()","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:26.424404Z","iopub.status.idle":"2024-03-06T06:42:26.424740Z","shell.execute_reply.started":"2024-03-06T06:42:26.424573Z","shell.execute_reply":"2024-03-06T06:42:26.424586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_eegs2 = {}\nDISPLAY = 1\nEEG_IDS2 = test.eeg_id.unique()\nPATH2 = '/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/'\n\nprint('Processing Test EEG parquets...'); print()\nfor i,eeg_id in enumerate(EEG_IDS2):\n        \n    # SAVE EEG TO PYTHON DICTIONARY OF NUMPY ARRAYS\n    data = eeg_from_parquet(f'{PATH2}{eeg_id}.parquet', i<DISPLAY)\n    all_eegs2[eeg_id] = data","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:26.425805Z","iopub.status.idle":"2024-03-06T06:42:26.426136Z","shell.execute_reply.started":"2024-03-06T06:42:26.425955Z","shell.execute_reply":"2024-03-06T06:42:26.425967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# INFER MLP ON TEST\npreds = []\nmodel = build_model()\ntest_gen = DataGenerator(test, shuffle=False, batch_size=64, eegs=all_eegs2, mode='test')\n\nprint('Inferring test... ',end='')\nfor i in range(FOLDS_TO_TRAIN):\n    print(f'fold {i+1}, ',end='')\n    if TRAIN_MODEL:\n        model.load_weights(f'WaveNet_{VER}_fold{i}.h5')\n    else:\n        model.load_weights(f'{LOAD_MODELS_FROM}WaveNet_{VER}_fold{i}.h5')\n    pred = model.predict(test_gen, verbose=0)\n    preds.append(pred)\npred = np.mean(preds,axis=0)\nprint()\nprint('Test preds shape',pred.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:26.427258Z","iopub.status.idle":"2024-03-06T06:42:26.427701Z","shell.execute_reply.started":"2024-03-06T06:42:26.427474Z","shell.execute_reply":"2024-03-06T06:42:26.427491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CREATE SUBMISSION.CSV\nfrom IPython.display import display\n\nsub = pd.DataFrame({'eeg_id':test.eeg_id.values})\nsub[TARGETS] = pred\nsub.to_csv('submission.csv',index=False)\nprint('Submission shape',sub.shape)\ndisplay( sub.head() )\n\n# SANITY CHECK TO CONFIRM PREDICTIONS SUM TO ONE\nprint('Sub row 0 sums to:',sub.iloc[0,-6:].sum())","metadata":{"execution":{"iopub.status.busy":"2024-03-06T06:42:26.428829Z","iopub.status.idle":"2024-03-06T06:42:26.429269Z","shell.execute_reply.started":"2024-03-06T06:42:26.429047Z","shell.execute_reply":"2024-03-06T06:42:26.429064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}