diff --git a/sw_lab9-10_1.ipynb b/sw_lab9-10_1.ipynb new file mode 100644 index 0000000..aed12e3 --- /dev/null +++ b/sw_lab9-10_1.ipynb @@ -0,0 +1,1185 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Aleksandra Jonas, Aleksandra Gronowska, Iwona Christop\n", + "# Zadanie 9-10 - VGG16 + ResNet on train_test_sw " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Przygotowanie danych" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import Image, display" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "2fe63b50", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "import subprocess\n", + "import pkg_resources\n", + "import numpy as np\n", + "\n", + "required = { 'scikit-image'}\n", + "installed = {pkg.key for pkg in pkg_resources.working_set}\n", + "missing = required - installed\n", + "# VGG16 requires images to be of dim = (224, 224, 3)\n", + "newSize = (224,224)\n", + "\n", + "if missing: \n", + " python = sys.executable\n", + " subprocess.check_call([python, '-m', 'pip', 'install', *missing], stdout=subprocess.DEVNULL)\n", + "\n", + "def load_train_data(input_dir):\n", + " import numpy as np\n", + " import pandas as pd\n", + " import os\n", + " from skimage.io import imread\n", + " import cv2 as cv\n", + " from pathlib import Path\n", + " import random\n", + " from shutil import copyfile, rmtree\n", + " import json\n", + "\n", + " import seaborn as sns\n", + " import matplotlib.pyplot as plt\n", + "\n", + " import matplotlib\n", + " \n", + " image_dir = Path(input_dir)\n", + " categories_name = []\n", + " for file in os.listdir(image_dir):\n", + " d = os.path.join(image_dir, file)\n", + " if os.path.isdir(d):\n", + " categories_name.append(file)\n", + "\n", + " folders = [directory for directory in image_dir.iterdir() if directory.is_dir()]\n", + "\n", + " train_img = []\n", + " categories_count=[]\n", + " labels=[]\n", + " for i, direc in enumerate(folders):\n", + " count = 0\n", + " for obj in direc.iterdir():\n", + " if os.path.isfile(obj) and os.path.basename(os.path.normpath(obj)) != 'desktop.ini':\n", + " labels.append(os.path.basename(os.path.normpath(direc)))\n", + " count += 1\n", + " img = imread(obj)#zwraca ndarry postaci xSize x ySize x colorDepth\n", + " img = img[:, :, :3]\n", + " img = cv.resize(img, newSize, interpolation=cv.INTER_AREA)# zwraca ndarray\n", + " img = img / 255 #normalizacja\n", + " train_img.append(img)\n", + " categories_count.append(count)\n", + " X={}\n", + " X[\"values\"] = np.array(train_img)\n", + " X[\"categories_name\"] = categories_name\n", + " X[\"categories_count\"] = categories_count\n", + " X[\"labels\"]=labels\n", + " return X\n", + "\n", + "def load_test_data(input_dir):\n", + " import numpy as np\n", + " import pandas as pd\n", + " import os\n", + " from skimage.io import imread\n", + " import cv2 as cv\n", + " from pathlib import Path\n", + " import random\n", + " from shutil import copyfile, rmtree\n", + " import json\n", + "\n", + " import seaborn as sns\n", + " import matplotlib.pyplot as plt\n", + "\n", + " import matplotlib\n", + "\n", + " image_path = Path(input_dir)\n", + "\n", + " labels_path = image_path.parents[0] / 'test_labels.json'\n", + "\n", + " jsonString = labels_path.read_text()\n", + " objects = json.loads(jsonString)\n", + "\n", + " categories_name = []\n", + " categories_count=[]\n", + " count = 0\n", + " c = objects[0]['value']\n", + " for e in objects:\n", + " if e['value'] != c:\n", + " categories_count.append(count)\n", + " c = e['value']\n", + " count = 1\n", + " else:\n", + " count += 1\n", + " if not e['value'] in categories_name:\n", + " categories_name.append(e['value'])\n", + "\n", + " categories_count.append(count)\n", + " \n", + " test_img = []\n", + "\n", + " labels=[]\n", + " for e in objects:\n", + " p = image_path / e['filename']\n", + " img = imread(p)#zwraca ndarry postaci xSize x ySize x colorDepth\n", + " img = img[:, :, :3]\n", + " img = cv.resize(img, newSize, interpolation=cv.INTER_AREA)# zwraca ndarray\n", + " img = img / 255#normalizacja\n", + " test_img.append(img)\n", + " labels.append(e['value'])\n", + "\n", + " X={}\n", + " X[\"values\"] = np.array(test_img)\n", + " X[\"categories_name\"] = categories_name\n", + " X[\"categories_count\"] = categories_count\n", + " X[\"labels\"]=labels\n", + " return X" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def create_tf_ds(X_train, y_train_enc, X_validate, y_validate_enc, X_test, y_test_enc):\n", + " import tensorflow as tf\n", + " \n", + " train_ds = tf.data.Dataset.from_tensor_slices((X_train, y_train_enc))\n", + " validation_ds = tf.data.Dataset.from_tensor_slices((X_validate, y_validate_enc))\n", + " test_ds = tf.data.Dataset.from_tensor_slices((X_test, y_test_enc))\n", + "\n", + " train_ds_size = tf.data.experimental.cardinality(train_ds).numpy()\n", + " test_ds_size = tf.data.experimental.cardinality(test_ds).numpy()\n", + " validation_ds_size = tf.data.experimental.cardinality(validation_ds).numpy()\n", + "\n", + " print(\"Training data size:\", train_ds_size)\n", + " print(\"Test data size:\", test_ds_size)\n", + " print(\"Validation data size:\", validation_ds_size)\n", + "\n", + " train_ds = (train_ds\n", + " .shuffle(buffer_size=train_ds_size)\n", + " .batch(batch_size=32, drop_remainder=True))\n", + " test_ds = (test_ds\n", + " .shuffle(buffer_size=train_ds_size)\n", + " .batch(batch_size=32, drop_remainder=True))\n", + " validation_ds = (validation_ds\n", + " .shuffle(buffer_size=train_ds_size)\n", + " .batch(batch_size=32, drop_remainder=True))\n", + " \n", + " return train_ds, test_ds, validation_ds" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "def get_run_logdir(root_logdir):\n", + " import os\n", + " import time\n", + "\n", + " run_id = time.strftime(\"run_%Y_%m_%d-%H_%M_%S\")\n", + " return os.path.join(root_logdir, run_id)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "def diagram_setup(model_name):\n", + " from tensorflow import keras\n", + " import os\n", + " \n", + " root_logdir = os.path.join(os.curdir, f\"logs\\\\fit\\\\{model_name}\\\\\")\n", + " \n", + " run_logdir = get_run_logdir(root_logdir)\n", + " tensorboard_cb = keras.callbacks.TensorBoard(run_logdir)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "cc941c5a", + "metadata": {}, + "outputs": [], + "source": [ + "# Data load\n", + "data_train = load_train_data(\"./train_test_sw/train_sw\")\n", + "values_train = data_train['values']\n", + "labels_train = data_train['labels']\n", + "\n", + "data_test = load_test_data(\"./train_test_sw/test_sw\")\n", + "X_test = data_test['values']\n", + "y_test = data_test['labels']" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "25040ac9", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "X_train, X_validate, y_train, y_validate = train_test_split(values_train, labels_train, test_size=0.2, random_state=42)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "a1fe47e6", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.preprocessing import LabelEncoder\n", + "class_le = LabelEncoder()\n", + "y_train_enc = class_le.fit_transform(y_train)\n", + "y_validate_enc = class_le.fit_transform(y_validate)\n", + "y_test_enc = class_le.fit_transform(y_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training data size: 820\n", + "Test data size: 259\n", + "Validation data size: 206\n" + ] + } + ], + "source": [ + "train_ds, test_ds, validation_ds = create_tf_ds(X_train, y_train_enc, X_validate, y_validate_enc, X_test, y_test_enc)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## VGG16" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "diagram_setup('vgg_sw')" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "import keras,os\n", + "from keras.models import Sequential\n", + "from keras.layers import Dense, Conv2D, MaxPool2D , Flatten\n", + "from keras.preprocessing.image import ImageDataGenerator\n", + "import numpy as np\n", + "\n", + "model = keras.models.Sequential([\n", + " keras.layers.Conv2D(filters=64, kernel_size=(3,3), activation='relu', input_shape=(224,224,3), padding=\"same\"),\n", + " keras.layers.Conv2D(filters=64, kernel_size=(3,3), activation='relu', input_shape=(224,224,3), padding=\"same\"),\n", + " keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2)),\n", + " keras.layers.Conv2D(filters=128, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.Conv2D(filters=128, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2)),\n", + " keras.layers.Conv2D(filters=256, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.Conv2D(filters=256, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.Conv2D(filters=256, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2)),\n", + " keras.layers.Conv2D(filters=512, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.Conv2D(filters=512, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.Conv2D(filters=512, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2)),\n", + " keras.layers.Conv2D(filters=512, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.Conv2D(filters=512, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.Conv2D(filters=512, kernel_size=(3,3), padding=\"same\", activation=\"relu\"),\n", + " keras.layers.Flatten(),\n", + " keras.layers.Dense(units = 4096, activation='relu'),\n", + " keras.layers.Dense(units = 4096, activation='relu'),\n", + " keras.layers.Dense(units = 5, activation='softmax')\n", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/jonas/Library/Python/3.9/lib/python/site-packages/keras/optimizers/optimizer_v2/adam.py:117: UserWarning: The `lr` argument is deprecated, use `learning_rate` instead.\n", + " super().__init__(name, **kwargs)\n" + ] + } + ], + "source": [ + "from keras.optimizers import Adam\n", + "opt = Adam(lr=0.001)\n", + "model.compile(optimizer=opt, loss=keras.losses.sparse_categorical_crossentropy, metrics=['accuracy'])" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: \"sequential\"\n", + "_________________________________________________________________\n", + " Layer (type) Output Shape Param # \n", + "=================================================================\n", + " conv2d (Conv2D) (None, 224, 224, 64) 1792 \n", + " \n", + " conv2d_1 (Conv2D) (None, 224, 224, 64) 36928 \n", + " \n", + " max_pooling2d (MaxPooling2D (None, 112, 112, 64) 0 \n", + " ) \n", + " \n", + " conv2d_2 (Conv2D) (None, 112, 112, 128) 73856 \n", + " \n", + " conv2d_3 (Conv2D) (None, 112, 112, 128) 147584 \n", + " \n", + " max_pooling2d_1 (MaxPooling (None, 56, 56, 128) 0 \n", + " 2D) \n", + " \n", + " conv2d_4 (Conv2D) (None, 56, 56, 256) 295168 \n", + " \n", + " conv2d_5 (Conv2D) (None, 56, 56, 256) 590080 \n", + " \n", + " conv2d_6 (Conv2D) (None, 56, 56, 256) 590080 \n", + " \n", + " max_pooling2d_2 (MaxPooling (None, 28, 28, 256) 0 \n", + " 2D) \n", + " \n", + " conv2d_7 (Conv2D) (None, 28, 28, 512) 1180160 \n", + " \n", + " conv2d_8 (Conv2D) (None, 28, 28, 512) 2359808 \n", + " \n", + " conv2d_9 (Conv2D) (None, 28, 28, 512) 2359808 \n", + " \n", + " max_pooling2d_3 (MaxPooling (None, 14, 14, 512) 0 \n", + " 2D) \n", + " \n", + " conv2d_10 (Conv2D) (None, 14, 14, 512) 2359808 \n", + " \n", + " conv2d_11 (Conv2D) (None, 14, 14, 512) 2359808 \n", + " \n", + " conv2d_12 (Conv2D) (None, 14, 14, 512) 2359808 \n", + " \n", + " flatten (Flatten) (None, 100352) 0 \n", + " \n", + " dense (Dense) (None, 4096) 411045888 \n", + " \n", + " dense_1 (Dense) (None, 4096) 16781312 \n", + " \n", + " dense_2 (Dense) (None, 5) 20485 \n", + " \n", + "=================================================================\n", + "Total params: 442,562,373\n", + "Trainable params: 442,562,373\n", + "Non-trainable params: 0\n", + "_________________________________________________________________\n" + ] + } + ], + "source": [ + "model.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:tensorflow:`period` argument is deprecated. Please use `save_freq` to specify the frequency in number of batches seen.\n", + "Epoch 1/2\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/6b/j4d60ym516x2s6wymzj707rh0000gn/T/ipykernel_8661/3543889534.py:4: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.\n", + " hist_vgg = model.fit_generator(steps_per_epoch=len(train_ds), generator=train_ds, validation_data= validation_ds, validation_steps=len(validation_ds), epochs=2, callbacks=[checkpoint,early])\n", + "2023-01-06 03:00:40.894219: W tensorflow/tsl/platform/profile_utils/cpu_utils.cc:128] Failed to get CPU frequency: 0 Hz\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 2/25 [=>............................] - ETA: 9:29 - loss: 1.5960 - accuracy: 0.2031" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[28], line 4\u001b[0m\n\u001b[1;32m 2\u001b[0m checkpoint \u001b[39m=\u001b[39m ModelCheckpoint(\u001b[39m\"\u001b[39m\u001b[39mvgg16_1.h5\u001b[39m\u001b[39m\"\u001b[39m, monitor\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mval_accuracy\u001b[39m\u001b[39m'\u001b[39m, verbose\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m, save_best_only\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m, save_weights_only\u001b[39m=\u001b[39m\u001b[39mFalse\u001b[39;00m, mode\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mauto\u001b[39m\u001b[39m'\u001b[39m, period\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m)\n\u001b[1;32m 3\u001b[0m early \u001b[39m=\u001b[39m EarlyStopping(monitor\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mval_accuracy\u001b[39m\u001b[39m'\u001b[39m, min_delta\u001b[39m=\u001b[39m\u001b[39m0\u001b[39m, patience\u001b[39m=\u001b[39m\u001b[39m20\u001b[39m, verbose\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m, mode\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mauto\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[0;32m----> 4\u001b[0m hist_vgg \u001b[39m=\u001b[39m model\u001b[39m.\u001b[39;49mfit_generator(steps_per_epoch\u001b[39m=\u001b[39;49m\u001b[39mlen\u001b[39;49m(train_ds), generator\u001b[39m=\u001b[39;49mtrain_ds, validation_data\u001b[39m=\u001b[39;49m validation_ds, validation_steps\u001b[39m=\u001b[39;49m\u001b[39mlen\u001b[39;49m(validation_ds), epochs\u001b[39m=\u001b[39;49m\u001b[39m2\u001b[39;49m, callbacks\u001b[39m=\u001b[39;49m[checkpoint,early])\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/keras/engine/training.py:2604\u001b[0m, in \u001b[0;36mModel.fit_generator\u001b[0;34m(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)\u001b[0m\n\u001b[1;32m 2592\u001b[0m \u001b[39m\u001b[39m\u001b[39m\"\"\"Fits the model on data yielded batch-by-batch by a Python generator.\u001b[39;00m\n\u001b[1;32m 2593\u001b[0m \n\u001b[1;32m 2594\u001b[0m \u001b[39mDEPRECATED:\u001b[39;00m\n\u001b[1;32m 2595\u001b[0m \u001b[39m `Model.fit` now supports generators, so there is no longer any need to\u001b[39;00m\n\u001b[1;32m 2596\u001b[0m \u001b[39m use this endpoint.\u001b[39;00m\n\u001b[1;32m 2597\u001b[0m \u001b[39m\"\"\"\u001b[39;00m\n\u001b[1;32m 2598\u001b[0m warnings\u001b[39m.\u001b[39mwarn(\n\u001b[1;32m 2599\u001b[0m \u001b[39m\"\u001b[39m\u001b[39m`Model.fit_generator` is deprecated and \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 2600\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mwill be removed in a future version. \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 2601\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mPlease use `Model.fit`, which supports generators.\u001b[39m\u001b[39m\"\u001b[39m,\n\u001b[1;32m 2602\u001b[0m stacklevel\u001b[39m=\u001b[39m\u001b[39m2\u001b[39m,\n\u001b[1;32m 2603\u001b[0m )\n\u001b[0;32m-> 2604\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mfit(\n\u001b[1;32m 2605\u001b[0m generator,\n\u001b[1;32m 2606\u001b[0m steps_per_epoch\u001b[39m=\u001b[39;49msteps_per_epoch,\n\u001b[1;32m 2607\u001b[0m epochs\u001b[39m=\u001b[39;49mepochs,\n\u001b[1;32m 2608\u001b[0m verbose\u001b[39m=\u001b[39;49mverbose,\n\u001b[1;32m 2609\u001b[0m callbacks\u001b[39m=\u001b[39;49mcallbacks,\n\u001b[1;32m 2610\u001b[0m validation_data\u001b[39m=\u001b[39;49mvalidation_data,\n\u001b[1;32m 2611\u001b[0m validation_steps\u001b[39m=\u001b[39;49mvalidation_steps,\n\u001b[1;32m 2612\u001b[0m validation_freq\u001b[39m=\u001b[39;49mvalidation_freq,\n\u001b[1;32m 2613\u001b[0m class_weight\u001b[39m=\u001b[39;49mclass_weight,\n\u001b[1;32m 2614\u001b[0m max_queue_size\u001b[39m=\u001b[39;49mmax_queue_size,\n\u001b[1;32m 2615\u001b[0m workers\u001b[39m=\u001b[39;49mworkers,\n\u001b[1;32m 2616\u001b[0m use_multiprocessing\u001b[39m=\u001b[39;49muse_multiprocessing,\n\u001b[1;32m 2617\u001b[0m shuffle\u001b[39m=\u001b[39;49mshuffle,\n\u001b[1;32m 2618\u001b[0m initial_epoch\u001b[39m=\u001b[39;49minitial_epoch,\n\u001b[1;32m 2619\u001b[0m )\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/keras/utils/traceback_utils.py:65\u001b[0m, in \u001b[0;36mfilter_traceback..error_handler\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 63\u001b[0m filtered_tb \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[1;32m 64\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m---> 65\u001b[0m \u001b[39mreturn\u001b[39;00m fn(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 66\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mException\u001b[39;00m \u001b[39mas\u001b[39;00m e:\n\u001b[1;32m 67\u001b[0m filtered_tb \u001b[39m=\u001b[39m _process_traceback_frames(e\u001b[39m.\u001b[39m__traceback__)\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/keras/engine/training.py:1650\u001b[0m, in \u001b[0;36mModel.fit\u001b[0;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)\u001b[0m\n\u001b[1;32m 1642\u001b[0m \u001b[39mwith\u001b[39;00m tf\u001b[39m.\u001b[39mprofiler\u001b[39m.\u001b[39mexperimental\u001b[39m.\u001b[39mTrace(\n\u001b[1;32m 1643\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mtrain\u001b[39m\u001b[39m\"\u001b[39m,\n\u001b[1;32m 1644\u001b[0m epoch_num\u001b[39m=\u001b[39mepoch,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1647\u001b[0m _r\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m,\n\u001b[1;32m 1648\u001b[0m ):\n\u001b[1;32m 1649\u001b[0m callbacks\u001b[39m.\u001b[39mon_train_batch_begin(step)\n\u001b[0;32m-> 1650\u001b[0m tmp_logs \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mtrain_function(iterator)\n\u001b[1;32m 1651\u001b[0m \u001b[39mif\u001b[39;00m data_handler\u001b[39m.\u001b[39mshould_sync:\n\u001b[1;32m 1652\u001b[0m context\u001b[39m.\u001b[39masync_wait()\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/tensorflow/python/util/traceback_utils.py:150\u001b[0m, in \u001b[0;36mfilter_traceback..error_handler\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 148\u001b[0m filtered_tb \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[1;32m 149\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m--> 150\u001b[0m \u001b[39mreturn\u001b[39;00m fn(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 151\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mException\u001b[39;00m \u001b[39mas\u001b[39;00m e:\n\u001b[1;32m 152\u001b[0m filtered_tb \u001b[39m=\u001b[39m _process_traceback_frames(e\u001b[39m.\u001b[39m__traceback__)\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/tensorflow/python/eager/polymorphic_function/polymorphic_function.py:880\u001b[0m, in \u001b[0;36mFunction.__call__\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m 877\u001b[0m compiler \u001b[39m=\u001b[39m \u001b[39m\"\u001b[39m\u001b[39mxla\u001b[39m\u001b[39m\"\u001b[39m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_jit_compile \u001b[39melse\u001b[39;00m \u001b[39m\"\u001b[39m\u001b[39mnonXla\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 879\u001b[0m \u001b[39mwith\u001b[39;00m OptionalXlaContext(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_jit_compile):\n\u001b[0;32m--> 880\u001b[0m result \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_call(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[1;32m 882\u001b[0m new_tracing_count \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mexperimental_get_tracing_count()\n\u001b[1;32m 883\u001b[0m without_tracing \u001b[39m=\u001b[39m (tracing_count \u001b[39m==\u001b[39m new_tracing_count)\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/tensorflow/python/eager/polymorphic_function/polymorphic_function.py:912\u001b[0m, in \u001b[0;36mFunction._call\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m 909\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_lock\u001b[39m.\u001b[39mrelease()\n\u001b[1;32m 910\u001b[0m \u001b[39m# In this case we have created variables on the first call, so we run the\u001b[39;00m\n\u001b[1;32m 911\u001b[0m \u001b[39m# defunned version which is guaranteed to never create variables.\u001b[39;00m\n\u001b[0;32m--> 912\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_no_variable_creation_fn(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds) \u001b[39m# pylint: disable=not-callable\u001b[39;00m\n\u001b[1;32m 913\u001b[0m \u001b[39melif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_variable_creation_fn \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[1;32m 914\u001b[0m \u001b[39m# Release the lock early so that multiple threads can perform the call\u001b[39;00m\n\u001b[1;32m 915\u001b[0m \u001b[39m# in parallel.\u001b[39;00m\n\u001b[1;32m 916\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_lock\u001b[39m.\u001b[39mrelease()\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/tensorflow/python/eager/polymorphic_function/tracing_compiler.py:134\u001b[0m, in \u001b[0;36mTracingCompiler.__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 131\u001b[0m \u001b[39mwith\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_lock:\n\u001b[1;32m 132\u001b[0m (concrete_function,\n\u001b[1;32m 133\u001b[0m filtered_flat_args) \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_maybe_define_function(args, kwargs)\n\u001b[0;32m--> 134\u001b[0m \u001b[39mreturn\u001b[39;00m concrete_function\u001b[39m.\u001b[39;49m_call_flat(\n\u001b[1;32m 135\u001b[0m filtered_flat_args, captured_inputs\u001b[39m=\u001b[39;49mconcrete_function\u001b[39m.\u001b[39;49mcaptured_inputs)\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/tensorflow/python/eager/polymorphic_function/monomorphic_function.py:1745\u001b[0m, in \u001b[0;36mConcreteFunction._call_flat\u001b[0;34m(self, args, captured_inputs, cancellation_manager)\u001b[0m\n\u001b[1;32m 1741\u001b[0m possible_gradient_type \u001b[39m=\u001b[39m gradients_util\u001b[39m.\u001b[39mPossibleTapeGradientTypes(args)\n\u001b[1;32m 1742\u001b[0m \u001b[39mif\u001b[39;00m (possible_gradient_type \u001b[39m==\u001b[39m gradients_util\u001b[39m.\u001b[39mPOSSIBLE_GRADIENT_TYPES_NONE\n\u001b[1;32m 1743\u001b[0m \u001b[39mand\u001b[39;00m executing_eagerly):\n\u001b[1;32m 1744\u001b[0m \u001b[39m# No tape is watching; skip to running the function.\u001b[39;00m\n\u001b[0;32m-> 1745\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_build_call_outputs(\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_inference_function\u001b[39m.\u001b[39;49mcall(\n\u001b[1;32m 1746\u001b[0m ctx, args, cancellation_manager\u001b[39m=\u001b[39;49mcancellation_manager))\n\u001b[1;32m 1747\u001b[0m forward_backward \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_select_forward_and_backward_functions(\n\u001b[1;32m 1748\u001b[0m args,\n\u001b[1;32m 1749\u001b[0m possible_gradient_type,\n\u001b[1;32m 1750\u001b[0m executing_eagerly)\n\u001b[1;32m 1751\u001b[0m forward_function, args_with_tangents \u001b[39m=\u001b[39m forward_backward\u001b[39m.\u001b[39mforward()\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/tensorflow/python/eager/polymorphic_function/monomorphic_function.py:378\u001b[0m, in \u001b[0;36m_EagerDefinedFunction.call\u001b[0;34m(self, ctx, args, cancellation_manager)\u001b[0m\n\u001b[1;32m 376\u001b[0m \u001b[39mwith\u001b[39;00m _InterpolateFunctionError(\u001b[39mself\u001b[39m):\n\u001b[1;32m 377\u001b[0m \u001b[39mif\u001b[39;00m cancellation_manager \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[0;32m--> 378\u001b[0m outputs \u001b[39m=\u001b[39m execute\u001b[39m.\u001b[39;49mexecute(\n\u001b[1;32m 379\u001b[0m \u001b[39mstr\u001b[39;49m(\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49msignature\u001b[39m.\u001b[39;49mname),\n\u001b[1;32m 380\u001b[0m num_outputs\u001b[39m=\u001b[39;49m\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_num_outputs,\n\u001b[1;32m 381\u001b[0m inputs\u001b[39m=\u001b[39;49margs,\n\u001b[1;32m 382\u001b[0m attrs\u001b[39m=\u001b[39;49mattrs,\n\u001b[1;32m 383\u001b[0m ctx\u001b[39m=\u001b[39;49mctx)\n\u001b[1;32m 384\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m 385\u001b[0m outputs \u001b[39m=\u001b[39m execute\u001b[39m.\u001b[39mexecute_with_cancellation(\n\u001b[1;32m 386\u001b[0m \u001b[39mstr\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39msignature\u001b[39m.\u001b[39mname),\n\u001b[1;32m 387\u001b[0m num_outputs\u001b[39m=\u001b[39m\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_num_outputs,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 390\u001b[0m ctx\u001b[39m=\u001b[39mctx,\n\u001b[1;32m 391\u001b[0m cancellation_manager\u001b[39m=\u001b[39mcancellation_manager)\n", + "File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/tensorflow/python/eager/execute.py:52\u001b[0m, in \u001b[0;36mquick_execute\u001b[0;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[1;32m 50\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[1;32m 51\u001b[0m ctx\u001b[39m.\u001b[39mensure_initialized()\n\u001b[0;32m---> 52\u001b[0m tensors \u001b[39m=\u001b[39m pywrap_tfe\u001b[39m.\u001b[39;49mTFE_Py_Execute(ctx\u001b[39m.\u001b[39;49m_handle, device_name, op_name,\n\u001b[1;32m 53\u001b[0m inputs, attrs, num_outputs)\n\u001b[1;32m 54\u001b[0m \u001b[39mexcept\u001b[39;00m core\u001b[39m.\u001b[39m_NotOkStatusException \u001b[39mas\u001b[39;00m e:\n\u001b[1;32m 55\u001b[0m \u001b[39mif\u001b[39;00m name \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "from keras.callbacks import ModelCheckpoint, EarlyStopping\n", + "checkpoint = ModelCheckpoint(\"vgg16_1.h5\", monitor='val_accuracy', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)\n", + "early = EarlyStopping(monitor='val_accuracy', min_delta=0, patience=20, verbose=1, mode='auto')\n", + "hist_vgg = model.fit_generator(steps_per_epoch=len(train_ds), generator=train_ds, validation_data= validation_ds, validation_steps=len(validation_ds), epochs=2, callbacks=[checkpoint,early])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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lISsrKxC/SMjI5GSkiI/rl+/XrYbQURERBWKWcONlZUV/P39ERsbK7fpdDrExsaiTZs2Bse0a9cOly5dgk6nk9suXLgADw8PWFlZFeqv0Wjg6Oio9yAiIiLlMvtpqYiICHz77bf47rvvcPbsWbz33ntIT0/H0KFDAQChoaGIjIyU+7/33nt48OABxo8fjwsXLmDHjh2YM2cOxowZY65NICIiogrE7Pe5CQkJwb179zBjxgwkJSWhefPm2LVrlzzJODExESrVswzm5eWF3bt3Y+LEiWjWrBlq1KiB8ePHY/LkyebaBCIiIqpAzH6fG1PjfW6IiIgqn0pznxsiIiKissZwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIpSIcLNsmXL4O3tDWtra7Ru3RpHjhwp0bgNGzZAkiT06tWrfAskIiKiSsPs4Wbjxo2IiIjAzJkzcezYMfj5+SEoKAh3794tdtzVq1cxadIktG/f3kSVEhERUWVg9nCzaNEijBw5EkOHDkWjRo2wYsUK2NraYtWqVUWO0Wq1GDRoEGbPng0fHx8TVktEREQVnVnDTVZWFo4ePYrAwEC5TaVSITAwEHFxcUWO+/jjj1GtWjUMHz7cFGUSERFRJWJhzpUnJydDq9WievXqeu3Vq1fHuXPnDI755ZdfsHLlSsTHx5doHZmZmcjMzJSfp6amlrpeIiIiqvjMflrKGI8ePcKQIUPw7bffwtXVtURj5s6dCycnJ/nh5eVVzlUSERGROZn1yI2rqyvUajXu3Lmj137nzh24u7sX6n/58mVcvXoVwcHBcptOpwMAWFhY4Pz586hTp47emMjISERERMjPU1NTGXCIiIgUzKzhxsrKCv7+/oiNjZUv59bpdIiNjcXYsWML9W/YsCFOnTql1zZt2jQ8evQIX375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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.plot(hist_vgg.history[\"accuracy\"])\n", + "plt.plot(hist_vgg.history['val_accuracy'])\n", + "plt.plot(hist_vgg.history['loss'])\n", + "plt.plot(hist_vgg.history['val_loss'])\n", + "plt.title(\"Model accuracy\")\n", + "plt.ylabel(\"Value\")\n", + "plt.xlabel(\"Epoch\")\n", + "plt.legend([\"Accuracy\",\"Validation Accuracy\",\"Loss\",\"Validation Loss\"])\n", + "plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ResNet50" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: \"model_1\"\n", + "__________________________________________________________________________________________________\n", + " Layer (type) Output Shape Param # Connected to \n", + "==================================================================================================\n", + " input_3 (InputLayer) [(None, 224, 224, 3 0 [] \n", + " )] \n", + " \n", + " conv1_pad (ZeroPadding2D) (None, 230, 230, 3) 0 ['input_3[0][0]'] \n", + " \n", + " conv1_conv (Conv2D) (None, 112, 112, 64 9472 ['conv1_pad[0][0]'] \n", + " ) \n", + " \n", + " conv1_bn (BatchNormalization) (None, 112, 112, 64 256 ['conv1_conv[0][0]'] \n", + " ) \n", + " \n", + " conv1_relu (Activation) (None, 112, 112, 64 0 ['conv1_bn[0][0]'] \n", + " ) \n", + " \n", + " pool1_pad (ZeroPadding2D) (None, 114, 114, 64 0 ['conv1_relu[0][0]'] \n", + " ) \n", + " \n", + " pool1_pool (MaxPooling2D) (None, 56, 56, 64) 0 ['pool1_pad[0][0]'] \n", + " \n", + " conv2_block1_1_conv (Conv2D) (None, 56, 56, 64) 4160 ['pool1_pool[0][0]'] \n", + " \n", + " conv2_block1_1_bn (BatchNormal (None, 56, 56, 64) 256 ['conv2_block1_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block1_1_relu (Activatio (None, 56, 56, 64) 0 ['conv2_block1_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv2_block1_2_conv (Conv2D) (None, 56, 56, 64) 36928 ['conv2_block1_1_relu[0][0]'] \n", + " \n", + " conv2_block1_2_bn (BatchNormal (None, 56, 56, 64) 256 ['conv2_block1_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block1_2_relu (Activatio (None, 56, 56, 64) 0 ['conv2_block1_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv2_block1_0_conv (Conv2D) (None, 56, 56, 256) 16640 ['pool1_pool[0][0]'] \n", + " \n", + " conv2_block1_3_conv (Conv2D) (None, 56, 56, 256) 16640 ['conv2_block1_2_relu[0][0]'] \n", + " \n", + " conv2_block1_0_bn (BatchNormal (None, 56, 56, 256) 1024 ['conv2_block1_0_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block1_3_bn (BatchNormal (None, 56, 56, 256) 1024 ['conv2_block1_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block1_add (Add) (None, 56, 56, 256) 0 ['conv2_block1_0_bn[0][0]', \n", + " 'conv2_block1_3_bn[0][0]'] \n", + " \n", + " conv2_block1_out (Activation) (None, 56, 56, 256) 0 ['conv2_block1_add[0][0]'] \n", + " \n", + " conv2_block2_1_conv (Conv2D) (None, 56, 56, 64) 16448 ['conv2_block1_out[0][0]'] \n", + " \n", + " conv2_block2_1_bn (BatchNormal (None, 56, 56, 64) 256 ['conv2_block2_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block2_1_relu (Activatio (None, 56, 56, 64) 0 ['conv2_block2_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv2_block2_2_conv (Conv2D) (None, 56, 56, 64) 36928 ['conv2_block2_1_relu[0][0]'] \n", + " \n", + " conv2_block2_2_bn (BatchNormal (None, 56, 56, 64) 256 ['conv2_block2_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block2_2_relu (Activatio (None, 56, 56, 64) 0 ['conv2_block2_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv2_block2_3_conv (Conv2D) (None, 56, 56, 256) 16640 ['conv2_block2_2_relu[0][0]'] \n", + " \n", + " conv2_block2_3_bn (BatchNormal (None, 56, 56, 256) 1024 ['conv2_block2_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block2_add (Add) (None, 56, 56, 256) 0 ['conv2_block1_out[0][0]', \n", + " 'conv2_block2_3_bn[0][0]'] \n", + " \n", + " conv2_block2_out (Activation) (None, 56, 56, 256) 0 ['conv2_block2_add[0][0]'] \n", + " \n", + " conv2_block3_1_conv (Conv2D) (None, 56, 56, 64) 16448 ['conv2_block2_out[0][0]'] \n", + " \n", + " conv2_block3_1_bn (BatchNormal (None, 56, 56, 64) 256 ['conv2_block3_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block3_1_relu (Activatio (None, 56, 56, 64) 0 ['conv2_block3_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv2_block3_2_conv (Conv2D) (None, 56, 56, 64) 36928 ['conv2_block3_1_relu[0][0]'] \n", + " \n", + " conv2_block3_2_bn (BatchNormal (None, 56, 56, 64) 256 ['conv2_block3_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block3_2_relu (Activatio (None, 56, 56, 64) 0 ['conv2_block3_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv2_block3_3_conv (Conv2D) (None, 56, 56, 256) 16640 ['conv2_block3_2_relu[0][0]'] \n", + " \n", + " conv2_block3_3_bn (BatchNormal (None, 56, 56, 256) 1024 ['conv2_block3_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv2_block3_add (Add) (None, 56, 56, 256) 0 ['conv2_block2_out[0][0]', \n", + " 'conv2_block3_3_bn[0][0]'] \n", + " \n", + " conv2_block3_out (Activation) (None, 56, 56, 256) 0 ['conv2_block3_add[0][0]'] \n", + " \n", + " conv3_block1_1_conv (Conv2D) (None, 28, 28, 128) 32896 ['conv2_block3_out[0][0]'] \n", + " \n", + " conv3_block1_1_bn (BatchNormal (None, 28, 28, 128) 512 ['conv3_block1_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block1_1_relu (Activatio (None, 28, 28, 128) 0 ['conv3_block1_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv3_block1_2_conv (Conv2D) (None, 28, 28, 128) 147584 ['conv3_block1_1_relu[0][0]'] \n", + " \n", + " conv3_block1_2_bn (BatchNormal (None, 28, 28, 128) 512 ['conv3_block1_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block1_2_relu (Activatio (None, 28, 28, 128) 0 ['conv3_block1_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv3_block1_0_conv (Conv2D) (None, 28, 28, 512) 131584 ['conv2_block3_out[0][0]'] \n", + " \n", + " conv3_block1_3_conv (Conv2D) (None, 28, 28, 512) 66048 ['conv3_block1_2_relu[0][0]'] \n", + " \n", + " conv3_block1_0_bn (BatchNormal (None, 28, 28, 512) 2048 ['conv3_block1_0_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block1_3_bn (BatchNormal (None, 28, 28, 512) 2048 ['conv3_block1_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block1_add (Add) (None, 28, 28, 512) 0 ['conv3_block1_0_bn[0][0]', \n", + " 'conv3_block1_3_bn[0][0]'] \n", + " \n", + " conv3_block1_out (Activation) (None, 28, 28, 512) 0 ['conv3_block1_add[0][0]'] \n", + " \n", + " conv3_block2_1_conv (Conv2D) (None, 28, 28, 128) 65664 ['conv3_block1_out[0][0]'] \n", + " \n", + " conv3_block2_1_bn (BatchNormal (None, 28, 28, 128) 512 ['conv3_block2_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block2_1_relu (Activatio (None, 28, 28, 128) 0 ['conv3_block2_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv3_block2_2_conv (Conv2D) (None, 28, 28, 128) 147584 ['conv3_block2_1_relu[0][0]'] \n", + " \n", + " conv3_block2_2_bn (BatchNormal (None, 28, 28, 128) 512 ['conv3_block2_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block2_2_relu (Activatio (None, 28, 28, 128) 0 ['conv3_block2_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv3_block2_3_conv (Conv2D) (None, 28, 28, 512) 66048 ['conv3_block2_2_relu[0][0]'] \n", + " \n", + " conv3_block2_3_bn (BatchNormal (None, 28, 28, 512) 2048 ['conv3_block2_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block2_add (Add) (None, 28, 28, 512) 0 ['conv3_block1_out[0][0]', \n", + " 'conv3_block2_3_bn[0][0]'] \n", + " \n", + " conv3_block2_out (Activation) (None, 28, 28, 512) 0 ['conv3_block2_add[0][0]'] \n", + " \n", + " conv3_block3_1_conv (Conv2D) (None, 28, 28, 128) 65664 ['conv3_block2_out[0][0]'] \n", + " \n", + " conv3_block3_1_bn (BatchNormal (None, 28, 28, 128) 512 ['conv3_block3_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block3_1_relu (Activatio (None, 28, 28, 128) 0 ['conv3_block3_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv3_block3_2_conv (Conv2D) (None, 28, 28, 128) 147584 ['conv3_block3_1_relu[0][0]'] \n", + " \n", + " conv3_block3_2_bn (BatchNormal (None, 28, 28, 128) 512 ['conv3_block3_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block3_2_relu (Activatio (None, 28, 28, 128) 0 ['conv3_block3_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv3_block3_3_conv (Conv2D) (None, 28, 28, 512) 66048 ['conv3_block3_2_relu[0][0]'] \n", + " \n", + " conv3_block3_3_bn (BatchNormal (None, 28, 28, 512) 2048 ['conv3_block3_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block3_add (Add) (None, 28, 28, 512) 0 ['conv3_block2_out[0][0]', \n", + " 'conv3_block3_3_bn[0][0]'] \n", + " \n", + " conv3_block3_out (Activation) (None, 28, 28, 512) 0 ['conv3_block3_add[0][0]'] \n", + " \n", + " conv3_block4_1_conv (Conv2D) (None, 28, 28, 128) 65664 ['conv3_block3_out[0][0]'] \n", + " \n", + " conv3_block4_1_bn (BatchNormal (None, 28, 28, 128) 512 ['conv3_block4_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block4_1_relu (Activatio (None, 28, 28, 128) 0 ['conv3_block4_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv3_block4_2_conv (Conv2D) (None, 28, 28, 128) 147584 ['conv3_block4_1_relu[0][0]'] \n", + " \n", + " conv3_block4_2_bn (BatchNormal (None, 28, 28, 128) 512 ['conv3_block4_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block4_2_relu (Activatio (None, 28, 28, 128) 0 ['conv3_block4_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv3_block4_3_conv (Conv2D) (None, 28, 28, 512) 66048 ['conv3_block4_2_relu[0][0]'] \n", + " \n", + " conv3_block4_3_bn (BatchNormal (None, 28, 28, 512) 2048 ['conv3_block4_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv3_block4_add (Add) (None, 28, 28, 512) 0 ['conv3_block3_out[0][0]', \n", + " 'conv3_block4_3_bn[0][0]'] \n", + " \n", + " conv3_block4_out (Activation) (None, 28, 28, 512) 0 ['conv3_block4_add[0][0]'] \n", + " \n", + " conv4_block1_1_conv (Conv2D) (None, 14, 14, 256) 131328 ['conv3_block4_out[0][0]'] \n", + " \n", + " conv4_block1_1_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block1_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block1_1_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block1_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block1_2_conv (Conv2D) (None, 14, 14, 256) 590080 ['conv4_block1_1_relu[0][0]'] \n", + " \n", + " conv4_block1_2_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block1_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block1_2_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block1_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block1_0_conv (Conv2D) (None, 14, 14, 1024 525312 ['conv3_block4_out[0][0]'] \n", + " ) \n", + " \n", + " conv4_block1_3_conv (Conv2D) (None, 14, 14, 1024 263168 ['conv4_block1_2_relu[0][0]'] \n", + " ) \n", + " \n", + " conv4_block1_0_bn (BatchNormal (None, 14, 14, 1024 4096 ['conv4_block1_0_conv[0][0]'] \n", + " ization) ) \n", + " \n", + " conv4_block1_3_bn (BatchNormal (None, 14, 14, 1024 4096 ['conv4_block1_3_conv[0][0]'] \n", + " ization) ) \n", + " \n", + " conv4_block1_add (Add) (None, 14, 14, 1024 0 ['conv4_block1_0_bn[0][0]', \n", + " ) 'conv4_block1_3_bn[0][0]'] \n", + " \n", + " conv4_block1_out (Activation) (None, 14, 14, 1024 0 ['conv4_block1_add[0][0]'] \n", + " ) \n", + " \n", + " conv4_block2_1_conv (Conv2D) (None, 14, 14, 256) 262400 ['conv4_block1_out[0][0]'] \n", + " \n", + " conv4_block2_1_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block2_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block2_1_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block2_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block2_2_conv (Conv2D) (None, 14, 14, 256) 590080 ['conv4_block2_1_relu[0][0]'] \n", + " \n", + " conv4_block2_2_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block2_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block2_2_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block2_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block2_3_conv (Conv2D) (None, 14, 14, 1024 263168 ['conv4_block2_2_relu[0][0]'] \n", + " ) \n", + " \n", + " conv4_block2_3_bn (BatchNormal (None, 14, 14, 1024 4096 ['conv4_block2_3_conv[0][0]'] \n", + " ization) ) \n", + " \n", + " conv4_block2_add (Add) (None, 14, 14, 1024 0 ['conv4_block1_out[0][0]', \n", + " ) 'conv4_block2_3_bn[0][0]'] \n", + " \n", + " conv4_block2_out (Activation) (None, 14, 14, 1024 0 ['conv4_block2_add[0][0]'] \n", + " ) \n", + " \n", + " conv4_block3_1_conv (Conv2D) (None, 14, 14, 256) 262400 ['conv4_block2_out[0][0]'] \n", + " \n", + " conv4_block3_1_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block3_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block3_1_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block3_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block3_2_conv (Conv2D) (None, 14, 14, 256) 590080 ['conv4_block3_1_relu[0][0]'] \n", + " \n", + " conv4_block3_2_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block3_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block3_2_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block3_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block3_3_conv (Conv2D) (None, 14, 14, 1024 263168 ['conv4_block3_2_relu[0][0]'] \n", + " ) \n", + " \n", + " conv4_block3_3_bn (BatchNormal (None, 14, 14, 1024 4096 ['conv4_block3_3_conv[0][0]'] \n", + " ization) ) \n", + " \n", + " conv4_block3_add (Add) (None, 14, 14, 1024 0 ['conv4_block2_out[0][0]', \n", + " ) 'conv4_block3_3_bn[0][0]'] \n", + " \n", + " conv4_block3_out (Activation) (None, 14, 14, 1024 0 ['conv4_block3_add[0][0]'] \n", + " ) \n", + " \n", + " conv4_block4_1_conv (Conv2D) (None, 14, 14, 256) 262400 ['conv4_block3_out[0][0]'] \n", + " \n", + " conv4_block4_1_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block4_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block4_1_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block4_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block4_2_conv (Conv2D) (None, 14, 14, 256) 590080 ['conv4_block4_1_relu[0][0]'] \n", + " \n", + " conv4_block4_2_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block4_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block4_2_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block4_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block4_3_conv (Conv2D) (None, 14, 14, 1024 263168 ['conv4_block4_2_relu[0][0]'] \n", + " ) \n", + " \n", + " conv4_block4_3_bn (BatchNormal (None, 14, 14, 1024 4096 ['conv4_block4_3_conv[0][0]'] \n", + " ization) ) \n", + " \n", + " conv4_block4_add (Add) (None, 14, 14, 1024 0 ['conv4_block3_out[0][0]', \n", + " ) 'conv4_block4_3_bn[0][0]'] \n", + " \n", + " conv4_block4_out (Activation) (None, 14, 14, 1024 0 ['conv4_block4_add[0][0]'] \n", + " ) \n", + " \n", + " conv4_block5_1_conv (Conv2D) (None, 14, 14, 256) 262400 ['conv4_block4_out[0][0]'] \n", + " \n", + " conv4_block5_1_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block5_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block5_1_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block5_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block5_2_conv (Conv2D) (None, 14, 14, 256) 590080 ['conv4_block5_1_relu[0][0]'] \n", + " \n", + " conv4_block5_2_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block5_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block5_2_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block5_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block5_3_conv (Conv2D) (None, 14, 14, 1024 263168 ['conv4_block5_2_relu[0][0]'] \n", + " ) \n", + " \n", + " conv4_block5_3_bn (BatchNormal (None, 14, 14, 1024 4096 ['conv4_block5_3_conv[0][0]'] \n", + " ization) ) \n", + " \n", + " conv4_block5_add (Add) (None, 14, 14, 1024 0 ['conv4_block4_out[0][0]', \n", + " ) 'conv4_block5_3_bn[0][0]'] \n", + " \n", + " conv4_block5_out (Activation) (None, 14, 14, 1024 0 ['conv4_block5_add[0][0]'] \n", + " ) \n", + " \n", + " conv4_block6_1_conv (Conv2D) (None, 14, 14, 256) 262400 ['conv4_block5_out[0][0]'] \n", + " \n", + " conv4_block6_1_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block6_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block6_1_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block6_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block6_2_conv (Conv2D) (None, 14, 14, 256) 590080 ['conv4_block6_1_relu[0][0]'] \n", + " \n", + " conv4_block6_2_bn (BatchNormal (None, 14, 14, 256) 1024 ['conv4_block6_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv4_block6_2_relu (Activatio (None, 14, 14, 256) 0 ['conv4_block6_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv4_block6_3_conv (Conv2D) (None, 14, 14, 1024 263168 ['conv4_block6_2_relu[0][0]'] \n", + " ) \n", + " \n", + " conv4_block6_3_bn (BatchNormal (None, 14, 14, 1024 4096 ['conv4_block6_3_conv[0][0]'] \n", + " ization) ) \n", + " \n", + " conv4_block6_add (Add) (None, 14, 14, 1024 0 ['conv4_block5_out[0][0]', \n", + " ) 'conv4_block6_3_bn[0][0]'] \n", + " \n", + " conv4_block6_out (Activation) (None, 14, 14, 1024 0 ['conv4_block6_add[0][0]'] \n", + " ) \n", + " \n", + " conv5_block1_1_conv (Conv2D) (None, 7, 7, 512) 524800 ['conv4_block6_out[0][0]'] \n", + " \n", + " conv5_block1_1_bn (BatchNormal (None, 7, 7, 512) 2048 ['conv5_block1_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block1_1_relu (Activatio (None, 7, 7, 512) 0 ['conv5_block1_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv5_block1_2_conv (Conv2D) (None, 7, 7, 512) 2359808 ['conv5_block1_1_relu[0][0]'] \n", + " \n", + " conv5_block1_2_bn (BatchNormal (None, 7, 7, 512) 2048 ['conv5_block1_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block1_2_relu (Activatio (None, 7, 7, 512) 0 ['conv5_block1_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv5_block1_0_conv (Conv2D) (None, 7, 7, 2048) 2099200 ['conv4_block6_out[0][0]'] \n", + " \n", + " conv5_block1_3_conv (Conv2D) (None, 7, 7, 2048) 1050624 ['conv5_block1_2_relu[0][0]'] \n", + " \n", + " conv5_block1_0_bn (BatchNormal (None, 7, 7, 2048) 8192 ['conv5_block1_0_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block1_3_bn (BatchNormal (None, 7, 7, 2048) 8192 ['conv5_block1_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block1_add (Add) (None, 7, 7, 2048) 0 ['conv5_block1_0_bn[0][0]', \n", + " 'conv5_block1_3_bn[0][0]'] \n", + " \n", + " conv5_block1_out (Activation) (None, 7, 7, 2048) 0 ['conv5_block1_add[0][0]'] \n", + " \n", + " conv5_block2_1_conv (Conv2D) (None, 7, 7, 512) 1049088 ['conv5_block1_out[0][0]'] \n", + " \n", + " conv5_block2_1_bn (BatchNormal (None, 7, 7, 512) 2048 ['conv5_block2_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block2_1_relu (Activatio (None, 7, 7, 512) 0 ['conv5_block2_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv5_block2_2_conv (Conv2D) (None, 7, 7, 512) 2359808 ['conv5_block2_1_relu[0][0]'] \n", + " \n", + " conv5_block2_2_bn (BatchNormal (None, 7, 7, 512) 2048 ['conv5_block2_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block2_2_relu (Activatio (None, 7, 7, 512) 0 ['conv5_block2_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv5_block2_3_conv (Conv2D) (None, 7, 7, 2048) 1050624 ['conv5_block2_2_relu[0][0]'] \n", + " \n", + " conv5_block2_3_bn (BatchNormal (None, 7, 7, 2048) 8192 ['conv5_block2_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block2_add (Add) (None, 7, 7, 2048) 0 ['conv5_block1_out[0][0]', \n", + " 'conv5_block2_3_bn[0][0]'] \n", + " \n", + " conv5_block2_out (Activation) (None, 7, 7, 2048) 0 ['conv5_block2_add[0][0]'] \n", + " \n", + " conv5_block3_1_conv (Conv2D) (None, 7, 7, 512) 1049088 ['conv5_block2_out[0][0]'] \n", + " \n", + " conv5_block3_1_bn (BatchNormal (None, 7, 7, 512) 2048 ['conv5_block3_1_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block3_1_relu (Activatio (None, 7, 7, 512) 0 ['conv5_block3_1_bn[0][0]'] \n", + " n) \n", + " \n", + " conv5_block3_2_conv (Conv2D) (None, 7, 7, 512) 2359808 ['conv5_block3_1_relu[0][0]'] \n", + " \n", + " conv5_block3_2_bn (BatchNormal (None, 7, 7, 512) 2048 ['conv5_block3_2_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block3_2_relu (Activatio (None, 7, 7, 512) 0 ['conv5_block3_2_bn[0][0]'] \n", + " n) \n", + " \n", + " conv5_block3_3_conv (Conv2D) (None, 7, 7, 2048) 1050624 ['conv5_block3_2_relu[0][0]'] \n", + " \n", + " conv5_block3_3_bn (BatchNormal (None, 7, 7, 2048) 8192 ['conv5_block3_3_conv[0][0]'] \n", + " ization) \n", + " \n", + " conv5_block3_add (Add) (None, 7, 7, 2048) 0 ['conv5_block2_out[0][0]', \n", + " 'conv5_block3_3_bn[0][0]'] \n", + " \n", + " conv5_block3_out (Activation) (None, 7, 7, 2048) 0 ['conv5_block3_add[0][0]'] \n", + " \n", + " flatten_6 (Flatten) (None, 100352) 0 ['conv5_block3_out[0][0]'] \n", + " \n", + " dense_13 (Dense) (None, 5) 501765 ['flatten_6[0][0]'] \n", + " \n", + "==================================================================================================\n", + "Total params: 24,089,477\n", + "Trainable params: 501,765\n", + "Non-trainable params: 23,587,712\n", + "__________________________________________________________________________________________________\n", + "Epoch 1/5\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/_h/ljwht4gd7lb99rm1hm78h7_00000gn/T/ipykernel_13133/3879957867.py:45: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.\n", + " r = model.fit_generator(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "25/25 [==============================] - 90s 3s/step - loss: 4.3387 - accuracy: 0.2100 - val_loss: 2.1355 - val_accuracy: 0.1875\n", + "Epoch 2/5\n", + "25/25 [==============================] - 84s 3s/step - loss: 1.9657 - accuracy: 0.2550 - val_loss: 2.3121 - val_accuracy: 0.2188\n", + "Epoch 3/5\n", + "25/25 [==============================] - 84s 3s/step - loss: 1.8658 - accuracy: 0.2600 - val_loss: 1.4832 - val_accuracy: 0.3073\n", + "Epoch 4/5\n", + "25/25 [==============================] - 83s 3s/step - loss: 1.7074 - accuracy: 0.2775 - val_loss: 1.5045 - val_accuracy: 0.3698\n", + "Epoch 5/5\n", + "25/25 [==============================] - 85s 3s/step - loss: 1.9758 - accuracy: 0.2800 - val_loss: 1.7073 - val_accuracy: 0.2812\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "ename": "KeyError", + "evalue": "'acc'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn [55], line 60\u001b[0m\n\u001b[1;32m 57\u001b[0m plt\u001b[39m.\u001b[39msavefig(\u001b[39m'\u001b[39m\u001b[39mLossVal_loss\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[1;32m 59\u001b[0m \u001b[39m# accuracies\u001b[39;00m\n\u001b[0;32m---> 60\u001b[0m plt\u001b[39m.\u001b[39mplot(r\u001b[39m.\u001b[39;49mhistory[\u001b[39m'\u001b[39;49m\u001b[39macc\u001b[39;49m\u001b[39m'\u001b[39;49m], label\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mtrain acc\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[1;32m 61\u001b[0m plt\u001b[39m.\u001b[39mplot(r\u001b[39m.\u001b[39mhistory[\u001b[39m'\u001b[39m\u001b[39mval_acc\u001b[39m\u001b[39m'\u001b[39m], label\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mval acc\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[1;32m 62\u001b[0m plt\u001b[39m.\u001b[39mlegend()\n", + "\u001b[0;31mKeyError\u001b[0m: 'acc'" + ] + }, + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from keras.layers import Input, Lambda, Dense, Flatten\n", + "from keras.models import Model\n", + "from keras.applications import ResNet50\n", + "from keras.preprocessing import image\n", + "from keras.preprocessing.image import ImageDataGenerator\n", + "from keras.models import Sequential\n", + "import numpy as np\n", + "from glob import glob\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# re-size all the images to this\n", + "IMAGE_SIZE = [224, 224]\n", + "\n", + "# add preprocessing layer to the front of resnet\n", + "resnet = ResNet50(input_shape=IMAGE_SIZE + [3], weights='imagenet', include_top=False)\n", + "\n", + "# don't train existing weights\n", + "for layer in resnet.layers:\n", + " layer.trainable = False\n", + " \n", + " # useful for getting number of classes\n", + "classes = 5\n", + " \n", + "\n", + "# our layers - you can add more if you want\n", + "x = Flatten()(resnet.output)\n", + "# x = Dense(1000, activation='relu')(x)\n", + "prediction = Dense(5, activation='softmax')(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# create a model object\n", + "model = Model(inputs=resnet.input, outputs=prediction)\n", + "\n", + "# view the structure of the model\n", + "model.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# tell the model what cost and optimization method to use\n", + "model.compile(\n", + " loss='sparse_categorical_crossentropy',\n", + " optimizer='adam',\n", + " metrics=['accuracy']\n", + ")\n", + "\n", + "#train_ds_vgg_sw, test_ds_vgg_sw, validation_ds_vgg_sw\n", + "# fit the model\n", + "r = model.fit_generator(\n", + " train_ds,\n", + " validation_data=validation_ds,\n", + " epochs=100,\n", + " steps_per_epoch=len(train_ds),\n", + " validation_steps=len(validation_ds)\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# loss\n", + "plt.plot(r.history[\"accuracy\"])\n", + "plt.plot(r.history['val_accuracy'])\n", + "plt.plot(r.history['loss'])\n", + "plt.plot(r.history['val_loss'])\n", + "plt.title(\"Model accuracy\")\n", + "plt.ylabel(\"Value\")\n", + "plt.xlabel(\"Epoch\")\n", + "plt.legend([\"Accuracy\",\"Validation Accuracy\",\"Loss\",\"Validation Loss\"])\n", + "plt.show()\n", + "\n", + "model.save('resnet_1.h5')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "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.9.6" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}