Symulowanie-wizualne/sw_lab9-10_1.ipynb

1330 lines
164 KiB
Plaintext

{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Aleksandra Jonas, Aleksandra Gronowska, Iwona Christop\n",
"# Zadanie 9-10, zadanie 1 - VGG16 + ResNet on train_test_sw "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Przygotowanie danych"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [],
"source": [
"from IPython.display import Image, display"
]
},
{
"cell_type": "code",
"execution_count": 61,
"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": 62,
"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": 63,
"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": 64,
"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": 65,
"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": 66,
"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": 67,
"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": 68,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training data size: 821\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": 69,
"metadata": {},
"outputs": [],
"source": [
"diagram_setup('vgg_sw')"
]
},
{
"cell_type": "code",
"execution_count": 70,
"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": 71,
"metadata": {},
"outputs": [],
"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": 72,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_1\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" conv2d_13 (Conv2D) (None, 224, 224, 64) 1792 \n",
" \n",
" conv2d_14 (Conv2D) (None, 224, 224, 64) 36928 \n",
" \n",
" max_pooling2d_4 (MaxPooling (None, 112, 112, 64) 0 \n",
" 2D) \n",
" \n",
" conv2d_15 (Conv2D) (None, 112, 112, 128) 73856 \n",
" \n",
" conv2d_16 (Conv2D) (None, 112, 112, 128) 147584 \n",
" \n",
" max_pooling2d_5 (MaxPooling (None, 56, 56, 128) 0 \n",
" 2D) \n",
" \n",
" conv2d_17 (Conv2D) (None, 56, 56, 256) 295168 \n",
" \n",
" conv2d_18 (Conv2D) (None, 56, 56, 256) 590080 \n",
" \n",
" conv2d_19 (Conv2D) (None, 56, 56, 256) 590080 \n",
" \n",
" max_pooling2d_6 (MaxPooling (None, 28, 28, 256) 0 \n",
" 2D) \n",
" \n",
" conv2d_20 (Conv2D) (None, 28, 28, 512) 1180160 \n",
" \n",
" conv2d_21 (Conv2D) (None, 28, 28, 512) 2359808 \n",
" \n",
" conv2d_22 (Conv2D) (None, 28, 28, 512) 2359808 \n",
" \n",
" max_pooling2d_7 (MaxPooling (None, 14, 14, 512) 0 \n",
" 2D) \n",
" \n",
" conv2d_23 (Conv2D) (None, 14, 14, 512) 2359808 \n",
" \n",
" conv2d_24 (Conv2D) (None, 14, 14, 512) 2359808 \n",
" \n",
" conv2d_25 (Conv2D) (None, 14, 14, 512) 2359808 \n",
" \n",
" flatten_2 (Flatten) (None, 100352) 0 \n",
" \n",
" dense_4 (Dense) (None, 4096) 411045888 \n",
" \n",
" dense_5 (Dense) (None, 4096) 16781312 \n",
" \n",
" dense_6 (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": 73,
"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/25\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/var/folders/3r/c8tg1h051m18qhsdccdysrt40000gn/T/ipykernel_2029/3158629982.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=25, callbacks=[checkpoint,early])\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"25/25 [==============================] - ETA: 0s - loss: 1.6264 - accuracy: 0.1900 \n",
"Epoch 1: val_accuracy improved from -inf to 0.18229, saving model to vgg16_1.h5\n",
"25/25 [==============================] - 854s 34s/step - loss: 1.6264 - accuracy: 0.1900 - val_loss: 1.6109 - val_accuracy: 0.1823\n",
"Epoch 2/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6108 - accuracy: 0.1950 \n",
"Epoch 2: val_accuracy improved from 0.18229 to 0.18750, saving model to vgg16_1.h5\n",
"25/25 [==============================] - 897s 36s/step - loss: 1.6108 - accuracy: 0.1950 - val_loss: 1.6098 - val_accuracy: 0.1875\n",
"Epoch 3/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6097 - accuracy: 0.2062 \n",
"Epoch 3: val_accuracy improved from 0.18750 to 0.19792, saving model to vgg16_1.h5\n",
"25/25 [==============================] - 870s 35s/step - loss: 1.6097 - accuracy: 0.2062 - val_loss: 1.6102 - val_accuracy: 0.1979\n",
"Epoch 4/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6097 - accuracy: 0.2037 \n",
"Epoch 4: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 692s 28s/step - loss: 1.6097 - accuracy: 0.2037 - val_loss: 1.6106 - val_accuracy: 0.1979\n",
"Epoch 5/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6095 - accuracy: 0.1963 \n",
"Epoch 5: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 634s 26s/step - loss: 1.6095 - accuracy: 0.1963 - val_loss: 1.6114 - val_accuracy: 0.1823\n",
"Epoch 6/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6094 - accuracy: 0.1925 \n",
"Epoch 6: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 643s 26s/step - loss: 1.6094 - accuracy: 0.1925 - val_loss: 1.6112 - val_accuracy: 0.1719\n",
"Epoch 7/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6095 - accuracy: 0.2025 \n",
"Epoch 7: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 697s 28s/step - loss: 1.6095 - accuracy: 0.2025 - val_loss: 1.6115 - val_accuracy: 0.1823\n",
"Epoch 8/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6097 - accuracy: 0.1762 \n",
"Epoch 8: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 667s 27s/step - loss: 1.6097 - accuracy: 0.1762 - val_loss: 1.6106 - val_accuracy: 0.1979\n",
"Epoch 9/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6096 - accuracy: 0.2025 \n",
"Epoch 9: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 656s 26s/step - loss: 1.6096 - accuracy: 0.2025 - val_loss: 1.6103 - val_accuracy: 0.1927\n",
"Epoch 10/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6095 - accuracy: 0.1950 \n",
"Epoch 10: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 651s 26s/step - loss: 1.6095 - accuracy: 0.1950 - val_loss: 1.6104 - val_accuracy: 0.1927\n",
"Epoch 11/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6094 - accuracy: 0.2062 \n",
"Epoch 11: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 646s 26s/step - loss: 1.6094 - accuracy: 0.2062 - val_loss: 1.6105 - val_accuracy: 0.1927\n",
"Epoch 12/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6095 - accuracy: 0.2062 \n",
"Epoch 12: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 648s 26s/step - loss: 1.6095 - accuracy: 0.2062 - val_loss: 1.6103 - val_accuracy: 0.1927\n",
"Epoch 13/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6096 - accuracy: 0.2025 \n",
"Epoch 13: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 636s 26s/step - loss: 1.6096 - accuracy: 0.2025 - val_loss: 1.6108 - val_accuracy: 0.1927\n",
"Epoch 14/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6097 - accuracy: 0.2050 \n",
"Epoch 14: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 664s 27s/step - loss: 1.6097 - accuracy: 0.2050 - val_loss: 1.6110 - val_accuracy: 0.1875\n",
"Epoch 15/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6096 - accuracy: 0.1775 \n",
"Epoch 15: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 657s 27s/step - loss: 1.6096 - accuracy: 0.1775 - val_loss: 1.6105 - val_accuracy: 0.1875\n",
"Epoch 16/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6095 - accuracy: 0.2000 \n",
"Epoch 16: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 664s 27s/step - loss: 1.6095 - accuracy: 0.2000 - val_loss: 1.6102 - val_accuracy: 0.1927\n",
"Epoch 17/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6094 - accuracy: 0.1937 \n",
"Epoch 17: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 676s 27s/step - loss: 1.6094 - accuracy: 0.1937 - val_loss: 1.6104 - val_accuracy: 0.1927\n",
"Epoch 18/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6093 - accuracy: 0.1975 \n",
"Epoch 18: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 673s 27s/step - loss: 1.6093 - accuracy: 0.1975 - val_loss: 1.6103 - val_accuracy: 0.1823\n",
"Epoch 19/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6094 - accuracy: 0.2050 \n",
"Epoch 19: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 681s 27s/step - loss: 1.6094 - accuracy: 0.2050 - val_loss: 1.6111 - val_accuracy: 0.1771\n",
"Epoch 20/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6093 - accuracy: 0.2050 \n",
"Epoch 20: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 672s 27s/step - loss: 1.6093 - accuracy: 0.2050 - val_loss: 1.6108 - val_accuracy: 0.1927\n",
"Epoch 21/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6094 - accuracy: 0.2050 \n",
"Epoch 21: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 663s 27s/step - loss: 1.6094 - accuracy: 0.2050 - val_loss: 1.6110 - val_accuracy: 0.1927\n",
"Epoch 22/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6096 - accuracy: 0.1850 \n",
"Epoch 22: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 675s 27s/step - loss: 1.6096 - accuracy: 0.1850 - val_loss: 1.6111 - val_accuracy: 0.1927\n",
"Epoch 23/25\n",
"25/25 [==============================] - ETA: 0s - loss: 1.6092 - accuracy: 0.1963 \n",
"Epoch 23: val_accuracy did not improve from 0.19792\n",
"25/25 [==============================] - 664s 27s/step - loss: 1.6092 - accuracy: 0.1963 - val_loss: 1.6110 - val_accuracy: 0.1823\n",
"Epoch 23: early stopping\n"
]
}
],
"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=25, callbacks=[checkpoint,early])"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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W1CDMN/GxZ6TJR+HguHyviiviPk+YTbebFixv1tm0xX1khT+X9iDYvYwFO+BRcH6FZ+q4L5UfHc069W50xtUsvdH7r0WRVPJDYoeFajtHNAJllOjTijesmUL2rdvj48//hj/93//B3t7ezz//PN47733YGtrW+o0OTk5yMnJke+npqZWSm1qR0d4vvVWpcybiIiIyq5GhZvLly/jjz/+gI2NDTZt2oSkpCS89tpruHXrFiLucUho/vz5mDt3bhVXSkRERJZSo77Ez2QyQZIkfPfdd+jYsSN69+6NhQsX4r///S+ysrJKnWbatGkwGAzy5dq1a1VcNREREVWlGtVz4+3tDV9fX+j1enlY06ZNIYTA9evX0bBhwxLTaLVaaLXaqiyTiIiILKhG9dx06dIFsbGxSE9Pl4edP38eKpUKtWrVsmBlREREVF1YNNykp6cjKioKUVFRAIDo6GhERUUhJiYGQMEhpdDQULn90KFD4erqipEjR+L06dPYu3cv3nrrLYwaNeqeJxQTERHR48Wi4ebo0aNo27Yt2rZtCwCYMmUK2rZti1mzZgEA4uLi5KADAA4ODtixYwdSUlLQvn17DBs2DCEhIVi8eLFF6iciIqLqhz+/QERERNVeeV6/a9Q5N0REREQPwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREimLRcLN3716EhITAx8cHkiRh8+bNZZ52//79sLKyQps2bSqtPiIiIqp5LBpuMjIy0Lp1ayxdurRc06WkpCA0NBQ9e/aspMqIiIioprKy5MKDg4MRHBxc7unGjh2LoUOHQq1Wl6u3h4iIiJSvxp1zExERgcuXL2P27Nllap+Tk4PU1FSzCxERESlXjQo3Fy5cwDvvvIP//e9/sLIqW6fT/Pnzodfr5Yufn18lV0lERESWVGPCjdFoxNChQzF37lw0atSozNNNmzYNBoNBvly7dq0SqyQiIiJLs+g5N+WRlpaGo0eP4q+//sL48eMBACaTCUIIWFlZYfv27ejRo0eJ6bRaLbRabVWXS0RERBZSY8KNTqfDyZMnzYZ9+eWX+P3337Fx40bUrVvXQpURERFRdWLRcJOeno6LFy/K96OjoxEVFQUXFxfUrl0b06ZNw40bN7Bq1SqoVCq0aNHCbHoPDw/Y2NiUGE5ERESPL4uGm6NHj6J79+7y/SlTpgAAwsLCsHLlSsTFxSEmJsZS5REREVENJAkhhKWLqEqpqanQ6/UwGAzQ6XSWLoeIiIjKoDyv3zXm01JEREREZcFwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIrCcENERESKwnBDREREisJwQ0RERIpi0XCzd+9ehISEwMfHB5IkYfPmzfdt/8MPP+CZZ56Bu7s7dDodOnXqhG3btlVNsURERFQjWDTcZGRkoHXr1li6dGmZ2u/duxfPPPMMfv31Vxw7dgzdu3dHSEgI/vrrr0qulIiIiGoKSQghLF0EAEiShE2bNqFv377lmq558+YYPHgwZs2aVab2qamp0Ov1MBgM0Ol0D1EpERERVbXyvH5bVVFNlcJkMiEtLQ0uLi73bJOTk4OcnBz5fmpqalWURkRERBZSo08o/uSTT5Ceno5Bgwbds838+fOh1+vli5+fXxVWSERERFWtxoab1atXY+7cuVi/fj08PDzu2W7atGkwGAzy5dq1a1VYJREREVW1GnlYau3atRg9ejQ2bNiAwMDA+7bVarXQarVVVBkRERFZWo3ruVmzZg1GjhyJNWvWoE+fPpYuh4iIiKoZi/bcpKen4+LFi/L96OhoREVFwcXFBbVr18a0adNw48YNrFq1CkDBoaiwsDB8/vnnCAgIQHx8PADA1tYWer3eIutA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af744w8sX74c3377bZmWMX/+fOj1evni5+f3yHUTERFR9WXxw1LlkZaWhuHDh+Pbb7+Fm5tbmaaZNm0aDAaDfLl27VolV0lERESWZGXJhbu5uUGtViMhIcFseEJCAry8vEq0v3TpEq5cuYKQkBB5mMlkAgBYWVnh3LlzqF+/vtk0Wq0WWq22EqonIiKi6siiPTcajQbt2rVDZGSkPMxkMiEyMhKdOnUq0b5JkyY4efIkoqKi5Mvzzz+P7t27IyoqioeciIiIyLI9NwAwZcoUhIWFoX379ujYsSMWLVqEjIwMjBw5EgAQGhoKX19fzJ8/HzY2NmjRooXZ9E5OTgBQYjgRERE9niwebgYPHoybN29i1qxZiI+PR5s2bbB161b5JOOYmBioVDXq1CAiIiKyIEkIISxdRFVKTU2FXq+HwWCATqezdDlERERUBuV5/WaXCBERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpCsMNERERKQrDDRERESkKww0REREpSrUIN0uXLoW/vz9sbGwQEBCAw4cP37Ptt99+i6eeegrOzs5wdnZGYGDgfdsTERHR48XK0gWsW7cOU6ZMwbJlyxAQEIBFixYhKCgI586dg4eHR4n2u3fvxpAhQ9C5c2fY2Njgo48+wrPPPot//vkHvr6+FliDmiU334Q8owkaKxWsVBIkSbJ0SfQYy803ITvfWKHzlADYWqthpa4W792IyAIkIYSwZAEBAQHo0KEDlixZAgAwmUzw8/PDhAkT8M477zxweqPRCGdnZyxZsgShoaEPbJ+amgq9Xg+DwQCdTvfI9Vc3+UYT4gzZuHY7E9eTs3D9diau384quH87C/Gp2Sh6xCUJ0FqpoFGroLFSF9y2UsnXBcOLD1PLw7TF2tlYq+Fsp4Grgwau9hq4OmjhYq+BzsZKkeEpMzcfcYZsONtp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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"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()"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"8/8 [==============================] - 35s 4s/step - loss: 1.6097 - accuracy: 0.1953\n"
]
},
{
"data": {
"text/plain": [
"[1.6096564531326294, 0.1953125]"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.evaluate(test_ds)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## ResNet50"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {},
"outputs": [],
"source": [
"from keras.layers import Input, Lambda, Dense, Flatten\n",
"from keras.models import Model\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",
"import ssl\n",
"ssl._create_default_https_context = ssl._create_unverified_context\n",
"from keras.applications import ResNet50\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": 77,
"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_3 (Flatten) (None, 100352) 0 ['conv5_block3_out[0][0]'] \n",
" \n",
" dense_7 (Dense) (None, 5) 501765 ['flatten_3[0][0]'] \n",
" \n",
"==================================================================================================\n",
"Total params: 24,089,477\n",
"Trainable params: 501,765\n",
"Non-trainable params: 23,587,712\n",
"__________________________________________________________________________________________________\n"
]
}
],
"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": 78,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/25\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/var/folders/3r/c8tg1h051m18qhsdccdysrt40000gn/T/ipykernel_2029/3602206220.py:10: 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 [==============================] - 38s 1s/step - loss: 6.4809 - accuracy: 0.1950 - val_loss: 2.9878 - val_accuracy: 0.2344\n",
"Epoch 2/25\n",
"25/25 [==============================] - 35s 1s/step - loss: 2.2159 - accuracy: 0.2338 - val_loss: 2.3206 - val_accuracy: 0.2396\n",
"Epoch 3/25\n",
"25/25 [==============================] - 35s 1s/step - loss: 1.9435 - accuracy: 0.2237 - val_loss: 1.8788 - val_accuracy: 0.2292\n",
"Epoch 4/25\n",
"25/25 [==============================] - 35s 1s/step - loss: 2.1113 - accuracy: 0.2350 - val_loss: 1.5820 - val_accuracy: 0.2604\n",
"Epoch 5/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.7911 - accuracy: 0.2975 - val_loss: 1.6257 - val_accuracy: 0.3229\n",
"Epoch 6/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.8471 - accuracy: 0.2975 - val_loss: 1.6844 - val_accuracy: 0.3542\n",
"Epoch 7/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.7567 - accuracy: 0.3075 - val_loss: 1.4758 - val_accuracy: 0.3281\n",
"Epoch 8/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.6541 - accuracy: 0.3550 - val_loss: 1.6412 - val_accuracy: 0.2708\n",
"Epoch 9/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.4498 - accuracy: 0.3762 - val_loss: 1.3539 - val_accuracy: 0.3958\n",
"Epoch 10/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.5093 - accuracy: 0.3525 - val_loss: 1.4342 - val_accuracy: 0.3385\n",
"Epoch 11/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.4125 - accuracy: 0.4062 - val_loss: 1.6245 - val_accuracy: 0.3438\n",
"Epoch 12/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.5308 - accuracy: 0.3650 - val_loss: 1.6150 - val_accuracy: 0.2292\n",
"Epoch 13/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.4149 - accuracy: 0.4263 - val_loss: 1.5404 - val_accuracy: 0.3906\n",
"Epoch 14/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.4894 - accuracy: 0.3925 - val_loss: 1.8275 - val_accuracy: 0.2292\n",
"Epoch 15/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.5978 - accuracy: 0.3775 - val_loss: 1.3376 - val_accuracy: 0.4375\n",
"Epoch 16/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.4227 - accuracy: 0.4175 - val_loss: 1.5674 - val_accuracy: 0.3958\n",
"Epoch 17/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.4758 - accuracy: 0.3837 - val_loss: 1.5279 - val_accuracy: 0.3698\n",
"Epoch 18/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.6931 - accuracy: 0.4137 - val_loss: 1.8716 - val_accuracy: 0.2865\n",
"Epoch 19/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.3378 - accuracy: 0.4500 - val_loss: 1.4395 - val_accuracy: 0.4271\n",
"Epoch 20/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.3173 - accuracy: 0.4825 - val_loss: 1.2535 - val_accuracy: 0.4583\n",
"Epoch 21/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.2702 - accuracy: 0.4900 - val_loss: 1.4282 - val_accuracy: 0.4896\n",
"Epoch 22/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.2848 - accuracy: 0.4600 - val_loss: 1.3511 - val_accuracy: 0.4115\n",
"Epoch 23/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.4002 - accuracy: 0.4487 - val_loss: 1.5821 - val_accuracy: 0.3281\n",
"Epoch 24/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.2507 - accuracy: 0.4800 - val_loss: 1.2901 - val_accuracy: 0.4635\n",
"Epoch 25/25\n",
"25/25 [==============================] - 36s 1s/step - loss: 1.3626 - accuracy: 0.4462 - val_loss: 1.5347 - val_accuracy: 0.3906\n"
]
}
],
"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=25,\n",
" steps_per_epoch=len(train_ds),\n",
" validation_steps=len(validation_ds)\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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X2bIkCG89tprBAYGotFoGDNmjPN85eliLTA2m+2iz7mwlaVQ37592bhxI88//zzNmzfH29sbu91Ot27drqjugQMHsnjxYjZu3EhsbCy//vorTz31lLNVSghRnIQXIaqQ+++/n8cff5zNmzfz/fffX3S/6OhoVqxYQU5OTpHWl0OHDjkfL/xqt9udrRuFDh8+XOR4hTORbDYbXbp0KZfX8sMPP9CpUydmz55dZHtmZibBwcHO+7Vr12bLli1YLBbc3NxKPFbt2rVZunQp6enpF219CQgIcB7/QoWtUKWRkZHBypUrmTp1Kq+88opz+5EjR4rsFxISgq+vL/v27bvsMbt160ZISAjfffcdbdu2JT8/n0cffbTUNQlxI5JoL0QV4u3tzaxZs5gyZQo9evS46H533303NpuNGTNmFNn+4YcfoiiKc8ZS4df/zlaaPn16kftarZbevXvz448/lviBnJKSUubXotVqi03bXrx4MWfPni2yrXfv3qSmphZ7LYDz+b1790ZVVaZOnXrRfXx9fQkODmbdunVFHp85c2aZar7wmIX++35pNBp69erFb7/95pyqXVJNADqdjn79+rFo0SLmzZtHbGxsmVuxhLjRSMuLEFXMxbptLtSjRw86derExIkTOXHiBM2aNWPZsmX88ssvjBkzxjnGpXnz5vTr14+ZM2eSlZXFLbfcwsqVKzl69GixY7711lusXr2atm3bMnz4cBo1akR6ejo7d+5kxYoVpKenl+l13Hvvvbz66qs89thj3HLLLezdu5fvvvuOWrVqFdlv4MCBfPPNN4wbN46tW7dy2223kZeXx4oVK3jqqafo2bMnnTp14tFHH+Xjjz/myJEjzi6c9evX06lTJ0aNGgU4poW/9dZbDBs2jFatWrFu3Tr+/fffUtfs6+vL7bffzjvvvIPFYqFatWosW7aMuLi4Yvu++eabLFu2jA4dOjBixAgaNmxIQkICixcv5u+//y7S5Tdw4EA+/vhjVq9ezdtvv12m91GIG5LL5jkJIS7rwqnSl/LfqdKqqqo5OTnq2LFj1cjISNXNzU2tW7eu+u677zqn6RYyGo3q008/rQYFBaleXl5qjx491NOnTxebPqyqqpqUlKSOHDlSjYqKUt3c3NTw8HC1c+fO6hdffOHcpyxTpZ999lk1IiJCNRgMavv27dVNmzapHTp0UDt06FBk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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"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')"
]
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"8/8 [==============================] - 9s 1s/step - loss: 1.4028 - accuracy: 0.4141\n"
]
},
{
"data": {
"text/plain": [
"[1.4027552604675293, 0.4140625]"
]
},
"execution_count": 80,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.evaluate(test_ds)"
]
}
],
"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.10.1 (v3.10.1:2cd268a3a9, Dec 6 2021, 14:28:59) [Clang 13.0.0 (clang-1300.0.29.3)]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}