{"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":"![brain_baner](http://www.mf-data-science.fr/images/projects/brain_baner.jpg)","metadata":{}},{"cell_type":"markdown","source":"**This Notebook is the extension of the tests of a CNN 3D model on all MRI types developed in a first Notebook *(with EDA)* :**\n\n<span style=\"font-size:18px\">[🧠Brain Tumor 3D Multimodal CNN - All MRI Type](https://www.kaggle.com/michaelfumery/brain-tumor-3d-multimodal-cnn-all-mri-type/)</span>\n\n<h1 style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\">Context</h1>\n\nThe goal of this competition, initiated by the **Radiological Society of North America *(RSNA)*** in partnership with the **Medical Image Computing and Computer Assisted Intervention Society *(the MICCAI Society)*** is to predict the methylation of the **MGMT promoter**, which is an important gene biomarker for treatment of brain tumors.\n\nThese predictions will be based on a database of **MRI *(magnetic resonance imaging)*** scans of several hundred patients.\n\n<h1 style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\">Data</h1>\n\nEach independent case has a dedicated folder identified by a five-digit number. Within each of these “case” folders, there are four sub-folders, each of them corresponding to each of the structural multi-parametric MRI (mpMRI) scans, in DICOM format. The exact mpMRI scans included are:\n\n- Fluid Attenuated Inversion Recovery (FLAIR)\n- T1-weighted pre-contrast (T1w)\n- T1-weighted post-contrast (T1Gd)\n- T2-weighted (T2)\n\n| ![brain_baner](http://www.mf-data-science.fr/images/projects/brain_tumor_types.png) | \n|:--:| \n| *Examples of the four MR sequence types included in this work* |\n\n<h1 style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\">Acknowledgement</h1>\n\nThis Notebook is inspired from *Ammar Alhaj Ali* work :\n- [🧠Brain Tumor 3D [Training]](https://www.kaggle.com/ammarnassanalhajali/brain-tumor-3d-training)\n- [🧠Brain Tumor 3D [Inference]](https://www.kaggle.com/ammarnassanalhajali/brain-tumor-3d-inference)","metadata":{}},{"cell_type":"markdown","source":"<h1 style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\">Sommaire</h1>\n\n1. [Load data](#section_1)      \n2. [Image preprocessing](#section_2)      \n3. [Load pre-trained ResNet50 model](#section_3)      \n4. [Create a matrix of vectors base on ResNet50 for each patient sequence](#section_4)     \n5. [Apply LSTM for classification with Kfold](#section_5)      \n6. [Predict on test set with best model](#section_6)","metadata":{}},{"cell_type":"markdown","source":"First, we have to load the usefull Python libraries :","metadata":{}},{"cell_type":"code","source":"import os\nimport glob\nimport re\nimport math\nimport numpy as np\nimport pandas as pd\nfrom tqdm.notebook import tqdm\nimport cv2\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport pydicom as dicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-09-14T10:54:58.673577Z","iopub.execute_input":"2021-09-14T10:54:58.673968Z","iopub.status.idle":"2021-09-14T10:55:03.789995Z","shell.execute_reply.started":"2021-09-14T10:54:58.673886Z","shell.execute_reply":"2021-09-14T10:55:03.789065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\" id=\"section_1\">Load data</span>\n\nWe will first load the anotated training data files:","metadata":{}},{"cell_type":"code","source":"data_directory = '../input/rsna-miccai-brain-tumor-radiogenomic-classification/'","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:03.793343Z","iopub.execute_input":"2021-09-14T10:55:03.793615Z","iopub.status.idle":"2021-09-14T10:55:03.799635Z","shell.execute_reply.started":"2021-09-14T10:55:03.793588Z","shell.execute_reply":"2021-09-14T10:55:03.798794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(data_directory+\"train_labels.csv\")\ntrain_df['BraTS21ID5'] = [format(x, '05d') for x in train_df.BraTS21ID]\ntrain_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:03.803625Z","iopub.execute_input":"2021-09-14T10:55:03.803903Z","iopub.status.idle":"2021-09-14T10:55:03.8424Z","shell.execute_reply.started":"2021-09-14T10:55:03.80387Z","shell.execute_reply":"2021-09-14T10:55:03.841684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"and the test data :","metadata":{}},{"cell_type":"code","source":"test = pd.read_csv(\n    data_directory+'sample_submission.csv')\n\ntest['BraTS21ID5'] = [format(x, '05d') for x in test.BraTS21ID]\ntest.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:03.845205Z","iopub.execute_input":"2021-09-14T10:55:03.845454Z","iopub.status.idle":"2021-09-14T10:55:03.865556Z","shell.execute_reply.started":"2021-09-14T10:55:03.845429Z","shell.execute_reply":"2021-09-14T10:55:03.864762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\" id=\"section_2\">Image preprocessing</span>\n\nFor each patient, we will carry out a pre-processing of the images by applying these different modifications:\n- Load an ordered sequence of 64 MRI scan\n- Crop images to reduce black borders\n- Resize image for pre-train model\n- Apply denoising filter\n- Convert each image in **3D array**","metadata":{}},{"cell_type":"code","source":"IMAGE_SIZE = 240\nSCALE = .8\nNUM_IMAGES = 64\nMRI_TYPE = \"FLAIR\"","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:03.866942Z","iopub.execute_input":"2021-09-14T10:55:03.867299Z","iopub.status.idle":"2021-09-14T10:55:03.872092Z","shell.execute_reply.started":"2021-09-14T10:55:03.867262Z","shell.execute_reply":"2021-09-14T10:55:03.871057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:#3c99dc; font-size:18px; text-transform: uppercase; font-weight:bold\" id=\"section_1_1\">Load single image</span>","metadata":{}},{"cell_type":"code","source":"def load_dicom_image(\n    path,\n    img_size=IMAGE_SIZE,\n    scale=SCALE):\n    '''\n    This function allows you to load a DCIM type image \n    and apply preprocessing steps such as crop, resize \n    and denoising filter to it.\n    ****************************************************\n    PARAMETERS\n    ****************************************************\n    - path : String\n        Path to the DCIM image file to load.\n    - img_size : Integer\n        Image size desired for resizing.\n    - scale : Float\n        Desired scale for the cropped image\n    - prep : Bool\n        True for a full preprocessing with\n        denoising.\n    '''\n    # Load single image\n    img = dicom.read_file(path).pixel_array\n    # Crop image\n    center_x, center_y = img.shape[1] / 2, img.shape[0] / 2\n    width_scaled, height_scaled = img.shape[1] * scale, img.shape[0] * scale\n    left_x, right_x = center_x - width_scaled / 2, center_x + width_scaled / 2\n    top_y, bottom_y = center_y - height_scaled / 2, center_y + height_scaled / 2\n    img = img[int(top_y):int(bottom_y), int(left_x):int(right_x)]\n    # Resize image\n    img = cv2.resize(img, (img_size, img_size))\n    \n    # Convert in 3D array\n    img = np.repeat(img[..., np.newaxis], 3, -1)\n    \n    return img","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:03.874392Z","iopub.execute_input":"2021-09-14T10:55:03.874915Z","iopub.status.idle":"2021-09-14T10:55:03.886961Z","shell.execute_reply.started":"2021-09-14T10:55:03.874871Z","shell.execute_reply":"2021-09-14T10:55:03.885549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can check the result of these different preprocessing steps on a random patient:","metadata":{}},{"cell_type":"code","source":"sample_img = dicom.read_file(\n    data_directory+\"train/00046/FLAIR/Image-90.dcm\").pixel_array\npreproc_img = load_dicom_image(data_directory+\"train/00046/FLAIR/Image-90.dcm\")\n\n\nfig = plt.figure(figsize=(12,8))\nax1 = plt.subplot(1,2,1)\nax1.imshow(sample_img, cmap=\"gray\")\nax1.set_title(f\"Original image shape = {sample_img.shape}\")\nax2 = plt.subplot(1,2,2)\nax2.imshow(preproc_img[:,:,0], cmap=\"gray\")\nax2.set_title(f\"Preproc image shape = {preproc_img.shape}\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:03.888913Z","iopub.execute_input":"2021-09-14T10:55:03.889853Z","iopub.status.idle":"2021-09-14T10:55:04.247445Z","shell.execute_reply.started":"2021-09-14T10:55:03.889793Z","shell.execute_reply":"2021-09-14T10:55:04.246605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:#3c99dc; font-size:18px; text-transform: uppercase; font-weight:bold\" id=\"section_1_2\">Load sequence of 64 preprocessed images</span>\n\nAs we saw **in the EDA part of the previous [Notebook](https://www.kaggle.com/michaelfumery/brain-tumor-3d-multimodal-cnn-all-mri-type)**, we are going to load the image sequence starting from the central image in order to avoid completely black images. We will then take the same number of images on each side of this central image.","metadata":{}},{"cell_type":"code","source":"def load_dicom_images_3d(\n    scan_id, \n    num_imgs=NUM_IMAGES, \n    img_size=IMAGE_SIZE, \n    mri_type=MRI_TYPE, \n    split=\"train\"):\n    '''\n    This function allows loading an ordered sequence \n    of x preprocessed images starting from the central \n    image of each folder.\n    ****************************************************\n    PARAMETERS\n    ****************************************************\n    - scan_id : String\n        ID of the patient to load.\n    - num_imgs : Integer\n        Number of desired images of the \n        sequence.\n    - img_size : Integer\n        Image size desired for resizing.\n    - scale : Float\n        Desired scale for the cropped image\n    - mri_type : String\n        Type of scan to load (FLAIR, T1w, \n        T1wCE, T2).\n    - split : String\n        Type of split desired : Train or Test\n    '''\n    files = sorted(glob.glob(f\"{data_directory}{split}/{scan_id}/{mri_type}/*.dcm\"), \n               key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)])\n\n    middle = len(files)//2\n    num_imgs2 = num_imgs//2\n    p1 = max(0, middle - num_imgs2)\n    p2 = min(len(files), middle + num_imgs2)\n    img3d = np.stack([load_dicom_image(f) for f in files[p1:p2]]) \n    if img3d.shape[0] < num_imgs:\n        n_zero = np.zeros((num_imgs - img3d.shape[0], img_size, img_size, 3))\n        img3d = np.concatenate((img3d,  n_zero), axis = 0)\n            \n    return img3d","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:04.249874Z","iopub.execute_input":"2021-09-14T10:55:04.250226Z","iopub.status.idle":"2021-09-14T10:55:04.258245Z","shell.execute_reply.started":"2021-09-14T10:55:04.250188Z","shell.execute_reply":"2021-09-14T10:55:04.257323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Here again we can test the loading of a sequence of preprocessed images for a patient:","metadata":{}},{"cell_type":"code","source":"sample_seq = load_dicom_images_3d(\"00046\")\nprint(\"Shape of the sequence is:\", sample_seq.shape)\nprint(\"Dimension of the 15th image in sequence is:\", sample_seq[15].shape)\nfig = plt.figure(figsize=(5,5))\nplt.imshow(np.squeeze(sample_seq[15][:,:,0]), cmap=\"gray\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:04.260363Z","iopub.execute_input":"2021-09-14T10:55:04.260903Z","iopub.status.idle":"2021-09-14T10:55:05.087168Z","shell.execute_reply.started":"2021-09-14T10:55:04.260863Z","shell.execute_reply":"2021-09-14T10:55:05.086398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\" id=\"section_3\">Load pre-trained ResNet50 model</span>\n\nTo carry out the Transfer Learning on each image of the sequence, we will load a pre-trained model thanks to `Keras.applications` with the pre-trained weights on **ImageNet**.      \nAs the notebook must be without Internet for the competition, the weights are loaded separately and imported from a specially created Dataset *(../input/resnet-imagenet-weights)*.\n\nHere we will chrger the **ResNet50 model**, knowing that other models have been tested such as ResNet50 and Xception.","metadata":{}},{"cell_type":"code","source":"base_resnet = keras.applications.ResNet50(\n    weights=None,\n    #weights=\"imagenet\",\n    pooling='avg',\n    input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3),\n    include_top=False)\n\n\"\"\"base_resnet.save_weights(\n    'base_resnet_imagenet.h5')\"\"\"\nbase_resnet.load_weights(\n    '../input/resnet-imagenet-weights/base_resnet_imagenet.h5')","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:05.08843Z","iopub.execute_input":"2021-09-14T10:55:05.088793Z","iopub.status.idle":"2021-09-14T10:55:09.511202Z","shell.execute_reply.started":"2021-09-14T10:55:05.088738Z","shell.execute_reply":"2021-09-14T10:55:09.510279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We are also going to **fix all the layers of the model** so that they are not re-trained for the detection of features. The classification layer is also not loaded (`include_top = False`).","metadata":{}},{"cell_type":"code","source":"base_resnet.trainable = False","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:09.512451Z","iopub.execute_input":"2021-09-14T10:55:09.512782Z","iopub.status.idle":"2021-09-14T10:55:09.525119Z","shell.execute_reply.started":"2021-09-14T10:55:09.512749Z","shell.execute_reply":"2021-09-14T10:55:09.524036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\" id=\"section_4\">Create a matrix of vectors base on ResNet50 for each patient sequence</span>\n\nFor this part of Transfer Learning, we will not train the ResNet50 model but only perform the prediction for each image of the sequence of each patient.     \nWe will thus obtain, for each image, a matrix of the model weights that we will integrate into a list to recreate the patient sequence.     \nFinally, we are going to create a global matrix which will group together the sequences of x ResNet50.predict matrices for all the patients.\n\nLet's look at the pseudo-code:\n```Python\n# Transfert Learning\nlistMatrix = []\nfor person in persons:\n    listVectors = []\n    for image in person.images:\n        img = preprocess(image)\n        vector = baseModel.predict(img)\n        listVectors.append(vector)\n\n    PatientMatrix = np.stack(listVectors)\n    listMatrix.append(PatientMatrix)\n```","metadata":{}},{"cell_type":"code","source":"train = train_df[['BraTS21ID5','MGMT_value']]\nX_train = train['BraTS21ID5'].values\ny_train = train['MGMT_value'].values","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:09.526729Z","iopub.execute_input":"2021-09-14T10:55:09.527317Z","iopub.status.idle":"2021-09-14T10:55:09.534861Z","shell.execute_reply.started":"2021-09-14T10:55:09.527278Z","shell.execute_reply":"2021-09-14T10:55:09.534068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**We will apply this process for just one type of MRI scans (here is T1w type)** for each patient. Each patient will therefore have 24 images for treatment.","metadata":{}},{"cell_type":"code","source":"listMatrix = []\nfor i, patient in enumerate(tqdm(X_train)):\n    listVectors = []\n    sequence = load_dicom_images_3d(scan_id=str(patient),mri_type=MRI_TYPE)\n    for j in range(len(sequence)):\n        img = sequence[j]\n        img = np.expand_dims(img, axis=0)\n        img = tf.keras.applications.resnet50.preprocess_input(img)\n        img_vector = base_resnet.predict(img)\n        listVectors.append(np.array(img_vector))\n    \n    PatientMatrix = np.stack(listVectors)\n    listMatrix.append(PatientMatrix)","metadata":{"execution":{"iopub.status.busy":"2021-09-14T10:55:09.538099Z","iopub.execute_input":"2021-09-14T10:55:09.53839Z","iopub.status.idle":"2021-09-14T11:24:30.757584Z","shell.execute_reply.started":"2021-09-14T10:55:09.538364Z","shell.execute_reply":"2021-09-14T11:24:30.756791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let us now look at the shapes of the matrices obtained following the application of this Learning Transfer:","metadata":{}},{"cell_type":"code","source":"print(f\"Number of patient matrix: {len(listMatrix)}\")\nprint(f\"Patient matrix shape: {listMatrix[0].shape}\")","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:24:30.758896Z","iopub.execute_input":"2021-09-14T11:24:30.75926Z","iopub.status.idle":"2021-09-14T11:24:30.76472Z","shell.execute_reply.started":"2021-09-14T11:24:30.75922Z","shell.execute_reply":"2021-09-14T11:24:30.763787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.array(listMatrix, dtype=object).shape","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:24:30.766022Z","iopub.execute_input":"2021-09-14T11:24:30.766378Z","iopub.status.idle":"2021-09-14T11:24:36.079709Z","shell.execute_reply.started":"2021-09-14T11:24:30.766342Z","shell.execute_reply":"2021-09-14T11:24:36.078676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\" id=\"section_5\">Apply LSTM for classification</span>\n\nRecurrent neural networks (RNNs) are widely used in artificial intelligence when a temporal notion is involved in the data.\n\nLSTM is a complex and very powerful algorithm which will allow in our case to take into account the past elements of our sequence of images.","metadata":{}},{"cell_type":"code","source":"model_input_dim = listMatrix[0].shape[2]","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:24:36.081084Z","iopub.execute_input":"2021-09-14T11:24:36.081489Z","iopub.status.idle":"2021-09-14T11:24:36.08615Z","shell.execute_reply.started":"2021-09-14T11:24:36.081449Z","shell.execute_reply":"2021-09-14T11:24:36.085015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_sequence_model():\n    '''Define the LSTM architecture'''\n    model = keras.models.Sequential()\n    model.add(keras.layers.LSTM(100, input_shape=(NUM_IMAGES, model_input_dim), return_sequences=True))\n    model.add(keras.layers.Dropout(0.2))\n    model.add(keras.layers.Dense(100, activation='relu'))\n    model.add(keras.layers.Dense(1, activation='sigmoid'))\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:24:36.087576Z","iopub.execute_input":"2021-09-14T11:24:36.088133Z","iopub.status.idle":"2021-09-14T11:24:36.09533Z","shell.execute_reply.started":"2021-09-14T11:24:36.088096Z","shell.execute_reply":"2021-09-14T11:24:36.094384Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import KFold\n\ninputs = np.array(listMatrix)\ntargets = np.array(y_train).astype('float32').reshape((-1,1))\n\nnum_folds = 5\n\n# Define the K-fold Cross Validator\nkfold = KFold(n_splits=num_folds, shuffle=True)\n\n# K-fold Cross Validation model evaluation\nhistory = {}\nfold_no = 1\nfor train_df, valid_df in kfold.split(inputs, targets):\n    \n    train_dataset = tf.data.Dataset.from_tensor_slices((inputs[train_df], targets[train_df]))\n    valid_dataset = tf.data.Dataset.from_tensor_slices((inputs[valid_df], targets[valid_df]))\n    \n    model = get_sequence_model()\n    model.compile(loss='binary_crossentropy', \n                  optimizer='adam', \n                  metrics='accuracy')\n    \n    # Define callbacks.\n    model_save = ModelCheckpoint(f'Brain_lstm_kfold_{fold_no}.h5', \n                                 save_best_only = True, \n                                 monitor = 'val_accuracy', \n                                 mode = 'max', verbose = 1)\n    early_stop = EarlyStopping(monitor = 'val_accuracy', \n                               patience = 25, mode = 'max', verbose = 1,\n                               restore_best_weights = True)\n    \n    print('------------------------------------------------------------------------')\n    print(f'Training for fold {fold_no} ...')\n    \n    epochs = 200\n    history[fold_no] = model.fit(\n        train_dataset,\n        validation_data=valid_dataset, \n        epochs=epochs, \n        batch_size=32,\n        callbacks = [model_save, early_stop])\n    \n    # Increase fold number\n    fold_no += 1","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-09-14T11:24:36.096655Z","iopub.execute_input":"2021-09-14T11:24:36.097275Z","iopub.status.idle":"2021-09-14T11:29:53.107166Z","shell.execute_reply.started":"2021-09-14T11:24:36.09724Z","shell.execute_reply":"2021-09-14T11:29:53.105919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We will now train this LSTM model on the matrices compiled for each patient using the Transfer Learning ResNet50.\n\nAn EarlyStopping is set up and the best model will be saved.","metadata":{}},{"cell_type":"markdown","source":"Now let's look at the results of this training:","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(1, 2, figsize=(20, 7))\nax = ax.ravel()\n\nfor fold in history:\n    for i, metric in enumerate([\"accuracy\",\"loss\"]):\n        ax[i].plot(history[fold].history[metric], label=\"train \"+str(fold))\n        ax[i].plot(history[fold].history[\"val_\" + metric], linestyle=\"dotted\", label=\"val \"+str(fold))\n        ax[i].set_title(\"Model {}\".format(metric))\n        ax[i].set_xlabel(\"epochs\")\n        ax[i].set_ylabel(metric)\n        ax[i].legend()","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:29:53.110019Z","iopub.execute_input":"2021-09-14T11:29:53.110278Z","iopub.status.idle":"2021-09-14T11:29:53.605519Z","shell.execute_reply.started":"2021-09-14T11:29:53.110252Z","shell.execute_reply":"2021-09-14T11:29:53.604543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kfold_results = pd.DataFrame(columns=[\"Fold\",\"Mean_Loss\",\"Mean_Accuracy\"])\nkey = []\nmean_loss = []\nmean_acc = []\nfor fold in history:\n    key.append(fold), \n    mean_loss.append(np.mean(history[fold].history[\"val_loss\"]))\n    mean_acc.append(np.mean(history[fold].history[\"val_accuracy\"]))\n\nkfold_results[\"Fold\"] = key\nkfold_results[\"Mean_Loss\"] = mean_loss\nkfold_results[\"Mean_Accuracy\"] = mean_acc\nkfold_results[\"Rank_Ratio\"] = (kfold_results[\"Mean_Loss\"] - kfold_results[\"Mean_Accuracy\"])\nkfold_results = kfold_results.sort_values(\"Rank_Ratio\", ascending=True)\nkfold_results","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:29:53.606871Z","iopub.execute_input":"2021-09-14T11:29:53.607338Z","iopub.status.idle":"2021-09-14T11:29:53.647501Z","shell.execute_reply.started":"2021-09-14T11:29:53.6073Z","shell.execute_reply":"2021-09-14T11:29:53.646812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"best_kfold_model = './Brain_lstm_kfold_' + str(kfold_results.Fold.values[0]) + '.h5'\nprint(f\"The best select model is {best_kfold_model}\")","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:29:53.648693Z","iopub.execute_input":"2021-09-14T11:29:53.649129Z","iopub.status.idle":"2021-09-14T11:29:53.656015Z","shell.execute_reply.started":"2021-09-14T11:29:53.649084Z","shell.execute_reply":"2021-09-14T11:29:53.654243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:#0b0a2d; font-size:24px; text-transform: uppercase; font-weight:bold\" id=\"section_6\">Predict on test set with best model</span>\n\nWe will now create the ResNet50 matrices for the test set and make the predictions on the test patients.","metadata":{}},{"cell_type":"code","source":"X_test = test['BraTS21ID5'].values\ntest_listMatrix = []\nfor i, patient in enumerate(tqdm(X_test)):\n    test_listVectors = []\n    test_sequence = load_dicom_images_3d(scan_id=str(patient),mri_type=MRI_TYPE,split=\"test\")\n    for j in range(len(test_sequence)):\n        img = test_sequence[j]\n        img = np.expand_dims(img, axis=0)\n        img = tf.keras.applications.resnet50.preprocess_input(img)\n        img_vector = base_resnet.predict(img)\n        test_listVectors.append(np.array(img_vector))\n    \n    test_PatientMatrix = np.stack(test_listVectors)\n    test_listMatrix.append(test_PatientMatrix)","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:29:53.65759Z","iopub.execute_input":"2021-09-14T11:29:53.658134Z","iopub.status.idle":"2021-09-14T11:34:16.370895Z","shell.execute_reply.started":"2021-09-14T11:29:53.658096Z","shell.execute_reply":"2021-09-14T11:34:16.37014Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Number of test patient matrix: {len(test_listMatrix)}\")\nprint(f\"Test patient matrix shape: {test_listMatrix[0].shape}\")","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:34:16.374088Z","iopub.execute_input":"2021-09-14T11:34:16.374341Z","iopub.status.idle":"2021-09-14T11:34:16.379501Z","shell.execute_reply.started":"2021-09-14T11:34:16.374315Z","shell.execute_reply":"2021-09-14T11:34:16.378475Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = tf.data.Dataset.from_tensor_slices(test_listMatrix)\nlen(test_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:34:16.381352Z","iopub.execute_input":"2021-09-14T11:34:16.381892Z","iopub.status.idle":"2021-09-14T11:34:19.844964Z","shell.execute_reply.started":"2021-09-14T11:34:16.381854Z","shell.execute_reply":"2021-09-14T11:34:19.844018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_model = keras.models.load_model(best_kfold_model)\npredict = final_model.predict(test_dataset)\nprint(predict.shape)","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:34:19.846519Z","iopub.execute_input":"2021-09-14T11:34:19.846897Z","iopub.status.idle":"2021-09-14T11:34:20.567568Z","shell.execute_reply.started":"2021-09-14T11:34:19.84686Z","shell.execute_reply":"2021-09-14T11:34:20.566665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict = predict[:,0,0]\nfinal_predict = []\nfor i in range(len(test_listMatrix)):\n    i+=1\n    final_predict.append(round(predict[((i-1)*NUM_IMAGES):(NUM_IMAGES*i)].mean(),3))\nsubmission = test[[\"BraTS21ID\",\"MGMT_value\"]]\nsubmission[\"MGMT_value\"] = final_predict\nsubmission.to_csv('submission.csv',index=False)\nsubmission.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:34:20.568958Z","iopub.execute_input":"2021-09-14T11:34:20.569307Z","iopub.status.idle":"2021-09-14T11:34:20.590033Z","shell.execute_reply.started":"2021-09-14T11:34:20.56927Z","shell.execute_reply":"2021-09-14T11:34:20.589003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(8, 8))\nplt.hist(submission[\"MGMT_value\"])\nplt.title(\"Predicted probabilites distribution on test set\", \n          fontsize=18, color=\"#0b0a2d\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-09-14T11:34:20.591554Z","iopub.execute_input":"2021-09-14T11:34:20.591954Z","iopub.status.idle":"2021-09-14T11:34:20.741955Z","shell.execute_reply.started":"2021-09-14T11:34:20.591916Z","shell.execute_reply":"2021-09-14T11:34:20.740969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color:red; font-size:18px\">Don't forget to **upvote** if this Notebook helped you!</span>","metadata":{}}]}