{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.10","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":29653,"databundleVersionId":2420395,"sourceType":"competition"},{"sourceId":848739,"sourceType":"datasetVersion","datasetId":251095}],"dockerImageVersionId":30121,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# RSNA-MICCAI Brain Tumor Radiogenomic Classification - Exploratory Data Analysis and Modeling\n\n\n### Predict the status of a genetic biomarker important for brain cancer treatment\n\nQuick Exploratory Data Analysis for [RSNA-MICCAI Brain Tumor Radiogenomic Classification](https://www.kaggle.com/c/rsna-miccai-brain-tumor-radiogenomic-classification) challenge    \n\n\n","metadata":{}},{"cell_type":"markdown","source":"![](https://storage.googleapis.com/kaggle-competitions/kaggle/29653/logos/header.png)","metadata":{}},{"cell_type":"markdown","source":"<a id=\"top\"></a>\n\n<div class=\"list-group\" id=\"list-tab\" role=\"tablist\">\n<h3 class=\"list-group-item list-group-item-action active\" data-toggle=\"list\" style='color:white; background:darkviolet; border:0' role=\"tab\" aria-controls=\"home\"><center>Quick Navigation</center></h3>\n\n* [Overview](#1)\n* [Data Visualization](#2)\n    \n\n* [Competition Metric](#10)\n* [Sample Submission](#20)\n    \n\n* [Modeling](#100)","metadata":{}},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n<h2 style='background:darkviolet; border:0; color:white'><center>Overview<center><h2>","metadata":{}},{"cell_type":"markdown","source":"The work uses some ideas from next great works:\n- https://www.kaggle.com/avloss/eda-with-animation - animation technique","metadata":{}},{"cell_type":"code","source":"import os\nimport json\nimport glob\nimport random\nimport collections\n\nimport numpy as np\nimport pandas as pd\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport cv2\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"execution":{"iopub.status.busy":"2023-12-16T08:37:45.818355Z","iopub.execute_input":"2023-12-16T08:37:45.81868Z","iopub.status.idle":"2023-12-16T08:37:46.963564Z","shell.execute_reply.started":"2023-12-16T08:37:45.818606Z","shell.execute_reply":"2023-12-16T08:37:46.962828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**train/** - folder containing the training files, with each top-level folder representing a subject  \n**train_labels.csv** - file containing the target MGMT_value for each subject in the training data (e.g. the presence of MGMT promoter methylation)   \n**test/** - the test files, which use the same structure as train/; your task is to predict the MGMT_value for each subject in the test data. NOTE: the total size of the rerun test set (Public and Private) is ~5x the size of the Public test set   \n**sample_submission.csv** - a sample submission file in the correct format","metadata":{}},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h2 style='background:darkviolet; border:0; color:white'><center>Data Visualization<center><h2>","metadata":{"execution":{"iopub.status.busy":"2021-07-14T06:41:32.077425Z","iopub.execute_input":"2021-07-14T06:41:32.077767Z","iopub.status.idle":"2021-07-14T06:41:32.0845Z","shell.execute_reply.started":"2021-07-14T06:41:32.077737Z","shell.execute_reply":"2021-07-14T06:41:32.082683Z"}}},{"cell_type":"code","source":"train_df = pd.read_csv(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train_labels.csv\")\ntrain_df","metadata":{"execution":{"iopub.status.busy":"2023-12-16T08:37:49.93289Z","iopub.execute_input":"2023-12-16T08:37:49.933237Z","iopub.status.idle":"2023-12-16T08:37:49.965624Z","shell.execute_reply.started":"2023-12-16T08:37:49.933206Z","shell.execute_reply":"2023-12-16T08:37:49.964781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2023-12-16T08:38:01.992072Z","iopub.execute_input":"2023-12-16T08:38:01.992458Z","iopub.status.idle":"2023-12-16T08:38:02.145968Z","shell.execute_reply.started":"2023-12-16T08:38:01.992425Z","shell.execute_reply":"2023-12-16T08:38:02.145166Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2023-12-16T08:38:29.212673Z","iopub.execute_input":"2023-12-16T08:38:29.213055Z","iopub.status.idle":"2023-12-16T08:38:29.224323Z","shell.execute_reply.started":"2023-12-16T08:38:29.213019Z","shell.execute_reply":"2023-12-16T08:38:29.223328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2023-12-16T08:38:35.673897Z","iopub.execute_input":"2023-12-16T08:38:35.674286Z","iopub.status.idle":"2023-12-16T08:38:43.216857Z","shell.execute_reply.started":"2023-12-16T08:38:35.67425Z","shell.execute_reply":"2023-12-16T08:38:43.215933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from matplotlib import animation, rc\nrc('animation', html='jshtml')\n\n\ndef create_animation(ims):\n    fig = plt.figure(figsize=(6, 6))\n    plt.axis('off')\n    im = plt.imshow(ims[0], cmap=\"gray\")\n\n    def animate_func(i):\n        im.set_array(ims[i])\n        return [im]\n\n    return animation.FuncAnimation(fig, animate_func, frames = len(ims), interval = 1000//24)","metadata":{"execution":{"iopub.status.busy":"2023-12-16T08:40:12.326653Z","iopub.execute_input":"2023-12-16T08:40:12.327006Z","iopub.status.idle":"2023-12-16T08:40:12.333567Z","shell.execute_reply.started":"2023-12-16T08:40:12.326976Z","shell.execute_reply":"2023-12-16T08:40:12.332589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dicom_line(path):\n    t_paths = sorted(\n        glob.glob(os.path.join(path, \"*\")), \n        key=lambda x: int(x[:-4].split(\"-\")[-1]),\n    )\n    images = []\n    for filename in t_paths:\n        data = load_dicom(filename)\n        if data.max() == 0:\n            continue\n        images.append(data)\n        \n    return images","metadata":{"execution":{"iopub.status.busy":"2023-12-16T08:40:12.664015Z","iopub.execute_input":"2023-12-16T08:40:12.664385Z","iopub.status.idle":"2023-12-16T08:40:12.67026Z","shell.execute_reply.started":"2023-12-16T08:40:12.664354Z","shell.execute_reply":"2023-12-16T08:40:12.669383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = load_dicom_line(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/FLAIR\")\ncreate_animation(images)","metadata":{"execution":{"iopub.status.busy":"2023-12-16T08:40:13.1595Z","iopub.execute_input":"2023-12-16T08:40:13.159843Z","iopub.status.idle":"2023-12-16T08:40:34.153926Z","shell.execute_reply.started":"2023-12-16T08:40:13.15981Z","shell.execute_reply":"2023-12-16T08:40:34.153041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = load_dicom_line(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/T1w\")\ncreate_animation(images)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:43:46.651702Z","iopub.execute_input":"2021-08-15T11:43:46.652273Z","iopub.status.idle":"2021-08-15T11:43:48.530273Z","shell.execute_reply.started":"2021-08-15T11:43:46.652235Z","shell.execute_reply":"2021-08-15T11:43:48.529249Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = load_dicom_line(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/T1wCE\")\ncreate_animation(images)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:43:48.531703Z","iopub.execute_input":"2021-08-15T11:43:48.532086Z","iopub.status.idle":"2021-08-15T11:43:54.03148Z","shell.execute_reply.started":"2021-08-15T11:43:48.53205Z","shell.execute_reply":"2021-08-15T11:43:54.030506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = load_dicom_line(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/T2w\")\ncreate_animation(images)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:43:54.032893Z","iopub.execute_input":"2021-08-15T11:43:54.033271Z","iopub.status.idle":"2021-08-15T11:44:12.823984Z","shell.execute_reply.started":"2021-08-15T11:43:54.033231Z","shell.execute_reply":"2021-08-15T11:44:12.823016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"10\"></a>\n<h2 style='background:darkviolet; border:0; color:white'><center>Competition Metric<center><h2>","metadata":{}},{"cell_type":"markdown","source":"Submissions are evaluated on [area under the ROC curve](https://en.wikipedia.org/wiki/Receiver_operating_characteristic) between the predicted probability and the observed target.","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import roc_auc_score, roc_curve, auc\n\nlist_y_true = [\n    [1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],\n    [1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],\n    [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 0.], #  IMBALANCE\n]\nlist_y_pred = [\n    [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5],\n    [0.9, 0.9, 0.9, 0.9, 0.1, 0.9, 0.9, 0.1, 0.9, 0.1, 0.1, 0.5],\n    [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], #  IMBALANCE\n]\n\nfor y_true, y_pred in zip(list_y_true, list_y_pred):\n    fpr, tpr, _ = roc_curve(y_true, y_pred)\n    roc_auc = auc(fpr, tpr)\n\n    plt.figure(figsize=(5, 5))\n    plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)\n    plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')\n    plt.xlim([-0.01, 1.0])\n    plt.ylim([0.0, 1.05])\n    plt.xlabel('False Positive Rate')\n    plt.ylabel('True Positive Rate')\n    plt.title('Receiver operating characteristic example')\n    plt.legend(loc=\"lower right\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:12.825488Z","iopub.execute_input":"2021-08-15T11:44:12.825831Z","iopub.status.idle":"2021-08-15T11:44:13.370003Z","shell.execute_reply.started":"2021-08-15T11:44:12.825798Z","shell.execute_reply":"2021-08-15T11:44:13.369065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"20\"></a>\n<h2 style='background:darkviolet; border:0; color:white'><center>Sample Submission<center><h2>","metadata":{}},{"cell_type":"code","source":"submission = pd.read_csv(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/sample_submission.csv\")\n# submission.to_csv(\"submission.csv\", index=False)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:13.371444Z","iopub.execute_input":"2021-08-15T11:44:13.371795Z","iopub.status.idle":"2021-08-15T11:44:13.392733Z","shell.execute_reply.started":"2021-08-15T11:44:13.371761Z","shell.execute_reply":"2021-08-15T11:44:13.391812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"100\"></a>\n<h2 style='background:darkviolet; border:0; color:white'><center>Modeling<center><h2>","metadata":{}},{"cell_type":"code","source":"package_path = \"../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master/\"\nimport sys \nsys.path.append(package_path)\n\nimport time\n\nimport torch\nfrom torch import nn\nfrom torch.utils import data as torch_data\nfrom sklearn import model_selection as sk_model_selection\nfrom torch.nn import functional as torch_functional\nimport efficientnet_pytorch\n\nfrom sklearn.model_selection import StratifiedKFold","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:13.39406Z","iopub.execute_input":"2021-08-15T11:44:13.394455Z","iopub.status.idle":"2021-08-15T11:44:14.624502Z","shell.execute_reply.started":"2021-08-15T11:44:13.394417Z","shell.execute_reply":"2021-08-15T11:44:14.623674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_seed(seed):\n    random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed_all(seed)\n        torch.backends.cudnn.deterministic = True\n\n\nset_seed(42)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:14.625724Z","iopub.execute_input":"2021-08-15T11:44:14.626072Z","iopub.status.idle":"2021-08-15T11:44:14.683352Z","shell.execute_reply.started":"2021-08-15T11:44:14.626039Z","shell.execute_reply":"2021-08-15T11:44:14.682462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train_labels.csv\")\ndf_train, df_valid = sk_model_selection.train_test_split(\n    df, \n    test_size=0.2, \n    random_state=42, \n    stratify=train_df[\"MGMT_value\"],\n)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:14.68447Z","iopub.execute_input":"2021-08-15T11:44:14.685115Z","iopub.status.idle":"2021-08-15T11:44:14.70084Z","shell.execute_reply.started":"2021-08-15T11:44:14.685078Z","shell.execute_reply":"2021-08-15T11:44:14.699206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DataRetriever(torch_data.Dataset):\n    def __init__(self, paths, targets):\n        self.paths = paths\n        self.targets = targets\n          \n    def __len__(self):\n        return len(self.paths)\n    \n    def __getitem__(self, index):\n        _id = self.paths[index]\n        patient_path = f\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/{str(_id).zfill(5)}/\"\n        channels = []\n        for t in (\"FLAIR\", \"T1w\", \"T1wCE\"): # \"T2w\"\n            t_paths = sorted(\n                glob.glob(os.path.join(patient_path, t, \"*\")), \n                key=lambda x: int(x[:-4].split(\"-\")[-1]),\n            )\n            # start, end = int(len(t_paths) * 0.475), int(len(t_paths) * 0.525)\n            x = len(t_paths)\n            if x < 10:\n                r = range(x)\n            else:\n                d = x // 10\n                r = range(d, x - d, d)\n                \n            channel = []\n            # for i in range(start, end + 1):\n            for i in r:\n                channel.append(cv2.resize(load_dicom(t_paths[i]), (256, 256)) / 255)\n            channel = np.mean(channel, axis=0)\n            channels.append(channel)\n            \n        y = torch.tensor(self.targets[index], dtype=torch.float)\n        \n        return {\"X\": torch.tensor(channels).float(), \"y\": y}","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:14.702126Z","iopub.execute_input":"2021-08-15T11:44:14.702509Z","iopub.status.idle":"2021-08-15T11:44:14.714707Z","shell.execute_reply.started":"2021-08-15T11:44:14.702473Z","shell.execute_reply":"2021-08-15T11:44:14.71373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data_retriever = DataRetriever(\n    df_train[\"BraTS21ID\"].values, \n    df_train[\"MGMT_value\"].values, \n)\n\nvalid_data_retriever = DataRetriever(\n    df_valid[\"BraTS21ID\"].values, \n    df_valid[\"MGMT_value\"].values,\n)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:14.716056Z","iopub.execute_input":"2021-08-15T11:44:14.716618Z","iopub.status.idle":"2021-08-15T11:44:14.72474Z","shell.execute_reply.started":"2021-08-15T11:44:14.716576Z","shell.execute_reply":"2021-08-15T11:44:14.723973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(16, 6))\nfor i in range(3):\n    plt.subplot(1, 3, i + 1)\n    plt.imshow(train_data_retriever[100][\"X\"].numpy()[i], cmap=\"gray\")","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:14.72617Z","iopub.execute_input":"2021-08-15T11:44:14.726504Z","iopub.status.idle":"2021-08-15T11:44:15.691725Z","shell.execute_reply.started":"2021-08-15T11:44:14.72647Z","shell.execute_reply":"2021-08-15T11:44:15.690963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.net = efficientnet_pytorch.EfficientNet.from_name(\"efficientnet-b0\")\n        checkpoint = torch.load(\"../input/efficientnet-pytorch/efficientnet-b0-08094119.pth\")\n        self.net.load_state_dict(checkpoint)\n        n_features = self.net._fc.in_features\n        self.net._fc = nn.Linear(in_features=n_features, out_features=1, bias=True)\n    \n    def forward(self, x):\n        out = self.net(x)\n        return out","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:15.693009Z","iopub.execute_input":"2021-08-15T11:44:15.693362Z","iopub.status.idle":"2021-08-15T11:44:15.699618Z","shell.execute_reply.started":"2021-08-15T11:44:15.693324Z","shell.execute_reply":"2021-08-15T11:44:15.69869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class LossMeter:\n    def __init__(self):\n        self.avg = 0\n        self.n = 0\n\n    def update(self, val):\n        self.n += 1\n        # incremental update\n        self.avg = val / self.n + (self.n - 1) / self.n * self.avg\n\n        \nclass AccMeter:\n    def __init__(self):\n        self.avg = 0\n        self.n = 0\n        \n    def update(self, y_true, y_pred):\n        y_true = y_true.cpu().numpy().astype(int)\n        y_pred = y_pred.cpu().numpy() >= 0\n        last_n = self.n\n        self.n += len(y_true)\n        true_count = np.sum(y_true == y_pred)\n        # incremental update\n        self.avg = true_count / self.n + last_n / self.n * self.avg","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:15.700947Z","iopub.execute_input":"2021-08-15T11:44:15.701278Z","iopub.status.idle":"2021-08-15T11:44:15.712589Z","shell.execute_reply.started":"2021-08-15T11:44:15.701242Z","shell.execute_reply":"2021-08-15T11:44:15.71179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Trainer:\n    def __init__(\n        self, \n        model, \n        device, \n        optimizer, \n        criterion, \n        loss_meter, \n        score_meter\n    ):\n        self.model = model\n        self.device = device\n        self.optimizer = optimizer\n        self.criterion = criterion\n        self.loss_meter = loss_meter\n        self.score_meter = score_meter\n        \n        self.best_valid_score = -np.inf\n        self.n_patience = 0\n        \n        self.messages = {\n            \"epoch\": \"[Epoch {}: {}] loss: {:.5f}, score: {:.5f}, time: {} s\",\n            \"checkpoint\": \"The score improved from {:.5f} to {:.5f}. Save model to '{}'\",\n            \"patience\": \"\\nValid score didn't improve last {} epochs.\"\n        }\n    \n    def fit(self, epochs, train_loader, valid_loader, save_path, patience):        \n        for n_epoch in range(1, epochs + 1):\n            self.info_message(\"EPOCH: {}\", n_epoch)\n            \n            train_loss, train_score, train_time = self.train_epoch(train_loader)\n            valid_loss, valid_score, valid_time = self.valid_epoch(valid_loader)\n            \n            self.info_message(\n                self.messages[\"epoch\"], \"Train\", n_epoch, train_loss, train_score, train_time\n            )\n            \n            self.info_message(\n                self.messages[\"epoch\"], \"Valid\", n_epoch, valid_loss, valid_score, valid_time\n            )\n\n            if True:\n#             if self.best_valid_score < valid_score:\n                self.info_message(\n                    self.messages[\"checkpoint\"], self.best_valid_score, valid_score, save_path\n                )\n                self.best_valid_score = valid_score\n                self.save_model(n_epoch, save_path)\n                self.n_patience = 0\n            else:\n                self.n_patience += 1\n            \n            if self.n_patience >= patience:\n                self.info_message(self.messages[\"patience\"], patience)\n                break\n            \n    def train_epoch(self, train_loader):\n        self.model.train()\n        t = time.time()\n        train_loss = self.loss_meter()\n        train_score = self.score_meter()\n        \n        for step, batch in enumerate(train_loader, 1):\n            X = batch[\"X\"].to(self.device)\n            targets = batch[\"y\"].to(self.device)\n            self.optimizer.zero_grad()\n            outputs = self.model(X).squeeze(1)\n            \n            loss = self.criterion(outputs, targets)\n            loss.backward()\n\n            train_loss.update(loss.detach().item())\n            train_score.update(targets, outputs.detach())\n\n            self.optimizer.step()\n            \n            _loss, _score = train_loss.avg, train_score.avg\n            message = 'Train Step {}/{}, train_loss: {:.5f}, train_score: {:.5f}'\n            self.info_message(message, step, len(train_loader), _loss, _score, end=\"\\r\")\n        \n        return train_loss.avg, train_score.avg, int(time.time() - t)\n    \n    def valid_epoch(self, valid_loader):\n        self.model.eval()\n        t = time.time()\n        valid_loss = self.loss_meter()\n        valid_score = self.score_meter()\n\n        for step, batch in enumerate(valid_loader, 1):\n            with torch.no_grad():\n                X = batch[\"X\"].to(self.device)\n                targets = batch[\"y\"].to(self.device)\n\n                outputs = self.model(X).squeeze(1)\n                loss = self.criterion(outputs, targets)\n\n                valid_loss.update(loss.detach().item())\n                valid_score.update(targets, outputs)\n                \n            _loss, _score = valid_loss.avg, valid_score.avg\n            message = 'Valid Step {}/{}, valid_loss: {:.5f}, valid_score: {:.5f}'\n            self.info_message(message, step, len(valid_loader), _loss, _score, end=\"\\r\")\n        \n        return valid_loss.avg, valid_score.avg, int(time.time() - t)\n    \n    def save_model(self, n_epoch, save_path):\n        torch.save(\n            {\n                \"model_state_dict\": self.model.state_dict(),\n                \"optimizer_state_dict\": self.optimizer.state_dict(),\n                \"best_valid_score\": self.best_valid_score,\n                \"n_epoch\": n_epoch,\n            },\n            save_path,\n        )\n    \n    @staticmethod\n    def info_message(message, *args, end=\"\\n\"):\n        print(message.format(*args), end=end)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:15.714169Z","iopub.execute_input":"2021-08-15T11:44:15.714589Z","iopub.status.idle":"2021-08-15T11:44:15.735541Z","shell.execute_reply.started":"2021-08-15T11:44:15.714554Z","shell.execute_reply":"2021-08-15T11:44:15.73464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\ntrain_data_retriever = DataRetriever(\n    df_train[\"BraTS21ID\"].values, \n    df_train[\"MGMT_value\"].values, \n)\n\nvalid_data_retriever = DataRetriever(\n    df_valid[\"BraTS21ID\"].values, \n    df_valid[\"MGMT_value\"].values,\n)\n\ntrain_loader = torch_data.DataLoader(\n    train_data_retriever,\n    batch_size=8,\n    shuffle=True,\n    num_workers=8,\n)\n\nvalid_loader = torch_data.DataLoader(\n    valid_data_retriever, \n    batch_size=8,\n    shuffle=False,\n    num_workers=8,\n)\n\nmodel = Model()\nmodel.to(device)\n\noptimizer = torch.optim.Adam(model.parameters(), lr=0.001)\ncriterion = torch_functional.binary_cross_entropy_with_logits\n\ntrainer = Trainer(\n    model, \n    device, \n    optimizer, \n    criterion, \n    LossMeter, \n    AccMeter\n)\n\nhistory = trainer.fit(\n    10, \n    train_loader, \n    valid_loader, \n    f\"best-model-0.pth\", \n    100,\n)\n","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:44:15.739001Z","iopub.execute_input":"2021-08-15T11:44:15.739262Z","iopub.status.idle":"2021-08-15T11:54:24.505004Z","shell.execute_reply.started":"2021-08-15T11:44:15.73924Z","shell.execute_reply":"2021-08-15T11:54:24.50345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []\nfor i in range(1):\n    model = Model()\n    model.to(device)\n    \n    checkpoint = torch.load(f\"best-model-{i}.pth\")\n    model.load_state_dict(checkpoint[\"model_state_dict\"])\n    model.eval()\n    \n    models.append(model)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:54:24.506818Z","iopub.execute_input":"2021-08-15T11:54:24.507209Z","iopub.status.idle":"2021-08-15T11:54:24.769529Z","shell.execute_reply.started":"2021-08-15T11:54:24.507159Z","shell.execute_reply":"2021-08-15T11:54:24.768706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DataRetriever(torch_data.Dataset):\n    def __init__(self, paths):\n        self.paths = paths\n          \n    def __len__(self):\n        return len(self.paths)\n    \n    def __getitem__(self, index):\n        _id = self.paths[index]\n        patient_path = f\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/test/{str(_id).zfill(5)}/\"\n        channels = []\n        for t in (\"FLAIR\", \"T1w\", \"T1wCE\"): # \"T2w\"\n            t_paths = sorted(\n                glob.glob(os.path.join(patient_path, t, \"*\")), \n                key=lambda x: int(x[:-4].split(\"-\")[-1]),\n            )\n            # start, end = int(len(t_paths) * 0.475), int(len(t_paths) * 0.525)\n            x = len(t_paths)\n            if x < 10:\n                r = range(x)\n            else:\n                d = x // 10\n                r = range(d, x - d, d)\n                \n            channel = []\n            # for i in range(start, end + 1):\n            for i in r:\n                channel.append(cv2.resize(load_dicom(t_paths[i]), (256, 256)) / 255)\n            channel = np.mean(channel, axis=0)\n            channels.append(channel)\n        \n        return {\"X\": torch.tensor(channels).float(), \"id\": _id}","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:54:32.318804Z","iopub.execute_input":"2021-08-15T11:54:32.319218Z","iopub.status.idle":"2021-08-15T11:54:32.328768Z","shell.execute_reply.started":"2021-08-15T11:54:32.319186Z","shell.execute_reply":"2021-08-15T11:54:32.32775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/sample_submission.csv\")\n\ntest_data_retriever = DataRetriever(\n    submission[\"BraTS21ID\"].values, \n)\n\ntest_loader = torch_data.DataLoader(\n    test_data_retriever,\n    batch_size=4,\n    shuffle=False,\n    num_workers=8,\n)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:54:32.996389Z","iopub.execute_input":"2021-08-15T11:54:32.996718Z","iopub.status.idle":"2021-08-15T11:54:33.008041Z","shell.execute_reply.started":"2021-08-15T11:54:32.996687Z","shell.execute_reply":"2021-08-15T11:54:33.007132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = []\nids = []\n\nfor e, batch in enumerate(test_loader):\n    print(f\"{e}/{len(test_loader)}\", end=\"\\r\")\n    with torch.no_grad():\n        tmp_pred = np.zeros((batch[\"X\"].shape[0], ))\n        for model in models:\n            tmp_res = torch.sigmoid(model(batch[\"X\"].to(device))).cpu().numpy().squeeze()\n            tmp_pred += tmp_res\n        y_pred.extend(tmp_pred)\n        ids.extend(batch[\"id\"].numpy().tolist())","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:54:33.801148Z","iopub.execute_input":"2021-08-15T11:54:33.80148Z","iopub.status.idle":"2021-08-15T11:54:44.184874Z","shell.execute_reply.started":"2021-08-15T11:54:33.801449Z","shell.execute_reply":"2021-08-15T11:54:44.183938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame({\"BraTS21ID\": ids, \"MGMT_value\": y_pred})\nsubmission.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:54:44.18665Z","iopub.execute_input":"2021-08-15T11:54:44.187042Z","iopub.status.idle":"2021-08-15T11:54:44.198411Z","shell.execute_reply.started":"2021-08-15T11:54:44.186999Z","shell.execute_reply":"2021-08-15T11:54:44.197597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(5, 5))\nplt.hist(submission[\"MGMT_value\"]);","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:55:50.982451Z","iopub.execute_input":"2021-08-15T11:55:50.982783Z","iopub.status.idle":"2021-08-15T11:55:51.117673Z","shell.execute_reply.started":"2021-08-15T11:55:50.982752Z","shell.execute_reply":"2021-08-15T11:55:51.116693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2021-08-15T11:54:44.200008Z","iopub.execute_input":"2021-08-15T11:54:44.200302Z","iopub.status.idle":"2021-08-15T11:54:44.218837Z","shell.execute_reply.started":"2021-08-15T11:54:44.200277Z","shell.execute_reply":"2021-08-15T11:54:44.218107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## WORK IN PROGRESS...","metadata":{}}]}