{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.9","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceType":"competition","sourceId":13451,"datasetId":654585,"databundleVersionId":1188070},{"sourceType":"datasetVersion","sourceId":2170623,"datasetId":1303051,"databundleVersionId":2211890}],"dockerImageVersionId":30068,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Load Data","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport pydicom\nimport os\nimport matplotlib.pyplot as plt\nimport collections\nfrom tqdm import tqdm_notebook as tqdm\nfrom tqdm import trange\nfrom math import ceil, floor, log\nimport cv2\nimport tensorflow as tf\nfrom tensorflow import keras\nimport sys\nimport PIL\nimport pathlib\nfrom PIL import Image\nfrom glob import glob\n\nfrom sklearn.model_selection import ShuffleSplit\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.metrics import multilabel_confusion_matrix, classification_report\n\nfrom keras.layers import *\nfrom keras.models import *\nfrom keras.layers import *\nfrom keras.optimizers import *\nfrom keras.applications import *\nfrom keras.applications.vgg16 import VGG16\nfrom keras.applications.inception_v3 import InceptionV3\nfrom keras.applications.xception import Xception\nfrom keras.applications import DenseNet121, ResNet50V2, InceptionV3\nfrom keras.callbacks import EarlyStopping\nfrom keras.utils import plot_model\nfrom keras.callbacks import TensorBoard\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom keras.utils import Sequence\n\nif 'checkpoint' not in os.listdir('./'):\n    os.mkdir('./checkpoint')","metadata":{"execution":{"iopub.status.busy":"2025-12-29T06:20:54.680275Z","iopub.execute_input":"2025-12-29T06:20:54.680602Z","iopub.status.idle":"2025-12-29T06:20:54.688837Z","shell.execute_reply.started":"2025-12-29T06:20:54.680574Z","shell.execute_reply":"2025-12-29T06:20:54.687887Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"input_path = \"../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/\"\ntest_images_dir = input_path + 'stage_2_test/'\ntrain_images_dir = input_path + 'stage_2_train/'","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path = '../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train/ID_000012eaf.dcm'\nimg = pydicom.dcmread(path)\nimg","metadata":{"execution":{"iopub.status.busy":"2025-12-29T05:50:23.543387Z","iopub.execute_input":"2025-12-29T05:50:23.543713Z","iopub.status.idle":"2025-12-29T05:50:23.568063Z","shell.execute_reply.started":"2025-12-29T05:50:23.543684Z","shell.execute_reply":"2025-12-29T05:50:23.567407Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Data Pre-Processing","metadata":{}},{"cell_type":"code","source":"def correct_dcm(dcm):\n    x = dcm.pixel_array + 1000\n    px_mode = 4096\n    x[x>=px_mode] = x[x>=px_mode] - px_mode\n    dcm.PixelData = x.tobytes()\n    dcm.RescaleIntercept = -1000\n\ndef window_image(dcm, window_center, window_width):\n    \n    if (dcm.BitsStored == 12) and (dcm.PixelRepresentation == 0) and (int(dcm.RescaleIntercept) > -100):\n        correct_dcm(dcm)\n    \n    img = dcm.pixel_array * dcm.RescaleSlope + dcm.RescaleIntercept\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img = np.clip(img, img_min, img_max)\n\n    return img\n\ndef bsb_window(dcm):\n    brain_img = window_image(dcm, 40, 80)\n    subdural_img = window_image(dcm, 80, 200)\n    soft_img = window_image(dcm, 40, 380)\n    \n    brain_img = (brain_img - 0) / 80\n    subdural_img = (subdural_img - (-20)) / 200\n    soft_img = (soft_img - (-150)) / 380\n    bsb_img = np.array([brain_img, subdural_img, soft_img]).transpose(1,2,0)\n\n    return bsb_img\n\ndicom = pydicom.dcmread(train_images_dir + 'ID_5c8b5d701' + '.dcm')\nplt.imshow(bsb_window(dicom), cmap=plt.cm.bone);\n","metadata":{"execution":{"iopub.status.busy":"2025-12-29T06:21:47.515012Z","iopub.execute_input":"2025-12-29T06:21:47.515317Z","iopub.status.idle":"2025-12-29T06:21:47.703907Z","shell.execute_reply.started":"2025-12-29T06:21:47.515292Z","shell.execute_reply":"2025-12-29T06:21:47.703158Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def window_with_correction(dcm, window_center, window_width):\n    if (dcm.BitsStored == 12) and (dcm.PixelRepresentation == 0) and (int(dcm.RescaleIntercept) > -100):\n        correct_dcm(dcm)\n    img = dcm.pixel_array * dcm.RescaleSlope + dcm.RescaleIntercept\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img = np.clip(img, img_min, img_max)\n    return img\n\ndef window_without_correction(dcm, window_center, window_width):\n    img = dcm.pixel_array * dcm.RescaleSlope + dcm.RescaleIntercept\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img = np.clip(img, img_min, img_max)\n    return img\n\ndef window_testing(img, window):\n    brain_img = window(img, 40, 80)\n    subdural_img = window(img, 80, 200)\n    soft_img = window(img, 40, 380)\n    \n    brain_img = (brain_img - 0) / 80\n    subdural_img = (subdural_img - (-20)) / 200\n    soft_img = (soft_img - (-150)) / 380\n    bsb_img = np.array([brain_img, subdural_img, soft_img]).transpose(1,2,0)\n\n    return bsb_img\n\n# example of a \"bad data point\" (i.e. (dcm.BitsStored == 12) and (dcm.PixelRepresentation == 0) and (int(dcm.RescaleIntercept) > -100) == True)\ndicom = pydicom.dcmread(train_images_dir + \"ID_036db39b7\" + \".dcm\")\n\nfig, ax = plt.subplots(1, 2)\n\nax[0].imshow(window_testing(dicom, window_without_correction), cmap=plt.cm.bone);\nax[0].set_title(\"original\")\nax[1].imshow(window_testing(dicom, window_with_correction), cmap=plt.cm.bone);\nax[1].set_title(\"corrected\");","metadata":{"execution":{"iopub.status.busy":"2025-12-29T06:21:48.841604Z","iopub.execute_input":"2025-12-29T06:21:48.841896Z","iopub.status.idle":"2025-12-29T06:21:49.120808Z","shell.execute_reply.started":"2025-12-29T06:21:48.841871Z","shell.execute_reply":"2025-12-29T06:21:49.120046Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv('../input/rsna-csv-files/RSNA_DATA/good_slices.csv',index_col = 'Unnamed: 0')","metadata":{"execution":{"iopub.status.busy":"2023-06-25T13:21:33.230222Z","iopub.execute_input":"2023-06-25T13:21:33.230961Z","iopub.status.idle":"2023-06-25T13:21:34.135041Z","shell.execute_reply.started":"2023-06-25T13:21:33.230916Z","shell.execute_reply":"2023-06-25T13:21:34.134079Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_partition_labels(df):\n    partition = dict()\n    labels = dict()\n    for i in trange(len(df)):\n        id_ = df.Image[i]\n        label = df.iloc[i,1:7].to_numpy(dtype = 'int32')\n        labels[id_] = label\n        \n    df = df.sample(frac = 0.1)\n    training = df.sample(frac = 0.8)\n    \n    validation = df.drop(training.index, axis = 0)\n    test = validation.sample(frac = 0.5)\n    validation = validation.drop(test.index, axis = 0) \n    \n    partition['train'] = list(training.Image)\n    partition['validation'] = list(validation.Image)\n    partition['test'] = list(test.Image)\n    return partition,labels","metadata":{"execution":{"iopub.status.busy":"2023-06-25T13:21:34.138802Z","iopub.execute_input":"2023-06-25T13:21:34.139082Z","iopub.status.idle":"2023-06-25T13:21:34.149694Z","shell.execute_reply.started":"2023-06-25T13:21:34.139054Z","shell.execute_reply":"2023-06-25T13:21:34.148925Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"partition,labels = get_partition_labels(df)","metadata":{"execution":{"iopub.status.busy":"2023-06-25T13:21:34.152413Z","iopub.execute_input":"2023-06-25T13:21:34.152991Z","iopub.status.idle":"2023-06-25T13:22:57.190898Z","shell.execute_reply.started":"2023-06-25T13:21:34.152959Z","shell.execute_reply":"2023-06-25T13:22:57.190076Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(partition['train'])\nvalues_view = labels.values()\nvalue_iterator = iter(values_view)\nfirst_value = next(value_iterator)\nprint(next(iter(labels)))\nprint(first_value)\n\n\nvalues_view2 = partition.values()\nvalue_iterator2 = iter(values_view)\nfirst_value2 = next(value_iterator)\nprint(next(iter(partition['train'])))\nprint(first_value2)","metadata":{"execution":{"iopub.status.busy":"2023-06-25T13:22:57.192527Z","iopub.execute_input":"2023-06-25T13:22:57.193051Z","iopub.status.idle":"2023-06-25T13:22:57.203375Z","shell.execute_reply.started":"2023-06-25T13:22:57.193012Z","shell.execute_reply":"2023-06-25T13:22:57.202507Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def _read(path, desired_size):\n    dcm = pydicom.dcmread(path)\n    \n    try:\n        img = bsb_window(dcm)\n    except:\n        img = np.zeros(desired_size)\n    \n    \n    img = cv2.resize(img, desired_size[:2], interpolation=cv2.INTER_LINEAR)\n    return img\n \nplt.imshow(\n    _read(train_images_dir+'ID_5c8b5d701'+'.dcm', (256, 256,3)), cmap=plt.cm.bone\n);","metadata":{"execution":{"iopub.status.busy":"2023-06-25T13:22:57.20537Z","iopub.execute_input":"2023-06-25T13:22:57.205973Z","iopub.status.idle":"2023-06-25T13:22:57.384657Z","shell.execute_reply.started":"2023-06-25T13:22:57.205934Z","shell.execute_reply":"2023-06-25T13:22:57.383712Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DataGenerator(keras.utils.Sequence):\n    'Generates data for Keras'\n    def __init__(self, list_IDs, labels, batch_size=64, dim=(32,32,32), n_channels=1,\n                 n_classes=10, shuffle=True):\n        'Initialization'\n        self.dim = dim\n        self.batch_size = batch_size\n        self.labels = labels\n        self.list_IDs = list_IDs\n        self.n_channels = n_channels\n        self.n_classes = n_classes\n        self.shuffle = shuffle\n        self.true_labels = []\n        self.on_epoch_end()\n\n    def __len__(self):\n        'Denotes the number of batches per epoch'\n        return int(np.floor(len(self.list_IDs) / self.batch_size))\n\n    def __getitem__(self, index):\n        'Generate one batch of data'\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n\n        list_IDs_temp = [self.list_IDs[k] for k in indexes]\n\n        X, y = self.__data_generation(list_IDs_temp)\n        \n        self.true_labels.append(y)\n\n        return X, y\n\n    def on_epoch_end(self):\n        'Updates indexes after each epoch'\n        self.indexes = np.arange(len(self.list_IDs))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n\n    def __data_generation(self, list_IDs_temp):\n        'Generates data containing batch_size samples' \n        X = np.empty((self.batch_size, *self.dim)) \n        y = np.empty((self.batch_size,6), dtype=int)\n\n        # Generate data\n        for i, ID in enumerate(list_IDs_temp):\n            image_dir = '../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train/'\n            X[i,] = _read(image_dir+ID+'.dcm',self.dim)\n            y[i] = self.labels[ID]\n\n        return X,y","metadata":{"execution":{"iopub.status.busy":"2023-06-25T13:22:57.410467Z","iopub.execute_input":"2023-06-25T13:22:57.410851Z","iopub.status.idle":"2023-06-25T13:22:57.425412Z","shell.execute_reply.started":"2023-06-25T13:22:57.410808Z","shell.execute_reply":"2023-06-25T13:22:57.42448Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Pretrained CNN Models","metadata":{}},{"cell_type":"markdown","source":"choose and run one of the model","metadata":{}},{"cell_type":"code","source":"params = {'dim':(224,224,3),\n         'batch_size':64,\n         'n_classes':6,\n         'n_channels':0,\n         'shuffle':True}","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ResNet50\ndef create_resnet_model(num_classes=6, trainable_base=False):\n    base_model = ResNet50V2(\n        include_top=False,\n        weights=\"imagenet\",\n        input_shape=params['dim'],\n        pooling='max'\n    )\n    \n    base_model.trainable = trainable_base\n    \n    model = Sequential([\n        base_model,\n        Flatten(),\n        Dense(30, activation='relu'),\n        Dropout(0.5),\n        Dense(num_classes, activation='sigmoid')\n    ])\n    \n    return model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# VGG16\ndef create_vgg16_model(num_classes=6, trainable_base=False):\n    base_model = VGG16(\n        include_top=False,\n        weights=\"imagenet\",\n        input_shape=params['dim'],\n        pooling='avg'\n    )\n    \n    base_model.trainable = trainable_base\n    \n    model = Sequential([\n        base_model,\n        Dense(256, activation='relu'),\n        Dropout(0.5),\n        Dense(num_classes, activation='sigmoid')\n    ])\n    \n    return model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Inception V#\ndef create_inception_model(num_classes=6, trainable_base=False):\n    inception_params = {'dim': (299, 299, 3)}\n    \n    base_model = InceptionV3(\n        include_top=False,\n        weights=\"imagenet\",\n        input_shape=inception_params['dim'],\n        pooling='avg'\n    )\n    \n    base_model.trainable = trainable_base\n    \n    model = Sequential([\n        base_model,\n        Dense(128, activation='relu'),\n        Dropout(0.5),\n        Dense(num_classes, activation='sigmoid')\n    ])\n    \n    return model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Xception\ndef create_xception_model(num_classes=6, trainable_base=False):\n    xception_params = {'dim': (299, 299, 3)}\n    \n    base_model = Xception(\n        include_top=False,\n        weights=\"imagenet\",\n        input_shape=xception_params['dim'],\n        pooling='avg'\n    )\n    \n    base_model.trainable = trainable_base\n    \n    model = Sequential([\n        base_model,\n        Dense(128, activation='relu'),\n        Dropout(0.5),\n        Dense(num_classes, activation='sigmoid')\n    ])\n    \n    return model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# DenseNet121 \ndef create_densenet_model(num_classes=6, trainable_base=False):\n    base_model = DenseNet121(\n        include_top=False,\n        weights=\"imagenet\",\n        input_shape=params['dim'],\n        pooling='avg'\n    )\n    \n    base_model.trainable = trainable_base\n    \n    model = Sequential([\n        base_model,\n        Dense(256, activation='relu'),\n        Dropout(0.5),\n        Dense(num_classes, activation='sigmoid')\n    ])\n    \n    return model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"code","source":"# add callbacks\ncallbacks = [\n    ModelCheckpoint(filepath='./checkpoint', monitor = 'val_weighted_loss' ,save_best_only=True,verbose = 3),\n    ReduceLROnPlateau(monitor= 'val_weighted_loss', factor=0.1, patience= 3, verbose=1,mode='auto', min_delta=0.0001)]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# data generator\ntraining_generator = DataGenerator(partition['train'], labels, **params)\nvalidation_generator = DataGenerator(partition['validation'], labels, **params)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[keras.metrics.BinaryAccuracy()])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# train model\n\nhistory = model.fit(training_generator,\n        validation_data=validation_generator, \n        epochs=100, \n        callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2023-06-25T13:22:57.426913Z","iopub.execute_input":"2023-06-25T13:22:57.427641Z","iopub.status.idle":"2023-06-25T14:59:21.935738Z","shell.execute_reply.started":"2023-06-25T13:22:57.427593Z","shell.execute_reply":"2023-06-25T14:59:21.933522Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Evaluation","metadata":{}},{"cell_type":"code","source":"# training graph\nacc = history.history['binary_accuracy']\nval_acc =  history.history['val_binary_accuracy']\n\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nepochs = range(1, len(acc) + 1)\n\nplt.plot(epochs, acc, 'r', label='Training Accuracy')\nplt.plot(epochs, val_acc, 'b', label='Validation Accuracy')\nplt.title('Training and validation acc')\nplt.legend()\nplt.figure()\n\nplt.plot(epochs, loss, 'r', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\nplt.figure()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-25T14:59:21.939628Z","iopub.execute_input":"2023-06-25T14:59:21.940056Z","iopub.status.idle":"2023-06-25T14:59:21.977492Z","shell.execute_reply.started":"2023-06-25T14:59:21.940018Z","shell.execute_reply":"2023-06-25T14:59:21.975331Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras import backend as K\n\ndef weighted_log_loss(y_true, y_pred):\n    class_weights =  tf.Variable([2., 1., 1., 1., 1., 1.])\n    eps = K.epsilon()\n    \n    y_pred = K.clip(y_pred, eps, 1.0-eps)\n\n    out = -(         y_true  * K.log(      y_pred) * class_weights\n            + (1.0 - y_true) * K.log(1.0 - y_pred) * class_weights)\n    \n    return K.mean(out, axis=-1)\n\ndef weighted_log_loss_V2(y_true, y_pred):\n    class_weights =  tf.constant([2., 1., 1., 1., 1., 1.])\n    \n    eps = tf.keras.backend.epsilon()\n    y_pred = tf.clip_by_value(y_pred, eps, 1.0-eps)\n\n    out = -(         y_true  * tf.math.log(      y_pred) * class_weights\n            + (1.0 - y_true) * tf.math.log(1.0 - y_pred) * class_weights)\n    \n    return tf.reduce_mean(out, axis=-1)\n\n\ndef _normalized_weighted_average(arr, weights=None):\n    if weights is not None:\n        scl = K.sum(weights)\n        weights = K.expand_dims(weights, axis=1)\n        return K.sum(K.dot(arr, weights), axis=1) / scl\n    return K.mean(arr, axis=1)\n\n\ndef weighted_loss(y_true, y_pred):\n\n    class_weights = tf.constant([2., 1., 1., 1., 1., 1.])\n    eps = tf.keras.backend.epsilon()\n    y_pred = tf.clip_by_value(y_pred, eps, 1.0-eps)\n\n    loss = -(        y_true  * tf.math.log(      y_pred)\n            + (1.0 - y_true) * tf.math.log(1.0 - y_pred))\n    \n    loss_samples = _normalized_weighted_average(loss, class_weights)\n    return tf.reduce_mean(loss_samples)\n\n\ndef weighted_log_loss_metric(trues, preds):\n    class_weights = [2., 1., 1., 1., 1., 1.]\n    \n    epsilon = 1e-7\n    \n    preds = np.clip(preds, epsilon, 1-epsilon)\n    loss = trues * np.log(preds) + (1 - trues) * np.log(1 - preds)\n    loss_samples = np.average(loss, axis=1, weights=class_weights)\n\n    return - loss_samples.mean()\n\n","metadata":{"execution":{"iopub.status.busy":"2023-06-25T14:59:37.891595Z","iopub.execute_input":"2023-06-25T14:59:37.891969Z","iopub.status.idle":"2023-06-25T14:59:37.910026Z","shell.execute_reply.started":"2023-06-25T14:59:37.891935Z","shell.execute_reply":"2023-06-25T14:59:37.909134Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# evaluation\nparams_test = {'dim':(224,224,3),\n         'batch_size':64,\n         'n_classes':6,\n         'n_channels':0,\n         'shuffle':False}\n\ntest_generator = DataGenerator(partition['test'], labels, **params_test)\ntest_pred = model.predict(test_generator,verbose=1)\npredicted_classes = tf.argmax(test_pred, axis=1)","metadata":{"execution":{"iopub.status.busy":"2023-06-25T15:01:49.554196Z","iopub.execute_input":"2023-06-25T15:01:49.554597Z","iopub.status.idle":"2023-06-25T15:02:28.060231Z","shell.execute_reply.started":"2023-06-25T15:01:49.554562Z","shell.execute_reply":"2023-06-25T15:02:28.059308Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(len(partition['test']))\nprediction_with_treshold = []\n\ntreshold = 0.1\n\nfor sample in test_pred:\n    prediction_with_treshold.append([1 if i>=treshold else 0 for i in sample ] )\nprediction_with_treshold = np.array(prediction_with_treshold)\nprint(len(prediction_with_treshold))\n\nprint(type(test_generator.true_labels[10]))\ntotal_list = np.concatenate(test_generator.true_labels)\ntotal_list = total_list[:-1, :]\nprint(len(total_list))\n\naccuracy_score(total_list, prediction_with_treshold)\nprint(multilabel_confusion_matrix(total_list, prediction_with_treshold))\nprint(classification_report(total_list, prediction_with_treshold, target_names = ['Any', 'Epidural', 'Intraparenychemal','Intraventricular','Subarachnoid','Subdural']))","metadata":{"execution":{"iopub.status.busy":"2023-06-25T14:59:21.985834Z","iopub.status.idle":"2023-06-25T14:59:21.986713Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Test Accuracy: \", model.evaluate(test_generator))","metadata":{"execution":{"iopub.status.busy":"2023-06-25T14:59:21.994098Z","iopub.status.idle":"2023-06-25T14:59:21.994911Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Fine Tuning","metadata":{}},{"cell_type":"code","source":"# unfreeze the base model\nbase_model = model.layers[0]\nbase_model.trainable = True\n\n# freeze all layers except the last 'unfreeze_layers'\nfor layer in base_model.layers[:-unfreeze_layers]:\n    layer.trainable = False","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(optimizer=Adam(learning_rate=1e-5), loss='binary_crossentropy', metrics=['accuracy', tf.keras.metrics.AUC()])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history_tuned = model.fit(\n        train_data,\n        validation_data=val_data,\n        epochs=20,\n        verbose=1\n    )","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}