{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":4477,"databundleVersionId":44220,"sourceType":"competition"}],"dockerImageVersionId":30635,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"%%time\n\n!pip install torch==1.13.0 --upgrade &> null\n!pip install ecgmentations &> null # library with 1d signal augmentations\n!pip install git+https://github.com/rostepifanov/nnspt@release_v0.0.2 &> null # library with 1d CNNs","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Fix seeds","metadata":{}},{"cell_type":"code","source":"import os\nimport torch\nimport random\nimport numpy as np\n\nseed = 1996\n\nrandom.seed(seed)\n\nnp.random.seed(seed)\n\ntorch.manual_seed(seed)\ntorch.cuda.manual_seed(seed)\ntorch.cuda.manual_seed_all(seed)\n\ntorch.backends.cudnn.determenistic = True\ntorch.use_deterministic_algorithms(True)\n\nos.environ['PYTHONHASHSEED'] = str(seed)\n\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\n\nprint(device)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load train data","metadata":{}},{"cell_type":"code","source":"%%time\n\nfrom pathlib import Path\nfrom zipfile import ZipFile\n\nlabels = [ 'HandStart', 'FirstDigitTouch', 'BothStartLoadPhase', 'LiftOff', 'Replace', 'BothReleased' ]\n\nzipdir = Path.cwd().parent / 'input' / 'grasp-and-lift-eeg-detection'\n\nfor zipfile in zipdir.glob('*.zip'):\n    with ZipFile(zipfile, 'r') as zf:\n        zf.extractall()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nimport pandas as pd\nfrom tqdm import tqdm\n\nxs = []\nys = []\nys_ = []\n\ntraindir = Path('train')\n\nfor datapath in tqdm([*sorted(traindir.glob('*_data.csv'))]):\n    eventpath = datapath.parent / ( datapath.stem[:-5] + '_events.csv' )\n\n    x = pd.read_csv(datapath)\n    y = pd.read_csv(eventpath)\n\n    x = x.iloc[:,1:].values\n    y_ = y.iloc[:,1:].values\n\n    xs.append(x.astype(np.float32))\n    ys.append(y_.astype(np.uint8))\n\nxs_train = xs[:-2]\nys_train = ys[:-2]\n\nxs_valid = xs[-2:]\nys_valid = ys[-2:]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import ecgmentations as E\n\nfrom torch.utils.data import DataLoader, Dataset\n\nclass EEGDataset(Dataset):\n    def __init__(self, x, y, augs=dict, train=False):\n        self.x = x\n        self.y = y\n        self.augs = augs\n        \n        self.train = train\n\n    def __getitem__(self, idx):\n        eeg = self.x[idx]\n        mask = self.y[idx]\n\n        if self.train:\n            length = mask.shape[0]\n\n            size = 5000\n            smask = (np.sum(mask[:-size], axis=1) > 0).astype(np.uint8)\n            smask = smask * 5 + 1\n            p = smask / smask.sum()\n\n            jdx = np.random.choice(length-size, p=p)\n\n            eeg = eeg[jdx:jdx+size]\n            mask = mask[jdx:jdx+size]\n\n        auged = self.augs(ecg=eeg, mask=mask)\n        eeg, mask = auged['ecg'], auged['mask']\n\n        return eeg.T, mask.T\n\n    def __len__(self):\n        return len(self.x)\n\naugs = E.Sequential([\n    E.TimeCrop(length=5000, p=1.0),\n])\n\ndataset = EEGDataset(xs_train, ys_train, augs, True) \ntrain_dataloader = DataLoader(dataset, batch_size=25, num_workers=3, shuffle=True)\n\ndataset = EEGDataset(xs_train, ys_train) \ntrain_dataloader_ = DataLoader(dataset, batch_size=1, num_workers=3, shuffle=False)\n\ndataset = EEGDataset(xs_valid, ys_valid)\nvalid_dataloader = DataLoader(dataset, batch_size=1, num_workers=3, shuffle=False)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train model","metadata":{}},{"cell_type":"code","source":"import copy\nimport torch.nn.functional as F\n\nfrom sklearn import metrics\nfrom nnspt.segmentation.unet import Unet\n\nmodel = Unet(in_channels=32, out_channels=6, encoder='timm-efficientnet-b1')\nmodel.to(device)\n\nnepochs = 1000\n\nopt = torch.optim.AdamW(model.parameters(), lr=0.00175)\nshed = torch.optim.lr_scheduler.CosineAnnealingLR(opt, nepochs*len(train_dataloader))\n\nloss_his, train_loss = [], []\n\nbest_score = 0.\nbest_state_dict = copy.deepcopy(model.state_dict())\n\nfor epoch in range(nepochs):\n    model.train()\n\n    for i, (eeg_batch, mask_batch) in enumerate(train_dataloader):\n        eeg_batch, mask_batch = eeg_batch.to(device), mask_batch.to(device)\n\n        logits = model(eeg_batch)\n        loss = F.binary_cross_entropy_with_logits(logits, mask_batch.float())\n        loss.backward()\n\n        opt.step()\n        shed.step()\n        opt.zero_grad()\n\n        train_loss.append(loss.item())\n\n    if (epoch + 1) % 25 == 0:\n        loss_his.append(np.mean(train_loss))\n        train_loss.clear()\n\n        print('[Epoch {}/{}] [Loss: {}]'.format(epoch+1, nepochs, loss_his[-1]))\n        \n        model.eval()\n\n        y_pred = []\n\n        size = 10000\n\n        for eeg_batch, _ in tqdm(valid_dataloader):\n            for idx in range((eeg_batch.shape[-1] + size - 1) // size):\n                with torch.no_grad():\n                    eeg_batch_ = eeg_batch[:, :, idx*size: (idx+1)*size].to(device)\n\n                    logits = model(eeg_batch_)\n                    probs = torch.sigmoid(logits).cpu().numpy()[0]\n\n                    y_pred.append(probs)\n\n        y_pred = np.concatenate(y_pred, axis=1).T\n        y_true = np.concatenate(ys_valid, axis=0)\n\n        score = metrics.roc_auc_score(y_true, y_pred)\n\n        print('[Epoch {}/{}] [Score: {}]'.format(epoch+1, nepochs, score))\n\n        if score > best_score:\n            best_score = score\n            best_state_dict = copy.deepcopy(model.state_dict())\n\nmodel.load_state_dict(best_state_dict)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Score on train part","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ndef plot_roc(y_true, y_pred):\n    fig, axs = plt.subplots(3, 2, figsize=(15, 13))\n\n    for i, label in enumerate(labels):\n        fpr, tpr, _ = metrics.roc_curve(y_true[i], y_pred[i])\n        ax = axs[i//2, i%2]\n        ax.plot(fpr, tpr)\n        ax.set_title(label + ' ROC')\n        ax.plot([0, 1], [0, 1], 'k--')\n\n    plt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\n\ny_pred = []\n\nsize = 10000\n\nfor eeg_batch, _ in tqdm(train_dataloader_):\n    for idx in range((eeg_batch.shape[-1] + size - 1) // size):\n        with torch.no_grad():\n            eeg_batch_ = eeg_batch[:, :, idx*size: (idx+1)*size].to(device)\n\n            logits = model(eeg_batch_)\n            probs = torch.sigmoid(logits).cpu().numpy()[0]\n\n            y_pred.append(probs)\n\ny_pred = np.concatenate(y_pred, axis=1).T\ny_true = np.concatenate(ys_train, axis=0)\n\nplot_roc(y_true.T, y_pred.T)\n\nprint('roc auc: ', metrics.roc_auc_score(y_true, y_pred))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Score on val part","metadata":{}},{"cell_type":"code","source":"model.eval()\n\ny_pred = []\n\nsize = 10000\n\nfor eeg_batch, _ in tqdm(valid_dataloader):\n    for idx in range((eeg_batch.shape[-1] + size - 1) // size):\n        with torch.no_grad():\n            eeg_batch_ = eeg_batch[:, :, idx*size: (idx+1)*size].to(device)\n\n            logits = model(eeg_batch_)\n            probs = torch.sigmoid(logits).cpu().numpy()[0]\n\n            y_pred.append(probs)\n\ny_pred = np.concatenate(y_pred, axis=1).T\ny_true = np.concatenate(ys_valid, axis=0)\n\nplot_roc(y_true.T, y_pred.T)\n\nprint('roc auc: ', metrics.roc_auc_score(y_true, y_pred))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create submission","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom tqdm import tqdm\n\nxs_test = []\nlengths = {}\n\ntestdir = Path('test')\n\nFNAME = 'subj{}_series{}_{}.csv'\n\nfor subj in range(1, 13):\n    for series in [9, 10]:\n        datapath = testdir / FNAME.format(subj, series, 'data')\n\n        x = pd.read_csv(datapath)\n        x = x.iloc[:,1:].values\n\n        xs_test.append(x.astype(np.float32))\n        lengths['{}_{}'.format(subj, series)] = xs_test[-1].shape[0]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class EEGDatasetTest(Dataset):\n    def __init__(self, x):\n        self.x = x\n\n    def __getitem__(self, idx):\n        eeg = self.x[idx]\n\n        return eeg.T\n\n    def __len__(self):\n        return len(self.x)\n\ndataset = EEGDatasetTest(xs_test)\ntest_dataloader = DataLoader(dataset, batch_size=1, num_workers=3, shuffle=False)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\n\ny_pred = []\n\nsize = 10000\n\nfor eeg_batch in tqdm(test_dataloader):\n    for idx in range((eeg_batch.shape[-1] + size - 1) // size):\n        with torch.no_grad():\n            eeg_batch_ = eeg_batch[:, :, idx*size: (idx+1)*size].to(device)\n\n            logits = model(eeg_batch_)\n            probs = torch.sigmoid(logits).cpu().numpy()[0]\n\n            y_pred.append(probs)\n\ny_pred = np.concatenate(y_pred, axis=1).T","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame(y_pred, index=['subj{}_series{}_{}'.format(sbj, i, j) for sbj in range(1, 13) for i in [9, 10] for j in range(lengths['{}_{}'.format(sbj, i)])], columns=labels)\nsubmission.to_csv('Submission.csv', index_label='id', float_format='%.3f')\n\nsubmission.tail()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!head Submission.csv","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!head sample_submission.csv","metadata":{},"execution_count":null,"outputs":[]}]}