{"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":2378330,"sourceType":"datasetVersion","datasetId":492658},{"sourceId":7392733,"sourceType":"datasetVersion","datasetId":4297749},{"sourceId":7392775,"sourceType":"datasetVersion","datasetId":4297782},{"sourceId":7402356,"sourceType":"datasetVersion","datasetId":4304475},{"sourceId":7549990,"sourceType":"datasetVersion","datasetId":4397175},{"sourceId":7754261,"sourceType":"datasetVersion","datasetId":4532886},{"sourceId":7805987,"sourceType":"datasetVersion","datasetId":4571300},{"sourceId":7810741,"sourceType":"datasetVersion","datasetId":4574781},{"sourceId":7810897,"sourceType":"datasetVersion","datasetId":4574876},{"sourceId":7813071,"sourceType":"datasetVersion","datasetId":4576535},{"sourceId":7818154,"sourceType":"datasetVersion","datasetId":4580420},{"sourceId":7819029,"sourceType":"datasetVersion","datasetId":4581021},{"sourceId":7828317,"sourceType":"datasetVersion","datasetId":4587588},{"sourceId":7870824,"sourceType":"datasetVersion","datasetId":4618382},{"sourceId":7872459,"sourceType":"datasetVersion","datasetId":4619437},{"sourceId":7945384,"sourceType":"datasetVersion","datasetId":4671804},{"sourceId":7972200,"sourceType":"datasetVersion","datasetId":4691112},{"sourceId":8028982,"sourceType":"datasetVersion","datasetId":4533761},{"sourceId":8049416,"sourceType":"datasetVersion","datasetId":4746751},{"sourceId":8061048,"sourceType":"datasetVersion","datasetId":4755000},{"sourceId":8061063,"sourceType":"datasetVersion","datasetId":4755011},{"sourceId":158958765,"sourceType":"kernelVersion"},{"sourceId":160700706,"sourceType":"kernelVersion"},{"sourceId":165876189,"sourceType":"kernelVersion"}],"dockerImageVersionId":30648,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nprint(tf.__version__)\n","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:10:31.153050Z","iopub.execute_input":"2024-04-09T09:10:31.153939Z","iopub.status.idle":"2024-04-09T09:10:43.226607Z","shell.execute_reply.started":"2024-04-09T09:10:31.153905Z","shell.execute_reply":"2024-04-09T09:10:43.225702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# TRAINING","metadata":{}},{"cell_type":"markdown","source":"## Global constants","metadata":{}},{"cell_type":"code","source":"# Set to True for inference only, False for training\nONLY_INFERENCE = True\n\n# Configuration for model training\nFOLDS = 4\nEPOCHS = 4\nBATCH = 32\nNAME = 'None'\n\nSPEC_SIZE  = (512, 512, 3)\nCLASSES = [\"seizure_vote\", \"lpd_vote\", \"gpd_vote\", \"lrda_vote\", \"grda_vote\", \"other_vote\"]\nN_CLASSES = len(CLASSES)\nTARGETS = CLASSES","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:10:43.228422Z","iopub.execute_input":"2024-04-09T09:10:43.228958Z","iopub.status.idle":"2024-04-09T09:10:43.234230Z","shell.execute_reply.started":"2024-04-09T09:10:43.228931Z","shell.execute_reply":"2024-04-09T09:10:43.233251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"IMPORTS","metadata":{}},{"cell_type":"code","source":"!pip install --no-index --find-links=/kaggle/input/tf-efficientnet-whl-files /kaggle/input/tf-efficientnet-whl-files/efficientnet-1.1.1-py3-none-any.whl","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:10:43.235469Z","iopub.execute_input":"2024-04-09T09:10:43.235808Z","iopub.status.idle":"2024-04-09T09:10:56.432789Z","shell.execute_reply.started":"2024-04-09T09:10:43.235775Z","shell.execute_reply":"2024-04-09T09:10:56.431593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\nimport os\nimport random\nimport sys\nimport time\n\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom sklearn.model_selection import StratifiedGroupKFold\nfrom tensorflow.keras import backend as K\nfrom tqdm import tqdm \nfrom scipy.ndimage import gaussian_filter\nfrom scipy.signal import butter, filtfilt, iirnotch\nfrom scipy.signal import spectrogram as spectrogram_np\n\nimport efficientnet.tfkeras as efn\n\nsys.path.append(f'/kaggle/input/kaggle-kl-div')\nfrom kaggle_kl_div import score","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:10:56.434506Z","iopub.execute_input":"2024-04-09T09:10:56.434894Z","iopub.status.idle":"2024-04-09T09:10:57.113006Z","shell.execute_reply.started":"2024-04-09T09:10:56.434858Z","shell.execute_reply":"2024-04-09T09:10:57.111972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n!nvidia-smi\n\n# Installation of RAPIDS to Use cuSignal\n!cp ../input/rapids/rapids.0.17.0 /opt/conda/envs/rapids.tar.gz\n!cd /opt/conda/envs/ && tar -xzvf rapids.tar.gz > /dev/null\n!rm /opt/conda/envs/rapids.tar.gz\n\nsys.path += [\"/opt/conda/envs/rapids/lib/python3.7/site-packages\"]\nsys.path += [\"/opt/conda/envs/rapids/lib/python3.7\"]\nsys.path += [\"/opt/conda/envs/rapids/lib\"]\n!cp /opt/conda/envs/rapids/lib/libxgboost.so /opt/conda/lib/\n\nimport cupy as cp\nimport cusignal","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:10:57.116314Z","iopub.execute_input":"2024-04-09T09:10:57.117486Z","iopub.status.idle":"2024-04-09T09:12:22.920824Z","shell.execute_reply.started":"2024-04-09T09:10:57.117457Z","shell.execute_reply":"2024-04-09T09:12:22.919822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Environment functions","metadata":{}},{"cell_type":"code","source":"# Set the visible CUDA devices\nos.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0,1\"\n\n# Set the strategy for using GPUs\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)} GPU')\nelse:\n    strategy = tf.distribute.MirroredStrategy()\n    print(f'Using {len(gpus)} GPUs')\n\n# Configure memory growth\nif gpus:\n    try:\n        for gpu in gpus:\n            tf.config.experimental.set_memory_growth(gpu, True)\n    except RuntimeError as e:\n        print(e)\n\n# Enable or disable mixed precision\nMIX = True\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-04-09T09:12:22.922148Z","iopub.execute_input":"2024-04-09T09:12:22.922488Z","iopub.status.idle":"2024-04-09T09:12:24.020761Z","shell.execute_reply.started":"2024-04-09T09:12:22.922459Z","shell.execute_reply":"2024-04-09T09:12:24.019685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to set random seed for reproducibility\ndef set_random_seed(seed: int = 42, deterministic: bool = False):\n    random.seed(seed)\n    np.random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    tf.random.set_seed(seed)\n    if deterministic:\n        os.environ['TF_DETERMINISTIC_OPS'] = '1'\n    else:\n        os.environ.pop('TF_DETERMINISTIC_OPS', None)\n\n# Set a deterministic behavior\nset_random_seed(deterministic=True)","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:24.021997Z","iopub.execute_input":"2024-04-09T09:12:24.022345Z","iopub.status.idle":"2024-04-09T09:12:25.029676Z","shell.execute_reply.started":"2024-04-09T09:12:24.022319Z","shell.execute_reply":"2024-04-09T09:12:25.028513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data","metadata":{}},{"cell_type":"code","source":"def create_train_data():\n    # Read the dataset\n    df = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')\n    \n    # Create a new identifier combining multiple columns\n    id_cols = ['eeg_id', 'spectrogram_id', 'seizure_vote', 'lpd_vote', 'gpd_vote', 'lrda_vote', 'grda_vote', 'other_vote']\n    df['new_id'] = df[id_cols].astype(str).agg('_'.join, axis=1)\n    \n    # Calculate the sum of votes for each class\n    df['sum_votes'] = df[CLASSES].sum(axis=1)\n    \n    # Group the data by the new identifier and aggregate various features\n    agg_functions = {\n        'eeg_id': 'first',\n        'eeg_label_offset_seconds': ['min', 'max'],\n        'spectrogram_label_offset_seconds': ['min', 'max'],\n        'spectrogram_id': 'first',\n        'patient_id': 'first',\n        'expert_consensus': 'first',\n        **{col: 'sum' for col in CLASSES},\n        'sum_votes': 'mean',\n    }\n    grouped_df = df.groupby('new_id').agg(agg_functions).reset_index()\n\n    # Flatten the MultiIndex columns and adjust column names\n    grouped_df.columns = [f\"{col[0]}_{col[1]}\" if col[1] else col[0] for col in grouped_df.columns]\n    grouped_df.columns = grouped_df.columns.str.replace('_first', '').str.replace('_sum', '').str.replace('_mean', '')\n    \n    # Normalize the class columns\n    y_data = grouped_df[CLASSES].values\n    y_data_normalized = y_data / y_data.sum(axis=1, keepdims=True)\n    grouped_df[CLASSES] = y_data_normalized\n\n    # Split the dataset into high and low quality based on the sum of votes\n    high_quality_df = grouped_df[grouped_df['sum_votes'] >= 10].reset_index(drop=True)\n    low_quality_df = grouped_df[(grouped_df['sum_votes'] < 10) & (grouped_df['sum_votes'] >= 0)].reset_index(drop=True)\n\n    return high_quality_df, low_quality_df","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:25.031079Z","iopub.execute_input":"2024-04-09T09:12:25.031494Z","iopub.status.idle":"2024-04-09T09:12:25.043860Z","shell.execute_reply.started":"2024-04-09T09:12:25.031456Z","shell.execute_reply":"2024-04-09T09:12:25.042840Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DataGenerator(tf.keras.utils.Sequence):\n\n    def __init__(self, data, batch_size=32, shuffle=False, mode='train'):\n        self.data = data\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.mode = mode\n        self.on_epoch_end()\n\n    def __len__(self):\n        \"\"\"Denotes the number of batches per epoch.\"\"\"\n        return int(np.ceil(len(self.data) / self.batch_size))\n\n    def __getitem__(self, index):\n        \"\"\"Generate one batch of data.\"\"\"\n        indexes = self.indexes[index * self.batch_size : (index + 1) * self.batch_size]\n        X, y = self.__data_generation(indexes)\n        return X, y\n\n    def on_epoch_end(self):\n        \"\"\"Updates indexes after each epoch.\"\"\"\n        self.indexes = np.arange(len(self.data))\n        if self.shuffle:\n            np.random.shuffle(self.indexes)\n\n    def __data_generation(self, indexes):\n        \"\"\"Generates data containing batch_size samples.\"\"\"\n        # Initialization\n        X = np.zeros((len(indexes), *SPEC_SIZE), dtype='float32')\n        y = np.zeros((len(indexes), len(CLASSES)), dtype='float32')\n\n        # Generate data\n        for j, i in enumerate(indexes):\n            row = self.data.iloc[i]\n            eeg_id = row['eeg_id']\n            spec_offset = int(row['spectrogram_label_offset_seconds_min'])\n            eeg_offset = int(row['eeg_label_offset_seconds_min'])\n            file_path = f'/kaggle/input/3-diff-time-specs-hms/images/{eeg_id}_{spec_offset}_{eeg_offset}.npz'\n            data = np.load(file_path)\n            eeg_data = data['final_image']\n            eeg_data_expanded = np.repeat(eeg_data[:, :, np.newaxis], 3, axis=2)\n\n            X[j] = eeg_data_expanded\n            if self.mode != 'test':\n                y[j] = row[CLASSES]\n\n        return X, y","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:25.045301Z","iopub.execute_input":"2024-04-09T09:12:25.045663Z","iopub.status.idle":"2024-04-09T09:12:25.060396Z","shell.execute_reply.started":"2024-04-09T09:12:25.045600Z","shell.execute_reply":"2024-04-09T09:12:25.059428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model","metadata":{}},{"cell_type":"code","source":"def lrfn(epoch):\n    lr_schedule = [1e-3, 1e-3, 1e-3, 1e-4, 1e-4, 1e-4, 1e-5, 1e-5, 1e-5]\n    return lr_schedule[epoch]\n\n# Define the learning rate scheduler callback\nLR = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=True)\n\ndef build_EfficientNetB2(input_shape=(512, 512, 3), num_classes=6):\n    inp = tf.keras.Input(shape=input_shape)\n\n    base_model = efn.EfficientNetB2(include_top=False, weights=None, input_shape=None)\n    base_model.load_weights(f'/kaggle/input/tf-efficientnet-imagenet-weights/efficientnet-b2_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5')\n\n    # OUTPUT\n    x = base_model(inp)\n    x = tf.keras.layers.GlobalAveragePooling2D()(x)\n    x = tf.keras.layers.Dense(num_classes,activation='softmax', dtype='float32')(x)\n\n    # COMPILE MODEL\n    model = tf.keras.Model(inputs=inp, outputs=x)\n    opt = tf.keras.optimizers.Adam(learning_rate = 1e-3)\n    loss = tf.keras.losses.KLDivergence()\n\n    model.compile(loss=loss, optimizer = opt)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:25.061662Z","iopub.execute_input":"2024-04-09T09:12:25.063720Z","iopub.status.idle":"2024-04-09T09:12:25.072771Z","shell.execute_reply.started":"2024-04-09T09:12:25.063686Z","shell.execute_reply":"2024-04-09T09:12:25.071826Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## cross_validate_model - Label Refine","metadata":{}},{"cell_type":"code","source":"def cross_validate_model(train_data, train_data_2, folds, random_seed, targets, nome_modelo):\n    inicio = time.time()\n    path_model = f'MLP_Model{nome_modelo}'\n    if not os.path.exists(path_model):\n        os.makedirs(path_model)\n\n    all_oof = []\n    all_oof2 = []\n    all_true = []\n    models = []\n    score_list = []\n    \n    # Separating the data to iterate over both dataframes simultaneously\n    gkf = StratifiedGroupKFold(n_splits=folds, shuffle=True, random_state=random_seed)\n    splits1 = list(gkf.split(train_data, train_data[[\"expert_consensus\"]], train_data[\"patient_id\"]))\n    splits2 = list(gkf.split(train_data_2, train_data_2[[\"expert_consensus\"]], train_data_2[\"patient_id\"]))\n\n    # Iterate over folds in parallel\n    for i, ((train_index, valid_index), (train_index2, valid_index2)) in enumerate(zip(splits1, splits2)):\n        \n        # Copy the dataframes to avoid leaks\n        train_data_ = train_data.copy()\n        train_data_2_ = train_data_2.copy()\n        set_random_seed(random_seed, deterministic=True)\n        \n        # Start folding\n        print('#' * 25)\n        print(f'### Fold {i + 1}')\n        print(f'### train size 1 {len(train_index)}, valid size {len(valid_index)}')\n        print(f'### train size 2 {len(train_index2)}, valid size {len(valid_index2)}')\n        print('#' * 25)\n\n        ### --------------------------- Performs model 1 training -------------- --------------------------- ###\n        K.clear_session()\n        train_gen = DataGenerator(train_data_.iloc[train_index], shuffle=True, batch_size=BATCH)\n        valid_gen = DataGenerator(train_data_.iloc[valid_index], shuffle=False, batch_size=(BATCH*2), mode='valid')\n        model = build_EfficientNetB2(input_shape=(512, 512, 3), num_classes=6)\n        history = model.fit(train_gen, verbose=2, validation_data=valid_gen, epochs=EPOCHS, callbacks=[LR])\n\n        # Model training result 1\n        train_loss = history.history['loss'][-1]  \n        valid_loss = history.history['val_loss'][-1]\n        print(f'train_loss 1 {train_loss} valid_loss 1 {valid_loss}')\n        score_list.append((train_loss, valid_loss))\n\n        \n        ### --------------------------- creation of pseudo labels ---------------- ------------------------- ###\n        # pseudo labels for low quality data\n        train_2_index_total_gen = DataGenerator(train_data_2_.iloc[train_index2], shuffle=False, batch_size=BATCH)\n        pseudo_labels_2 = model.predict(train_2_index_total_gen, verbose=2)\n        # Refinement of low quality labels\n        train_data_2_.loc[train_index2, TARGETS] /= 2\n        train_data_2_.loc[train_index2, TARGETS] += pseudo_labels_2 / 2\n\n        # pseudo labels for high quality data (50% of data)\n        train_data_3_ = train_data_\n        train_3_index_total_gen = DataGenerator(train_data_3_.iloc[train_index], shuffle=False, batch_size=BATCH)\n        pseudo_labels_3 = model.predict(train_3_index_total_gen, verbose=2)\n        # Refinement of high quality labels\n        train_data_3_.loc[train_index, TARGETS] /= 2\n        train_data_3_.loc[train_index, TARGETS] += pseudo_labels_3 / 2\n\n        ### --------------------------- Creation of the data generator for the refined labels model --------- -------------------------------- ###\n        # Low quality data\n        np.random.shuffle(train_index)\n        np.random.shuffle(valid_index)\n        sixty_percent_length = int(0.5 * len(train_data_3_))\n        train_index_60 = train_index[:int(sixty_percent_length * len(train_index) / len(train_data_3_))]\n        valid_index_60 = valid_index[:int(sixty_percent_length * len(valid_index) / len(train_data_3_))]\n        train_gen_2 = DataGenerator(pd.concat([train_data_3_.iloc[train_index_60], train_data_2_.iloc[train_index2]]), shuffle=True, batch_size=BATCH)\n        valid_gen_2 = DataGenerator(pd.concat([train_data_3_.iloc[valid_index_60], train_data_2_.iloc[valid_index2]]), shuffle=False, batch_size=BATCH*2, mode='valid')\n        # Rebuild the high quality data generator with 50% of the labels refined\n        train_gen = DataGenerator(train_data_.iloc[train_index], shuffle=True, batch_size=BATCH)\n        valid_gen = DataGenerator(train_data_.iloc[valid_index], shuffle=False, batch_size=(BATCH*2), mode='valid')\n        \n        ### --------------------------- Model 2 training and finetunning -------------- --------------------------- ###\n        K.clear_session()\n        new_model = build_EfficientNetB2(input_shape=(512, 512, 3), num_classes=6)\n        # Training with the refined low-quality data\n        history = new_model.fit(train_gen_2, verbose=2, validation_data=valid_gen_2, epochs=EPOCHS, callbacks=[LR])\n        # Finetuning with refined high-quality data\n        history = new_model.fit(train_gen, verbose=2, validation_data=valid_gen, epochs=EPOCHS, callbacks=[LR])\n        new_model.save_weights(f'{path_model}/MLP_fold{i}.weights.h5')\n        models.append(new_model)\n\n        # Model 2 training result\n        train_loss = history.history['loss'][-1]  # Valor da perda do último epoch de treinamento\n        valid_loss = history.history['val_loss'][-1]  # Valor da perda do último epoch de validação\n        print(f'train_loss 2 {train_loss} valid_loss 2 {valid_loss}')\n        score_list.append((train_loss, valid_loss))\n\n\n        # MLP OOF\n        oof = new_model.predict(valid_gen, verbose=2)\n        all_oof.append(oof)\n        all_true.append(train_data.iloc[valid_index][TARGETS].values)\n\n        # TRAIN MEAN OOF\n        y_train = train_data.iloc[train_index][targets].values\n        y_valid = train_data.iloc[valid_index][targets].values\n        oof = y_valid.copy()\n        for j in range(6):\n            oof[:,j] = y_train[:,j].mean()\n        oof = oof / oof.sum(axis=1,keepdims=True)\n        all_oof2.append(oof)\n\n        del model, new_model, train_gen, valid_gen, train_2_index_total_gen, train_gen_2, valid_gen_2, oof, y_train, y_valid, train_index, valid_index\n        K.clear_session()\n        gc.collect()\n\n        if i==folds-1: break\n\n    all_oof = np.concatenate(all_oof)\n    all_oof2 = np.concatenate(all_oof2)\n    all_true = np.concatenate(all_true)\n\n    oof = pd.DataFrame(all_oof.copy())\n    oof['id'] = np.arange(len(oof))\n\n    true = pd.DataFrame(all_true.copy())\n    true['id'] = np.arange(len(true))\n\n    cv = score(solution=true, submission=oof, row_id_column_name='id')\n    fim = time.time()\n    tempo_execucao = fim - inicio\n    print(f'{nome_modelo} CV Score with EEG Spectrograms ={cv} tempo: {tempo_execucao}')\n    \n    gc.collect()\n\n    score_array = np.array(score_list)\n    std_dev = np.std(score_array, axis=0)\n    std_dev = std_dev.tolist()\n\n    return cv, tempo_execucao, all_oof, all_oof2, all_true, models, score_list, std_dev, path_model","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:25.074831Z","iopub.execute_input":"2024-04-09T09:12:25.075107Z","iopub.status.idle":"2024-04-09T09:12:25.105825Z","shell.execute_reply.started":"2024-04-09T09:12:25.075085Z","shell.execute_reply":"2024-04-09T09:12:25.104950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if not ONLY_INFERENCE:\n    high_quality_df, low_quality_df = create_train_data()\n    result, tempo_execucao, all_oof, all_oof2, all_true, models, score_list, std_dev, path_model = cross_validate_model(high_quality_df, low_quality_df, FOLDS, 42, CLASSES, NAME)\n    print(f'Result cv V1 final {result}{tempo_execucao} {score_list} {std_dev}')\n    display(result)","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:25.107091Z","iopub.execute_input":"2024-04-09T09:12:25.107587Z","iopub.status.idle":"2024-04-09T09:12:25.117340Z","shell.execute_reply.started":"2024-04-09T09:12:25.107555Z","shell.execute_reply":"2024-04-09T09:12:25.116313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# INFERENCE","metadata":{}},{"cell_type":"code","source":"def create_spectrogram_with_cusignal(eeg_data, eeg_id, start, duration= 50,\n                                    low_cut_freq = 0.7, high_cut_freq = 20, order_band = 5,\n                                    spec_size_freq = 267, spec_size_time = 30,\n                                    nperseg_ = 1500, noverlap_ = 1483, nfft_ = 2750,\n                                    sigma_gaussian = 0.7, \n                                    mean_montage_names = 4):\n    \n    electrode_names = ['LL', 'RL', 'LP', 'RP']\n\n    electrode_pairs = [\n        ['Fp1', 'F7', 'T3', 'T5', 'O1'],\n        ['Fp2', 'F8', 'T4', 'T6', 'O2'],\n        ['Fp1', 'F3', 'C3', 'P3', 'O1'],\n        ['Fp2', 'F4', 'C4', 'P4', 'O2']\n    ]\n    \n    # Filter specifications\n    nyquist_freq = 0.5 * 200\n    low_cut_freq_normalized = low_cut_freq / nyquist_freq\n    high_cut_freq_normalized = high_cut_freq / nyquist_freq\n\n    # Bandpass and notch filter\n    bandpass_coefficients = butter(order_band, [low_cut_freq_normalized, high_cut_freq_normalized], btype='band')\n    notch_coefficients = iirnotch(w0=60, Q=30, fs=200)\n    \n    spec_size = duration * 200\n    start = start * 200\n    real_start = start + (10_000//2) - (spec_size//2)\n    eeg_data = eeg_data.iloc[real_start:real_start+spec_size]\n    \n    \n    # Spectrogram parameters\n    fs = 200\n    nperseg = nperseg_\n    noverlap = noverlap_\n    nfft = nfft_\n    \n    if spec_size_freq <=0 or spec_size_time <=0:\n        frequencias_size = int((nfft // 2)/5.15198)+1\n        segmentos = int((spec_size - noverlap) / (nperseg - noverlap)) \n    else:\n        frequencias_size = spec_size_freq\n        segmentos = spec_size_time\n        \n    spectrogram = cp.zeros((frequencias_size, segmentos, 4), dtype='float32')\n    \n    processed_eeg = {}\n\n    for i, name in enumerate(electrode_names):\n        cols = electrode_pairs[i]\n        processed_eeg[name] = np.zeros(spec_size)\n        for j in range(4):\n            # Compute differential signals\n            signal = cp.array(eeg_data[cols[j]].values - eeg_data[cols[j+1]].values)\n\n            # Handle NaNs\n            mean_signal = cp.nanmean(signal)\n            signal = cp.nan_to_num(signal, nan=mean_signal) if cp.isnan(signal).mean() < 1 else cp.zeros_like(signal)\n            \n\n            # Filter bandpass and notch\n            signal_filtered = filtfilt(*notch_coefficients, signal.get())\n            signal_filtered = filtfilt(*bandpass_coefficients, signal_filtered)\n            signal = cp.asarray(signal_filtered)\n            \n            frequencies, times, Sxx = cusignal.spectrogram(signal, fs, nperseg=nperseg, noverlap=noverlap, nfft=nfft)\n\n            # Filter frequency range\n            valid_freqs = (frequencies >= 0.59) & (frequencies <= 20)\n            frequencies_filtered = frequencies[valid_freqs]\n            Sxx_filtered = Sxx[valid_freqs, :]\n\n            # Logarithmic transformation and normalization using Cupy\n            spectrogram_slice = cp.clip(Sxx_filtered, cp.exp(-4), cp.exp(6))\n            spectrogram_slice = cp.log10(spectrogram_slice)\n\n            normalization_epsilon = 1e-6\n            mean = spectrogram_slice.mean(axis=(0, 1), keepdims=True)\n            std = spectrogram_slice.std(axis=(0, 1), keepdims=True)\n            spectrogram_slice = (spectrogram_slice - mean) / (std + normalization_epsilon)\n            \n            spectrogram[:, :, i] += spectrogram_slice\n            processed_eeg[f'{cols[j]}_{cols[j+1]}'] = signal.get()\n            processed_eeg[name] += signal.get()\n        \n        # AVERAGE THE 4 MONTAGE DIFFERENCES\n        if mean_montage_names > 0:\n            spectrogram[:,:,i] /= mean_montage_names\n\n    # Convert to NumPy and apply Gaussian filter\n    spectrogram_np = cp.asnumpy(spectrogram)\n    if sigma_gaussian > 0.0:\n        spectrogram_np = gaussian_filter(spectrogram_np, sigma=sigma_gaussian)\n\n    # Filter EKG signal\n    ekg_signal_filtered = filtfilt(*notch_coefficients, eeg_data[\"EKG\"].values)\n    ekg_signal_filtered = filtfilt(*bandpass_coefficients, ekg_signal_filtered)\n    processed_eeg['EKG'] = np.array(ekg_signal_filtered)\n\n    return spectrogram_np, processed_eeg","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:25.118629Z","iopub.execute_input":"2024-04-09T09:12:25.119421Z","iopub.status.idle":"2024-04-09T09:12:25.139528Z","shell.execute_reply.started":"2024-04-09T09:12:25.119387Z","shell.execute_reply":"2024-04-09T09:12:25.138611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_spectogram_competition(spec_id, seconds_min):\n    spec = pd.read_parquet(f'/kaggle/input/hms-harmful-brain-activity-classification/test_spectrograms/{spec_id}.parquet')\n    inicio = (seconds_min) // 2\n    img = spec.fillna(0).values[:, 1:].T.astype(\"float32\")\n    img = img[:, inicio:inicio+300]\n    \n    # Log transform and normalize\n    img = np.clip(img, np.exp(-4), np.exp(6))\n    img = np.log(img)\n    eps = 1e-6\n    img_mean = img.mean()\n    img_std = img.std()\n    img = (img - img_mean) / (img_std + eps)\n    \n    return img ","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:25.145215Z","iopub.execute_input":"2024-04-09T09:12:25.145522Z","iopub.status.idle":"2024-04-09T09:12:25.152579Z","shell.execute_reply.started":"2024-04-09T09:12:25.145500Z","shell.execute_reply":"2024-04-09T09:12:25.151562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nfrom tqdm import tqdm\nimport pandas as pd\nimport cv2\nimport os\nimport matplotlib.pyplot as plt\nall_eegs2 = {}\n# Make sure the 'images' folder exists\noutput_folder = 'imagens'\nif not os.path.exists(output_folder):\n    os.makedirs(output_folder)\n    \ntest = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/test.csv')\nprint('Test shape:',test.shape)\nprint(test.head())\n\n# Creation of spectograms on the test base\nfor i in tqdm(range(len(test)), desc=\"Processing EEGs\"):\n    row = test.iloc[i]\n    eeg_id = row['eeg_id']\n    spec_id = row['spectrogram_id']\n    seconds_min = 0\n    start_second = 0\n    eeg_data = pd.read_parquet(f'/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/{eeg_id}.parquet')\n    eeg_new_key = eeg_id\n    image_50s, _ = create_spectrogram_with_cusignal(eeg_data=eeg_data, eeg_id=eeg_id, start=start_second, duration= 50,\n                                    low_cut_freq = 0.7, high_cut_freq = 20, order_band = 5,\n                                    spec_size_freq = 267, spec_size_time = 501,\n                                    nperseg_ = 1500, noverlap_ = 1483, nfft_ = 2750,\n                                    sigma_gaussian = 0.0, \n                                    mean_montage_names = 4)\n    image_10s, _ = create_spectrogram_with_cusignal(eeg_data=eeg_data, eeg_id=eeg_id, start=start_second, duration= 10,\n                                    low_cut_freq = 0.7, high_cut_freq = 20, order_band = 5,\n                                    spec_size_freq = 100, spec_size_time = 291,\n                                    nperseg_ = 260, noverlap_ = 254, nfft_ = 1030,\n                                    sigma_gaussian = 0.0, \n                                    mean_montage_names = 4)\n    image_10m = create_spectogram_competition(spec_id, seconds_min)\n    \n    imagem_final_unico_canal = np.zeros((1068, 501))\n    for j in range(4):\n        inicio = j * 267 \n        fim = inicio + 267\n        imagem_final_unico_canal[inicio:fim, :] = image_50s[:, :, j]\n        \n    \n    imagem_final_unico_canal2 = np.zeros((400, 291))\n    for n in range(4):\n        inicio = n * 100 \n        fim = inicio + 100\n        imagem_final_unico_canal2[inicio:fim, :] = image_10s[:, :, n]\n    \n    imagem_final_unico_canal_resized = cv2.resize(imagem_final_unico_canal, (400, 800), interpolation=cv2.INTER_AREA)\n    imagem_final_unico_canal2_resized = cv2.resize(imagem_final_unico_canal2, (300, 400), interpolation=cv2.INTER_AREA)\n    eeg_new_resized = cv2.resize(image_10m, (300, 400), interpolation=cv2.INTER_AREA)\n    imagem_final = np.zeros((800, 700), dtype=np.float32)\n    imagem_final[0:800, 0:400] = imagem_final_unico_canal_resized\n    imagem_final[0:400,400:700] = imagem_final_unico_canal2_resized\n    imagem_final[400:800, 400:700] = eeg_new_resized\n    imagem_final = imagem_final[::-1]\n    \n    imagem_final = cv2.resize(imagem_final, (512, 512), interpolation=cv2.INTER_AREA)\n    \n    all_eegs2[eeg_new_key] = imagem_final\n    \n    if i ==0:\n        plt.figure(figsize=(10, 10))\n        plt.imshow(imagem_final, cmap='jet')\n        plt.axis('off')\n        plt.show()\n\n        print(imagem_final.shape)","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:12:25.153979Z","iopub.execute_input":"2024-04-09T09:12:25.154258Z","iopub.status.idle":"2024-04-09T09:14:21.478650Z","shell.execute_reply.started":"2024-04-09T09:12:25.154235Z","shell.execute_reply":"2024-04-09T09:14:21.477758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n\nclass DataGeneratorTest(tf.keras.utils.Sequence):\n    'Generates data for Keras'\n    def __init__(self, data, batch_size=32, shuffle=False, eegs={}, mode='train'):\n\n        self.data = data\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.eegs = eegs\n        self.mode = mode\n        self.on_epoch_end()\n\n    def __len__(self):\n        'Denotes the number of batches per epoch'\n        ct = int( np.ceil( len(self.data) / self.batch_size ) )\n        return ct\n\n    def __getitem__(self, index):\n        'Generate one batch of data'\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n        X, y = self.__data_generation(indexes)\n        return X, y\n\n    def on_epoch_end(self):\n        'Updates indexes after each epoch'\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        'Generates data containing batch_size samples'\n\n        X = np.zeros((len(indexes),SPEC_SIZE[0],SPEC_SIZE[1],SPEC_SIZE[2]),dtype='float32')\n        y = np.zeros((len(indexes),6),dtype='float32')\n\n        for j,i in enumerate(indexes):\n            row = self.data.iloc[i]\n            eeg_data = self.eegs[row.eeg_id] \n            eeg_data_expanded = np.repeat(eeg_data[:, :, np.newaxis], 3, axis=2)\n            X[j,] = eeg_data_expanded\n            if self.mode!='test':\n                y[j] = row[CLASSES]\n\n        return X,y","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:21.479843Z","iopub.execute_input":"2024-04-09T09:14:21.480181Z","iopub.status.idle":"2024-04-09T09:14:21.494712Z","shell.execute_reply.started":"2024-04-09T09:14:21.480150Z","shell.execute_reply":"2024-04-09T09:14:21.493782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# INFER MLP ON TEST\npreds = []\nmodel = build_EfficientNetB2((SPEC_SIZE[0],SPEC_SIZE[1],SPEC_SIZE[2]), 6)\ntest_gen = DataGeneratorTest(test, shuffle=False, batch_size=BATCH, eegs=all_eegs2, mode='test')\n\nprint('Inferring test... ',end='')\nfor i in range(FOLDS):\n    print(f'fold {i+1}, ',end='')\n    model.load_weights(f'/kaggle/input/hms-train/MLP_fold{i}.weights.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-04-09T09:14:21.496057Z","iopub.execute_input":"2024-04-09T09:14:21.496354Z","iopub.status.idle":"2024-04-09T09:14:39.559760Z","shell.execute_reply.started":"2024-04-09T09:14:21.496330Z","shell.execute_reply":"2024-04-09T09:14:39.558639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predss_1 = pred\npredss_1","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:39.561044Z","iopub.execute_input":"2024-04-09T09:14:39.561448Z","iopub.status.idle":"2024-04-09T09:14:39.569379Z","shell.execute_reply.started":"2024-04-09T09:14:39.561410Z","shell.execute_reply":"2024-04-09T09:14:39.568174Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:39.571080Z","iopub.execute_input":"2024-04-09T09:14:39.571921Z","iopub.status.idle":"2024-04-09T09:14:39.843905Z","shell.execute_reply.started":"2024-04-09T09:14:39.571891Z","shell.execute_reply":"2024-04-09T09:14:39.842758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model 2","metadata":{}},{"cell_type":"code","source":"import gc\nimport os\nimport random\nimport warnings\nimport numpy as np\nimport pandas as pd\nfrom IPython.display import display\n\nimport timm\nimport torch\nimport torch.nn as nn  \nimport torch.optim as optim\nimport torch.nn.functional as F\nimport torchvision.transforms as transforms\n\nfrom scipy import signal\n\nwarnings.filterwarnings('ignore', category=Warning)\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:39.845422Z","iopub.execute_input":"2024-04-09T09:14:39.845765Z","iopub.status.idle":"2024-04-09T09:14:46.090192Z","shell.execute_reply.started":"2024-04-09T09:14:39.845739Z","shell.execute_reply":"2024-04-09T09:14:46.089024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    seed = 3131\n    image_transform = transforms.Resize((512, 512))\n    num_folds = 1\n    dataset_wide_mean = -0.2972692229201065 #From Train notebook\n    dataset_wide_std = 2.5997336315611026 #From Train notebook\n    ownspec_mean = 7.29084372799223e-05 # From Train spectrograms notebook\n    ownspec_std = 4.510082606216031 # From Train spectrograms notebook\n    \ndef set_seed(seed):\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n    \n    torch.manual_seed(seed)\n    np.random.seed(seed)\n    random.seed(seed)\n    \nset_seed(Config.seed)","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:46.091669Z","iopub.execute_input":"2024-04-09T09:14:46.092253Z","iopub.status.idle":"2024-04-09T09:14:46.101042Z","shell.execute_reply.started":"2024-04-09T09:14:46.092199Z","shell.execute_reply":"2024-04-09T09:14:46.100076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/test.csv\")\nsubmission = pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\n\nsubmission = submission.merge(test_df, on='eeg_id', how='left')\nsubmission['path_spec'] = submission['spectrogram_id'].apply(lambda x: f\"/kaggle/input/hms-harmful-brain-activity-classification/test_spectrograms/{x}.parquet\")\nsubmission['path_eeg'] = submission['eeg_id'].apply(lambda x: f\"/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/{x}.parquet\")\n\ndisplay(submission)\n\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:46.102053Z","iopub.execute_input":"2024-04-09T09:14:46.102359Z","iopub.status.idle":"2024-04-09T09:14:46.487459Z","shell.execute_reply.started":"2024-04-09T09:14:46.102335Z","shell.execute_reply":"2024-04-09T09:14:46.486454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []\n\n# Load in original EfficientnetB0 model\nfor i in range(Config.num_folds):\n    model_effnet_b0 = timm.create_model('efficientnet_b1', pretrained=False, num_classes=6, in_chans=1)\n    model_effnet_b0.load_state_dict(torch.load(f'/kaggle/input/efficientnetb1-for-eeg-classification-weights/efficientnet_b1_fold{i}.pth', map_location=torch.device('cpu')))\n    models.append(model_effnet_b0)\n    \nmodels_datawide = []\n# Load in hyperparameter optimized EfficientnetB1\nfor i in range(Config.num_folds):\n    model_effnet_b1 = timm.create_model('efficientnet_b4', pretrained=False, num_classes=6, in_chans=1)\n    model_effnet_b1.load_state_dict(torch.load(f'/kaggle/input/train-b4/efficientnet_b4_fold{i}.pth', map_location=torch.device('cpu')))\n    models_datawide.append(model_effnet_b1)\n    \nmodels_ownspec = []\n# Load in EfficientnetB1 with new spectrograms\nfor i in range(Config.num_folds):\n    model_effnet_b1 = timm.create_model('efficientnet_b4', pretrained=False, num_classes=6, in_chans=1)\n    model_effnet_b1.load_state_dict(torch.load(f'/kaggle/input/efficientnet-b4-ownspectrograms/efficientnet_b4_fold{i}_datawide_CosineAnnealingLR_0.001_False.pth', map_location=torch.device('cpu')))\n    models_ownspec.append(model_effnet_b1)\n    \ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:46.488640Z","iopub.execute_input":"2024-04-09T09:14:46.488920Z","iopub.status.idle":"2024-04-09T09:14:50.015002Z","shell.execute_reply.started":"2024-04-09T09:14:46.488897Z","shell.execute_reply":"2024-04-09T09:14:50.014102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predictions = []\n\ndef create_spectrogram(data):\n    \"\"\"Creating a spectrogram\"\"\"\n    nperseg = 150  # Length of each segment\n    noverlap = 128  # Overlap between segments\n    NFFT = max(256, 2 ** int(np.ceil(np.log2(nperseg))))\n\n    # LL Spec = ( spec(Fp1 - F7) + spec(F7 - T3) + spec(T3 - T5) + spec(T5 - O1) )/4\n    freqs, t,spectrum_LL1 = signal.spectrogram(data['Fp1']-data['F7'],nfft=NFFT,noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LL2 = signal.spectrogram(data['F7']-data['T3'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LL3 = signal.spectrogram(data['T3']-data['T5'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LL4 = signal.spectrogram(data['T5']-data['O1'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n\n    LL = (spectrum_LL1+ spectrum_LL2 +spectrum_LL3 + spectrum_LL4)/4\n\n    # LP Spec = ( spec(Fp1 - F3) + spec(F3 - C3) + spec(C3 - P3) + spec(P3 - O1) )/4\n    freqs, t,spectrum_LP1 = signal.spectrogram(data['Fp1']-data['F3'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LP2 = signal.spectrogram(data['F3']-data['C3'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LP3 = signal.spectrogram(data['C3']-data['P3'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LP4 = signal.spectrogram(data['P3']-data['O1'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n\n    LP = (spectrum_LP1+ spectrum_LP2 +spectrum_LP3 + spectrum_LP4)/4\n\n    # RP Spec = ( spec(Fp2 - F4) + spec(F4 - C4) + spec(C4 - P4) + spec(P4 - O2) )/4\n    freqs, t,spectrum_RP1 = signal.spectrogram(data['Fp2']-data['F4'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RP2 = signal.spectrogram(data['F4']-data['C4'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RP3 = signal.spectrogram(data['C4']-data['P4'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RP4 = signal.spectrogram(data['P4']-data['O2'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n\n    RP = (spectrum_RP1+ spectrum_RP2 +spectrum_RP3 + spectrum_RP4)/4\n\n\n    # RL Spec = ( spec(Fp2 - F8) + spec(F8 - T4) + spec(T4 - T6) + spec(T6 - O2) )/4\n    freqs, t,spectrum_RL1 = signal.spectrogram(data['Fp2']-data['F8'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RL2 = signal.spectrogram(data['F8']-data['T4'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RL3 = signal.spectrogram(data['T4']-data['T6'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RL4 = signal.spectrogram(data['T6']-data['O2'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    RL = (spectrum_RL1+ spectrum_RL2 +spectrum_RL3 + spectrum_RL4)/4\n    spectogram = np.concatenate((LL, LP,RP,RL), axis=0)\n    return spectogram\n\ndef preprocess_ownspec(path_to_parquet):\n    \"\"\"EEG to spectrogramdata\"\"\"\n    data = pd.read_parquet(path_to_parquet)\n    data = create_spectrogram(data)\n    mask = np.isnan(data)\n    data[mask] = -1\n    data = np.clip(data, np.exp(-6), np.exp(10))\n    data = np.log(data)\n    \n    return data \n\ndef preprocess(path_to_parquet):\n    data = pd.read_parquet(path_to_parquet)\n    data = data.fillna(-1).values[:, 1:].T\n    data = np.clip(data, np.exp(-6), np.exp(10))\n    data = np.log(data)\n    \n    return data\n\n\ndef normalize_datawide(data_point):\n    \"\"\"The spectrogram data will be normalized data wide.\"\"\"\n    eps = 1e-6\n\n    data_point = (data_point - Config.dataset_wide_mean) / (Config.dataset_wide_std + eps)\n\n    data_tensor = torch.unsqueeze(torch.Tensor(data_point), dim=0)\n    data_point = Config.image_transform(data_tensor)\n\n    return data_point\n\n\ndef normalize_datawide_ownspec(data):\n    \"\"\"The new spectrogram data will be normalized data wide.\"\"\"\n    eps = 1e-6\n    \n    data = (data - Config.ownspec_mean) / (Config.ownspec_std + eps)\n    data_tensor = torch.unsqueeze(torch.Tensor(data), dim=0)\n    data = Config.image_transform(data_tensor)\n    \n    return data\n\n\ndef normalize_instance_wise(data_point):\n    \"\"\"The spectrogram data will be normalized instance wise.\"\"\"\n    eps = 1e-6\n    \n    data_mean = data_point.mean(axis=(0, 1))\n    data_std = data_point.std(axis=(0, 1))\n    data_point = (data_point - data_mean) / (data_std + eps)\n    \n    data_tensor = torch.unsqueeze(torch.Tensor(data_point), dim=0)\n    data_point = Config.image_transform(data_tensor)\n    \n    return data_point\n\n# Loop over samples\nfor index in submission.index:\n    test_predictions_per_model = []\n    \n    preprocessed_data = preprocess(submission.iloc[index]['path_spec'])\n    preprocessed_data_ownspec = preprocess_ownspec(submission.iloc[index]['path_eeg'])\n    \n    # Predict based on original EfficientnetB0 models. \n    for i in range(len(models)):\n        models[i].eval()\n        \n        current_parquet_data = normalize_instance_wise(preprocessed_data).unsqueeze(0)\n        \n        with torch.no_grad():\n            model_output = models[i](current_parquet_data)\n            current_model_prediction = F.softmax(model_output)[0].detach().cpu().numpy()\n            \n        test_predictions_per_model.append(current_model_prediction)\n    \n    # Predict based on hyperparameter optimized EffcientnetB1.\n    for i in range(len(models_datawide)):\n        models_datawide[i].eval()\n        \n        current_parquet_data = normalize_datawide(preprocessed_data).unsqueeze(0)\n        \n        with torch.no_grad():\n            model_output = models_datawide[i](current_parquet_data)\n            current_model_prediction = F.softmax(model_output)[0].detach().cpu().numpy()\n            \n        test_predictions_per_model.append(current_model_prediction)\n    \n    # Predict based on EfficientnetB1 model with new spectrograms.\n    for i in range(len(models_ownspec)):\n        models_ownspec[i].eval()\n        \n        current_parquet_data = normalize_datawide_ownspec(preprocessed_data_ownspec).unsqueeze(0)\n        \n        with torch.no_grad():\n            model_output = models_ownspec[i](current_parquet_data)\n            current_model_prediction = F.softmax(model_output)[0].detach().cpu().numpy()\n            \n        test_predictions_per_model.append(current_model_prediction)\n    \n    # The mean of all models is taken.\n    ensemble_prediction = np.mean(test_predictions_per_model,axis=0)\n    \n    test_predictions.append(ensemble_prediction)\n\ntest_predictions = np.array(test_predictions)\n\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:50.016432Z","iopub.execute_input":"2024-04-09T09:14:50.016777Z","iopub.status.idle":"2024-04-09T09:14:51.556285Z","shell.execute_reply.started":"2024-04-09T09:14:50.016745Z","shell.execute_reply":"2024-04-09T09:14:51.555299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predss_2 = test_predictions\npredss_2","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:51.557595Z","iopub.execute_input":"2024-04-09T09:14:51.558023Z","iopub.status.idle":"2024-04-09T09:14:51.564781Z","shell.execute_reply.started":"2024-04-09T09:14:51.557991Z","shell.execute_reply":"2024-04-09T09:14:51.563559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model 3","metadata":{}},{"cell_type":"code","source":"import os\nimport gc\nimport sys\nimport math\nimport time\nimport random\nimport datetime as dt\nimport numpy as np\nimport pandas as pd\n\nfrom glob import glob\nfrom pathlib import Path\nfrom typing import Dict, List, Union, Tuple\nfrom scipy.signal import butter, lfilter, freqz\nfrom matplotlib import pyplot as plt\nfrom tqdm.auto import tqdm\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.optim import Adam, SGD, AdamW\nfrom torch.utils.data import DataLoader, Dataset\n\nsys.path.append(\"/kaggle/input/kaggle-kl-div\")\nfrom kaggle_kl_div import score\n\nimport warnings\n\nwarnings.filterwarnings(\"ignore\")\n\ndevice = torch.device(\"cuda\")\nos.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0,1\"\n\n!cat /etc/os-release | grep -oP \"PRETTY_NAME=\\\"\\K([^\\\"]*)\"\nprint(f\"BUILD_DATE={os.environ['BUILD_DATE']}, CONTAINER_NAME={os.environ['CONTAINER_NAME']}\")\n\ntry:\n    print(\n        f\"PyTorch Version:{torch.__version__}, CUDA is available:{torch.cuda.is_available()}, Version CUDA:{torch.version.cuda}\"\n    )\n    print(\n        f\"Device Capability:{torch.cuda.get_device_capability()}, {torch.cuda.get_arch_list()}\"\n    )\n    print(\n        f\"CuDNN Enabled:{torch.backends.cudnn.enabled}, Version:{torch.backends.cudnn.version()}\"\n    )\nexcept Exception:\n    pass","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:51.566317Z","iopub.execute_input":"2024-04-09T09:14:51.566686Z","iopub.status.idle":"2024-04-09T09:14:52.677430Z","shell.execute_reply.started":"2024-04-09T09:14:51.566647Z","shell.execute_reply":"2024-04-09T09:14:52.676275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class APP:\n    jupyter = \"ipykernel\" in globals()\n    if not jupyter:\n        try:\n            if \"IPython\" in globals().get(\"__doc__\", \"\"):\n                jupyter = True\n        except Exception as inst:\n            print(inst)\n\n    kaggle = os.environ.get(\"KAGGLE_KERNEL_RUN_TYPE\", \"\") != \"\"\n    local = os.environ.get(\"DOCKER_USING\", \"\") == \"LOCAL\"\n    date_time_start = dt.datetime.now()\n    dt_start_ymd_hms = date_time_start.strftime(\"%Y.%m.%d_%H-%M-%S\")\n\n    file_run_path = \"\"\n    if jupyter:\n        try:\n            file_run_path = Path(globals().get(\"__vsc_ipynb_file__\", \"\"))\n        except Exception as inst:\n            print(inst)\n\n    else:\n        try:\n            file_run_path = Path(__file__)\n        except Exception as inst:\n            print(inst)\n\n    file_run_name = file_run_path.stem\n    path_app = file_run_path.parent\n    path_run = Path(os.getcwd())\n    path_out = (\n        Path(\"/kaggle/working\")\n        if kaggle\n        else file_run_path / f\"{file_run_name}_{dt_start_ymd_hms}\"\n    )\n\n\nprint(f\"jupyter:{APP.jupyter}, kaggle:{APP.kaggle}, local:{APP.local}\")\nprint(APP.file_run_path)\nprint(APP.path_out)","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.679403Z","iopub.execute_input":"2024-04-09T09:14:52.680365Z","iopub.status.idle":"2024-04-09T09:14:52.690827Z","shell.execute_reply.started":"2024-04-09T09:14:52.680322Z","shell.execute_reply":"2024-04-09T09:14:52.689856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CFG:\n    VERSION = 113-3\n\n    model_name = \"resnet1d_gru\"\n\n    seed = 2024\n    batch_size = 32\n    num_workers = 0\n\n    fixed_kernel_size = 5\n    # kernels = [3, 5, 7, 9]\n    # linear_layer_features = 424\n    kernels = [3, 5, 7, 9, 11]\n    #linear_layer_features = 448  # Full Signal = 10_000\n    #linear_layer_features = 352  # Half Signal = 5_000\n    linear_layer_features = 304   # 1/5  Signal = 2_000\n\n    seq_length = 50  # Second's\n    sampling_rate = 200  # Hz\n    nsamples = seq_length * sampling_rate  # Число семплов\n    out_samples = nsamples // 5\n\n    # bandpass_filter = {\"low\": 0.5, \"high\": 20, \"order\": 2}\n    # rand_filter = {\"probab\": 0.1, \"low\": 10, \"high\": 20, \"band\": 1.0, \"order\": 2}\n    freq_channels = []  # [(8.0, 12.0)]; [(0.5, 4.5)]\n    filter_order = 2\n\n    random_divide_signal = 0.0\n    random_close_zone = 0.0\n    random_common_negative_signal = 0.0\n    random_common_reverse_signal = 0.0\n    random_negative_signal = 0.0\n    random_reverse_signal = 0.0\n\n    target_cols = [\n        \"seizure_vote\",\n        \"lpd_vote\",\n        \"gpd_vote\",\n        \"lrda_vote\",\n        \"grda_vote\",\n        \"other_vote\",\n    ]\n    target_size = len(target_cols)\n\n    # target_preds = [x + \"_pred\" for x in target_cols]\n    # label_to_num = {\"Seizure\": 0, \"LPD\": 1, \"GPD\": 2, \"LRDA\": 3, \"GRDA\": 4, \"Other\": 5}\n    # num_to_label = {v: k for k, v in label_to_num.items()}\n\n    PATH = \"/kaggle/input/hms-harmful-brain-activity-classification/\"\n    test_eeg = \"/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/\"\n    test_csv = \"/kaggle/input/hms-harmful-brain-activity-classification/test.csv\"\n\nclass FEAT_MAIN:\n    map_features = [\n        (\"Fp1\", \"T3\"),\n        (\"T3\", \"O1\"),\n        (\"Fp1\", \"C3\"),\n        (\"C3\", \"O1\"),\n        (\"Fp2\", \"C4\"),\n        (\"C4\", \"O2\"),\n        (\"Fp2\", \"T4\"),\n        (\"T4\", \"O2\"),\n        #('Fz', 'Cz'), ('Cz', 'Pz'),        \n    ]\n\n    eeg_features = [\"Fp1\", \"T3\", \"C3\", \"O1\", \"Fp2\", \"C4\", \"T4\", \"O2\"]  # 'Fz', 'Cz', 'Pz']\n        # 'F3', 'P3', 'F7', 'T5', 'Fz', 'Cz', 'Pz', 'F4', 'P4', 'F8', 'T6', 'EKG']                    \n    feature_to_index = {x: y for x, y in zip(eeg_features, range(len(eeg_features)))}\n    simple_features = []  # 'Fz', 'Cz', 'Pz', 'EKG'\n\n    # eeg_features = [row for row in feature_to_index]\n    # eeg_feat_size = len(eeg_features)\n    \n    n_map_features = len(map_features)\n    in_channels = n_map_features + n_map_features * len(CFG.freq_channels) + len(simple_features)\n\nclass FEAT_WAVE:\n    map_features = [\n        (\"Fp1\", \"T3\"),\n        (\"T3\", \"O1\"),\n        (\"Fp1\", \"C3\"),\n        (\"C3\", \"O1\"),\n        (\"Fp2\", \"C4\"),\n        (\"C4\", \"O2\"),\n        (\"Fp2\", \"T4\"),\n        (\"T4\", \"O2\"),\n        #('Fz', 'Cz'), ('Cz', 'Pz'),\n        #'F7', 'F3', 'Cz', 'P4', 'T6'\n        #'F8', 'F4', 'Cz', 'P3', 'T5'\n        ('F7', 'F3'),\n        ('F3', 'Cz'),\n        ('Cz', 'P4'),\n        ('P4', 'T6'),\n        ('F8', 'F4'),\n        ('F4', 'Cz'),\n        ('Cz', 'P3'),\n        ('P3', 'T5'),\n    ]\n\n    eeg_features = [\"Fp1\", \"T3\", \"C3\", \"O1\", \"Fp2\", \"C4\", \"T4\", \"O2\",  # 'Fz', 'Cz', 'Pz'\n        'F3', 'P3', 'F7', 'T5', 'Fz', 'Cz', 'Pz', 'F4', 'P4', 'F8', 'T6']  # , 'EKG'\n    feature_to_index = {x: y for x, y in zip(eeg_features, range(len(eeg_features)))}\n    simple_features = []  # 'Fz', 'Cz', 'Pz', 'EKG'\n\n    # eeg_features = [row for row in feature_to_index]\n    # eeg_feat_size = len(eeg_features)\n    \n    n_map_features = len(map_features)\n    in_channels = n_map_features + n_map_features * len(CFG.freq_channels) + len(simple_features)\n    ","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.692111Z","iopub.execute_input":"2024-04-09T09:14:52.692445Z","iopub.status.idle":"2024-04-09T09:14:52.713947Z","shell.execute_reply.started":"2024-04-09T09:14:52.692414Z","shell.execute_reply":"2024-04-09T09:14:52.713012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"koef_1 = 1.0\nmodel_weights = [\n    {\n        'feat': FEAT_MAIN,\n        'bandpass_filter':{'low':0.5, 'high':20, 'order':2}, \n        'file_data': \n        [\n            # 1-Stage\n            #{'koef':koef_1, 'file_mask':\"/kaggle/input/hms-resnet1d-gru-weights-v102/pop_1_weight_oof/*_best.pth\"},  # 0.37 +\n            \n            # 2-Stage\n            #{'koef':koef_1, 'file_mask':\"/kaggle/input/hms-resnet1d-gru-weights-v82/pop_2_weight_oof/*_best.pth\"},  # 0.36 +++\n            #{'koef':koef_1, 'file_mask':\"/kaggle/input/hms-resnet1d-gru-weights-v84/pop_2_weight_oof/*_best.pth\"},  # 0.37\n            #{'koef':koef_1, 'file_mask':\"/kaggle/input/hms-resnet1d-gru-weights-v96-full/pop_2_weight_oof/*_full.pth\"},  # 0.36 +\n            #{'koef':koef_1, 'file_mask':\"/kaggle/input/hms-resnet1d-gru-weights-v98/pop_2_weight_oof/*_full.pth\"},  # 0.36 ++\n            \n            # 3-Stage\n            {'koef':koef_1, 'file_mask':\"/kaggle/input/hms-resnet1d-gru-weights-v90/pop_3_weight_oof/*_best.pth\"},  # 0.36 ++\n        ]        \n    },\n    {\n        'feat': FEAT_WAVE,\n        'bandpass_filter':{'low':0.5, 'high':20, 'order':2}, \n        'file_data': \n        [\n            # 1-Stage\n            {'koef':koef_1, 'file_mask':\"/kaggle/input/hms-resnet1d-gru-weights-v102-3/pop_1_weight_oof/*_best.pth\"},     # 0.36\n\n            # 2-Stage\n            {'koef':koef_1, 'file_mask':\"/kaggle/input/hms-resnet1d-gru-weights-v82-6-zip/pop_2_weight_oof/*_best.pth\"},  # 0.36\n        ]\n    },\n]","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.715168Z","iopub.execute_input":"2024-04-09T09:14:52.715468Z","iopub.status.idle":"2024-04-09T09:14:52.725009Z","shell.execute_reply.started":"2024-04-09T09:14:52.715444Z","shell.execute_reply":"2024-04-09T09:14:52.724033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def init_logger(log_file=\"./test.log\"):\n    from logging import getLogger, INFO, FileHandler, Formatter, StreamHandler\n\n    logger = getLogger(__name__)\n    logger.setLevel(INFO)\n    handler1 = StreamHandler()\n    handler1.setFormatter(Formatter(\"%(message)s\"))\n    handler2 = FileHandler(filename=log_file)\n    handler2.setFormatter(Formatter(\"%(message)s\"))\n    logger.addHandler(handler1)\n    logger.addHandler(handler2)\n    return logger\n\n\ndef asMinutes(s):\n    m = math.floor(s / 60)\n    s -= m * 60\n    return \"%dm %ds\" % (m, s)\n\n\ndef timeSince(since, percent):\n    now = time.time()\n    s = now - since\n    es = s / (percent)\n    rs = es - s\n    return \"%s (remain %s)\" % (asMinutes(s), asMinutes(rs))\n\n\ndef quantize_data(data, classes):\n    mu_x = mu_law_encoding(data, classes)\n    return mu_x  # quantized\n\n\ndef mu_law_encoding(data, mu):\n    mu_x = np.sign(data) * np.log(1 + mu * np.abs(data)) / np.log(mu + 1)\n    return mu_x\n\n\ndef mu_law_expansion(data, mu):\n    s = np.sign(data) * (np.exp(np.abs(data) * np.log(mu + 1)) - 1) / mu\n    return s\n\n\ndef butter_bandpass(lowcut, highcut, fs, order=5):\n    return butter(order, [lowcut, highcut], fs=fs, btype=\"band\")\n\n\ndef butter_bandpass_filter(data, lowcut, highcut, fs, order=5):\n    b, a = butter_bandpass(lowcut, highcut, fs, order=order)\n    y = lfilter(b, a, data)\n    return y\n\n\ndef butter_lowpass_filter(\n    data, cutoff_freq=20, sampling_rate=CFG.sampling_rate, order=4\n):\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\n\n\ndef denoise_filter(x):\n    # Частота дискретизации и желаемые частоты среза (в Гц).\n    # Отфильтруйте шумный сигнал\n    y = butter_bandpass_filter(x, CFG.lowcut, CFG.highcut, CFG.sampling_rate, order=6)\n    y = (y + np.roll(y, -1) + np.roll(y, -2) + np.roll(y, -3)) / 4\n    y = y[0:-1:4]\n    return y","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.726418Z","iopub.execute_input":"2024-04-09T09:14:52.726756Z","iopub.status.idle":"2024-04-09T09:14:52.744369Z","shell.execute_reply.started":"2024-04-09T09:14:52.726725Z","shell.execute_reply":"2024-04-09T09:14:52.743405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def eeg_from_parquet(\n    parquet_path: str, eeg_features: List[str], display: bool = False, seq_length=CFG.seq_length\n) -> np.ndarray:\n    \"\"\"\n    Эта функция читает файл паркета и извлекает средние 50 секунд показаний. Затем он заполняет значения NaN\n    со средним значением (игнорируя NaN).\n        :param parquet_path: путь к файлу паркета.\n        :param display: отображать графики ЭЭГ или нет.\n        :return data: np.array формы (time_steps, eeg_features) -> (10_000, 8)\n    \"\"\"\n\n    # Вырезаем среднюю 50 секундную часть\n    eeg = pd.read_parquet(parquet_path, columns=eeg_features)\n    rows = len(eeg)\n\n    # начало смещения данных, чтобы забрать середину\n    offset = (rows - CFG.nsamples) // 2\n\n    # средние 50 секунд, имеет одинаковое количество показаний слева и справа\n    eeg = eeg.iloc[offset : offset + CFG.nsamples]\n\n    if display:\n        plt.figure(figsize=(10, 5))\n        offset = 0\n\n    # Конвертировать в numpy\n\n    # создать заполнитель той же формы с нулями\n    data = np.zeros((CFG.nsamples, len(eeg_features)))\n\n    for index, feature in enumerate(eeg_features):\n        x = eeg[feature].values.astype(\"float32\")  # конвертировать в float32\n\n        # Вычисляет среднее арифметическое вдоль указанной оси, игнорируя NaN.\n        mean = np.nanmean(x)\n        nan_percentage = np.isnan(x).mean()  # percentage of NaN values in feature\n\n        # Заполнение значения Nan\n        # Поэлементная проверка на NaN и возврат результата в виде логического массива.\n        if nan_percentage < 1:  # если некоторые значения равны Nan, но не все\n            x = np.nan_to_num(x, nan=mean)\n        else:  # если все значения — Nan\n            x[:] = 0\n        data[:, index] = x\n\n        if display:\n            if index != 0:\n                offset += x.max()\n            plt.plot(range(CFG.nsamples), x - offset, label=feature)\n            offset -= x.min()\n\n    if display:\n        plt.legend()\n        name = parquet_path.split(\"/\")[-1].split(\".\")[0]\n        plt.yticks([])\n        plt.title(f\"EEG {name}\", size=16)\n        plt.show()\n    return data","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.745856Z","iopub.execute_input":"2024-04-09T09:14:52.746184Z","iopub.status.idle":"2024-04-09T09:14:52.759082Z","shell.execute_reply.started":"2024-04-09T09:14:52.746155Z","shell.execute_reply":"2024-04-09T09:14:52.758198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class EEGDataset(Dataset):\n    def __init__(\n        self,\n        df: pd.DataFrame,\n        batch_size: int,\n        in_channels: int,\n        map_features: List[Tuple[str,str]],\n        feature_to_index: Dict[str, int],\n        n_map_features: int,\n        simple_features:List[str],\n        target_size: int,\n        eegs: Dict[int, np.ndarray],\n        mode: str = \"train\",\n        downsample: int = None,\n        bandpass_filter: Dict[str, Union[int, float]] = None,\n        rand_filter: Dict[str, Union[int, float]] = None,\n    ):\n        self.df = df\n        self.batch_size = batch_size\n        self.in_channels = in_channels\n        self.map_features = map_features\n        self.feature_to_index = feature_to_index\n        self.n_map_features = n_map_features\n        self.simple_features = simple_features\n        self.target_size = target_size\n        self.mode = mode\n        self.eegs = eegs\n        self.downsample = downsample\n        self.bandpass_filter = bandpass_filter\n        self.rand_filter = rand_filter\n        \n    def __len__(self):\n        \"\"\"\n        Length of dataset.\n        \"\"\"\n        # Обозначает количество пакетов за эпоху\n        return len(self.df)\n\n    def __getitem__(self, index):\n        \"\"\"\n        Get one item.\n        \"\"\"\n        # Сгенерировать один пакет данных\n        X, y_prob = self.__data_generation(index)\n        if self.downsample is not None:\n            X = X[:: self.downsample, :]\n        output = {\n            \"eeg\": torch.tensor(X, dtype=torch.float32),\n            \"labels\": torch.tensor(y_prob, dtype=torch.float32),\n        }\n        return output\n\n    def __data_generation(self, index):\n        # Генерирует данные, содержащие образцы размера партии\n        X = np.zeros(\n            (CFG.out_samples, self.in_channels), dtype=\"float32\"\n        )  # Size=(10000, 14)\n\n        row = self.df.iloc[index]  # Строка Pandas\n        data = self.eegs[row.eeg_id]  # Size=(10000, 8)\n        if CFG.nsamples != CFG.out_samples:\n            if self.mode != \"train\":\n                offset = (CFG.nsamples - CFG.out_samples) // 2\n            else:\n                #offset = random.randint(0, CFG.nsamples - CFG.out_samples)                \n                offset = ((CFG.nsamples - CFG.out_samples) * random.randint(0, 1000)) // 1000\n            data = data[offset:offset+CFG.out_samples,:]\n\n        for i, (feat_a, feat_b) in enumerate(self.map_features):\n            if self.mode == \"train\" and CFG.random_close_zone > 0 and random.uniform(0.0, 1.0) <= CFG.random_close_zone:\n                continue\n                \n            diff_feat = (\n                data[:, self.feature_to_index[feat_a]]\n                - data[:, self.feature_to_index[feat_b]]\n            )  # Size=(10000,)\n\n            if not self.bandpass_filter is None:\n                diff_feat = butter_bandpass_filter(\n                    diff_feat,\n                    self.bandpass_filter[\"low\"],\n                    self.bandpass_filter[\"high\"],\n                    CFG.sampling_rate,\n                    order=self.bandpass_filter[\"order\"],\n                )\n                    \n            if (\n                self.mode == \"train\"\n                and not self.rand_filter is None\n                and random.uniform(0.0, 1.0) <= self.rand_filter[\"probab\"]\n            ):\n                lowcut = random.randint(\n                    self.rand_filter[\"low\"], self.rand_filter[\"high\"]\n                )\n                highcut = lowcut + self.rand_filter[\"band\"]\n                diff_feat = butter_bandpass_filter(\n                    diff_feat,\n                    lowcut,\n                    highcut,\n                    CFG.sampling_rate,\n                    order=self.rand_filter[\"order\"],\n                )\n\n            X[:, i] = diff_feat\n\n        n = self.n_map_features\n        if len(CFG.freq_channels) > 0:\n            for i in range(self.n_map_features):\n                diff_feat = X[:, i]\n                for j, (lowcut, highcut) in enumerate(CFG.freq_channels):\n                    band_feat = butter_bandpass_filter(\n                        diff_feat, lowcut, highcut, CFG.sampling_rate, order=CFG.filter_order,  # 6\n                    )\n                    X[:, n] = band_feat\n                    n += 1\n\n        for spml_feat in self.simple_features:\n            feat_val = data[:, CFG.feature_to_index[spml_feat]]\n            \n            if not self.bandpass_filter is None:\n                feat_val = butter_bandpass_filter(\n                    feat_val,\n                    self.bandpass_filter[\"low\"],\n                    self.bandpass_filter[\"high\"],\n                    CFG.sampling_rate,\n                    order=self.bandpass_filter[\"order\"],\n                )\n\n            if (\n                self.mode == \"train\"\n                and not self.rand_filter is None\n                and random.uniform(0.0, 1.0) <= self.rand_filter[\"probab\"]\n            ):\n                lowcut = random.randint(\n                    self.rand_filter[\"low\"], self.rand_filter[\"high\"]\n                )\n                highcut = lowcut + self.rand_filter[\"band\"]\n                feat_val = butter_bandpass_filter(\n                    feat_val,\n                    lowcut,\n                    highcut,\n                    CFG.sampling_rate,\n                    order=self.rand_filter[\"order\"],\n                )\n\n            X[:, n] = feat_val\n            n += 1\n            \n        # Обрезать края превышающие значения [-1024, 1024]\n        X = np.clip(X, -1024, 1024)\n\n        # Замените NaN нулем и разделить все на 32\n        X = np.nan_to_num(X, nan=0) / 32.0\n\n        # обрезать полосовым фильтром верхнюю границу в 20 Hz.\n        X = butter_lowpass_filter(X, order=CFG.filter_order)  # 4\n\n        y_prob = np.zeros(self.target_size, dtype=\"float32\")  # Size=(6,)\n        if self.mode != \"test\":\n            y_prob = row[CFG.target_cols].values.astype(np.float32)\n\n        return X, y_prob","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.760702Z","iopub.execute_input":"2024-04-09T09:14:52.761266Z","iopub.status.idle":"2024-04-09T09:14:52.790171Z","shell.execute_reply.started":"2024-04-09T09:14:52.761232Z","shell.execute_reply":"2024-04-09T09:14:52.789147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ResNet_1D_Block(nn.Module):\n    def __init__(\n        self,\n        in_channels,\n        out_channels,\n        kernel_size,\n        stride,\n        padding,\n        downsampling,\n        dilation=1,\n        groups=1,\n        dropout=0.0,\n    ):\n        super(ResNet_1D_Block, self).__init__()\n\n        self.bn1 = nn.BatchNorm1d(num_features=in_channels)\n        # self.relu = nn.ReLU(inplace=False)\n        # self.relu_1 = nn.PReLU()\n        # self.relu_2 = nn.PReLU()\n        self.relu_1 = nn.Hardswish()\n        self.relu_2 = nn.Hardswish()\n\n        self.dropout = nn.Dropout(p=dropout, inplace=False)\n        self.conv1 = nn.Conv1d(\n            in_channels=in_channels,\n            out_channels=out_channels,\n            kernel_size=kernel_size,\n            stride=stride,\n            padding=padding,\n            dilation=dilation,\n            groups=groups,\n            bias=False,\n        )\n\n        self.bn2 = nn.BatchNorm1d(num_features=out_channels)\n        self.conv2 = nn.Conv1d(\n            in_channels=out_channels,\n            out_channels=out_channels,\n            kernel_size=kernel_size,\n            stride=stride,\n            padding=padding,\n            dilation=dilation,\n            groups=groups,\n            bias=False,\n        )\n\n        self.maxpool = nn.MaxPool1d(\n            kernel_size=2,\n            stride=2,\n            padding=0,\n            dilation=dilation,\n        )\n        self.downsampling = downsampling\n\n    def forward(self, x):\n        identity = x\n\n        out = self.bn1(x)\n        out = self.relu_1(out)\n        out = self.dropout(out)\n        out = self.conv1(out)\n        out = self.bn2(out)\n        out = self.relu_2(out)\n        out = self.dropout(out)\n        out = self.conv2(out)\n\n        out = self.maxpool(out)\n        identity = self.downsampling(x)\n\n        out += identity\n        return out\n\n\nclass EEGNet(nn.Module):\n    def __init__(\n        self,\n        kernels,\n        in_channels,\n        fixed_kernel_size,\n        num_classes,\n        linear_layer_features,\n        dilation=1,\n        groups=1,\n    ):\n        super(EEGNet, self).__init__()\n        self.kernels = kernels\n        self.planes = 24\n        self.parallel_conv = nn.ModuleList()\n        self.in_channels = in_channels\n\n        for i, kernel_size in enumerate(list(self.kernels)):\n            sep_conv = nn.Conv1d(\n                in_channels=in_channels,\n                out_channels=self.planes,\n                kernel_size=(kernel_size),\n                stride=1,\n                padding=0,\n                dilation=dilation,\n                groups=groups,\n                bias=False,\n            )\n            self.parallel_conv.append(sep_conv)\n\n        self.bn1 = nn.BatchNorm1d(num_features=self.planes)\n        # self.relu = nn.ReLU(inplace=False)\n        # self.relu_1 = nn.ReLU()\n        # self.relu_2 = nn.ReLU()\n        self.relu_1 = nn.SiLU()\n        self.relu_2 = nn.SiLU()\n\n        self.conv1 = nn.Conv1d(\n            in_channels=self.planes,\n            out_channels=self.planes,\n            kernel_size=fixed_kernel_size,\n            stride=2,\n            padding=2,\n            dilation=dilation,\n            groups=groups,\n            bias=False,\n        )\n\n        self.block = self._make_resnet_layer(\n            kernel_size=fixed_kernel_size,\n            stride=1,\n            dilation=dilation,\n            groups=groups,\n            padding=fixed_kernel_size // 2,\n        )\n        self.bn2 = nn.BatchNorm1d(num_features=self.planes)\n        self.avgpool = nn.AvgPool1d(kernel_size=6, stride=6, padding=2)\n\n        self.rnn = nn.GRU(\n            input_size=self.in_channels,\n            hidden_size=128,\n            num_layers=1,\n            bidirectional=True,\n            # dropout=0.2,\n        )\n\n        self.fc = nn.Linear(in_features=linear_layer_features, out_features=num_classes)\n\n    def _make_resnet_layer(\n        self,\n        kernel_size,\n        stride,\n        dilation=1,\n        groups=1,\n        blocks=9,\n        padding=0,\n        dropout=0.0,\n    ):\n        layers = []\n        downsample = None\n        base_width = self.planes\n\n        for i in range(blocks):\n            downsampling = nn.Sequential(\n                nn.MaxPool1d(kernel_size=2, stride=2, padding=0)\n            )\n            layers.append(\n                ResNet_1D_Block(\n                    in_channels=self.planes,\n                    out_channels=self.planes,\n                    kernel_size=kernel_size,\n                    stride=stride,\n                    padding=padding,\n                    downsampling=downsampling,\n                    dilation=dilation,\n                    groups=groups,\n                    dropout=dropout,\n                )\n            )\n        return nn.Sequential(*layers)\n\n    def extract_features(self, x):\n        x = x.permute(0, 2, 1)\n        out_sep = []\n\n        for i in range(len(self.kernels)):\n            sep = self.parallel_conv[i](x)\n            out_sep.append(sep)\n\n        out = torch.cat(out_sep, dim=2)\n        out = self.bn1(out)\n        out = self.relu_1(out)\n        out = self.conv1(out)\n\n        out = self.block(out)\n        out = self.bn2(out)\n        out = self.relu_2(out)\n        out = self.avgpool(out)\n\n        out = out.reshape(out.shape[0], -1)\n        rnn_out, _ = self.rnn(x.permute(0, 2, 1))\n        new_rnn_h = rnn_out[:, -1, :]  # <~~\n\n        new_out = torch.cat([out, new_rnn_h], dim=1)\n        return new_out\n\n    def forward(self, x):\n        new_out = self.extract_features(x)\n        result = self.fc(new_out)\n        return result","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.791415Z","iopub.execute_input":"2024-04-09T09:14:52.791768Z","iopub.status.idle":"2024-04-09T09:14:52.820924Z","shell.execute_reply.started":"2024-04-09T09:14:52.791743Z","shell.execute_reply":"2024-04-09T09:14:52.819992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def inference_function(test_loader, model, device):\n    model.eval()  # set model in evaluation mode\n    softmax = nn.Softmax(dim=1)\n    prediction_dict = {}\n    preds = []\n    with tqdm(test_loader, unit=\"test_batch\", desc=\"Inference\") as tqdm_test_loader:\n        for step, batch in enumerate(tqdm_test_loader):\n            X = batch.pop(\"eeg\").to(device)  # send inputs to `device`\n            batch_size = X.size(0)\n            with torch.no_grad():\n                y_preds = model(X)  # forward propagation pass\n            y_preds = softmax(y_preds)\n            preds.append(y_preds.to(\"cpu\").numpy())  # save predictions\n\n    prediction_dict[\"predictions\"] = np.concatenate(\n        preds\n    )  # np.array() of shape (fold_size, target_cols)\n    return prediction_dict","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.822311Z","iopub.execute_input":"2024-04-09T09:14:52.822679Z","iopub.status.idle":"2024-04-09T09:14:52.832022Z","shell.execute_reply.started":"2024-04-09T09:14:52.822647Z","shell.execute_reply":"2024-04-09T09:14:52.831109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_eeg_parquet_paths = glob(CFG.test_eeg + \"*.parquet\")\ntest_eeg_df = pd.read_parquet(test_eeg_parquet_paths[0])\ntest_eeg_features = test_eeg_df.columns\nprint(f\"There are {len(test_eeg_features)} raw eeg features\")\nprint(list(test_eeg_features))\ndel test_eeg_df\n_ = gc.collect()\n\ntest_df = pd.read_csv(CFG.test_csv)\nprint(f\"Test dataframe shape is: {test_df.shape}\")\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:52.833537Z","iopub.execute_input":"2024-04-09T09:14:52.833830Z","iopub.status.idle":"2024-04-09T09:14:53.311806Z","shell.execute_reply.started":"2024-04-09T09:14:52.833807Z","shell.execute_reply":"2024-04-09T09:14:53.310819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"koef_sum = 0\nkoef_count = 0\npredictions = []\nfiles = []\n    \nfor model_block in model_weights:\n    feat = model_block['feat']\n\n    # %%time\n    all_eegs = {}\n    eeg_ids = test_df.eeg_id.unique()\n    for i, eeg_id in tqdm(enumerate(eeg_ids)):\n        # Save EEG to Python dictionary of numpy arrays\n        eeg_path = CFG.test_eeg + str(eeg_id) + \".parquet\"\n        data = eeg_from_parquet(eeg_path, eeg_features=feat.eeg_features)\n        all_eegs[eeg_id] = data\n\n    test_dataset = EEGDataset(\n        df=test_df,\n        batch_size=CFG.batch_size,\n        mode=\"test\",\n        eegs=all_eegs,\n        bandpass_filter=model_block['bandpass_filter'],\n        in_channels=feat.in_channels,\n        map_features=feat.map_features,\n        feature_to_index=feat.feature_to_index,\n        n_map_features = feat.n_map_features,\n        simple_features = feat.simple_features,\n        target_size = CFG.target_size,\n    )\n\n    if len(predictions) == 0:\n        output = test_dataset[0]\n        X = output[\"eeg\"]\n        print(f\"X shape: {X.shape}\")\n                \n    test_loader = DataLoader(\n        test_dataset,\n        batch_size=CFG.batch_size,\n        shuffle=False,\n        num_workers=CFG.num_workers,\n        pin_memory=True,\n        drop_last=False,\n    )\n\n    model = EEGNet(\n        kernels=CFG.kernels,\n        in_channels=feat.in_channels,\n        fixed_kernel_size=CFG.fixed_kernel_size,\n        num_classes=CFG.target_size,\n        linear_layer_features=CFG.linear_layer_features,\n    )\n\n    for file_line in model_block['file_data']:\n        koef = file_line['koef']\n        for weight_model_file in glob(file_line['file_mask']):\n            files.append(weight_model_file)\n            checkpoint = torch.load(weight_model_file, map_location=device)\n            model.load_state_dict(checkpoint[\"model\"])\n            model.to(device)\n            prediction_dict = inference_function(test_loader, model, device)\n            predict = prediction_dict[\"predictions\"]\n            predict *= koef\n            koef_sum += koef\n            koef_count += 1\n            predictions.append(predict)\n            torch.cuda.empty_cache()\n            _ = gc.collect()\n    \n    del all_eegs\n    _ = gc.collect()\n\npredictions = np.array(predictions)\nkoef_sum /= koef_count\npredictions /= koef_sum\npredictions = np.mean(predictions, axis=0)","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:14:53.313179Z","iopub.execute_input":"2024-04-09T09:14:53.313483Z","iopub.status.idle":"2024-04-09T09:15:01.552759Z","shell.execute_reply.started":"2024-04-09T09:14:53.313459Z","shell.execute_reply":"2024-04-09T09:15:01.551635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predss_3 = predictions\npredss_3","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:15:01.554137Z","iopub.execute_input":"2024-04-09T09:15:01.554474Z","iopub.status.idle":"2024-04-09T09:15:01.562308Z","shell.execute_reply.started":"2024-04-09T09:15:01.554447Z","shell.execute_reply":"2024-04-09T09:15:01.561228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submision","metadata":{}},{"cell_type":"code","source":"submission=pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\nlabels=['seizure','lpd','gpd','lrda','grda','other']\nfor i in range(len(labels)):\n    submission[f'{labels[i]}_vote']=(predss_1[:,i] * 0.45 + predss_2[:, i] * 0.2 + predss_3[:, i] * 0.35)\nsubmission.to_csv(\"submission.csv\",index=None)\ndisplay(submission.head())","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:15:01.564117Z","iopub.execute_input":"2024-04-09T09:15:01.564569Z","iopub.status.idle":"2024-04-09T09:15:01.588464Z","shell.execute_reply.started":"2024-04-09T09:15:01.564535Z","shell.execute_reply":"2024-04-09T09:15:01.587342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# SANITY CHECK TO CONFIRM PREDICTIONS SUM TO ONE\nsubmission.iloc[:,-6:].sum(axis=1)","metadata":{"execution":{"iopub.status.busy":"2024-04-09T09:15:01.589676Z","iopub.execute_input":"2024-04-09T09:15:01.590011Z","iopub.status.idle":"2024-04-09T09:15:01.599636Z","shell.execute_reply.started":"2024-04-09T09:15:01.589984Z","shell.execute_reply":"2024-04-09T09:15:01.598619Z"},"trusted":true},"execution_count":null,"outputs":[]}]}