{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":8023050,"sourceType":"datasetVersion","datasetId":4727914}],"dockerImageVersionId":30699,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd, numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib\n\n\nimport pandas as pd\nfrom mne.filter import filter_data, notch_filter\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport pyarrow.parquet as pq\nimport librosa\nimport pandas as pd, numpy as np, os\nimport matplotlib.pyplot as plt, gc\nimport pandas as pd, numpy as np, os\nimport matplotlib.pyplot as plt, gc\n\nimport torch, gc\nimport torchaudio.transforms as T\nimport numpy as np, cv2\nimport typing as tp\nfrom pathlib import Path\nfrom io import BytesIO\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom tqdm.notebook import tqdm\nimport albumentations as A\nimport timm\nimport torch.nn as nn\nfrom torch import nn\nimport timm\nfrom torch.utils.data import DataLoader\n\nimport torch, gc\nimport torchaudio.transforms as T\nimport numpy as np, cv2\nimport typing as tp\nfrom pathlib import Path\nfrom io import BytesIO\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom tqdm.notebook import tqdm\n\n\nimport warnings\nwarnings.filterwarnings('ignore')\nfrom mne.filter import filter_data, notch_filter\n\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom mne.filter import notch_filter, filter_data\n\ndef to_device(\n    tensors: tp.Union[tp.Tuple[torch.Tensor], tp.Dict[str, torch.Tensor]],\n    device: torch.device, *args, **kwargs\n):\n    if isinstance(tensors, tuple):\n        return (t.to(device, *args, **kwargs) for t in tensors)\n    elif isinstance(tensors, dict):\n        return {\n            k: t.to(device, *args, **kwargs) for k, t in tensors.items()}\n    else:\n        return tensors.to(device, *args, **kwargs)\n\ndef interpolate_2d_array(original_array, new_columns):\n    R, C = original_array.shape\n\n    # Create an array of indices for the original array columns\n    original_indices = np.arange(C)\n\n    # Create an array of indices for the new array columns\n    new_indices = np.linspace(0, C - 1, new_columns)\n\n    # Interpolate along each row to compute values at the new column indices\n    interpolated_values = np.array([np.interp(new_indices, original_indices, row) for row in original_array])\n\n    return interpolated_values\n\ndef process_eegs(eegs_df):\n\n    raw_eegs_b10 = {}\n    labels = []\n    PATH = '/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/'\n\n    for index, row in eegs_df.iterrows():\n        eeg_id = row['eeg_id']\n        offset_seconds = row['eeg_label_offset_seconds']\n        label = row['expert_consensus']\n        eeg_data = pd.read_parquet(f'{PATH}{eeg_id}.parquet')  # Read single EEG file\n\n        # Extract 10 seconds preceding the central 10 seconds\n        eeg_b10 = extract_50(eeg_data, offset_seconds)\n\n        # Impute NaN values with the mean of each column\n        eeg_b10 = eeg_b10.fillna(eeg_b10.mean())\n\n        # eeg_tensor = torch.tensor(eeg_b10.values, dtype=torch.float32)\n        raw_eegs_b10[index] = eeg_b10\n        labels.append(label)\n\n    return raw_eegs_b10, labels\n\ndef extract_b10(eeg_data, offset_seconds, sampling_rate=200):\n    # Calculate the total span of 50 seconds starting from offset_seconds\n    start_50s = int(offset_seconds * sampling_rate)    \n    # Calculate the start index of the central 10 seconds within the 50 seconds\n    central_start = start_50s + (20 * sampling_rate)  # 20 seconds into the 50 seconds span\n\n    # Calculate the start index for the preceding 10 seconds relative to the central 10 seconds\n    preceding_start = central_start - (10 * sampling_rate)\n    \n    # Calculate the end index for the preceding 10 seconds\n    preceding_end = central_start\n    \n    # Return the slice of EEG data for the preceding 10 seconds\n    return eeg_data.iloc[preceding_start:preceding_end]\n\ndef extract_50(eeg_data, offset_seconds, sampling_rate=200):\n    # Calculate the total span of 50 seconds starting from offset_seconds\n    start_50s = int(offset_seconds * sampling_rate)    \n    # Calculate the start index of the central 10 seconds within the 50 seconds\n    end_50s = start_50s + (50 * sampling_rate)  # 20 seconds into the 50 seconds span\n    # Return the slice of EEG data for the preceding 10 seconds\n    return eeg_data.iloc[start_50s:end_50s]\n\ntransform=test_transform = A.Compose([\n        A.Resize(p=1.0, height=299, width=299),\n        ToTensorV2(p=1.0)\n    ])\n\ndef create(eeg, valid=True, cflip=False,\n            flip=False, rflip=False, crop=False, freq_aug=False):  \n    \n    img = eeg\n    img0 = img.copy()\n            \n    ##################\n    ### WAVEFORM INVERT AUGMENTATION\n    FLIPS = [1,1,1,1]\n    if flip:\n        FLIPS = np.random.choice([1,-1],4,replace=True)\n        \n    # WAVEFORM BRAIN RIGHT LEFT FLIP AUGMENTAION\n    img = img0.copy()\n    if cflip & (np.random.uniform(0,1)<0.5):\n        for k in range(4):\n            img[0+k,] = FLIPS[0] * img0[4+k,]\n            img[4+k,] = FLIPS[1] * img0[0+k,]\n            img[8+k,] = FLIPS[2] * img0[12+k,]\n            img[12+k,] = FLIPS[3] * img0[8+k,]\n    else:\n        for k in range(4):\n            img[0+k,] = FLIPS[0] * img0[0+k,]\n            img[4+k,] = FLIPS[1] * img0[4+k,]\n            img[8+k,] = FLIPS[2] * img0[8+k,]\n            img[12+k,] = FLIPS[3] * img0[12+k,]\n            \n    # WAVEFORM BRAIN TEMPORAL PARASAGITTAL FLIP AUGMENTAION\n    img0 = img.copy()\n    if rflip & (np.random.uniform(0,1)<0.5):\n        for k in range(4):\n            img[0+k,] = img0[8+k,]\n            img[8+k,] = img0[0+k,]\n            img[4+k,] = img0[12+k,]\n            img[12+k,] = img0[4+k,]\n            \n    # WAVEFORM CROP AND SCALE AUGMENTATION\n    if crop:\n        r = int( np.random.normal(0,200) ) #40\n        if r>=0:\n            img = interpolate_2d_array(img[:,r:], 10_000).astype('float32')\n        else:\n            img = interpolate_2d_array(img[:,:r], 10_000).astype('float32')\n    img0 = img.copy()\n    ##################\n    \n    ##################\n    ### MATPLOTLIB 2D PLOT OF WAVEFORMS\n    image_size = (224, 224)\n    fig = plt.figure(figsize=(image_size[0] / 100, image_size[1] / 100), dpi=100)\n    for k in range(16):\n        plt.plot(range(2_000),img0[k,][4000:6000]+k*200,linewidth=0.5)\n    plt.axis('off')\n    plt.subplots_adjust(left=0, right=1, top=1, bottom=0)\n    buffer = BytesIO()\n    plt.savefig(buffer, format='png', bbox_inches='tight', pad_inches=0, transparent=False)\n    buffer.seek(0)\n    img9 = np.transpose( plt.imread(buffer)[:,:,:3], (2,0,1) )\n    buffer.close()\n    plt.clf()\n    plt.close('all')\n    ##################\n    \n    ###################\n    ### MAKE SPECTROGRAMS\n    make_spec1 = T.MelSpectrogram(n_fft=2048, win_length=1280, hop_length=19,\n                                    f_min=0,f_max=20,sample_rate=200,n_mels=64).to(device2)\n    make_spec2 = T.MelSpectrogram(n_fft=1024+256, win_length=32, hop_length=4,\n                                    f_min=0,f_max=20,sample_rate=200,n_mels=64).to(device2)\n    ###################\n\n        ###################\n    ### MAKE SPECTROGRAMS 50 SECONDS\n    specs2 = []\n    for j in range(4):\n        specs = []\n        for k in range(4):\n            waveform = torch.tensor(img0[4*j+k,][140:-140], dtype=torch.float32).to(device2)\n            specgram = make_spec1(waveform)\n            specs.append( specgram ) # SIZE 64x512\n        specs2.append( torch.mean(torch.stack(specs),dim=0) )\n    img = torch.cat(specs2,axis=0) # SIZE 256x512\n    #####################\n    ### NORMALIZE\n    img = torch.clamp(img, 1e-8, 1e8)\n    img = torch.log(img)\n    eps = 1e-6\n    img_mean = img.mean(dim=(0, 1))\n    img = img - img_mean\n    img_std = img.std(dim=(0, 1))\n    img = img / (img_std + eps)\n    \n    ### MAKE SPECTROGRAMS 10 SECONDS\n    specs2 = []\n    for j in range(4):\n        specs = []\n        for k in range(4):\n            waveform = torch.tensor(img0[4*j+k,][3977:-3977], dtype=torch.float32).to(device2)\n            specgram = make_spec2(waveform)\n            specs.append( specgram ) # SIZE 64x512\n        specs2.append( torch.mean(torch.stack(specs),dim= 0) )\n    img2 = torch.cat(specs2,axis=0) # SIZE 256x512\n    #####################\n    ### NORMALIZE\n    img2 = torch.clamp(img2, 1e-8, 1e8)\n    img2 = torch.log(img2)\n    eps = 1e-6\n    img_mean = img2.mean(dim=(0, 1))\n    img2 = img2 - img_mean\n    img_std = img2.std(dim=(0, 1))\n    img2 = img2 / (img_std + eps)\n    #####################\n    img = torch.cat([img,img2],axis=0) #512x512\n    img = img[..., None]\n    img_cpu = img2.cpu().numpy()\n    img_cpu = cv2.cvtColor(img_cpu,cv2.COLOR_GRAY2RGB)\n\n\n    ###################\n    ### SPECTROGRAM FREQUENCY AUGMENTATION\n    if freq_aug:\n        rr = np.random.randint(1,4) \n        for j in range(rr):\n            r = np.random.randint(0,64)\n            d = np.random.randint(2,11) \n            a = np.max([0,r-d])\n            b = np.min([63,r+d])\n            for k in range(8):\n                img_cpu[a+k*64:b+k*64,] = 0\n\n    img = _apply_transform( img_cpu)\n    return img\n\ndef _apply_transform(img: np.ndarray):\n        \"\"\"apply transform to image and mask\"\"\"\n        transformed = transform(image=img)\n        img = transformed[\"image\"]\n        return img\n# LOAD TEST DATA\ncount = 4\n\nlabel_dict = {\n    \"Seizure\": torch.tensor([1.0, 0, 0, 0, 0, 0]),\n    \"GPD\": torch.tensor([0, 1.0, 0, 0, 0, 0]),\n    \"LRDA\": torch.tensor([0, 0, 1.0, 0, 0, 0]),\n    \"GRDA\": torch.tensor([0, 0, 0, 1.0, 0, 0]),\n    \"Other\" : torch.tensor([0, 0, 0, 0, 1.0, 0]),\n    \"LPD\" : torch.tensor([0, 0, 0, 0, 0, 1.0]),\n}\n\n\ntest = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')\ntest = test[0:4000]\n\n# WORKERS=0 USES GPU SPECTROGRAMS AND WORKERS>0 USES CPU SPECTROGRAMS\nWORKERS = 1\n\n# DEVICE FOR MODEL INFERENCE\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# DEVICE FOR CREATING SPECTROGRAMS\ndevice2 = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nif WORKERS>0: device2 = \"cpu\" # TO AVOID MULTIPROCESSING ERROR\nprint( device, device2 )\nraw_eegs_b10, labels = process_eegs(test)\n\nall_eegs = []\n\nfor index in raw_eegs_b10:\n        \n    # data = pd.read_parquet(f'{PATH}{eeg_id}.parquet').values[:,:19]\n    data =  raw_eegs_b10[index].values[:,:19]\n    sample = data.T[[0,4,5,6, 11,15,16,17, 0,1,2,3, 11,12,13,14]]\\\n             - data.T[[4,5,6,7, 15,16,17,18, 1,2,3,7, 12,13,14,18]]\n    sample = notch_filter(sample.astype('float64'), 200, 60, n_jobs=-1, verbose='ERROR')\n    sample = filter_data(sample.astype('float64'), 200, 0.5, 40, n_jobs=-1, verbose='ERROR') \n    sample = np.clip(sample,-500,500)\n    sample = np.nan_to_num(sample, nan=0)\n    all_eegs.append(sample)\nfrom torch.utils.data import Dataset\nfrom torchvision import transforms\nfrom PIL import Image\nimport cv2\nimport torch\n\nclass CustomImageDataset(Dataset):\n    def __init__(self, image_paths, labels, transform=None):\n        \"\"\"\n        Args:\n            image_paths (list of str): List of image file paths\n            labels (list of int): List of label indices corresponding to the images\n            transform (callable, optional): Optional transform to be applied on a sample.\n        \"\"\"\n        self.image_paths = image_paths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, idx):\n        image = create(self.image_paths[idx])\n        label = self.labels[idx]\n\n        return image, label_dict[label]\n\n# Example usage:\nimage_paths = all_eegs\nlabels = labels\n\ndataset = CustomImageDataset(image_paths=image_paths, labels=labels)\n\nfrom torch.utils.data import DataLoader\n\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader\n\nfrom torchvision import models\nimport torchvision.utils\nimport torchvision.datasets as dsets\nimport torchvision.transforms as transforms\nimport torch.nn.functional as F\n\n\nimport numpy as np\n\nbatch_size = 2\nnum_epochs = 5\nnum_datapoints = len(all_eegs)\n\n\ntrain_loader = DataLoader(dataset,\n                          batch_size=batch_size,\n                          shuffle=True,  drop_last=True)\n\nmodel = models.inception_v3(pretrained=False)\n\nmodel.aux_logits = False\n\nfor parameter in model.parameters():\n    parameter.requires_grad = False\n\nmodel.fc = nn.Sequential(\n    nn.Linear(model.fc.in_features, 10),\n    nn.Linear(10, 6)\n)\n\nmodel = model.cuda()\n\nloss = nn.CrossEntropyLoss()\noptimizer = torch.optim.RMSprop(filter(lambda p: p.requires_grad, model.parameters()), lr=0.001)\nfor epoch in range(num_epochs):\n    \n    total_batch = num_datapoints//batch_size\n\n    for i, (batch_images, batch_labels) in enumerate(train_loader):\n        \n        print(i)\n\n        X = batch_images.cuda()\n        Y = batch_labels.cuda()\n\n        \n        pre = model(X)\n        cost = loss(pre, Y)\n\n        optimizer.zero_grad()\n        cost.backward()\n        optimizer.step()\n\n        if (i+1) % 5 == 0:\n            print('Epoch [%d/%d], lter [%d/%d] Loss: %.4f'\n                 %(epoch+1, num_epochs, i+1, total_batch, cost.item()))\n        \n\nreal_test = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/test.csv')\n# Test\ndef process_test_egs(eegs_df):\n    raw_test_eegs = {}\n    test_eeg_ids = []\n    PATH = '/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/'\n    for index, row in eegs_df.iterrows():\n        eeg_id = row['eeg_id']\n        eeg_data = pd.read_parquet(f'{PATH}{eeg_id}.parquet')  # Read single EEG file\n        raw_test_eegs[index] = eeg_data\n        test_eeg_ids.append(eeg_id)\n\n    return raw_test_eegs, test_eeg_ids\n\nraw_eegs_test, test_eeg_ids = process_test_egs(real_test)\n\nall_eeg_test = []\n\nfor index in raw_eegs_test:\n        \n    # data = pd.read_parquet(f'{PATH}{eeg_id}.parquet').values[:,:19]\n    data =  raw_eegs_test[index].values[:,:19]\n    sample = data.T[[0,4,5,6, 11,15,16,17, 0,1,2,3, 11,12,13,14]]\\\n             - data.T[[4,5,6,7, 15,16,17,18, 1,2,3,7, 12,13,14,18]]\n    sample = notch_filter(sample.astype('float64'), 200, 60, n_jobs=-1, verbose='ERROR')\n    sample = filter_data(sample.astype('float64'), 200, 0.5, 40, n_jobs=-1, verbose='ERROR') \n    sample = np.clip(sample,-500,500)\n    sample = np.nan_to_num(sample, nan=0)\n    all_eeg_test.append(sample)\n\ntest_eeg_ids[0]\n\nfrom torch.utils.data import Dataset\nfrom torchvision import transforms\nfrom PIL import Image\nimport cv2\nimport torch\n\nclass TestDataset(Dataset):\n    def __init__(self, image_paths, transform=None):\n        \"\"\"\n        Args:\n            image_paths (list of str): List of image file paths\n            labels (list of int): List of label indices corresponding to the images\n            transform (callable, optional): Optional transform to be applied on a sample.\n        \"\"\"\n        self.image_paths = image_paths\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, idx):\n        image = create(self.image_paths[idx])\n        return image\n\n# Example usage:\ndataset = TestDataset(image_paths=all_eeg_test)\n\ndataset\ntest_loader =  DataLoader(dataset,\n                          batch_size=1,\n                          shuffle=False)\nmodel.eval()\n\ncorrect = 0\ntotal = 0\ntrue_labels = []\nresult = []\n\nfor images in test_loader:\n    \n    images = images.cuda()\n    outputs = model(images)    \n    #_, predicted = torch.max(outputs.data, 1)\n    probabilities = F.softmax(outputs, dim=1)\n    result.append(probabilities.tolist()[0])\n\ntransposed_result = list(map(list, zip(*result)))\n\ntransposed_result\ndata = {\n    'eeg_id': test_eeg_ids,\n    'seizure_vote': transposed_result[0],\n    'lpd_vote': transposed_result[1],\n    'gpd_vote': transposed_result[2],\n    'lrda_vote': transposed_result[3],\n    'grda_vote' :transposed_result[4],\n    'other_vote': transposed_result[5]\n}\n\n\ndata\ndf = pd.DataFrame(data)\n\nsmpl_sub = pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\nsub = pd.merge(\n    smpl_sub[[\"eeg_id\"]], df, on=\"eeg_id\", how=\"left\")\nsub.to_csv(\"submission.csv\", index=False)\nsub.head()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]}]}