{"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"}},"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-media/kaggle/RSNA-2021/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 warnings\nwarnings.filterwarnings('ignore')","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:49.026510Z","iopub.execute_input":"2023-10-22T04:07:49.026923Z","iopub.status.idle":"2023-10-22T04:07:49.037676Z","shell.execute_reply.started":"2023-10-22T04:07:49.026811Z","shell.execute_reply":"2023-10-22T04:07:49.036665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport cv2\nimport json\nimport glob\nimport random\nimport pydicom\nimport collections\n\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport os.path as osp\nimport matplotlib.pyplot as plt\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:50.396922Z","iopub.execute_input":"2023-10-22T04:07:50.397269Z","iopub.status.idle":"2023-10-22T04:07:51.523698Z","shell.execute_reply.started":"2023-10-22T04:07:50.397240Z","shell.execute_reply":"2023-10-22T04:07:51.522918Z"},"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":"!pwd","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:51.644775Z","iopub.execute_input":"2023-10-22T04:07:51.645098Z","iopub.status.idle":"2023-10-22T04:07:52.602607Z","shell.execute_reply.started":"2023-10-22T04:07:51.645069Z","shell.execute_reply":"2023-10-22T04:07:52.601624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls ../input","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:52.604180Z","iopub.execute_input":"2023-10-22T04:07:52.604455Z","iopub.status.idle":"2023-10-22T04:07:53.573538Z","shell.execute_reply.started":"2023-10-22T04:07:52.604426Z","shell.execute_reply":"2023-10-22T04:07:53.572680Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATA_ROOT = osp.join(\"..\", \"input\", \"rsna-miccai-brain-tumor-radiogenomic-classification\")\nTYPES = (\"FLAIR\", \"T1w\", \"T1wCE\", \"T2w\")\ntrain_df = pd.read_csv(osp.join(DATA_ROOT, \"train_labels.csv\"))\ntrain_df","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:53.576021Z","iopub.execute_input":"2023-10-22T04:07:53.576422Z","iopub.status.idle":"2023-10-22T04:07:53.617564Z","shell.execute_reply.started":"2023-10-22T04:07:53.576378Z","shell.execute_reply":"2023-10-22T04:07:53.616712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(5, 5))\nsns.countplot(data=train_df, x=\"MGMT_value\");","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:53.618960Z","iopub.execute_input":"2023-10-22T04:07:53.619242Z","iopub.status.idle":"2023-10-22T04:07:53.769382Z","shell.execute_reply.started":"2023-10-22T04:07:53.619216Z","shell.execute_reply":"2023-10-22T04:07:53.768567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls $DATA_ROOT/train/00000","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:53.770362Z","iopub.execute_input":"2023-10-22T04:07:53.770632Z","iopub.status.idle":"2023-10-22T04:07:54.728475Z","shell.execute_reply.started":"2023-10-22T04:07:53.770606Z","shell.execute_reply":"2023-10-22T04:07:54.727535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dicom(path):\n    dicom = pydicom.read_file(path)\n    data = dicom.pixel_array\n    data = data - np.min(data)  # (X - X_min) / (X_max - X_min)\n    if np.max(data) != 0:\n        data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n    return data\n\n\ndef visualize_sample(\n    brats21id, \n    mgmt_value,\n    slice_i,\n    types=(\"FLAIR\", \"T1w\", \"T1wCE\", \"T2w\")\n):\n    _, axes = plt.subplots(ncols=len(types), figsize=(4*len(types), 5))\n    patient_path = os.path.join(DATA_ROOT, \"train\", str(brats21id).zfill(5))\n    for i, t in enumerate(types):\n        t_paths = sorted(\n            glob.glob(os.path.join(patient_path, t, \"*\")), \n            key=lambda x: int(x[:-4].split(\"-\")[-1]),\n        )\n        data = load_dicom(t_paths[int(len(t_paths) * slice_i)])\n        axes[i].imshow(data, cmap=\"gray\")\n        axes[i].set_title(f\"{t}\", fontsize=16)\n        axes[i].axis(\"off\")\n\n    plt.suptitle(f\"MGMT_value: {mgmt_value}\", fontsize=16)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:54.729915Z","iopub.execute_input":"2023-10-22T04:07:54.730230Z","iopub.status.idle":"2023-10-22T04:07:54.741309Z","shell.execute_reply.started":"2023-10-22T04:07:54.730194Z","shell.execute_reply":"2023-10-22T04:07:54.740438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nshutil.copytree(osp.join(DATA_ROOT, \"train\", \"00000\"), \"./00000\")","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:07:54.742520Z","iopub.execute_input":"2023-10-22T04:07:54.742865Z","iopub.status.idle":"2023-10-22T04:08:05.236908Z","shell.execute_reply.started":"2023-10-22T04:07:54.742798Z","shell.execute_reply":"2023-10-22T04:08:05.236035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!tar -czf example.tar.gz ./00000","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:05.240070Z","iopub.execute_input":"2023-10-22T04:08:05.240345Z","iopub.status.idle":"2023-10-22T04:08:13.594763Z","shell.execute_reply.started":"2023-10-22T04:08:05.240317Z","shell.execute_reply":"2023-10-22T04:08:13.593628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!zip -qr 00000.zip ./00000","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:13.596886Z","iopub.execute_input":"2023-10-22T04:08:13.597184Z","iopub.status.idle":"2023-10-22T04:08:21.510812Z","shell.execute_reply.started":"2023-10-22T04:08:13.597150Z","shell.execute_reply":"2023-10-22T04:08:21.509657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in random.sample(range(train_df.shape[0]), 10):\n    _brats21id = train_df.iloc[i][\"BraTS21ID\"]\n    _mgmt_value = train_df.iloc[i][\"MGMT_value\"]\n    visualize_sample(brats21id=_brats21id, mgmt_value=_mgmt_value, slice_i=0.5)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:21.512447Z","iopub.execute_input":"2023-10-22T04:08:21.512869Z","iopub.status.idle":"2023-10-22T04:08:29.377494Z","shell.execute_reply.started":"2023-10-22T04:08:21.512805Z","shell.execute_reply":"2023-10-22T04:08:29.376622Z"},"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    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-10-22T04:08:29.378690Z","iopub.execute_input":"2023-10-22T04:08:29.378994Z","iopub.status.idle":"2023-10-22T04:08:29.384800Z","shell.execute_reply.started":"2023-10-22T04:08:29.378965Z","shell.execute_reply":"2023-10-22T04:08:29.383997Z"},"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    return images","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:29.386140Z","iopub.execute_input":"2023-10-22T04:08:29.386514Z","iopub.status.idle":"2023-10-22T04:08:29.396296Z","shell.execute_reply.started":"2023-10-22T04:08:29.386467Z","shell.execute_reply":"2023-10-22T04:08:29.395519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%matplotlib notebook","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:29.397348Z","iopub.execute_input":"2023-10-22T04:08:29.397610Z","iopub.status.idle":"2023-10-22T04:08:29.410639Z","shell.execute_reply.started":"2023-10-22T04:08:29.397585Z","shell.execute_reply":"2023-10-22T04:08:29.409869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import clear_output\nanimations = dict()\nfor t in (\"FLAIR\", \"T1w\", \"T1wCE\", \"T2w\"):\n    images = load_dicom_line(osp.join(DATA_ROOT, 'train', '00000', t))\n    animations[t] = create_animation(images)\nclear_output()","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:29.411706Z","iopub.execute_input":"2023-10-22T04:08:29.412042Z","iopub.status.idle":"2023-10-22T04:08:33.165734Z","shell.execute_reply.started":"2023-10-22T04:08:29.412007Z","shell.execute_reply":"2023-10-22T04:08:33.164922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"animations['FLAIR']","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:33.167071Z","iopub.execute_input":"2023-10-22T04:08:33.167436Z","iopub.status.idle":"2023-10-22T04:08:43.014067Z","shell.execute_reply.started":"2023-10-22T04:08:33.167398Z","shell.execute_reply":"2023-10-22T04:08:43.012645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"animations['T1w']","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:43.015887Z","iopub.execute_input":"2023-10-22T04:08:43.016178Z","iopub.status.idle":"2023-10-22T04:08:44.029233Z","shell.execute_reply.started":"2023-10-22T04:08:43.016151Z","shell.execute_reply":"2023-10-22T04:08:44.028352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"animations['T1wCE']","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:44.030456Z","iopub.execute_input":"2023-10-22T04:08:44.030805Z","iopub.status.idle":"2023-10-22T04:08:46.850971Z","shell.execute_reply.started":"2023-10-22T04:08:44.030771Z","shell.execute_reply":"2023-10-22T04:08:46.849941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"animations['T2w']","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:46.852073Z","iopub.execute_input":"2023-10-22T04:08:46.852351Z","iopub.status.idle":"2023-10-22T04:08:56.186315Z","shell.execute_reply.started":"2023-10-22T04:08:46.852323Z","shell.execute_reply":"2023-10-22T04:08:56.184713Z"},"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":"%matplotlib inline","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:56.187526Z","iopub.execute_input":"2023-10-22T04:08:56.187824Z","iopub.status.idle":"2023-10-22T04:08:56.198519Z","shell.execute_reply.started":"2023-10-22T04:08:56.187771Z","shell.execute_reply":"2023-10-22T04:08:56.197696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":"2023-10-22T04:08:56.199751Z","iopub.execute_input":"2023-10-22T04:08:56.200097Z","iopub.status.idle":"2023-10-22T04:08:56.760640Z","shell.execute_reply.started":"2023-10-22T04:08:56.200065Z","shell.execute_reply":"2023-10-22T04:08:56.759787Z"},"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(osp.join(DATA_ROOT, \"sample_submission.csv\"))\n# submission.to_csv(\"submission.csv\", index=False)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:56.761926Z","iopub.execute_input":"2023-10-22T04:08:56.762288Z","iopub.status.idle":"2023-10-22T04:08:56.782714Z","shell.execute_reply.started":"2023-10-22T04:08:56.762251Z","shell.execute_reply":"2023-10-22T04:08:56.781933Z"},"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":"import time\nimport torch\n\nfrom torch import nn\nfrom tqdm.notebook import tqdm\nfrom sklearn.model_selection import StratifiedKFold\n\nfrom torch.utils import data as torch_data\nimport torch.nn.functional as torch_functional\nimport sklearn.model_selection as sk_model_selection","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:56.783977Z","iopub.execute_input":"2023-10-22T04:08:56.784342Z","iopub.status.idle":"2023-10-22T04:08:58.204076Z","shell.execute_reply.started":"2023-10-22T04:08:56.784305Z","shell.execute_reply":"2023-10-22T04:08:58.203319Z"},"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\nset_seed(42)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:58.207172Z","iopub.execute_input":"2023-10-22T04:08:58.207463Z","iopub.status.idle":"2023-10-22T04:08:58.275788Z","shell.execute_reply.started":"2023-10-22T04:08:58.207433Z","shell.execute_reply":"2023-10-22T04:08:58.275106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DataRetriever(torch_data.Dataset):\n    def __init__(self, img_paths, ids, mri_type=\"T1wCE\", targets=None, folder='train', transforms=None):\n        self.ids = ids\n        self.img_paths = img_paths\n        self.targets = targets\n        self.folder = folder\n        self.transforms = transforms\n        assert mri_type in TYPES\n        self.mri_type = mri_type\n          \n    def __len__(self):\n        return len(self.img_paths)\n    \n    def __getitem__(self, index):\n        _id = self.ids[index]\n        image_path = self.img_paths[index]\n        X = cv2.resize(load_dicom(image_path), (256, 256)) / 255\n        X = torch.tensor(X[None,...]).float()\n        if self.transforms is not None:\n            X = self.transforms(X)\n        if self.targets is not None:\n            y = torch.tensor(self.targets[index], dtype=torch.float)\n            return {\"X\": X, \"y\": y, \"id\": _id}\n        return {\"X\": X, \"id\": _id}","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:58.277155Z","iopub.execute_input":"2023-10-22T04:08:58.277413Z","iopub.status.idle":"2023-10-22T04:08:58.286411Z","shell.execute_reply.started":"2023-10-22T04:08:58.277388Z","shell.execute_reply":"2023-10-22T04:08:58.285466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"![](https://cheris8.github.io/assets/images/AI/CV/CNN-overview.jpeg)","metadata":{}},{"cell_type":"code","source":"def get_valid_paths(ids, labels=None, mri_type=\"T1wCE\", folder=\"train\"):\n    assert mri_type in TYPES\n    all_valid_paths = []\n    all_ids = []\n    if labels is not None:\n        all_labels = []\n    for i, patient_id in enumerate(ids):\n        patient_path = osp.join(DATA_ROOT, folder, str(patient_id).zfill(5))\n        images_paths = sorted(\n            glob.glob(osp.join(patient_path, mri_type, \"*\")),\n            key=lambda x: int(x[:-4].split('-')[-1])\n        )\n        start, end = int(len(images_paths) * 0.25), int(len(images_paths) * 0.75)\n        step = 1 if len(images_paths) < 10 else 3\n        cur_valid_paths = images_paths[start:end:step]\n        all_valid_paths.extend(cur_valid_paths)\n        all_ids.extend([patient_id] * len(cur_valid_paths))\n        if labels is not None:\n            all_labels.extend([labels[i]] * len(cur_valid_paths))\n    if labels is not None:\n        return all_valid_paths, all_ids, all_labels\n    return all_valid_paths, all_ids\n\nids_train, ids_val, y_train, y_val = \\\nsk_model_selection.train_test_split(train_df['BraTS21ID'].values,\n                                    train_df['MGMT_value'].values,\n                                    test_size=0.2,\n                                    random_state=42,\n                                    stratify=train_df[\"MGMT_value\"],\n                                   )\nX_train, ids_train, y_train = get_valid_paths(ids_train, labels=y_train)\nX_val, ids_val, y_val = get_valid_paths(ids_val, labels=y_val)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:08:58.287867Z","iopub.execute_input":"2023-10-22T04:08:58.288230Z","iopub.status.idle":"2023-10-22T04:09:45.926591Z","shell.execute_reply.started":"2023-10-22T04:08:58.288193Z","shell.execute_reply":"2023-10-22T04:09:45.925769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.mean(y_train), np.mean(y_val)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:09:45.927681Z","iopub.execute_input":"2023-10-22T04:09:45.927949Z","iopub.status.idle":"2023-10-22T04:09:45.935959Z","shell.execute_reply.started":"2023-10-22T04:09:45.927923Z","shell.execute_reply":"2023-10-22T04:09:45.935185Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchvision.transforms as T\ntransforms = T.Compose([\n    T.CenterCrop((224, 224)),\n    T.Lambda(lambda x: x.float()),\n])\n\ntrain_data_retriever = DataRetriever(\n    X_train,\n    ids_train,\n    targets=y_train,\n    transforms=transforms,\n)\n\nvalid_data_retriever = DataRetriever(\n    X_val, \n    ids_val,\n    targets=y_val,\n    transforms=transforms,\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:09:45.937055Z","iopub.execute_input":"2023-10-22T04:09:45.937338Z","iopub.status.idle":"2023-10-22T04:09:46.082700Z","shell.execute_reply.started":"2023-10-22T04:09:45.937292Z","shell.execute_reply":"2023-10-22T04:09:46.081777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(6, 6))\nplt.imshow(train_data_retriever[120][\"X\"].numpy()[0], cmap=\"gray\");","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:09:46.083952Z","iopub.execute_input":"2023-10-22T04:09:46.084243Z","iopub.status.idle":"2023-10-22T04:09:46.330496Z","shell.execute_reply.started":"2023-10-22T04:09:46.084214Z","shell.execute_reply":"2023-10-22T04:09:46.329604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision import models\nclass Model(nn.Module):\n    def __init__(self, model_name=\"efficientnet-b0\", num_classes=2):\n        super().__init__()\n        assert num_classes >= 2\n        num_classes = 1 if num_classes == 2 else num_classes\n        self.net = nn.Sequential(\n            nn.Conv2d(1, 32, 3, padding=1),  # (N, 32, 224, 224)\n            nn.BatchNorm2d(32),\n            nn.ReLU(),\n            nn.Conv2d(32, 64, 3, padding=1),  # (N, 64, 224, 224)\n            nn.BatchNorm2d(64),\n            nn.ReLU(),\n            nn.MaxPool2d(2),  # (N, 64, 112, 112)\n            nn.Conv2d(64, 128, 3, padding=1),  # (N, 128, 112, 112)\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n            nn.Conv2d(128, 128, 3, padding=1),  # (N, 128, 112, 112)\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n            nn.MaxPool2d(2),  # (N, 128, 56, 56)\n            nn.Conv2d(128, 128, 3, stride=2),  # (N, 128, 27, 27)\n            nn.BatchNorm2d(128),\n            nn.Dropout2d(p=0.3),\n            nn.ReLU(),\n            nn.Conv2d(128, 128, 3, stride=2),  # (N, 128, 12, 12)\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n            nn.MaxPool2d(2),  # (N, 128, 6, 6)\n            nn.Flatten(),\n            nn.Linear(128*6*6, 1028),\n#             nn.Dropout(p=0.3),\n            nn.ReLU(),\n            nn.Linear(1028, 512),\n            nn.ReLU(),\n            nn.Linear(512, num_classes)\n        )\n\n    def forward(self, x):\n        out = self.net(x)\n        return out\nmodel = Model(num_classes=2)\nmodel(torch.randn((4, 1, 224, 224)))","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:25:43.676819Z","iopub.execute_input":"2023-10-22T04:25:43.677186Z","iopub.status.idle":"2023-10-22T04:25:44.193207Z","shell.execute_reply.started":"2023-10-22T04:25:43.677152Z","shell.execute_reply":"2023-10-22T04:25:44.192244Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"$$\\{1, 2, ..., N\\} \\rightarrow \\{1, 2, ..., N, N+1, ..., M\\}$$\n$$\\text{prev_avg} = \\frac{1}{N}\\sum_{i=1}^{N}x_{i}; \\quad \\text{avg} = \\frac{1}{M}\\sum_{i=1}^{M}x_{i} = \\frac{1}{M} \\frac{N}{N} \\sum_{i=1}^{N}x_{i} + \\frac{1}{M}\\sum_{i=N+1}^{M}x_{i}=\\frac{N}{M}\\text{prev_avg} + \\frac{1}{M}\\sum_{i=N+1}^{M}x_{i}$$","metadata":{}},{"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 = (self.n - 1) / self.n * self.avg + val / self.n\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 = last_n / self.n * self.avg + true_count / self.n","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:09:47.008931Z","iopub.execute_input":"2023-10-22T04:09:47.009214Z","iopub.status.idle":"2023-10-22T04:09:47.016801Z","shell.execute_reply.started":"2023-10-22T04:09:47.009187Z","shell.execute_reply":"2023-10-22T04:09:47.015904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Trainer:\n    def __init__(self, model, device, optimizer, criterion, loss_meter, score_meter):\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        history = {'train': {'loss': [], 'score': []},\n                   'val': {'loss': [], 'score': []}}\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            history['train']['loss'].append(train_loss)\n            history['train']['score'].append(train_score)\n            history['val']['loss'].append(valid_loss)\n            history['val']['score'].append(valid_score)\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 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        return history\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":"2023-10-22T04:09:47.018044Z","iopub.execute_input":"2023-10-22T04:09:47.018317Z","iopub.status.idle":"2023-10-22T04:09:47.042594Z","shell.execute_reply.started":"2023-10-22T04:09:47.018290Z","shell.execute_reply":"2023-10-22T04:09:47.041750Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nset_seed(42)\n\ntransforms = {\n    \"train\": T.Compose([\n        T.CenterCrop((224, 224)),\n        T.RandomHorizontalFlip(),\n        T.RandomAffine(60),\n        T.Lambda(lambda x: x.float()),\n    ]),\n    \"val\": T.Compose([\n        T.CenterCrop((224, 224)),\n        T.Lambda(lambda x: x.float()),\n    ])\n}\n\ntrain_data_retriever = DataRetriever(\n    X_train,\n    ids_train,\n    targets=y_train,\n    transforms=transforms['train'],\n)\n\nvalid_data_retriever = DataRetriever(\n    X_val, \n    ids_val,\n    targets=y_val,\n    transforms=transforms['val'],\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# optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\noptimizer = torch.optim.SGD(model.parameters(), lr=0.0001)\ncriterion = torch_functional.binary_cross_entropy_with_logits\ntrainer = Trainer(model, device, optimizer, criterion, LossMeter, AccMeter)\nhistory = trainer.fit(100, train_loader, valid_loader, \"best-model-0.pth\", 100)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T07:43:03.952132Z","iopub.execute_input":"2023-10-22T07:43:03.952485Z","iopub.status.idle":"2023-10-22T10:22:48.790764Z","shell.execute_reply.started":"2023-10-22T07:43:03.952449Z","shell.execute_reply":"2023-10-22T10:22:48.789650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Model()\nmodel.to(device)\ntrained_weights = torch.load(f\"best-model-0.pth\")\nmodel.load_state_dict(trained_weights[\"model_state_dict\"])\nmodel.eval();","metadata":{"execution":{"iopub.status.busy":"2023-10-22T10:48:51.775521Z","iopub.execute_input":"2023-10-22T10:48:51.775877Z","iopub.status.idle":"2023-10-22T10:48:51.860595Z","shell.execute_reply.started":"2023-10-22T10:48:51.775828Z","shell.execute_reply":"2023-10-22T10:48:51.859837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2023-10-22T10:48:53.628684Z","iopub.execute_input":"2023-10-22T10:48:53.629030Z","iopub.status.idle":"2023-10-22T10:48:53.644189Z","shell.execute_reply.started":"2023-10-22T10:48:53.628993Z","shell.execute_reply":"2023-10-22T10:48:53.643325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(osp.join(DATA_ROOT, 'sample_submission.csv'))\n\nX_test, ids_test = get_valid_paths(submission['BraTS21ID'], folder='test')\n\ntest_data_retriever = DataRetriever(\n    X_test, \n    ids_test,\n    transforms=transforms['val'],\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":"2023-10-22T10:49:16.610995Z","iopub.execute_input":"2023-10-22T10:49:16.611351Z","iopub.status.idle":"2023-10-22T10:49:24.178619Z","shell.execute_reply.started":"2023-10-22T10:49:16.611315Z","shell.execute_reply":"2023-10-22T10:49:24.177722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = []\nids = []\n\nfor e, batch in enumerate(test_loader, 1):\n    print(f\"{e}/{len(test_loader)}\", end=\"\\r\")\n    with torch.no_grad():\n        pred = torch.sigmoid(model(batch[\"X\"].to(device))).cpu().numpy().squeeze(1)\n        y_pred.extend(pred)\n        ids.extend(batch[\"id\"].numpy().tolist())","metadata":{"execution":{"iopub.status.busy":"2023-10-22T10:49:34.597704Z","iopub.execute_input":"2023-10-22T10:49:34.598086Z","iopub.status.idle":"2023-10-22T10:49:42.189619Z","shell.execute_reply.started":"2023-10-22T10:49:34.598049Z","shell.execute_reply":"2023-10-22T10:49:42.188675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame({\"BraTS21ID\": ids, \"MGMT_value\": y_pred})\nsubmission = submission.groupby('BraTS21ID').mean().reset_index()\nsubmission.to_csv(\"submission.csv\", index=False)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2023-10-22T10:49:45.106410Z","iopub.execute_input":"2023-10-22T10:49:45.106776Z","iopub.status.idle":"2023-10-22T10:49:45.134956Z","shell.execute_reply.started":"2023-10-22T10:49:45.106736Z","shell.execute_reply":"2023-10-22T10:49:45.134238Z"},"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":"2023-10-22T10:50:04.231907Z","iopub.execute_input":"2023-10-22T10:50:04.232248Z","iopub.status.idle":"2023-10-22T10:50:04.428954Z","shell.execute_reply.started":"2023-10-22T10:50:04.232219Z","shell.execute_reply":"2023-10-22T10:50:04.428101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = []\nids = []\ny_true = []\n\nfor e, batch in enumerate(valid_loader, 1):\n    print(f\"{e}/{len(valid_loader)}\", end=\"\\r\")\n    with torch.no_grad():\n        pred = torch.sigmoid(model(batch[\"X\"].to(device))).cpu().numpy().squeeze(1)\n        y_pred.extend(pred)\n        ids.extend(batch[\"id\"].numpy().tolist())\n        y_true.extend(batch[\"y\"].numpy().tolist())","metadata":{"execution":{"iopub.status.busy":"2023-10-22T10:53:49.949967Z","iopub.execute_input":"2023-10-22T10:53:49.950301Z","iopub.status.idle":"2023-10-22T10:53:58.086197Z","shell.execute_reply.started":"2023-10-22T10:53:49.950272Z","shell.execute_reply":"2023-10-22T10:53:58.085190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = pd.DataFrame({\"BraTS21ID\": ids, \"MGMT_value\": y_pred, \"GT\": y_true})\npreds = preds.groupby('BraTS21ID').mean().reset_index()","metadata":{"execution":{"iopub.status.busy":"2023-10-22T10:54:27.532153Z","iopub.execute_input":"2023-10-22T10:54:27.532484Z","iopub.status.idle":"2023-10-22T10:54:27.544775Z","shell.execute_reply.started":"2023-10-22T10:54:27.532455Z","shell.execute_reply":"2023-10-22T10:54:27.543927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fpr, tpr, _ = roc_curve(preds[\"GT\"], preds[\"MGMT_value\"])\nroc_auc = auc(fpr, tpr)\n\nplt.figure(figsize=(5, 5))\nplt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)\nplt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')\nplt.xlim([-0.01, 1.0])\nplt.ylim([0.0, 1.05])\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver operating characteristic example')\nplt.legend(loc=\"lower right\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-22T10:55:18.286650Z","iopub.execute_input":"2023-10-22T10:55:18.287022Z","iopub.status.idle":"2023-10-22T10:55:18.441405Z","shell.execute_reply.started":"2023-10-22T10:55:18.286987Z","shell.execute_reply":"2023-10-22T10:55:18.440570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install --upgrade efficientnet-pytorch","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:25:53.387210Z","iopub.execute_input":"2023-10-22T03:25:53.387651Z","iopub.status.idle":"2023-10-22T03:26:04.880642Z","shell.execute_reply.started":"2023-10-22T03:25:53.387616Z","shell.execute_reply":"2023-10-22T03:26:04.879510Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# package_path = \"../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master/\"\n# import sys \n# sys.path.append(package_path)\n\nfrom efficientnet_pytorch import EfficientNet","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:26:04.882803Z","iopub.execute_input":"2023-10-22T03:26:04.883205Z","iopub.status.idle":"2023-10-22T03:26:04.893232Z","shell.execute_reply.started":"2023-10-22T03:26:04.883159Z","shell.execute_reply":"2023-10-22T03:26:04.892371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ids_train, ids_val, y_train, y_val = \\\nsk_model_selection.train_test_split(train_df['BraTS21ID'].values,\n                                    train_df['MGMT_value'].values,\n                                    test_size=0.2,\n                                    random_state=42,\n                                    stratify=train_df[\"MGMT_value\"],\n                                   )","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:29:23.191734Z","iopub.execute_input":"2023-10-22T03:29:23.192125Z","iopub.status.idle":"2023-10-22T03:29:23.200425Z","shell.execute_reply.started":"2023-10-22T03:29:23.192091Z","shell.execute_reply":"2023-10-22T03:29:23.199689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DataRetriever(torch_data.Dataset):\n    def __init__(self, ids, targets=None, folder='train', transforms=None):\n        self.ids = ids\n        self.targets = targets\n        self.folder = folder\n        self.transforms = transforms\n          \n    def __len__(self):\n        return len(self.ids)\n    \n    def __getitem__(self, index):\n        _id = self.ids[index]\n        patient_path = osp.join(DATA_ROOT, self.folder, 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        X = torch.tensor(channels).float()\n        if self.transforms is not None:\n            X = self.transforms(X)\n        if self.targets is not None:\n            y = torch.tensor(self.targets[index], dtype=torch.float)\n            return {\"X\": X, \"y\": y}\n        return {\"X\": X, \"id\": index}","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:29:26.042269Z","iopub.execute_input":"2023-10-22T03:29:26.042657Z","iopub.status.idle":"2023-10-22T03:29:26.056605Z","shell.execute_reply.started":"2023-10-22T03:29:26.042625Z","shell.execute_reply":"2023-10-22T03:29:26.055607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data_retriever = DataRetriever(\n    ids_train, \n    y_train, \n    transforms=transforms['train'],\n)\n\nvalid_data_retriever = DataRetriever(\n    ids_val, \n    y_val,\n    transforms=transforms['val'],\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:30:27.823650Z","iopub.execute_input":"2023-10-22T03:30:27.824003Z","iopub.status.idle":"2023-10-22T03:30:27.829115Z","shell.execute_reply.started":"2023-10-22T03:30:27.823972Z","shell.execute_reply":"2023-10-22T03:30:27.828121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data_retriever[101]['X'].shape","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:30:30.796303Z","iopub.execute_input":"2023-10-22T03:30:30.796720Z","iopub.status.idle":"2023-10-22T03:30:31.218750Z","shell.execute_reply.started":"2023-10-22T03:30:30.796688Z","shell.execute_reply":"2023-10-22T03:30:31.217664Z"},"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":"2023-10-22T03:30:38.760688Z","iopub.execute_input":"2023-10-22T03:30:38.761063Z","iopub.status.idle":"2023-10-22T03:30:40.050452Z","shell.execute_reply.started":"2023-10-22T03:30:38.761030Z","shell.execute_reply":"2023-10-22T03:30:40.049400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self, model_name=\"efficientnet-b0\", num_classes=2):\n        super().__init__()\n        self.net = EfficientNet.from_pretrained(model_name)\n        assert num_classes >= 2\n        num_classes = 1 if num_classes==2 else num_classes\n        self.net._fc = nn.Sequential(\n            nn.Linear(self.net._fc.in_features, 512),\n            nn.ReLU(),\n            nn.Linear(512, 128),\n            nn.ReLU(),\n            nn.Linear(128, num_classes)\n        )\n\n    def forward(self, x):\n        out = self.net(x)\n        return out\nmodel = Model(num_classes=2)\nmodel(torch.randn((4, 3, 256, 256)))","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:30:51.871179Z","iopub.execute_input":"2023-10-22T03:30:51.871572Z","iopub.status.idle":"2023-10-22T03:30:52.956064Z","shell.execute_reply.started":"2023-10-22T03:30:51.871540Z","shell.execute_reply":"2023-10-22T03:30:52.955070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\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)\noptimizer = torch.optim.Adam(model.parameters(), lr=0.001)\ncriterion = torch_functional.binary_cross_entropy_with_logits\ntrainer = Trainer(model, device, optimizer, criterion, LossMeter, AccMeter)\nhistory = trainer.fit(5, train_loader, valid_loader, \"best-model-3channels.pth\", 100)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:32:26.508287Z","iopub.execute_input":"2023-10-22T03:32:26.508704Z","iopub.status.idle":"2023-10-22T03:35:49.727332Z","shell.execute_reply.started":"2023-10-22T03:32:26.508670Z","shell.execute_reply":"2023-10-22T03:35:49.726265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Model()\nmodel.to(device)\ntrained_weights = torch.load(\"best-model-3channels.pth\")\nmodel.load_state_dict(trained_weights[\"model_state_dict\"])\nmodel.eval();","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:36:26.237026Z","iopub.execute_input":"2023-10-22T03:36:26.237474Z","iopub.status.idle":"2023-10-22T03:36:26.574450Z","shell.execute_reply.started":"2023-10-22T03:36:26.237434Z","shell.execute_reply":"2023-10-22T03:36:26.573379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(osp.join(DATA_ROOT, 'sample_submission.csv'))\n\ntest_data_retriever = DataRetriever(\n    submission[\"BraTS21ID\"].values,\n    folder='test',\n    transforms=transforms['val'],\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":"2023-10-22T03:38:00.768878Z","iopub.execute_input":"2023-10-22T03:38:00.769225Z","iopub.status.idle":"2023-10-22T03:38:00.782705Z","shell.execute_reply.started":"2023-10-22T03:38:00.769197Z","shell.execute_reply":"2023-10-22T03:38:00.781769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = []\nids = []\n\nfor e, batch in enumerate(test_loader, 1):\n    print(f\"{e}/{len(test_loader)}\", end=\"\\r\")\n    with torch.no_grad():\n        pred = torch.sigmoid(model(batch[\"X\"].to(device))).cpu().numpy().squeeze(1)\n        y_pred.extend(pred)\n        ids.extend(batch[\"id\"].numpy().tolist())","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:38:02.047011Z","iopub.execute_input":"2023-10-22T03:38:02.047390Z","iopub.status.idle":"2023-10-22T03:38:09.144614Z","shell.execute_reply.started":"2023-10-22T03:38:02.047345Z","shell.execute_reply":"2023-10-22T03:38:09.143311Z"},"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)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:38:09.146552Z","iopub.execute_input":"2023-10-22T03:38:09.146871Z","iopub.status.idle":"2023-10-22T03:38:09.168761Z","shell.execute_reply.started":"2023-10-22T03:38:09.146836Z","shell.execute_reply":"2023-10-22T03:38:09.167829Z"},"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":"2023-10-22T03:38:11.958445Z","iopub.execute_input":"2023-10-22T03:38:11.958840Z","iopub.status.idle":"2023-10-22T03:38:12.179828Z","shell.execute_reply.started":"2023-10-22T03:38:11.958780Z","shell.execute_reply":"2023-10-22T03:38:12.178858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"100\"></a>\n<h2 style='background:darkviolet; border:0; color:white'><center>3DCNN<center><h2>","metadata":{}},{"cell_type":"code","source":"!pip install git+https://github.com/shijianjian/EfficientNet-PyTorch-3D","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:38:23.933996Z","iopub.execute_input":"2023-10-22T03:38:23.934544Z","iopub.status.idle":"2023-10-22T03:38:35.289914Z","shell.execute_reply.started":"2023-10-22T03:38:23.934488Z","shell.execute_reply":"2023-10-22T03:38:35.288675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"![](https://iq.opengenus.org/content/images/2023/01/2023_01_20_0tc_Kleki-min.png)","metadata":{}},{"cell_type":"markdown","source":"![](https://www.researchgate.net/publication/353834504/figure/fig2/AS:1118867006980102@1643770090268/Illustration-of-3D-convolution-and-3D-pooling.png)","metadata":{}},{"cell_type":"code","source":"from efficientnet_pytorch_3d import EfficientNet3D","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:38:35.292220Z","iopub.execute_input":"2023-10-22T03:38:35.292616Z","iopub.status.idle":"2023-10-22T03:38:35.305340Z","shell.execute_reply.started":"2023-10-22T03:38:35.292578Z","shell.execute_reply":"2023-10-22T03:38:35.304443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"counts = {t: [] for t in (\"FLAIR\", \"T1w\", \"T1wCE\", \"T2w\")}\npatient_paths = glob.glob(osp.join(DATA_ROOT, 'train', '*'))\nfor patient_path in patient_paths:\n    for t in (\"FLAIR\", \"T1w\", \"T1wCE\", \"T2w\"):\n        dicom_paths = glob.glob(osp.join(patient_path, t, '*'))\n        counts[t].append(len(dicom_paths))","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:39:03.711140Z","iopub.execute_input":"2023-10-22T03:39:03.711555Z","iopub.status.idle":"2023-10-22T03:39:43.937266Z","shell.execute_reply.started":"2023-10-22T03:39:03.711516Z","shell.execute_reply":"2023-10-22T03:39:43.936145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.hist(counts[\"FLAIR\"])","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:39:43.938844Z","iopub.execute_input":"2023-10-22T03:39:43.939182Z","iopub.status.idle":"2023-10-22T03:39:44.165745Z","shell.execute_reply.started":"2023-10-22T03:39:43.939147Z","shell.execute_reply":"2023-10-22T03:39:44.164721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.hist(counts[\"T1w\"])","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:39:44.167984Z","iopub.execute_input":"2023-10-22T03:39:44.168322Z","iopub.status.idle":"2023-10-22T03:39:44.398835Z","shell.execute_reply.started":"2023-10-22T03:39:44.168288Z","shell.execute_reply":"2023-10-22T03:39:44.397505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.hist(counts[\"T1wCE\"])","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:39:44.400878Z","iopub.execute_input":"2023-10-22T03:39:44.401205Z","iopub.status.idle":"2023-10-22T03:39:44.634627Z","shell.execute_reply.started":"2023-10-22T03:39:44.401173Z","shell.execute_reply":"2023-10-22T03:39:44.633551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.hist(counts[\"T2w\"])","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:39:44.635975Z","iopub.execute_input":"2023-10-22T03:39:44.636302Z","iopub.status.idle":"2023-10-22T03:39:44.849238Z","shell.execute_reply.started":"2023-10-22T03:39:44.636260Z","shell.execute_reply":"2023-10-22T03:39:44.848262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from scipy import stats\nfor k, val in counts.items():\n    print(k, stats.mode(val))","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:39:44.850584Z","iopub.execute_input":"2023-10-22T03:39:44.850902Z","iopub.status.idle":"2023-10-22T03:39:44.861405Z","shell.execute_reply.started":"2023-10-22T03:39:44.850872Z","shell.execute_reply":"2023-10-22T03:39:44.860416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DepthCutter():\n    def __init__(self, depth, ratio):\n        self.depth = depth\n        self.ratio = ratio\n        assert 0 <= self.ratio <= 1\n    \n    def construct_3d_image(self, path):\n        dicom_paths = sorted(\n            glob.glob(os.path.join(path, \"*\")), \n            key=lambda x: int(x[:-4].split(\"-\")[-1]),\n        )\n        \n        if len(dicom_paths) <= self.depth:\n            return self._construct_with_pad(dicom_paths)\n        else:\n            return self._construct_from_ratio(dicom_paths)\n    \n    def _construct_with_pad(self, dicom_paths):\n        result = np.stack([\n            cv2.resize(load_dicom(path), (256, 256))[28:-28,28:-28] / 255\n            for path in dicom_paths\n        ])\n        pad = self.depth - result.shape[0]\n        assert pad >= 0\n        pad = (pad // 2, pad // 2) if pad % 2 == 0 else (pad // 2, pad // 2 + 1)\n        return np.pad(result, pad_width=(pad, (0, 0), (0, 0)))\n    \n    def _construct_from_ratio(self, dicom_paths):\n        start = int(len(dicom_paths) * (1-self.ratio) / 2)\n        end = len(dicom_paths) - start\n        assert abs(self.ratio - (end - start) / len(dicom_paths)) < 0.1\n        dicom_paths = dicom_paths[start:end]\n        if len(dicom_paths) <= self.depth:\n            return self._construct_with_pad(dicom_paths)\n        step = len(dicom_paths) // self.depth\n        result = []\n        for i in range(0, step*self.depth, step):\n            result.append(cv2.resize(load_dicom(dicom_paths[i]), (256, 256))[28:-28,28:-28] / 255)\n        result = np.stack(result)\n        return result","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:39:44.862962Z","iopub.execute_input":"2023-10-22T03:39:44.863427Z","iopub.status.idle":"2023-10-22T03:39:44.881234Z","shell.execute_reply.started":"2023-10-22T03:39:44.863381Z","shell.execute_reply":"2023-10-22T03:39:44.880136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DataRetriever(torch_data.Dataset):\n    def __init__(self, ids, targets=None,\n                 folder='train', transforms=None,\n                 depths_ratios=None\n                ):\n        self.depths_ratios = {\n            \"FLAIR\": (50, 0.8),\n            \"T1w\": (50, 0.8),\n            \"T1wCE\": (50, 0.8),\n            \"T2w\": (50, 0.8)\n        }\n        self.ids = ids\n        self.targets = targets\n        self.folder = folder\n        self.transforms = transforms\n          \n    def __len__(self):\n        return len(self.ids)\n    \n    def __getitem__(self, index):\n        _id = self.ids[index]\n        patient_path = osp.join(DATA_ROOT, self.folder, str(_id).zfill(5))        \n        depths = None\n        for t in (\"FLAIR\", \"T1w\", \"T1wCE\", \"T2w\"):\n            dc = DepthCutter(*self.depths_ratios[t])\n            depth = dc.construct_3d_image(osp.join(patient_path, t))\n            depths = depth if depths is None else np.concatenate([depths, depth])\n        X = torch.tensor(depths[None,...]).float()\n        if self.transforms is not None:\n            X = self.transforms(X)\n        if self.targets is not None:\n            y = torch.tensor(self.targets[index], dtype=torch.float)\n            return {\"X\": X, \"y\": y}\n        return {\"X\": X, \"id\": index}","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:39:48.801705Z","iopub.execute_input":"2023-10-22T03:39:48.802096Z","iopub.status.idle":"2023-10-22T03:39:48.815617Z","shell.execute_reply.started":"2023-10-22T03:39:48.802063Z","shell.execute_reply":"2023-10-22T03:39:48.814270Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data_retriever = DataRetriever(\n    ids_train, \n    y_train,\n)\n\nvalid_data_retriever = DataRetriever(\n    ids_val, \n    y_val, \n)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:40:30.161071Z","iopub.execute_input":"2023-10-22T03:40:30.161487Z","iopub.status.idle":"2023-10-22T03:40:30.166570Z","shell.execute_reply.started":"2023-10-22T03:40:30.161448Z","shell.execute_reply":"2023-10-22T03:40:30.165427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(10):\n    print(train_data_retriever[i]['X'].shape)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:40:32.562631Z","iopub.execute_input":"2023-10-22T03:40:32.563038Z","iopub.status.idle":"2023-10-22T03:40:50.767243Z","shell.execute_reply.started":"2023-10-22T03:40:32.563004Z","shell.execute_reply":"2023-10-22T03:40:50.766092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"xxx = train_data_retriever[0]['X'].cpu().numpy()","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:41:00.104943Z","iopub.execute_input":"2023-10-22T03:41:00.105320Z","iopub.status.idle":"2023-10-22T03:41:00.773342Z","shell.execute_reply.started":"2023-10-22T03:41:00.105289Z","shell.execute_reply":"2023-10-22T03:41:00.772439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plt.imshow(xxx[0][49], cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:41:53.247669Z","iopub.execute_input":"2023-10-22T03:41:53.248072Z","iopub.status.idle":"2023-10-22T03:41:53.251904Z","shell.execute_reply.started":"2023-10-22T03:41:53.248037Z","shell.execute_reply":"2023-10-22T03:41:53.250878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self, model_name=\"efficientnet-b0\", num_classes=2):\n        super().__init__()\n        self.net = EfficientNet3D.from_name(model_name, in_channels=1)\n        assert num_classes >= 2\n        num_classes = 1 if num_classes==2 else num_classes\n        self.net._fc = nn.Sequential(\n            nn.Linear(self.net._fc.in_features, 512),\n            nn.ReLU(),\n            nn.Linear(512, 128),\n            nn.ReLU(),\n            nn.Linear(128, num_classes)\n        )\n\n    def forward(self, x):\n        out = self.net(x)\n        return out\nmodel = Model(num_classes=2)\nmodel(torch.randn((4, 1, 200, 200, 200)))","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:41:56.768064Z","iopub.execute_input":"2023-10-22T03:41:56.768515Z","iopub.status.idle":"2023-10-22T03:42:03.959992Z","shell.execute_reply.started":"2023-10-22T03:41:56.768476Z","shell.execute_reply":"2023-10-22T03:42:03.958930Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\ntrain_loader = torch_data.DataLoader(\n    train_data_retriever,\n    batch_size=2,\n    shuffle=True,\n    num_workers=8,\n)\n\nvalid_loader = torch_data.DataLoader(\n    valid_data_retriever,\n    batch_size=2,\n    shuffle=False,\n    num_workers=8,\n)\n\nmodel = Model()\nmodel.to(device)\noptimizer = torch.optim.Adam(model.parameters(), lr=0.001)\ncriterion = torch_functional.binary_cross_entropy_with_logits\ntrainer = Trainer(model, device, optimizer, criterion, LossMeter, AccMeter)\nhistory = trainer.fit(1, train_loader, valid_loader, \"best-model-3DCNN.pth\",100)","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:47:13.991339Z","iopub.execute_input":"2023-10-22T03:47:13.991764Z","iopub.status.idle":"2023-10-22T03:55:35.547608Z","shell.execute_reply.started":"2023-10-22T03:47:13.991728Z","shell.execute_reply":"2023-10-22T03:55:35.546394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Model()\nmodel.to(device)\ntrained_weights = torch.load(\"best-model-3channels.pth\")\nmodel.load_state_dict(trained_weights[\"model_state_dict\"])\nmodel.eval();","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:57:54.188536Z","iopub.execute_input":"2023-10-22T03:57:54.188925Z","iopub.status.idle":"2023-10-22T03:57:54.466053Z","shell.execute_reply.started":"2023-10-22T03:57:54.188892Z","shell.execute_reply":"2023-10-22T03:57:54.465181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(osp.join(DATA_ROOT, 'sample_submission.csv'))\n\ntest_data_retriever = DataRetriever(\n    submission[\"BraTS21ID\"].values,\n    folder='test'\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":"2023-10-22T03:57:58.521650Z","iopub.execute_input":"2023-10-22T03:57:58.522034Z","iopub.status.idle":"2023-10-22T03:57:58.533456Z","shell.execute_reply.started":"2023-10-22T03:57:58.522003Z","shell.execute_reply":"2023-10-22T03:57:58.532427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = []\nids = []\n\nfor e, batch in enumerate(test_loader, 1):\n    print(f\"{e}/{len(test_loader)}\", end=\"\\r\")\n    with torch.no_grad():\n        pred = torch.sigmoid(model(batch[\"X\"].to(device))).cpu().numpy().squeeze(1)\n        y_pred.extend(pred)\n        ids.extend(batch[\"id\"].numpy().tolist())","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:58:04.876182Z","iopub.execute_input":"2023-10-22T03:58:04.876647Z","iopub.status.idle":"2023-10-22T03:58:36.343899Z","shell.execute_reply.started":"2023-10-22T03:58:04.876609Z","shell.execute_reply":"2023-10-22T03:58:36.342706Z"},"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)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2023-10-22T03:58:45.162430Z","iopub.execute_input":"2023-10-22T03:58:45.162839Z","iopub.status.idle":"2023-10-22T03:58:45.185565Z","shell.execute_reply.started":"2023-10-22T03:58:45.162796Z","shell.execute_reply":"2023-10-22T03:58:45.184496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(5, 5))\nplt.hist(submission[\"MGMT_value\"], bins=10, range=(0,1));","metadata":{"execution":{"iopub.status.busy":"2023-10-22T04:02:15.147610Z","iopub.execute_input":"2023-10-22T04:02:15.147995Z","iopub.status.idle":"2023-10-22T04:02:15.337662Z","shell.execute_reply.started":"2023-10-22T04:02:15.147962Z","shell.execute_reply":"2023-10-22T04:02:15.336504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"![](https://media.geeksforgeeks.org/wp-content/uploads/20230425134047/recurrent_neural_networks.png)","metadata":{}},{"cell_type":"markdown","source":"![](https://lmb.informatik.uni-freiburg.de/people/ronneber/u-net/u-net-architecture.png)","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}