Created
February 10, 2024 23:28
-
-
Save 0x61nas/9e30febfa9608ad102dc74393740437a to your computer and use it in GitHub Desktop.
Brain Tumor Detection.ipynb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "view-in-github", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "<a href=\"https://colab.research.google.com/gist/0x61nas/9e30febfa9608ad102dc74393740437a/brain-tumor-detection.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "SAMPLES = [[]]" | |
| ], | |
| "metadata": { | |
| "id": "ea5K6WYTkDUR" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "#@title # Dataset Settings\n", | |
| "\n", | |
| "#@markdown ## The avilable datasets are:\n", | |
| "#@markdown * [Br35H](https://www.kaggle.com/datasets/ahmedhamada0/brain-tumor-detection) - 1500 nig, 1500 pos.\n", | |
| "#@markdown * [huggingface](https://huggingface.co/datasets/PranomVignesh/MRI-Images-of-Brain-Tumor) - 1312 nig, 4057 pos.\n", | |
| "\n", | |
| "import subprocess, sys, os, shutil, re, random\n", | |
| "from os.path import exists\n", | |
| "from os import remove, mkdir\n", | |
| "from shutil import rmtree\n", | |
| "from datetime import datetime\n", | |
| "\n", | |
| "#@markdown The choosen dataset name (not case sensetive)\n", | |
| "DATASET = \"Br35H\" # @param [\"Br35H\", \"Huggingface\"] {allow-input: true}\n", | |
| "#DATASET_DIR = \"dataset\" #@param {type:\"string\"}\n", | |
| "SAMPLES_LIMT = 690 # @param {type:\"slider\", min:50, max:5000, step:5}\n", | |
| "#@markdown If dataset is larger than the selected `SAMPLES_LIMIT` then split it and train the model on more then one step.\n", | |
| "SPLIT_DATASET = True #@param {type:\"boolean\"}\n", | |
| "# VALIDATION_PERSENTAGE = 0.17 #@param {type:\"slider\", min:0.1, max:0.7, step:0.01}\n", | |
| "TESTING_PERSENTAGE = 0.3 #@param {type:\"slider\", min:0.1, max:0.7, step:0.01}\n", | |
| "#@markdown Delete the old samples list from a previous run\n", | |
| "CLEAN_RUN = True #@param {type:\"boolean\"}\n", | |
| "AUGMENTED_TRAIN_SAMPLES = False #@param {type:\"boolean\"}\n", | |
| "AUGMENTED_TEST_SAMPLES = False #@param {type:\"boolean\"}\n", | |
| "\n", | |
| "_cwd = os.getcwd()\n", | |
| "os.path.expanduser(_cwd)\n", | |
| "env = os.environ.copy()\n", | |
| "env['HOME'] = _cwd\n", | |
| "\n", | |
| "# if exists(DATASET_DIR) and CLEAN_RUN:\n", | |
| "# rmtree(DATASET_DIR)\n", | |
| "# if not exists(DATASET_DIR):\n", | |
| "# mkdir(DATASET_DIR)\n", | |
| "\n", | |
| "if CLEAN_RUN:\n", | |
| " SAMPLES = [[]]\n", | |
| "\n", | |
| "img_pattern = re.compile(r'\\.(png|jpg)$', re.IGNORECASE)\n", | |
| "\n", | |
| "def copy_samples(source_directory: str) -> list[str]:\n", | |
| " # DIST_DIR = DATASET_DIR + \"/\" + dist\n", | |
| " # if not exists(DIST_DIR):\n", | |
| " # os.mkdir(DIST_DIR)\n", | |
| " files = [source_directory + \"/\" + file for file in os.listdir(source_directory) if img_pattern.search(file)]\n", | |
| " return files\n", | |
| " # for i, src_file in enumerate(files):\n", | |
| " # _, file_extension = os.path.splitext(src_file)\n", | |
| " # dist = f\"{DIST_DIR}/{DATASET}_{i}_{int(datetime.timestamp(datetime.now()))}{file_extension}\"\n", | |
| " # shutil.copy(os.path.join(source_directory, src_file), dist)\n", | |
| "\n", | |
| "\n", | |
| "def cmd(cmd: str, _capture=True, _cwd=_cwd, _env=env) -> str:\n", | |
| " if _capture:\n", | |
| " result = subprocess.run(cmd, shell=True, capture_output=True, cwd = _cwd, env=_env, text=True)\n", | |
| " else:\n", | |
| " result = subprocess.run(cmd, shell=True, cwd = _cwd, env=_env, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n", | |
| " try:\n", | |
| " result.check_returncode()\n", | |
| " if _capture:\n", | |
| " print(f\"{result.stdout}\")\n", | |
| " return result.stdout\n", | |
| "\n", | |
| " except subprocess.CalledProcessError:\n", | |
| " print(f\"{result.stderr}\\n\", file=sys.stderr)\n", | |
| " raise Exception(f\"Enconter an error while running `{cmd}`\")\n", | |
| "\n", | |
| "def download_kaggle_ds(target: str, ds: str):\n", | |
| " ZIP_NAME = ds.split('/')[-1] + \".zip\"\n", | |
| " print(ZIP_NAME)\n", | |
| " if exists(target):\n", | |
| " rmtree(target)\n", | |
| " if not exists(ZIP_NAME):\n", | |
| " if not exists(\"/content/.kaggle/kaggle.json\"):\n", | |
| " print(\"Plese upload your kaggle API token.\\n\")\n", | |
| " from google.colab import files\n", | |
| " files.upload()\n", | |
| " mkdir(\".kaggle\")\n", | |
| " cmd(\"mv /content/kaggle.json .kaggle\")\n", | |
| " cmd(\"chmod 600 .kaggle/kaggle.json\")\n", | |
| " cmd(f\"kaggle datasets download -d {ds}\", False)\n", | |
| " cmd(f\"unzip {ZIP_NAME} -d {target}\", False)\n", | |
| "\n", | |
| "def br35h():\n", | |
| " DIR = \"br35h\"\n", | |
| " download_kaggle_ds(DIR, \"ahmedhamada0/brain-tumor-detection\")\n", | |
| " return (copy_samples(DIR + \"/\" + \"no\"), copy_samples(DIR + \"/\" + \"yes\"))\n", | |
| "\n", | |
| "POSITIVE_SAMPLES = []\n", | |
| "NIGATIVE_SAMPLES = []\n", | |
| "\n", | |
| "match DATASET.lower():\n", | |
| " case \"br35h\":\n", | |
| " n, y = br35h()\n", | |
| " NIGATIVE_SAMPLES.extend(n)\n", | |
| " POSITIVE_SAMPLES.extend(y)\n", | |
| "\n", | |
| " case \"huggingface\":\n", | |
| " DIR = \"huggingface\"\n", | |
| " if not exists(DIR):\n", | |
| " cmd(f\"git clone --depth=1 https://huggingface.co/datasets/PranomVignesh/MRI-Images-of-Brain-Tumor.git {DIR}\")\n", | |
| " DIR = f\"{DIR}/timri\"\n", | |
| " for topdir in [\"test\", \"valid\", \"train\"]:\n", | |
| " dir = f\"{DIR}/{topdir}\"\n", | |
| " for ydir in [\"glioma\", \"meningioma\", \"pituitary\"]:\n", | |
| " POSITIVE_SAMPLES.extend(copy_samples(f\"{dir}/{ydir}\"))\n", | |
| " NIGATIVE_SAMPLES.extend(copy_samples(f\"{dir}/no-tumor\"))\n", | |
| "\n", | |
| " case _:\n", | |
| " raise ValueError(\"The choosen database dosn't exist\")\n", | |
| "\n", | |
| "\n", | |
| "print(f\"Total pisitive samples: {len(POSITIVE_SAMPLES)}\")\n", | |
| "print(f\"Total nigative samples: {len(NIGATIVE_SAMPLES)}\")\n", | |
| "\n", | |
| "# Shuffle our data\n", | |
| "SAMPLES[0].extend([(path, 1) for path in POSITIVE_SAMPLES])\n", | |
| "SAMPLES[0].extend([(path, 0) for path in NIGATIVE_SAMPLES])\n", | |
| "random.shuffle(SAMPLES[0])\n", | |
| "\n", | |
| "# Split our samples or chrink them if needed\n", | |
| "def chunk_list(lst, chunk_size):\n", | |
| " return [lst[i:i + chunk_size] for i in range(0, len(lst), chunk_size)]\n", | |
| "\n", | |
| "if len(SAMPLES[0]) > SAMPLES_LIMT:\n", | |
| " if SPLIT_DATASET:\n", | |
| " SAMPLES = chunk_list(SAMPLES[0], SAMPLES_LIMT)\n", | |
| " print(f\"Samples has chanked into: {len(SAMPLES)} chunk\")\n", | |
| " else:\n", | |
| " SAMPLES[0] = SAMPLES[:SAMPLES_LIMT]\n" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "xwxdc_KOE1jD", | |
| "outputId": "b282c517-d821-47ec-853d-518e96c789e6" | |
| }, | |
| "execution_count": null, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "brain-tumor-detection.zip\n", | |
| "Total pisitive samples: 1500\n", | |
| "Total nigative samples: 1500\n", | |
| "Samples has chanked into: 5 chunk\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "fmnhwZy1UOi1" | |
| }, | |
| "source": [ | |
| "## Import Necessary Modules" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "id": "xS99NGTOUOi2" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "import tensorflow as tf\n", | |
| "from sklearn.utils import shuffle\n", | |
| "import cv2\n", | |
| "import imutils\n", | |
| "import numpy as np\n", | |
| "import matplotlib.pyplot as plt\n", | |
| "import time\n", | |
| "from os import listdir\n", | |
| "\n", | |
| "%matplotlib inline" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "j8t4MAVoUOi2" | |
| }, | |
| "source": [ | |
| "## Data Preparation & Preprocessing" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "id": "fM5ULE98UOi3" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "#@title Edges Crop\n", | |
| "#@markdown In order to crop the part that contains only the brain of the image,\n", | |
| "#@markdown We used a cropping technique to find the extreme top, bottom, left and right points\n", | |
| "#@markdown of the brain. You can read more about it here [Finding extreme points in contours with OpenCV](https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/).\n", | |
| "\n", | |
| "def crop_brain_contour(image, plot=False):\n", | |
| " # Convert the image to grayscale, and blur it slightly\n", | |
| " gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n", | |
| " gray = cv2.GaussianBlur(gray, (5, 5), 0)\n", | |
| "\n", | |
| " # Threshold the image, then perform a series of erosions +\n", | |
| " # dilations to remove any small regions of noise\n", | |
| " thresh = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY)[1]\n", | |
| " thresh = cv2.erode(thresh, None, iterations=2)\n", | |
| " thresh = cv2.dilate(thresh, None, iterations=2)\n", | |
| "\n", | |
| " # Find contours in thresholded image, then grab the largest one\n", | |
| " cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n", | |
| " cnts = imutils.grab_contours(cnts)\n", | |
| " c = max(cnts, key=cv2.contourArea)\n", | |
| "\n", | |
| "\n", | |
| " # Find the extreme points\n", | |
| " extLeft = tuple(c[c[:, :, 0].argmin()][0])\n", | |
| " extRight = tuple(c[c[:, :, 0].argmax()][0])\n", | |
| " extTop = tuple(c[c[:, :, 1].argmin()][0])\n", | |
| " extBot = tuple(c[c[:, :, 1].argmax()][0])\n", | |
| "\n", | |
| " # crop new image out of the original image using the four extreme points (left, right, top, bottom)\n", | |
| " new_image = image[extTop[1]:extBot[1], extLeft[0]:extRight[0]]\n", | |
| "\n", | |
| " if plot:\n", | |
| " plt.figure()\n", | |
| "\n", | |
| " plt.subplot(1, 2, 1)\n", | |
| " plt.imshow(image)\n", | |
| "\n", | |
| " plt.tick_params(axis='both', which='both',\n", | |
| " top=False, bottom=False, left=False, right=False,\n", | |
| " labelbottom=False, labeltop=False, labelleft=False, labelright=False)\n", | |
| "\n", | |
| " plt.title('Original Image')\n", | |
| "\n", | |
| " plt.subplot(1, 2, 2)\n", | |
| " plt.imshow(new_image)\n", | |
| "\n", | |
| " plt.tick_params(axis='both', which='both',\n", | |
| " top=False, bottom=False, left=False, right=False,\n", | |
| " labelbottom=False, labeltop=False, labelleft=False, labelright=False)\n", | |
| "\n", | |
| " plt.title('Cropped Image')\n", | |
| "\n", | |
| " plt.show()\n", | |
| "\n", | |
| " return new_image" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "m283uH9JUOi6" | |
| }, | |
| "source": [ | |
| "### Load up the data:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "i29zaIpxUOi6" | |
| }, | |
| "source": [ | |
| "The following function takes two arguments, the first one is a list of directory paths for the folders 'yes' and 'no' that contain the image data and the second argument is the image size, and for every image in both directories and does the following:\n", | |
| "1. Read the image.\n", | |
| "2. Crop the part of the image representing only the brain.\n", | |
| "3. Resize the image (because the images in the dataset come in different sizes (meaning width, height and # of channels). So, we want all of our images to be (240, 240, 3) to feed it as an input to the neural network.\n", | |
| "4. Apply normalization because we want pixel values to be scaled to the range 0-1.\n", | |
| "5. Append the image to <i>X</i> and its label to <i>y</i>.<br>\n", | |
| "\n", | |
| "After that, Shuffle <i>X</i> and <i>y</i>, because the data is ordered (meaning the arrays contains the first part belonging to one class and the second part belonging to the other class, and we don't want that).<br>\n", | |
| "Finally, Return <i>X</i> and <i>y</i>." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "id": "duQ-YX5UUOi6" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "#@title Prepare images and resize them\n", | |
| "\n", | |
| "WIDTH = 340 #@param {type:\"number\"}\n", | |
| "HEIGHT = 340 #@param {type:\"number\"}\n", | |
| "\n", | |
| "\n", | |
| "def load_data(sampels_list):\n", | |
| " \"\"\"\n", | |
| " Returns:\n", | |
| " X: A numpy array with shape = (#_examples, image_width, image_height, #_channels)\n", | |
| " y: A numpy array with shape = (#_examples, 1)\n", | |
| " \"\"\"\n", | |
| " x = []\n", | |
| " y = []\n", | |
| " for filename, y_val in sampels_list:\n", | |
| " #print(f\"file: {filename}\")\n", | |
| " # load the image\n", | |
| " image = cv2.imread(filename)\n", | |
| " #print(f\"Cropping {image}\")\n", | |
| " # crop the brain and ignore the unnecessary rest part of the image\n", | |
| " image = crop_brain_contour(image, plot=False)\n", | |
| " # resize image\n", | |
| " image = cv2.resize(image, dsize=(WIDTH, HEIGHT), interpolation=cv2.INTER_CUBIC)\n", | |
| " # normalize values\n", | |
| " image = image / 255.\n", | |
| " # convert image to numpy array and append it to X\n", | |
| " x.append(image)\n", | |
| " y.append([y_val])\n", | |
| "\n", | |
| " x = np.array(x)\n", | |
| " y = np.array(y)\n", | |
| "\n", | |
| " # Shuffle the data\n", | |
| " # x, y = shuffle(X, y)\n", | |
| " return x, y\n", | |
| "\n", | |
| "\n", | |
| "def plot_sample_images(X, y, n=50):\n", | |
| " \"\"\"\n", | |
| " Plots n sample images for both values of y (labels).\n", | |
| " Arguments:\n", | |
| " X: A numpy array with shape = (#_examples, image_width, image_height, #_channels)\n", | |
| " y: A numpy array with shape = (#_examples, 1)\n", | |
| " \"\"\"\n", | |
| "\n", | |
| " for label in [0,1]:\n", | |
| " # grab the first n images with the corresponding y values equal to label\n", | |
| " images = X[np.argwhere(y == label)]\n", | |
| " n_images = images[:n]\n", | |
| "\n", | |
| " columns_n = 10\n", | |
| " rows_n = int(n/ columns_n)\n", | |
| "\n", | |
| " plt.figure(figsize=(20, 10))\n", | |
| "\n", | |
| " i = 1 # current plot\n", | |
| " for image in n_images:\n", | |
| " plt.subplot(rows_n, columns_n, i)\n", | |
| " plt.imshow(image[0])\n", | |
| "\n", | |
| " # remove ticks\n", | |
| " plt.tick_params(axis='both', which='both',\n", | |
| " top=False, bottom=False, left=False, right=False,\n", | |
| " labelbottom=False, labeltop=False, labelleft=False, labelright=False)\n", | |
| "\n", | |
| " i += 1\n", | |
| "\n", | |
| " label_to_str = lambda label: \"Yes\" if label == 1 else \"No\"\n", | |
| " plt.suptitle(f\"Brain Tumor: {label_to_str(label)}\")\n", | |
| " plt.show()\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "kuDqMjOiUOi7" | |
| }, | |
| "source": [ | |
| "Load up the data that we augmented earlier in the Data Augmentation notebook.<br>\n", | |
| "**Note:** the augmented data directory contains not only the new generated images but also the original images." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "zXl4MRAdUOjA", | |
| "outputId": "b74a07e5-0233-4aef-e941-c7e5ca4aa51b" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Model: \"BrainDetectionModel\"\n", | |
| "_________________________________________________________________\n", | |
| " Layer (type) Output Shape Param # \n", | |
| "=================================================================\n", | |
| " input_1 (InputLayer) [(None, 340, 340, 3)] 0 \n", | |
| " \n", | |
| " zero_padding2d (ZeroPaddin (None, 344, 344, 3) 0 \n", | |
| " g2D) \n", | |
| " \n", | |
| " conv0 (Conv2D) (None, 338, 338, 32) 4736 \n", | |
| " \n", | |
| " bn0 (BatchNormalization) (None, 338, 338, 32) 128 \n", | |
| " \n", | |
| " activation (Activation) (None, 338, 338, 32) 0 \n", | |
| " \n", | |
| " max_pool0 (MaxPooling2D) (None, 84, 84, 32) 0 \n", | |
| " \n", | |
| " max_pool1 (MaxPooling2D) (None, 21, 21, 32) 0 \n", | |
| " \n", | |
| " flatten (Flatten) (None, 14112) 0 \n", | |
| " \n", | |
| " fc (Dense) (None, 1) 14113 \n", | |
| " \n", | |
| "=================================================================\n", | |
| "Total params: 18977 (74.13 KB)\n", | |
| "Trainable params: 18913 (73.88 KB)\n", | |
| "Non-trainable params: 64 (256.00 Byte)\n", | |
| "_________________________________________________________________\n", | |
| "Model compiling...\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "#@title Build the model\n", | |
| "\n", | |
| "from tensorflow.keras.layers import Conv2D, Input, ZeroPadding2D, BatchNormalization, Activation, MaxPooling2D, Flatten, Dense\n", | |
| "from tensorflow.keras.models import Model, load_model\n", | |
| "from tensorflow.keras.optimizers import Adam, AdamW\n", | |
| "from tensorflow.keras.optimizers.experimental import Adagrad, Nadam, RMSprop, SGD, Adamax\n", | |
| "from tensorflow.keras.callbacks import TensorBoard, ModelCheckpoint, ReduceLROnPlateau\n", | |
| "\n", | |
| "#@markdown Please refer to: https://www.tensorflow.org/api_docs/python/tf/keras/optimizers\n", | |
| "OPTIMIZER = \"AdamW\" #@param [\"Adam\", \"AdamW\", \"Adagrad\", \"Nadam\", \"RMSprop\", \"SGD\", \"Adamax\"] {type:\"string\", allow-input: true}\n", | |
| "#@markdown AdamW's default learning rate is often 0.001, but in practice, values between 0.0001 and 0.01 are commonly used.\n", | |
| "LEARNING_RATE = 0.0001 #@param {type:\"number\"}\n", | |
| "DECAY = True #@param {type:\"boolean\"}\n", | |
| "WEIGTH_DECAY = 0.01 #@param {type:\"number\"}\n", | |
| "\n", | |
| "match OPTIMIZER:\n", | |
| " case \"Adam\":\n", | |
| " OPTIMIZER = Adam(learning_rate=LEARNING_RATE)\n", | |
| " case \"Adagrad\":\n", | |
| " OPTIMIZER = Adagrad(learning_rate=LEARNING_RATE)\n", | |
| " case \"AdamW\":\n", | |
| " OPTIMIZER = AdamW(learning_rate=LEARNING_RATE)\n", | |
| " case \"Nadam\":\n", | |
| " OPTIMIZER = Nadam(learning_rate=LEARNING_RATE)\n", | |
| " case \"RMSprop\":\n", | |
| " OPTIMIZER = RMSprop(learning_rate=LEARNING_RATE)\n", | |
| " case \"SGD\":\n", | |
| " OPTIMIZER = SGD(learning_rate=LEARNING_RATE)\n", | |
| " case \"Adamax\":\n", | |
| " OPTIMIZER = Adamax(learning_rate=LEARNING_RATE)\n", | |
| " case _:\n", | |
| " raise ValueError(\"The choosen optimizer dosn't exist\")\n", | |
| "\n", | |
| "if DECAY:\n", | |
| " OPTIMIZER.weight_decay = WEIGTH_DECAY\n", | |
| "\n", | |
| "# reduce_lr = ReduceLROnPlateau(monitor='val_accuracy', factor=0.01, patience=2, min_lr=1e-6)\n", | |
| "\n", | |
| "def build_model(input_shape):\n", | |
| " \"\"\"\n", | |
| " Arugments:\n", | |
| " input_shape: A tuple representing the shape of the input of the model. shape=(image_width, image_height, #_channels)\n", | |
| " Returns:\n", | |
| " model: A Model object.\n", | |
| " \"\"\"\n", | |
| " # Define the input placeholder as a tensor with shape input_shape.\n", | |
| " X_input = Input(input_shape)\n", | |
| "\n", | |
| " # Zero-Padding: pads the border of X_input with zeroes\n", | |
| " X = ZeroPadding2D((2, 2))(X_input) # shape=(?, 244, 244, 3)\n", | |
| "\n", | |
| " # CONV -> BN -> RELU Block applied to X\n", | |
| " X = Conv2D(32, (7, 7), strides = (1, 1), name = 'conv0')(X)\n", | |
| " X = BatchNormalization(axis = 3, name = 'bn0')(X)\n", | |
| " X = Activation('relu')(X) # shape=(?, 238, 238, 32)\n", | |
| "\n", | |
| " # MAXPOOL\n", | |
| " X = MaxPooling2D((4, 4), name='max_pool0')(X) # shape=(?, 59, 59, 32)\n", | |
| "\n", | |
| " # MAXPOOL\n", | |
| " X = MaxPooling2D((4, 4), name='max_pool1')(X) # shape=(?, 14, 14, 32)\n", | |
| "\n", | |
| " # FLATTEN X\n", | |
| " X = Flatten()(X) # shape=(?, 6272)\n", | |
| " # FULLYCONNECTED\n", | |
| " X = Dense(1, activation='sigmoid', name='fc')(X) # shape=(?, 1)\n", | |
| "\n", | |
| " # Create model. This creates your Keras model instance, you'll use this instance to train/test the model.\n", | |
| " model = Model(inputs = X_input, outputs = X, name='BrainDetectionModel')\n", | |
| "\n", | |
| " return model\n", | |
| "\n", | |
| "IMG_SHAPE = (WIDTH, HEIGHT, 3)\n", | |
| "model = build_model(IMG_SHAPE)\n", | |
| "model.summary()\n", | |
| "\n", | |
| "print(\"Model compiling...\")\n", | |
| "model.compile(optimizer=OPTIMIZER, loss='binary_crossentropy', metrics=['accuracy'])\n", | |
| "\n", | |
| "# tensorboard\n", | |
| "log_file_name = f'brain_tumor_detection_cnn_{int(time.time())}'\n", | |
| "tensorboard = TensorBoard(log_dir=f'logs/{log_file_name}')\n", | |
| "\n", | |
| "# checkpoint\n", | |
| "# unique file name that will include the epoch and the validation (development) accuracy\n", | |
| "filepath=\"cnn-parameters-improvement-{epoch:02d}\"\n", | |
| "# save the model with the best validation (development) accuracy till now\n", | |
| "checkpoint = ModelCheckpoint(\"models/{}.model\".format(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max'))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "scrolled": false, | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "Id4qkujtUOjC", | |
| "outputId": "3199f419-67a6-4594-a1a3-380a739ae778" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Chunk 0:\n", | |
| "\t x shape: (690, 340, 340, 3), y shape: (690, 1)\n", | |
| "\t Split the chunk into:\n", | |
| "\t\t Number of training examples: 483\n", | |
| "\t\t Number of test examples: 207\n", | |
| "\t\t x_train shape: (483, 340, 340, 3)\n", | |
| "\t\t y_train shape: (483, 1)\n", | |
| ">>> Traning on chanck 0 starts\n", | |
| "Epoch 1/32\n", | |
| "8/8 [==============================] - 5s 602ms/step - loss: 0.3172 - accuracy: 0.8675 - val_loss: 0.3607 - val_accuracy: 0.8502\n", | |
| "Epoch 2/32\n", | |
| "8/8 [==============================] - 3s 390ms/step - loss: 0.2927 - accuracy: 0.8696 - val_loss: 0.3473 - val_accuracy: 0.8744\n", | |
| "Epoch 3/32\n", | |
| "8/8 [==============================] - 3s 435ms/step - loss: 0.2867 - accuracy: 0.8820 - val_loss: 0.4137 - val_accuracy: 0.8357\n", | |
| "Epoch 4/32\n", | |
| "8/8 [==============================] - 3s 378ms/step - loss: 0.2637 - accuracy: 0.9151 - val_loss: 0.4003 - val_accuracy: 0.8454\n", | |
| "Epoch 5/32\n", | |
| "8/8 [==============================] - 3s 394ms/step - loss: 0.2626 - accuracy: 0.8965 - val_loss: 0.2895 - val_accuracy: 0.8889\n", | |
| "Epoch 6/32\n", | |
| "8/8 [==============================] - 3s 375ms/step - loss: 0.2639 - accuracy: 0.9068 - val_loss: 0.3990 - val_accuracy: 0.8261\n", | |
| "Epoch 7/32\n", | |
| "8/8 [==============================] - 3s 380ms/step - loss: 0.2377 - accuracy: 0.9213 - val_loss: 0.3821 - val_accuracy: 0.8406\n", | |
| "Epoch 8/32\n", | |
| "8/8 [==============================] - 3s 379ms/step - loss: 0.2312 - accuracy: 0.9275 - val_loss: 0.2771 - val_accuracy: 0.8889\n", | |
| "Epoch 9/32\n", | |
| "8/8 [==============================] - 3s 441ms/step - loss: 0.2401 - accuracy: 0.9255 - val_loss: 0.2766 - val_accuracy: 0.8937\n", | |
| "Epoch 10/32\n", | |
| "8/8 [==============================] - 3s 337ms/step - loss: 0.2230 - accuracy: 0.9213 - val_loss: 0.3793 - val_accuracy: 0.8454\n", | |
| "Epoch 11/32\n", | |
| "8/8 [==============================] - 3s 372ms/step - loss: 0.2304 - accuracy: 0.9172 - val_loss: 0.3925 - val_accuracy: 0.8406\n", | |
| "Epoch 12/32\n", | |
| "8/8 [==============================] - 3s 378ms/step - loss: 0.2209 - accuracy: 0.9358 - val_loss: 0.2629 - val_accuracy: 0.8937\n", | |
| "Epoch 13/32\n", | |
| "8/8 [==============================] - 3s 373ms/step - loss: 0.2081 - accuracy: 0.9420 - val_loss: 0.3018 - val_accuracy: 0.8841\n", | |
| "Epoch 14/32\n", | |
| "8/8 [==============================] - 3s 367ms/step - loss: 0.2007 - accuracy: 0.9420 - val_loss: 0.3166 - val_accuracy: 0.8792\n", | |
| "Epoch 15/32\n", | |
| "8/8 [==============================] - 3s 337ms/step - loss: 0.2028 - accuracy: 0.9441 - val_loss: 0.2616 - val_accuracy: 0.9034\n", | |
| "Epoch 16/32\n", | |
| "8/8 [==============================] - 3s 344ms/step - loss: 0.1985 - accuracy: 0.9441 - val_loss: 0.2566 - val_accuracy: 0.9082\n", | |
| "Epoch 17/32\n", | |
| "8/8 [==============================] - 3s 391ms/step - loss: 0.2023 - accuracy: 0.9337 - val_loss: 0.3308 - val_accuracy: 0.8647\n", | |
| "Epoch 18/32\n", | |
| "8/8 [==============================] - 3s 409ms/step - loss: 0.1815 - accuracy: 0.9648 - val_loss: 0.2535 - val_accuracy: 0.9034\n", | |
| "Epoch 19/32\n", | |
| "8/8 [==============================] - 3s 339ms/step - loss: 0.1788 - accuracy: 0.9627 - val_loss: 0.2533 - val_accuracy: 0.9034\n", | |
| "Epoch 20/32\n", | |
| "8/8 [==============================] - 3s 341ms/step - loss: 0.1807 - accuracy: 0.9607 - val_loss: 0.3100 - val_accuracy: 0.8696\n", | |
| "Epoch 21/32\n", | |
| "8/8 [==============================] - 3s 339ms/step - loss: 0.1796 - accuracy: 0.9627 - val_loss: 0.2657 - val_accuracy: 0.8986\n", | |
| "Epoch 22/32\n", | |
| "8/8 [==============================] - 3s 392ms/step - loss: 0.1677 - accuracy: 0.9731 - val_loss: 0.2509 - val_accuracy: 0.9130\n", | |
| "Epoch 23/32\n", | |
| "8/8 [==============================] - 3s 353ms/step - loss: 0.1656 - accuracy: 0.9689 - val_loss: 0.2509 - val_accuracy: 0.9179\n", | |
| "Epoch 24/32\n", | |
| "8/8 [==============================] - 3s 384ms/step - loss: 0.1617 - accuracy: 0.9731 - val_loss: 0.2708 - val_accuracy: 0.8937\n", | |
| "Epoch 25/32\n", | |
| "8/8 [==============================] - 3s 387ms/step - loss: 0.1548 - accuracy: 0.9793 - val_loss: 0.2526 - val_accuracy: 0.9130\n", | |
| "Epoch 26/32\n", | |
| "8/8 [==============================] - 3s 418ms/step - loss: 0.1547 - accuracy: 0.9814 - val_loss: 0.2793 - val_accuracy: 0.8889\n", | |
| "Epoch 27/32\n", | |
| "8/8 [==============================] - 3s 396ms/step - loss: 0.1590 - accuracy: 0.9731 - val_loss: 0.2508 - val_accuracy: 0.9034\n", | |
| "Epoch 28/32\n", | |
| "8/8 [==============================] - 3s 383ms/step - loss: 0.1514 - accuracy: 0.9752 - val_loss: 0.2470 - val_accuracy: 0.9130\n", | |
| "Epoch 29/32\n", | |
| "8/8 [==============================] - 3s 382ms/step - loss: 0.1549 - accuracy: 0.9731 - val_loss: 0.3064 - val_accuracy: 0.8696\n", | |
| "Epoch 30/32\n", | |
| "8/8 [==============================] - 3s 410ms/step - loss: 0.1465 - accuracy: 0.9752 - val_loss: 0.2473 - val_accuracy: 0.9082\n", | |
| "Epoch 31/32\n", | |
| "8/8 [==============================] - 3s 400ms/step - loss: 0.1406 - accuracy: 0.9814 - val_loss: 0.2473 - val_accuracy: 0.9179\n", | |
| "Epoch 32/32\n", | |
| "8/8 [==============================] - 3s 334ms/step - loss: 0.1396 - accuracy: 0.9834 - val_loss: 0.2551 - val_accuracy: 0.9130\n", | |
| "Elapsed time: 0:2:23.8\n", | |
| "Chunk 1:\n", | |
| "\t x shape: (690, 340, 340, 3), y shape: (690, 1)\n", | |
| "\t Split the chunk into:\n", | |
| "\t\t Number of training examples: 483\n", | |
| "\t\t Number of test examples: 207\n", | |
| "\t\t x_train shape: (483, 340, 340, 3)\n", | |
| "\t\t y_train shape: (483, 1)\n", | |
| ">>> Traning on chanck 1 starts\n", | |
| "Epoch 1/32\n", | |
| "8/8 [==============================] - 4s 516ms/step - loss: 0.2221 - accuracy: 0.9234 - val_loss: 0.2307 - val_accuracy: 0.8937\n", | |
| "Epoch 2/32\n", | |
| "8/8 [==============================] - 3s 359ms/step - loss: 0.2228 - accuracy: 0.9234 - val_loss: 0.2200 - val_accuracy: 0.8937\n", | |
| "Epoch 3/32\n", | |
| "8/8 [==============================] - 3s 356ms/step - loss: 0.2374 - accuracy: 0.9068 - val_loss: 0.2623 - val_accuracy: 0.8792\n", | |
| "Epoch 4/32\n", | |
| "8/8 [==============================] - 3s 330ms/step - loss: 0.2332 - accuracy: 0.8986 - val_loss: 0.2532 - val_accuracy: 0.8792\n", | |
| "Epoch 5/32\n", | |
| "8/8 [==============================] - 3s 332ms/step - loss: 0.2201 - accuracy: 0.9151 - val_loss: 0.3612 - val_accuracy: 0.8357\n", | |
| "Epoch 6/32\n", | |
| "8/8 [==============================] - 3s 375ms/step - loss: 0.2265 - accuracy: 0.9027 - val_loss: 0.3217 - val_accuracy: 0.8406\n", | |
| "Epoch 7/32\n", | |
| "8/8 [==============================] - 3s 400ms/step - loss: 0.1978 - accuracy: 0.9234 - val_loss: 0.2366 - val_accuracy: 0.8889\n", | |
| "Epoch 8/32\n", | |
| "8/8 [==============================] - 3s 338ms/step - loss: 0.1836 - accuracy: 0.9379 - val_loss: 0.2556 - val_accuracy: 0.9034\n", | |
| "Epoch 9/32\n", | |
| "8/8 [==============================] - 3s 380ms/step - loss: 0.1726 - accuracy: 0.9462 - val_loss: 0.3137 - val_accuracy: 0.8502\n", | |
| "Epoch 10/32\n", | |
| "8/8 [==============================] - 3s 335ms/step - loss: 0.1752 - accuracy: 0.9379 - val_loss: 0.2298 - val_accuracy: 0.8986\n", | |
| "Epoch 11/32\n", | |
| "8/8 [==============================] - 3s 375ms/step - loss: 0.1649 - accuracy: 0.9503 - val_loss: 0.2376 - val_accuracy: 0.8937\n", | |
| "Epoch 12/32\n", | |
| "8/8 [==============================] - 3s 382ms/step - loss: 0.1595 - accuracy: 0.9545 - val_loss: 0.2841 - val_accuracy: 0.8647\n", | |
| "Epoch 13/32\n", | |
| "8/8 [==============================] - 3s 341ms/step - loss: 0.1531 - accuracy: 0.9586 - val_loss: 0.2358 - val_accuracy: 0.8889\n", | |
| "Epoch 14/32\n", | |
| "8/8 [==============================] - 3s 333ms/step - loss: 0.1481 - accuracy: 0.9627 - val_loss: 0.2341 - val_accuracy: 0.8889\n", | |
| "Epoch 15/32\n", | |
| "8/8 [==============================] - 3s 376ms/step - loss: 0.1386 - accuracy: 0.9669 - val_loss: 0.2472 - val_accuracy: 0.8841\n", | |
| "Epoch 16/32\n", | |
| "8/8 [==============================] - 3s 375ms/step - loss: 0.1329 - accuracy: 0.9731 - val_loss: 0.2403 - val_accuracy: 0.8986\n", | |
| "Epoch 17/32\n", | |
| "8/8 [==============================] - 3s 427ms/step - loss: 0.1315 - accuracy: 0.9648 - val_loss: 0.2553 - val_accuracy: 0.8744\n", | |
| "Epoch 18/32\n", | |
| "8/8 [==============================] - 3s 383ms/step - loss: 0.1287 - accuracy: 0.9710 - val_loss: 0.2409 - val_accuracy: 0.8937\n", | |
| "Epoch 19/32\n", | |
| "8/8 [==============================] - 3s 343ms/step - loss: 0.1251 - accuracy: 0.9752 - val_loss: 0.2497 - val_accuracy: 0.8889\n", | |
| "Epoch 20/32\n", | |
| "8/8 [==============================] - 3s 405ms/step - loss: 0.1223 - accuracy: 0.9752 - val_loss: 0.2491 - val_accuracy: 0.8937\n", | |
| "Epoch 21/32\n", | |
| "8/8 [==============================] - 3s 378ms/step - loss: 0.1188 - accuracy: 0.9752 - val_loss: 0.2518 - val_accuracy: 0.8889\n", | |
| "Epoch 22/32\n", | |
| "8/8 [==============================] - 3s 383ms/step - loss: 0.1212 - accuracy: 0.9793 - val_loss: 0.2516 - val_accuracy: 0.8889\n", | |
| "Epoch 23/32\n", | |
| "8/8 [==============================] - 3s 340ms/step - loss: 0.1161 - accuracy: 0.9752 - val_loss: 0.2475 - val_accuracy: 0.8889\n", | |
| "Epoch 24/32\n", | |
| "8/8 [==============================] - 3s 387ms/step - loss: 0.1156 - accuracy: 0.9752 - val_loss: 0.2551 - val_accuracy: 0.8889\n", | |
| "Epoch 25/32\n", | |
| "8/8 [==============================] - 3s 438ms/step - loss: 0.1113 - accuracy: 0.9793 - val_loss: 0.2475 - val_accuracy: 0.8841\n", | |
| "Epoch 26/32\n", | |
| "8/8 [==============================] - 3s 334ms/step - loss: 0.1111 - accuracy: 0.9793 - val_loss: 0.2587 - val_accuracy: 0.8889\n", | |
| "Epoch 27/32\n", | |
| "8/8 [==============================] - 3s 376ms/step - loss: 0.1074 - accuracy: 0.9855 - val_loss: 0.2533 - val_accuracy: 0.8937\n", | |
| "Epoch 28/32\n", | |
| "8/8 [==============================] - 3s 380ms/step - loss: 0.1047 - accuracy: 0.9896 - val_loss: 0.2734 - val_accuracy: 0.8647\n", | |
| "Epoch 29/32\n", | |
| "8/8 [==============================] - 3s 403ms/step - loss: 0.1069 - accuracy: 0.9876 - val_loss: 0.2478 - val_accuracy: 0.8744\n", | |
| "Epoch 30/32\n", | |
| "8/8 [==============================] - 3s 383ms/step - loss: 0.1015 - accuracy: 0.9834 - val_loss: 0.2506 - val_accuracy: 0.8744\n", | |
| "Epoch 31/32\n", | |
| "8/8 [==============================] - 3s 378ms/step - loss: 0.1005 - accuracy: 0.9876 - val_loss: 0.2529 - val_accuracy: 0.8889\n", | |
| "Epoch 32/32\n", | |
| "8/8 [==============================] - 3s 419ms/step - loss: 0.1011 - accuracy: 0.9876 - val_loss: 0.2606 - val_accuracy: 0.8792\n", | |
| "Elapsed time: 0:1:33.2\n", | |
| "Chunk 2:\n", | |
| "\t x shape: (690, 340, 340, 3), y shape: (690, 1)\n", | |
| "\t Split the chunk into:\n", | |
| "\t\t Number of training examples: 483\n", | |
| "\t\t Number of test examples: 207\n", | |
| "\t\t x_train shape: (483, 340, 340, 3)\n", | |
| "\t\t y_train shape: (483, 1)\n", | |
| ">>> Traning on chanck 2 starts\n", | |
| "Epoch 1/32\n", | |
| "8/8 [==============================] - 4s 587ms/step - loss: 0.2117 - accuracy: 0.9234 - val_loss: 0.2328 - val_accuracy: 0.9275\n", | |
| "Epoch 2/32\n", | |
| "8/8 [==============================] - 3s 391ms/step - loss: 0.2051 - accuracy: 0.9296 - val_loss: 0.2157 - val_accuracy: 0.9227\n", | |
| "Epoch 3/32\n", | |
| "8/8 [==============================] - 3s 378ms/step - loss: 0.2247 - accuracy: 0.9006 - val_loss: 0.3749 - val_accuracy: 0.8599\n", | |
| "Epoch 4/32\n", | |
| "8/8 [==============================] - 3s 376ms/step - loss: 0.1877 - accuracy: 0.9337 - val_loss: 0.2459 - val_accuracy: 0.9034\n", | |
| "Epoch 5/32\n", | |
| "8/8 [==============================] - 3s 342ms/step - loss: 0.1830 - accuracy: 0.9337 - val_loss: 0.2299 - val_accuracy: 0.9324\n", | |
| "Epoch 6/32\n", | |
| "8/8 [==============================] - 3s 394ms/step - loss: 0.1844 - accuracy: 0.9337 - val_loss: 0.2236 - val_accuracy: 0.9324\n", | |
| "Epoch 7/32\n", | |
| "8/8 [==============================] - 3s 375ms/step - loss: 0.1632 - accuracy: 0.9462 - val_loss: 0.2264 - val_accuracy: 0.9227\n", | |
| "Epoch 8/32\n", | |
| "8/8 [==============================] - 3s 383ms/step - loss: 0.1568 - accuracy: 0.9503 - val_loss: 0.2135 - val_accuracy: 0.9324\n", | |
| "Epoch 9/32\n", | |
| "8/8 [==============================] - 3s 386ms/step - loss: 0.1545 - accuracy: 0.9482 - val_loss: 0.2282 - val_accuracy: 0.9275\n", | |
| "Epoch 10/32\n", | |
| "8/8 [==============================] - 3s 401ms/step - loss: 0.1598 - accuracy: 0.9545 - val_loss: 0.2308 - val_accuracy: 0.9082\n", | |
| "Epoch 11/32\n", | |
| "8/8 [==============================] - 3s 381ms/step - loss: 0.1457 - accuracy: 0.9565 - val_loss: 0.2146 - val_accuracy: 0.9324\n", | |
| "Epoch 12/32\n", | |
| "8/8 [==============================] - 3s 378ms/step - loss: 0.1393 - accuracy: 0.9689 - val_loss: 0.2183 - val_accuracy: 0.9227\n", | |
| "Epoch 13/32\n", | |
| "8/8 [==============================] - 3s 381ms/step - loss: 0.1327 - accuracy: 0.9710 - val_loss: 0.2124 - val_accuracy: 0.9324\n", | |
| "Epoch 14/32\n", | |
| "8/8 [==============================] - 3s 423ms/step - loss: 0.1320 - accuracy: 0.9669 - val_loss: 0.2136 - val_accuracy: 0.9227\n", | |
| "Epoch 15/32\n", | |
| "8/8 [==============================] - 3s 383ms/step - loss: 0.1263 - accuracy: 0.9710 - val_loss: 0.2197 - val_accuracy: 0.9130\n", | |
| "Epoch 16/32\n", | |
| "8/8 [==============================] - 3s 381ms/step - loss: 0.1224 - accuracy: 0.9752 - val_loss: 0.2243 - val_accuracy: 0.9130\n", | |
| "Epoch 17/32\n", | |
| "8/8 [==============================] - 3s 335ms/step - loss: 0.1219 - accuracy: 0.9772 - val_loss: 0.2269 - val_accuracy: 0.9082\n", | |
| "Epoch 18/32\n", | |
| "8/8 [==============================] - 3s 464ms/step - loss: 0.1195 - accuracy: 0.9752 - val_loss: 0.2199 - val_accuracy: 0.9179\n", | |
| "Epoch 19/32\n", | |
| "8/8 [==============================] - 3s 383ms/step - loss: 0.1150 - accuracy: 0.9752 - val_loss: 0.2138 - val_accuracy: 0.9179\n", | |
| "Epoch 20/32\n", | |
| "8/8 [==============================] - 3s 380ms/step - loss: 0.1129 - accuracy: 0.9731 - val_loss: 0.2216 - val_accuracy: 0.9179\n", | |
| "Epoch 21/32\n", | |
| "8/8 [==============================] - 3s 336ms/step - loss: 0.1109 - accuracy: 0.9793 - val_loss: 0.2152 - val_accuracy: 0.9179\n", | |
| "Epoch 22/32\n", | |
| "8/8 [==============================] - 3s 430ms/step - loss: 0.1108 - accuracy: 0.9793 - val_loss: 0.2181 - val_accuracy: 0.9179\n", | |
| "Epoch 23/32\n", | |
| "8/8 [==============================] - 3s 379ms/step - loss: 0.1069 - accuracy: 0.9834 - val_loss: 0.2307 - val_accuracy: 0.9034\n", | |
| "Epoch 24/32\n", | |
| "8/8 [==============================] - 3s 381ms/step - loss: 0.1052 - accuracy: 0.9834 - val_loss: 0.2116 - val_accuracy: 0.9227\n", | |
| "Epoch 25/32\n", | |
| "8/8 [==============================] - 3s 381ms/step - loss: 0.1064 - accuracy: 0.9855 - val_loss: 0.2759 - val_accuracy: 0.8841\n", | |
| "Epoch 26/32\n", | |
| "8/8 [==============================] - 3s 393ms/step - loss: 0.1044 - accuracy: 0.9814 - val_loss: 0.2192 - val_accuracy: 0.9034\n", | |
| "Epoch 27/32\n", | |
| "8/8 [==============================] - 3s 344ms/step - loss: 0.1047 - accuracy: 0.9855 - val_loss: 0.2366 - val_accuracy: 0.8937\n", | |
| "Epoch 28/32\n", | |
| "8/8 [==============================] - 3s 335ms/step - loss: 0.0990 - accuracy: 0.9834 - val_loss: 0.2211 - val_accuracy: 0.9130\n", | |
| "Epoch 29/32\n", | |
| "8/8 [==============================] - 3s 334ms/step - loss: 0.0994 - accuracy: 0.9814 - val_loss: 0.2219 - val_accuracy: 0.9179\n", | |
| "Epoch 30/32\n", | |
| "8/8 [==============================] - 3s 337ms/step - loss: 0.0958 - accuracy: 0.9855 - val_loss: 0.2293 - val_accuracy: 0.9082\n", | |
| "Epoch 31/32\n", | |
| "8/8 [==============================] - 3s 389ms/step - loss: 0.0924 - accuracy: 0.9855 - val_loss: 0.2293 - val_accuracy: 0.9082\n", | |
| "Epoch 32/32\n", | |
| "8/8 [==============================] - 3s 380ms/step - loss: 0.0892 - accuracy: 0.9917 - val_loss: 0.2268 - val_accuracy: 0.9082\n", | |
| "Elapsed time: 0:1:34.9\n", | |
| "Chunk 3:\n", | |
| "\t x shape: (690, 340, 340, 3), y shape: (690, 1)\n", | |
| "\t Split the chunk into:\n", | |
| "\t\t Number of training examples: 483\n", | |
| "\t\t Number of test examples: 207\n", | |
| "\t\t x_train shape: (483, 340, 340, 3)\n", | |
| "\t\t y_train shape: (483, 1)\n", | |
| ">>> Traning on chanck 3 starts\n", | |
| "Epoch 1/32\n", | |
| "8/8 [==============================] - 4s 539ms/step - loss: 0.2012 - accuracy: 0.9358 - val_loss: 0.2799 - val_accuracy: 0.8647\n", | |
| "Epoch 2/32\n", | |
| "8/8 [==============================] - 3s 350ms/step - loss: 0.1937 - accuracy: 0.9317 - val_loss: 0.3281 - val_accuracy: 0.8502\n", | |
| "Epoch 3/32\n", | |
| "8/8 [==============================] - 3s 378ms/step - loss: 0.1820 - accuracy: 0.9420 - val_loss: 0.2526 - val_accuracy: 0.8841\n", | |
| "Epoch 4/32\n", | |
| "8/8 [==============================] - 3s 402ms/step - loss: 0.1831 - accuracy: 0.9358 - val_loss: 0.2067 - val_accuracy: 0.8986\n", | |
| "Epoch 5/32\n", | |
| "8/8 [==============================] - 3s 359ms/step - loss: 0.1663 - accuracy: 0.9420 - val_loss: 0.2240 - val_accuracy: 0.8889\n", | |
| "Epoch 6/32\n", | |
| "8/8 [==============================] - 3s 337ms/step - loss: 0.1481 - accuracy: 0.9462 - val_loss: 0.2317 - val_accuracy: 0.8889\n", | |
| "Epoch 7/32\n", | |
| "8/8 [==============================] - 3s 389ms/step - loss: 0.1443 - accuracy: 0.9482 - val_loss: 0.2067 - val_accuracy: 0.9034\n", | |
| "Epoch 8/32\n", | |
| "8/8 [==============================] - 3s 337ms/step - loss: 0.1378 - accuracy: 0.9565 - val_loss: 0.2022 - val_accuracy: 0.9034\n", | |
| "Epoch 9/32\n", | |
| "8/8 [==============================] - 3s 441ms/step - loss: 0.1357 - accuracy: 0.9545 - val_loss: 0.2358 - val_accuracy: 0.8889\n", | |
| "Epoch 10/32\n", | |
| "8/8 [==============================] - 3s 343ms/step - loss: 0.1334 - accuracy: 0.9607 - val_loss: 0.1946 - val_accuracy: 0.9082\n", | |
| "Epoch 11/32\n", | |
| "8/8 [==============================] - 3s 379ms/step - loss: 0.1258 - accuracy: 0.9648 - val_loss: 0.2211 - val_accuracy: 0.8986\n", | |
| "Epoch 12/32\n", | |
| "8/8 [==============================] - 3s 382ms/step - loss: 0.1253 - accuracy: 0.9648 - val_loss: 0.1934 - val_accuracy: 0.9082\n", | |
| "Epoch 13/32\n", | |
| "8/8 [==============================] - 3s 404ms/step - loss: 0.1214 - accuracy: 0.9689 - val_loss: 0.2156 - val_accuracy: 0.8937\n", | |
| "Epoch 14/32\n", | |
| "8/8 [==============================] - 3s 383ms/step - loss: 0.1217 - accuracy: 0.9689 - val_loss: 0.1985 - val_accuracy: 0.9227\n", | |
| "Epoch 15/32\n", | |
| "8/8 [==============================] - 3s 335ms/step - loss: 0.1166 - accuracy: 0.9627 - val_loss: 0.2016 - val_accuracy: 0.9082\n", | |
| "Epoch 16/32\n", | |
| "8/8 [==============================] - 3s 384ms/step - loss: 0.1143 - accuracy: 0.9648 - val_loss: 0.1908 - val_accuracy: 0.9082\n", | |
| "Epoch 17/32\n", | |
| "8/8 [==============================] - 3s 374ms/step - loss: 0.1118 - accuracy: 0.9710 - val_loss: 0.2297 - val_accuracy: 0.8986\n", | |
| "Epoch 18/32\n", | |
| "8/8 [==============================] - 3s 435ms/step - loss: 0.1089 - accuracy: 0.9710 - val_loss: 0.1917 - val_accuracy: 0.9179\n", | |
| "Epoch 19/32\n", | |
| "8/8 [==============================] - 3s 341ms/step - loss: 0.1070 - accuracy: 0.9710 - val_loss: 0.1869 - val_accuracy: 0.9227\n", | |
| "Epoch 20/32\n", | |
| "8/8 [==============================] - 3s 375ms/step - loss: 0.1050 - accuracy: 0.9772 - val_loss: 0.1917 - val_accuracy: 0.9034\n", | |
| "Epoch 21/32\n", | |
| "8/8 [==============================] - 3s 343ms/step - loss: 0.1005 - accuracy: 0.9752 - val_loss: 0.1856 - val_accuracy: 0.9227\n", | |
| "Epoch 22/32\n", | |
| "8/8 [==============================] - 3s 404ms/step - loss: 0.1023 - accuracy: 0.9752 - val_loss: 0.1940 - val_accuracy: 0.9034\n", | |
| "Epoch 23/32\n", | |
| "8/8 [==============================] - 3s 339ms/step - loss: 0.1010 - accuracy: 0.9772 - val_loss: 0.1895 - val_accuracy: 0.9179\n", | |
| "Epoch 24/32\n", | |
| "8/8 [==============================] - 3s 336ms/step - loss: 0.0964 - accuracy: 0.9814 - val_loss: 0.1911 - val_accuracy: 0.9082\n", | |
| "Epoch 25/32\n", | |
| "8/8 [==============================] - 3s 379ms/step - loss: 0.0950 - accuracy: 0.9793 - val_loss: 0.1871 - val_accuracy: 0.9179\n", | |
| "Epoch 26/32\n", | |
| "8/8 [==============================] - 3s 464ms/step - loss: 0.0951 - accuracy: 0.9731 - val_loss: 0.1976 - val_accuracy: 0.9275\n", | |
| "Epoch 27/32\n", | |
| "8/8 [==============================] - 3s 339ms/step - loss: 0.0986 - accuracy: 0.9793 - val_loss: 0.2276 - val_accuracy: 0.8986\n", | |
| "Epoch 28/32\n", | |
| "8/8 [==============================] - 3s 389ms/step - loss: 0.1037 - accuracy: 0.9731 - val_loss: 0.2220 - val_accuracy: 0.9227\n", | |
| "Epoch 29/32\n", | |
| "8/8 [==============================] - 3s 377ms/step - loss: 0.0930 - accuracy: 0.9814 - val_loss: 0.2189 - val_accuracy: 0.8986\n", | |
| "Epoch 30/32\n", | |
| "8/8 [==============================] - 3s 420ms/step - loss: 0.0878 - accuracy: 0.9793 - val_loss: 0.1906 - val_accuracy: 0.9179\n", | |
| "Epoch 31/32\n", | |
| "8/8 [==============================] - 3s 335ms/step - loss: 0.0849 - accuracy: 0.9834 - val_loss: 0.1869 - val_accuracy: 0.9179\n", | |
| "Epoch 32/32\n", | |
| "8/8 [==============================] - 3s 375ms/step - loss: 0.0840 - accuracy: 0.9834 - val_loss: 0.1871 - val_accuracy: 0.9179\n", | |
| "Elapsed time: 0:1:34.0\n", | |
| "Chunk 4:\n", | |
| "\t x shape: (240, 340, 340, 3), y shape: (240, 1)\n", | |
| "\t Split the chunk into:\n", | |
| "\t\t Number of training examples: 168\n", | |
| "\t\t Number of test examples: 72\n", | |
| "\t\t x_train shape: (168, 340, 340, 3)\n", | |
| "\t\t y_train shape: (168, 1)\n", | |
| ">>> Traning on chanck 4 starts\n", | |
| "Epoch 1/32\n", | |
| "3/3 [==============================] - 2s 767ms/step - loss: 0.2609 - accuracy: 0.9048 - val_loss: 0.1913 - val_accuracy: 0.9444\n", | |
| "Epoch 2/32\n", | |
| "3/3 [==============================] - 2s 1s/step - loss: 0.2443 - accuracy: 0.9107 - val_loss: 0.1933 - val_accuracy: 0.9444\n", | |
| "Epoch 3/32\n", | |
| "3/3 [==============================] - 1s 586ms/step - loss: 0.2267 - accuracy: 0.9107 - val_loss: 0.2158 - val_accuracy: 0.9167\n", | |
| "Epoch 4/32\n", | |
| "3/3 [==============================] - 2s 673ms/step - loss: 0.2056 - accuracy: 0.9226 - val_loss: 0.3258 - val_accuracy: 0.8333\n", | |
| "Epoch 5/32\n", | |
| "3/3 [==============================] - 1s 599ms/step - loss: 0.2135 - accuracy: 0.9286 - val_loss: 0.2757 - val_accuracy: 0.8750\n", | |
| "Epoch 6/32\n", | |
| "3/3 [==============================] - 1s 604ms/step - loss: 0.1832 - accuracy: 0.9345 - val_loss: 0.3566 - val_accuracy: 0.8472\n", | |
| "Epoch 7/32\n", | |
| "3/3 [==============================] - 1s 610ms/step - loss: 0.1712 - accuracy: 0.9464 - val_loss: 0.3427 - val_accuracy: 0.8333\n", | |
| "Epoch 8/32\n", | |
| "3/3 [==============================] - 1s 603ms/step - loss: 0.1655 - accuracy: 0.9524 - val_loss: 0.3555 - val_accuracy: 0.8333\n", | |
| "Epoch 9/32\n", | |
| "3/3 [==============================] - 1s 645ms/step - loss: 0.1512 - accuracy: 0.9524 - val_loss: 0.3796 - val_accuracy: 0.8333\n", | |
| "Epoch 10/32\n", | |
| "3/3 [==============================] - 2s 932ms/step - loss: 0.1504 - accuracy: 0.9464 - val_loss: 0.3574 - val_accuracy: 0.8472\n", | |
| "Epoch 11/32\n", | |
| "3/3 [==============================] - 1s 592ms/step - loss: 0.1301 - accuracy: 0.9643 - val_loss: 0.3312 - val_accuracy: 0.8750\n", | |
| "Epoch 12/32\n", | |
| "3/3 [==============================] - 1s 599ms/step - loss: 0.1302 - accuracy: 0.9702 - val_loss: 0.2809 - val_accuracy: 0.9028\n", | |
| "Epoch 13/32\n", | |
| "3/3 [==============================] - 1s 607ms/step - loss: 0.1212 - accuracy: 0.9643 - val_loss: 0.2625 - val_accuracy: 0.9028\n", | |
| "Epoch 14/32\n", | |
| "3/3 [==============================] - 1s 593ms/step - loss: 0.1163 - accuracy: 0.9702 - val_loss: 0.2901 - val_accuracy: 0.8889\n", | |
| "Epoch 15/32\n", | |
| "3/3 [==============================] - 1s 589ms/step - loss: 0.1139 - accuracy: 0.9762 - val_loss: 0.3028 - val_accuracy: 0.8889\n", | |
| "Epoch 16/32\n", | |
| "3/3 [==============================] - 1s 592ms/step - loss: 0.1068 - accuracy: 0.9821 - val_loss: 0.2918 - val_accuracy: 0.8889\n", | |
| "Epoch 17/32\n", | |
| "3/3 [==============================] - 1s 630ms/step - loss: 0.1037 - accuracy: 0.9881 - val_loss: 0.2845 - val_accuracy: 0.8889\n", | |
| "Epoch 18/32\n", | |
| "3/3 [==============================] - 2s 968ms/step - loss: 0.0992 - accuracy: 0.9881 - val_loss: 0.2837 - val_accuracy: 0.8889\n", | |
| "Epoch 19/32\n", | |
| "3/3 [==============================] - 1s 600ms/step - loss: 0.0967 - accuracy: 0.9881 - val_loss: 0.2895 - val_accuracy: 0.8889\n", | |
| "Epoch 20/32\n", | |
| "3/3 [==============================] - 2s 666ms/step - loss: 0.0940 - accuracy: 0.9881 - val_loss: 0.2960 - val_accuracy: 0.9028\n", | |
| "Epoch 21/32\n", | |
| "3/3 [==============================] - 1s 595ms/step - loss: 0.0898 - accuracy: 0.9940 - val_loss: 0.2794 - val_accuracy: 0.8889\n", | |
| "Epoch 22/32\n", | |
| "3/3 [==============================] - 2s 680ms/step - loss: 0.0886 - accuracy: 1.0000 - val_loss: 0.2745 - val_accuracy: 0.9028\n", | |
| "Epoch 23/32\n", | |
| "3/3 [==============================] - 1s 611ms/step - loss: 0.0859 - accuracy: 1.0000 - val_loss: 0.2786 - val_accuracy: 0.9028\n", | |
| "Epoch 24/32\n", | |
| "3/3 [==============================] - 1s 598ms/step - loss: 0.0819 - accuracy: 1.0000 - val_loss: 0.2826 - val_accuracy: 0.9028\n", | |
| "Epoch 25/32\n", | |
| "3/3 [==============================] - 2s 757ms/step - loss: 0.0835 - accuracy: 1.0000 - val_loss: 0.2653 - val_accuracy: 0.9028\n", | |
| "Epoch 26/32\n", | |
| "3/3 [==============================] - 2s 829ms/step - loss: 0.0812 - accuracy: 1.0000 - val_loss: 0.2694 - val_accuracy: 0.9028\n", | |
| "Epoch 27/32\n", | |
| "3/3 [==============================] - 1s 605ms/step - loss: 0.0793 - accuracy: 1.0000 - val_loss: 0.2910 - val_accuracy: 0.9028\n", | |
| "Epoch 28/32\n", | |
| "3/3 [==============================] - 1s 600ms/step - loss: 0.0779 - accuracy: 1.0000 - val_loss: 0.2616 - val_accuracy: 0.9028\n", | |
| "Epoch 29/32\n", | |
| "3/3 [==============================] - 1s 638ms/step - loss: 0.0762 - accuracy: 1.0000 - val_loss: 0.2562 - val_accuracy: 0.9028\n", | |
| "Epoch 30/32\n", | |
| "3/3 [==============================] - 1s 595ms/step - loss: 0.0710 - accuracy: 1.0000 - val_loss: 0.2613 - val_accuracy: 0.9028\n", | |
| "Epoch 31/32\n", | |
| "3/3 [==============================] - 1s 595ms/step - loss: 0.0727 - accuracy: 1.0000 - val_loss: 0.2826 - val_accuracy: 0.9028\n", | |
| "Epoch 32/32\n", | |
| "3/3 [==============================] - 1s 593ms/step - loss: 0.0724 - accuracy: 1.0000 - val_loss: 0.2673 - val_accuracy: 0.9028\n", | |
| "Elapsed time: 0:0:49.9\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "#@title Traning\n", | |
| "\n", | |
| "from sklearn.model_selection import train_test_split\n", | |
| "from sklearn.metrics import f1_score\n", | |
| "\n", | |
| "EPOCHS = 32 #@param {type:\"number\"}\n", | |
| "#@markdown Try powers of 2 (16, 32, 64, 128, etc.) to find the optimal balance for your specific problem and hardware.\n", | |
| "BATCH_SIZE = 64 #@param{type:\"number\"}\n", | |
| "\n", | |
| "# Nicely formatted time string\n", | |
| "def hms_string(sec_elapsed):\n", | |
| " h = int(sec_elapsed / (60 * 60))\n", | |
| " m = int((sec_elapsed % (60 * 60)) / 60)\n", | |
| " s = sec_elapsed % 60\n", | |
| " return f\"{h}:{m}:{round(s,1)}\"\n", | |
| "\n", | |
| "def split_data(X, y, test_size=0.2):\n", | |
| " \"\"\"\n", | |
| " Splits data into training, development and test sets.\n", | |
| " Arguments:\n", | |
| " X: A numpy array with shape = (#_examples, image_width, image_height, #_channels)\n", | |
| " y: A numpy array with shape = (#_examples, 1)\n", | |
| " Returns:\n", | |
| " X_train: A numpy array with shape = (#_train_examples, image_width, image_height, #_channels)\n", | |
| " y_train: A numpy array with shape = (#_train_examples, 1)\n", | |
| " X_test: A numpy array with shape = (#_test_examples, image_width, image_height, #_channels)\n", | |
| " y_test: A numpy array with shape = (#_test_examples, 1)\n", | |
| " \"\"\"\n", | |
| "\n", | |
| " x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=test_size)\n", | |
| "\n", | |
| " return x_train, y_train, x_test, y_test\n", | |
| "\n", | |
| "def compute_f1_score(y_true, prob):\n", | |
| " # convert the vector of probabilities to a target vector\n", | |
| " y_pred = np.where(prob > 0.5, 1, 0)\n", | |
| "\n", | |
| " score = f1_score(y_true, y_pred)\n", | |
| "\n", | |
| " return score\n", | |
| "\n", | |
| "for i, images_list in enumerate(SAMPLES):\n", | |
| " print(f\"Chunk {i}:\")\n", | |
| " x, y = load_data(images_list)\n", | |
| " print(f\"\\t x shape: {x.shape}, y shape: {y.shape}\")\n", | |
| " print(f\"\\t Split the chunk into:\")\n", | |
| " x_train, y_train, x_test, y_test = split_data(x,y, TESTING_PERSENTAGE)\n", | |
| " print(f\"\\t\\t Number of training examples: {x_train.shape[0]}\")\n", | |
| " print(f\"\\t\\t Number of test examples: {x_test.shape[0]}\")\n", | |
| " print(f\"\\t\\t x_train shape: {x_train.shape}\")\n", | |
| " print(f\"\\t\\t y_train shape: {y_train.shape}\")\n", | |
| " print(f\">>> Traning on chanck {i} starts\")\n", | |
| " start_time = time.time()\n", | |
| " model.fit(x=x_train, y=y_train, batch_size=BATCH_SIZE, epochs=EPOCHS, validation_data=(x_test, y_test), callbacks=[tensorboard, checkpoint])\n", | |
| " end_time = time.time()\n", | |
| " execution_time = (end_time - start_time)\n", | |
| " print(f\"Elapsed time: {hms_string(execution_time)}\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "id": "ZYU_rj2iUOjD" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "history = model.history.history" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "ntq8L7U-UOjE" | |
| }, | |
| "source": [ | |
| "## Plot Loss & Accuracy" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "id": "ebAV78QAUOjE" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def plot_metrics(history):\n", | |
| "\n", | |
| " train_loss = history['loss']\n", | |
| " val_loss = history['val_loss']\n", | |
| " train_acc = history['accuracy']\n", | |
| " val_acc = history['val_accuracy']\n", | |
| "\n", | |
| " # Loss\n", | |
| " plt.figure()\n", | |
| " plt.plot(train_loss, label='Training Loss')\n", | |
| " plt.plot(val_loss, label='Validation Loss')\n", | |
| " plt.title('Loss')\n", | |
| " plt.legend()\n", | |
| " plt.show()\n", | |
| "\n", | |
| " # Accuracy\n", | |
| " plt.figure()\n", | |
| " plt.plot(train_acc, label='Training Accuracy')\n", | |
| " plt.plot(val_acc, label='Validation Accuracy')\n", | |
| " plt.title('Accuracy')\n", | |
| " plt.legend()\n", | |
| " plt.show()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "vNvD-K04UOjE" | |
| }, | |
| "source": [ | |
| "**Note:** Since we trained the model using more than model.fit() function call, this made the history only contain the metric values of the epochs for the last call (which was for 5 epochs), so to plot the metric values across the whole process of trianing the model from the beginning, I had to grab the rest of the values." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 887 | |
| }, | |
| "id": "aSRkK6lJUOjF", | |
| "outputId": "42307036-36d9-4b35-cd55-c1ad0a8301ce" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": [ | |
| "<Figure size 640x480 with 1 Axes>" | |
| ], | |
| "image/png": "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r2EYhvHyyy8b4eHhxjfffGOsX7/eGDJkiNGkSRPj+PHjbo68+pzrPcrJyTHGjx9vLFu2zNi9e7cxb948o2vXrkaLFi2MgoICd4deLcaMGWOEhYUZCxcuNFJTUx23/Px8xzn33HOP0ahRI+Pnn382Vq1aZfTq1cvo1auXG6OuXud7j3bu3Gk8//zzxqpVq4zdu3cb33zzjdG0aVOjb9++bo68+jzxxBPGokWLjN27dxvr1683nnjiCcNisRhz5swxDKPmfoaUsJzHW2+9ZTRq1Mjw9fU1evbsafz222/uDskjjBgxwoiLizN8fX2NBg0aGCNGjDB27tzp7rDcasGCBQZw2m3UqFGGYZhLm59++mkjJibG8PPzMwYMGGBs27bNvUFXs3O9R/n5+cZll11mREdHGz4+Pkbjxo2Nu+66q079gXCm9wYw3nvvPcc5x48fN+69914jIiLCCAwMNIYNG2akpqa6L+hqdr73KCUlxejbt69Rr149w8/Pz2jevLnx6KOPGllZWe4NvBrdfvvtRuPGjQ1fX18jOjraGDBggCNZMYya+xmyGIZhVF9/joiIiIjzNIdFREREPJ4SFhEREfF4SlhERETE4ylhEREREY+nhEVEREQ8nhIWERER8XhKWERERMTjKWERERERj6eERURERDyeEhYRERHxeEpYRERExOP9P+HAJoSiXsAlAAAAAElFTkSuQmCC\n" | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": [ | |
| "<Figure size 640x480 with 1 Axes>" | |
| ], | |
| "image/png": "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\n" | |
| }, | |
| "metadata": {} | |
| } | |
| ], | |
| "source": [ | |
| "#display(history)\n", | |
| "plot_metrics(history)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "g2b7pfmPUOjF" | |
| }, | |
| "source": [ | |
| "# Results" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "C90aBSydUOjF" | |
| }, | |
| "source": [ | |
| "Let's experiment with the best model (the one with the best validation accuracy):" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "#@title Evaluaton\n", | |
| "#@markdown The avilable datasets are:\n", | |
| "#@markdown * [k1](https://www.kaggle.com/datasets/navoneel/brain-mri-images-for-brain-tumor-detection) - 253 samples.\n", | |
| "EVALUATION_DATASET = \"k1\" #@param [\"k1\", \"br35h\"] {allow-input: true}\n", | |
| "\n", | |
| "SAMPLES = []\n", | |
| "\n", | |
| "match EVALUATION_DATASET:\n", | |
| " case \"k1\":\n", | |
| " DIR = \"eval_data\"\n", | |
| " download_kaggle_ds(DIR, \"navoneel/brain-mri-images-for-brain-tumor-detection\")\n", | |
| " rmtree(f\"{DIR}/brain_tumor_dataset\")\n", | |
| " SAMPLES.extend([(path, 0) for path in copy_samples(f\"{DIR}/no\")])\n", | |
| " SAMPLES.extend([(path, 1) for path in copy_samples(f\"{DIR}/yes\")])\n", | |
| "\n", | |
| " case \"br35h\":\n", | |
| " n, y = br35h()\n", | |
| " SAMPLES.extend([(path, 0) for path in n])\n", | |
| " SAMPLES.extend([(path, 1) for path in y])\n", | |
| "\n", | |
| " case _:\n", | |
| " raise ValueError(\"The choosen database dosn't exist\")\n", | |
| "\n", | |
| "print(f\"Number of evaluation samples {len(SAMPLES)}\")\n", | |
| "\n", | |
| "SAMPLES = chunk_list(SAMPLES, 1000)\n", | |
| "\n", | |
| "random.shuffle(SAMPLES)" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "D4OhgeWm6bhv", | |
| "outputId": "64bae883-f162-46ad-9c33-33bb79c3ebc9" | |
| }, | |
| "execution_count": null, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "brain-mri-images-for-brain-tumor-detection.zip\n", | |
| "Number of evaluation samples 247\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "j9R1GF4sUOjF" | |
| }, | |
| "source": [ | |
| "### Load the best model" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "id": "EuTn5DHPUOjG" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "best_model = load_model(filepath=f\"models/cnn-parameters-improvement-{EPOCHS}.model\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "1o61vBwoUOjG", | |
| "outputId": "7ab790b7-d3aa-45c0-aaa3-7cdc08c595a6" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "['loss', 'accuracy']" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "execution_count": 13 | |
| } | |
| ], | |
| "source": [ | |
| "best_model.metrics_names" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "qFAW97luUOjH" | |
| }, | |
| "source": [ | |
| "Evaluate the best model on the testing data:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "scrolled": true, | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "A7RqtJN3UOjH", | |
| "outputId": "947e783a-ef78-4dc5-a645-e83c8fda11fd" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "x_eval shape: (247, 340, 340, 3)\n", | |
| "y_eval shape: (247, 1)\n", | |
| "8/8 [==============================] - 1s 94ms/step - loss: 0.2041 - accuracy: 0.9231\n", | |
| "Evaluation Loss = 0.20405875146389008\n", | |
| "Evaluation Accuracy = 0.9230769276618958\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "total_loss = 0.0\n", | |
| "total_acc = 0.0\n", | |
| "for samples in SAMPLES:\n", | |
| " x_eval, y_eval = load_data(samples)\n", | |
| " print(f\"x_eval shape: {x_eval.shape}\")\n", | |
| " print(f\"y_eval shape: {y_eval.shape}\")\n", | |
| " loss, acc = best_model.evaluate(x=x_eval, y=y_eval)\n", | |
| " total_loss += loss\n", | |
| " total_acc += acc\n", | |
| "\n", | |
| "print (f\"Evaluation Loss = {total_loss}\")\n", | |
| "print (f\"Evaluation Accuracy = {total_acc}\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "EFUtjVJfUOjH" | |
| }, | |
| "source": [ | |
| "### F1 score for the best model on the testing data:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "o2fGb4bEUOjI", | |
| "outputId": "b1c8badc-6dbb-4b2c-c555-93bd5ee9535e" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "8/8 [==============================] - 0s 44ms/step\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "y_eval_prop = best_model.predict(x_eval)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "NM7e4qX-UOjI", | |
| "outputId": "a43cf815-1eb5-4ba9-e00e-374580d0062b" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "F1 score: 0.9396825396825398\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "f1score = compute_f1_score(y_eval, y_eval_prop)\n", | |
| "print(f\"F1 score: {f1score}\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "RPiKJRIdUOjJ" | |
| }, | |
| "source": [ | |
| "### Results Interpretation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "wEzVvX7pUOjJ" | |
| }, | |
| "source": [ | |
| "Let's remember the percentage of positive and negative examples:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "id": "LGir7mGXUOjJ" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def data_percentage(y):\n", | |
| "\n", | |
| " m=len(y)\n", | |
| " n_positive = np.sum(y)\n", | |
| " n_negative = m - n_positive\n", | |
| "\n", | |
| " pos_prec = (n_positive* 100.0)/ m\n", | |
| " neg_prec = (n_negative* 100.0)/ m\n", | |
| "\n", | |
| " print(f\"Number of examples: {m}\")\n", | |
| " print(f\"Percentage of positive examples: {pos_prec}%, number of pos examples: {n_positive}\")\n", | |
| " print(f\"Percentage of negative examples: {neg_prec}%, number of neg examples: {n_negative}\")\n", | |
| "\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "FtU62eOGUOjJ", | |
| "outputId": "0b9f1e5c-dd49-473e-f43f-a9e6f93e8afb" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Number of examples: 465\n", | |
| "Percentage of positive examples: 48.81720430107527%, number of pos examples: 227\n", | |
| "Percentage of negative examples: 51.18279569892473%, number of neg examples: 238\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# the whole data\n", | |
| "data_percentage(y)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "rQzWPj95UOjJ", | |
| "outputId": "d796f732-2d83-4db0-fa51-2d08db4f6b40" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Training Data:\n", | |
| "Number of examples: 420\n", | |
| "Percentage of positive examples: 51.42857142857143%, number of pos examples: 216\n", | |
| "Percentage of negative examples: 48.57142857142857%, number of neg examples: 204\n", | |
| "Validation Data:\n", | |
| "Number of examples: 90\n", | |
| "Percentage of positive examples: 50.0%, number of pos examples: 45\n", | |
| "Percentage of negative examples: 50.0%, number of neg examples: 45\n", | |
| "Testing Data:\n", | |
| "Number of examples: 90\n", | |
| "Percentage of positive examples: 43.333333333333336%, number of pos examples: 39\n", | |
| "Percentage of negative examples: 56.666666666666664%, number of neg examples: 51\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "print(\"Training Data:\")\n", | |
| "data_percentage(y_train)\n", | |
| "print(\"Validation Data:\")\n", | |
| "data_percentage(y_val)\n", | |
| "print(\"Testing Data:\")\n", | |
| "data_percentage(y_test)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "X4_bDuUpUOjK" | |
| }, | |
| "source": [ | |
| "As expectred, the percentage of positive examples are around 50%." | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "name": "python3" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.6.7" | |
| }, | |
| "colab": { | |
| "provenance": [], | |
| "gpuType": "T4", | |
| "include_colab_link": true | |
| }, | |
| "accelerator": "GPU" | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 0 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment