From 0e30b8aa0e68344980095a066234bed9238398fd Mon Sep 17 00:00:00 2001 From: Alexander Merdian-Tarko Date: Tue, 3 Dec 2024 22:14:31 +0100 Subject: [PATCH] Adapt training to kaggle --- notebooks/training.ipynb | 1105 +------------------------------------- 1 file changed, 1 insertion(+), 1104 deletions(-) diff --git a/notebooks/training.ipynb b/notebooks/training.ipynb index 3219502..299f11e 100644 --- a/notebooks/training.ipynb +++ b/notebooks/training.ipynb @@ -1,1104 +1 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [], - "gpuType": "T4" - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - }, - "accelerator": "GPU" - }, - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# Training" - ], - "metadata": { - "id": "0goBcwsXEl7q" - } - }, - { - "cell_type": "markdown", - "source": [ - "## Setup" - ], - "metadata": { - "id": "_AciCyGkEpkC" - } - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "id": "5eYEEjcmEjKA" - }, - "outputs": [], - "source": [ - "from google.colab import drive" - ] - }, - { - "cell_type": "code", - "source": [ - "drive.mount('/content/drive')" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "ktrt8P-TErVU", - "outputId": "da29023a-aa42-4c83-dbc7-a92ec1c5e551" - }, - "execution_count": 2, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Mounted at /content/drive\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "%cd drive/MyDrive/tiger_classification" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "eRkEBiiVEvBh", - "outputId": "866c5ae8-dff5-482e-ae46-c0f3588e00ea" - }, - "execution_count": 3, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "/content/drive/MyDrive/tiger_classification\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "!pip install keras kimm -U" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "KVoOmsrBExwK", - "outputId": "266204f1-044a-49f4-cf32-5ce95a872f9b" - }, - "execution_count": 4, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Requirement already satisfied: keras in /usr/local/lib/python3.10/dist-packages (3.5.0)\n", - "Collecting keras\n", - " Downloading keras-3.7.0-py3-none-any.whl.metadata (5.8 kB)\n", - "Collecting kimm\n", - " Downloading kimm-0.2.5-py3-none-any.whl.metadata (12 kB)\n", - "Requirement already satisfied: absl-py in /usr/local/lib/python3.10/dist-packages (from keras) (1.4.0)\n", - "Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (from keras) (1.26.4)\n", - "Requirement already satisfied: rich in /usr/local/lib/python3.10/dist-packages (from keras) (13.9.4)\n", - "Requirement already satisfied: namex in /usr/local/lib/python3.10/dist-packages (from keras) (0.0.8)\n", - "Requirement already satisfied: h5py in /usr/local/lib/python3.10/dist-packages (from keras) (3.12.1)\n", - "Requirement already satisfied: optree in /usr/local/lib/python3.10/dist-packages (from keras) (0.13.1)\n", - "Requirement already satisfied: ml-dtypes in /usr/local/lib/python3.10/dist-packages (from keras) (0.4.1)\n", - "Requirement already satisfied: packaging in /usr/local/lib/python3.10/dist-packages (from keras) (24.2)\n", - "Requirement already satisfied: typing-extensions>=4.5.0 in /usr/local/lib/python3.10/dist-packages (from optree->keras) (4.12.2)\n", - "Requirement already satisfied: markdown-it-py>=2.2.0 in /usr/local/lib/python3.10/dist-packages (from rich->keras) (3.0.0)\n", - "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /usr/local/lib/python3.10/dist-packages (from rich->keras) (2.18.0)\n", - "Requirement already satisfied: mdurl~=0.1 in /usr/local/lib/python3.10/dist-packages (from markdown-it-py>=2.2.0->rich->keras) (0.1.2)\n", - "Downloading keras-3.7.0-py3-none-any.whl (1.2 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m49.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hDownloading kimm-0.2.5-py3-none-any.whl (123 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m123.4/123.4 kB\u001b[0m \u001b[31m11.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hInstalling collected packages: keras, kimm\n", - " Attempting uninstall: keras\n", - " Found existing installation: keras 3.5.0\n", - " Uninstalling keras-3.5.0:\n", - " Successfully uninstalled keras-3.5.0\n", - "Successfully installed keras-3.7.0 kimm-0.2.5\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "import os\n", - "import random\n", - "import shutil\n", - "import numpy as np\n", - "\n", - "import keras\n", - "from keras import layers, optimizers, losses, callbacks\n", - "import kimm\n", - "import tensorflow as tf\n", - "import tensorflow_datasets as tfds\n", - "from sklearn.metrics import confusion_matrix, classification_report\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import seaborn as sns" - ], - "metadata": { - "id": "WNSWKPrzEzy_" - }, - "execution_count": 5, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "def sample_images(source_dir, target_dir, samples_per_class, seed=42):\n", - " \"\"\"\n", - " Samples a fixed number of images per class from a directory structure.\n", - "\n", - " Args:\n", - " source_dir (str): Path to the source dataset directory.\n", - " target_dir (str): Path to the target dataset directory to store sampled data.\n", - " samples_per_class (int): Number of images to sample per class.\n", - " seed (int): Random seed for reproducibility.\n", - " \"\"\"\n", - " random.seed(seed)\n", - "\n", - " if not os.path.exists(target_dir):\n", - " os.makedirs(target_dir)\n", - "\n", - " for class_name in os.listdir(source_dir):\n", - " class_path = os.path.join(source_dir, class_name)\n", - " if os.path.isdir(class_path):\n", - " sampled_class_dir = os.path.join(target_dir, class_name)\n", - " os.makedirs(sampled_class_dir, exist_ok=True)\n", - "\n", - " # list and shuffle all files in class directory\n", - " all_images = os.listdir(class_path)\n", - " random.shuffle(all_images)\n", - "\n", - " # select desired number of samples\n", - " sampled_images = all_images[:samples_per_class]\n", - "\n", - " # copy sampled images to new directory\n", - " for image_name in sampled_images:\n", - " source_image_path = os.path.join(class_path, image_name)\n", - " target_image_path = os.path.join(sampled_class_dir, image_name)\n", - " shutil.copy(source_image_path, target_image_path)" - ], - "metadata": { - "id": "RjGj2LDNR15z" - }, - "execution_count": 6, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# set seed\n", - "seed = 42\n", - "\n", - "# set batch size\n", - "batch_size = 16\n", - "\n", - "# set num classes\n", - "num_classes = 5\n", - "\n", - "# define paths to train and test images\n", - "train_dir = 'images/train'\n", - "train_dir_sampled = 'images/train_sampled'\n", - "test_dir = 'images/test'\n", - "test_dir_sampled = 'images/test_sampled'\n", - "test2_dir = 'images/test2'\n", - "\n", - "# define path to model dir\n", - "model_dir = 'model'\n", - "!mkdir -p \"$model_dir\"\n", - "\n", - "# define path to media dir\n", - "media_dir = 'media'\n", - "!mkdir -p \"$media_dir\"" - ], - "metadata": { - "id": "4bedI2X2QDdf" - }, - "execution_count": 7, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "## Prepare train and test datasets" - ], - "metadata": { - "id": "o-oFY9SuE8dT" - } - }, - { - "cell_type": "code", - "source": [ - "!ls images/train/class_1 | wc -l\n", - "!ls images/train/class_2 | wc -l\n", - "!ls images/train/class_3 | wc -l\n", - "!ls images/train/class_4 | wc -l\n", - "!ls images/train/class_5 | wc -l" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "MXg7ZTD6Q1Hs", - "outputId": "60a198ec-b224-4a8e-974f-e78ad5ca670e" - }, - "execution_count": 8, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "4896\n", - "1451\n", - "1667\n", - "2101\n", - "951\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "!ls images/test/class_1 | wc -l\n", - "!ls images/test/class_2 | wc -l\n", - "!ls images/test/class_3 | wc -l\n", - "!ls images/test/class_4 | wc -l\n", - "!ls images/test/class_5 | wc -l" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "yF7p2pr0GhVf", - "outputId": "9c6dd7bd-76ed-4544-be47-0b05367e3fa6" - }, - "execution_count": 9, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "2825\n", - "626\n", - "677\n", - "920\n", - "842\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "!ls images/test2/class_1 | wc -l" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "yMpDTj64ScbO", - "outputId": "c482c381-7d9e-41e1-9507-6b9238d4a4a8" - }, - "execution_count": 10, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "307\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# create new directory with sampled train images\n", - "!rm -rf \"$train_dir_sampled\"\n", - "sample_images(train_dir, train_dir_sampled, 1000)" - ], - "metadata": { - "id": "KewO2flaRgLu" - }, - "execution_count": 11, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# create new directory with sampled test images\n", - "!rm -rf \"$test_dir_sampled\"\n", - "sample_images(test_dir, test_dir_sampled, 300)" - ], - "metadata": { - "id": "feQggHlSWEh4" - }, - "execution_count": 12, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# create train dataset\n", - "train_ds = tf.keras.preprocessing.image_dataset_from_directory(\n", - " train_dir_sampled,\n", - " label_mode='categorical',\n", - " shuffle=True,\n", - " seed=seed,\n", - ")\n", - "\n", - "# create test dataset\n", - "test_ds = tf.keras.preprocessing.image_dataset_from_directory(\n", - " test_dir_sampled,\n", - " label_mode='categorical',\n", - " shuffle=False,\n", - ")\n", - "\n", - "# create test2 dataset\n", - "test2_ds = tf.keras.preprocessing.image_dataset_from_directory(\n", - " test2_dir,\n", - " label_mode='categorical',\n", - " shuffle=False,\n", - ")\n", - "\n", - "# we need to unbatch because there's somehow an unwanted additional dimension\n", - "train_ds = train_ds.unbatch()\n", - "test_ds = test_ds.unbatch()\n", - "test2_ds = test2_ds.unbatch()\n", - "\n", - "print(f'Number of train samples: {train_ds.cardinality()}')\n", - "print(f'Number of test samples: {test_ds.cardinality()}')" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "J5i-u-VSE74K", - "outputId": "cda0d93f-4445-41f3-bb1b-5b1942d838b6" - }, - "execution_count": 13, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Found 5000 files belonging to 5 classes.\n", - "Found 1500 files belonging to 5 classes.\n", - "Found 307 files belonging to 1 classes.\n", - "Number of train samples: -2\n", - "Number of test samples: -2\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# check dimensions\n", - "print(train_ds.element_spec, test_ds.element_spec)" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "myqLQZuqFZkx", - "outputId": "1636afdc-4dcd-4ad9-9041-bedfc196f415" - }, - "execution_count": 14, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "(TensorSpec(shape=(256, 256, 3), dtype=tf.float32, name=None), TensorSpec(shape=(5,), dtype=tf.float32, name=None)) (TensorSpec(shape=(256, 256, 3), dtype=tf.float32, name=None), TensorSpec(shape=(5,), dtype=tf.float32, name=None))\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# setup dataset with tf.data\n", - "resize_fn = keras.layers.Resizing(224, 224)\n", - "\n", - "train_ds = train_ds.map(lambda x, y: (resize_fn(x), y))\n", - "test_ds = test_ds.map(lambda x, y: (resize_fn(x), y))\n", - "test2_ds = test2_ds.map(lambda x, y: (resize_fn(x), y))\n", - "\n", - "train_ds = train_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE).cache()\n", - "test_ds = test_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE).cache()\n", - "test2_ds = test2_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE).cache()" - ], - "metadata": { - "id": "YCc38anvFgJc" - }, - "execution_count": 15, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "## Prepare model" - ], - "metadata": { - "id": "CdVE1QLMFtA5" - } - }, - { - "cell_type": "code", - "source": [ - "# create base model\n", - "base_model = kimm.models.EfficientNetV2B0(\n", - " input_shape=(224, 224, 3),\n", - " include_preprocessing=True,\n", - " include_top=False,\n", - ")\n", - "\n", - "# freeze base model\n", - "base_model.trainable = False\n", - "\n", - "# create new model on top\n", - "inputs = keras.Input(shape=(224, 224, 3))\n", - "x = inputs\n", - "\n", - "# The base model contains batchnorm layers. We want to keep them in inference mode\n", - "# when we unfreeze the base model for fine-tuning, so we make sure that the\n", - "# base_model is running in inference mode here.\n", - "x = base_model(x, training=False)\n", - "x = keras.layers.GlobalAveragePooling2D()(x)\n", - "x = keras.layers.Dropout(0.2)(x) # regularize with dropout\n", - "outputs = keras.layers.Dense(num_classes, activation='softmax')(x)\n", - "model = keras.Model(inputs, outputs)\n", - "\n", - "model.summary(show_trainable=True)" - ], - "metadata": { - "id": "3mmwlJBDFf_6", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 359 - }, - "outputId": "73087a5a-85e9-43f0-bdee-b067a8168bcb" - }, - "execution_count": 16, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Downloading data from https://github.com/james77777778/keras-image-models/releases/download/0.1.0/efficientnetv2b0_tf_efficientnetv2_b0.in1k.keras\n", - "\u001b[1m29451563/29451563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 0us/step\n" - ] - }, - { - "output_type": "display_data", - "data": { - "text/plain": [ - "\u001b[1mModel: \"functional\"\u001b[0m\n" - ], - "text/html": [ - "
Model: \"functional\"\n",
-              "
\n" - ] - }, - "metadata": {} - }, - { - "output_type": "display_data", - "data": { - "text/plain": [ - "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━┓\n", - "┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mTraina…\u001b[0m\u001b[1m \u001b[0m┃\n", - "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━┩\n", - "│ input_layer_1 (\u001b[38;5;33mInputLayer\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m224\u001b[0m, \u001b[38;5;34m224\u001b[0m, \u001b[38;5;34m3\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ \u001b[1m-\u001b[0m │\n", - "├─────────────────────────────────────┼──────────────────────────────┼───────────────┼─────────┤\n", - "│ EfficientNetV2B0 (\u001b[38;5;33mEfficientNetV2B0\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m7\u001b[0m, \u001b[38;5;34m7\u001b[0m, \u001b[38;5;34m1280\u001b[0m) │ \u001b[38;5;34m5,919,312\u001b[0m │ \u001b[1;91mN\u001b[0m │\n", - "├─────────────────────────────────────┼──────────────────────────────┼───────────────┼─────────┤\n", - "│ global_average_pooling2d │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1280\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ \u001b[1m-\u001b[0m │\n", - "│ (\u001b[38;5;33mGlobalAveragePooling2D\u001b[0m) │ │ │ │\n", - "├─────────────────────────────────────┼──────────────────────────────┼───────────────┼─────────┤\n", - "│ dropout (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1280\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ \u001b[1m-\u001b[0m │\n", - "├─────────────────────────────────────┼──────────────────────────────┼───────────────┼─────────┤\n", - "│ dense (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m5\u001b[0m) │ \u001b[38;5;34m6,405\u001b[0m │ \u001b[1;38;5;34mY\u001b[0m │\n", - "└─────────────────────────────────────┴──────────────────────────────┴───────────────┴─────────┘\n" - ], - "text/html": [ - "
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━┓\n",
-              "┃ Layer (type)                         Output Shape                        Param #  Traina… ┃\n",
-              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━┩\n",
-              "│ input_layer_1 (InputLayer)          │ (None, 224, 224, 3)          │             0-    │\n",
-              "├─────────────────────────────────────┼──────────────────────────────┼───────────────┼─────────┤\n",
-              "│ EfficientNetV2B0 (EfficientNetV2B0) │ (None, 7, 7, 1280)           │     5,919,312N    │\n",
-              "├─────────────────────────────────────┼──────────────────────────────┼───────────────┼─────────┤\n",
-              "│ global_average_pooling2d            │ (None, 1280)                 │             0-    │\n",
-              "│ (GlobalAveragePooling2D)            │                              │               │         │\n",
-              "├─────────────────────────────────────┼──────────────────────────────┼───────────────┼─────────┤\n",
-              "│ dropout (Dropout)                   │ (None, 1280)                 │             0-    │\n",
-              "├─────────────────────────────────────┼──────────────────────────────┼───────────────┼─────────┤\n",
-              "│ dense (Dense)                       │ (None, 5)                    │         6,405Y    │\n",
-              "└─────────────────────────────────────┴──────────────────────────────┴───────────────┴─────────┘\n",
-              "
\n" - ] - }, - "metadata": {} - }, - { - "output_type": "display_data", - "data": { - "text/plain": [ - "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m5,925,717\u001b[0m (22.60 MB)\n" - ], - "text/html": [ - "
 Total params: 5,925,717 (22.60 MB)\n",
-              "
\n" - ] - }, - "metadata": {} - }, - { - "output_type": "display_data", - "data": { - "text/plain": [ - "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m6,405\u001b[0m (25.02 KB)\n" - ], - "text/html": [ - "
 Trainable params: 6,405 (25.02 KB)\n",
-              "
\n" - ] - }, - "metadata": {} - }, - { - "output_type": "display_data", - "data": { - "text/plain": [ - "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m5,919,312\u001b[0m (22.58 MB)\n" - ], - "text/html": [ - "
 Non-trainable params: 5,919,312 (22.58 MB)\n",
-              "
\n" - ] - }, - "metadata": {} - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Training\n", - "\n", - "Follow [mewc-train](https://github.com/zaandahl/mewc-train)" - ], - "metadata": { - "id": "YcYVdF_1F9EQ" - } - }, - { - "cell_type": "code", - "source": [ - "# df_size = 2500\n", - "\n", - "epochs = 30\n", - "\n", - "lr_init = 1e-4\n", - "# min_lr_frac = 1/5 # default minimum learning rate fraction of initial learning rate\n", - "# steps_per_epoch = df_size // batch_size\n", - "# total_steps = epochs * steps_per_epoch # total number of steps for monotonic exponential decay across all epochs\n", - "# lr = optimizers.schedules.ExponentialDecay(initial_learning_rate=lr_init, decay_steps=total_steps, decay_rate=min_lr_frac, staircase=False)\n", - "amsgrad = True\n", - "weight_decay = 1e-4\n", - "optimizer = optimizers.AdamW(learning_rate=lr_init, amsgrad=amsgrad, weight_decay=weight_decay)\n", - "\n", - "# if num_classes == 2:\n", - "# loss_f = losses.BinaryFocalCrossentropy() # use for binary classification tasks\n", - "# act_f = 'sigmoid' # use for binary classification tasks\n", - "# else:\n", - "# loss_f = losses.CategoricalFocalCrossentropy() # use for unbalanced multi-class tasks (typical for wildlife datasets)\n", - "# act_f = 'softmax' # use for multi-class classification tasks\n", - "loss_f = losses.CategoricalCrossentropy()\n", - "\n", - "metrics = ['accuracy']\n", - "\n", - "callbacks = [callbacks.EarlyStopping(monitor='loss', mode='min', min_delta=0.001, patience=5, restore_best_weights=True)]" - ], - "metadata": { - "id": "Ho-88Fe_GxVd" - }, - "execution_count": 17, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "model.compile(\n", - " optimizer=optimizer,\n", - " loss=loss_f,\n", - " metrics=metrics,\n", - ")" - ], - "metadata": { - "id": "fAHCE7OrGCGF" - }, - "execution_count": 18, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "model.fit(train_ds, epochs=epochs, callbacks=callbacks)" - ], - "metadata": { - "id": "GZKd2EixF8yO", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "e8424e62-1116-4b52-90af-5fe25403927f" - }, - "execution_count": 19, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Epoch 1/30\n", - " 313/Unknown \u001b[1m57s\u001b[0m 112ms/step - accuracy: 0.3851 - loss: 1.4539" - ] - }, - { - "output_type": "stream", - "name": "stderr", - "text": [ - "/usr/local/lib/python3.10/dist-packages/keras/src/trainers/epoch_iterator.py:151: UserWarning: Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches. You may need to use the `.repeat()` function when building your dataset.\n", - " self._interrupted_warning()\n" - ] - }, - { - "output_type": "stream", - "name": "stdout", - "text": [ - "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m57s\u001b[0m 113ms/step - accuracy: 0.3856 - loss: 1.4532\n", - "Epoch 2/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m40s\u001b[0m 19ms/step - accuracy: 0.7550 - loss: 0.8330\n", - "Epoch 3/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8037 - loss: 0.6392\n", - "Epoch 4/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8197 - loss: 0.5564\n", - "Epoch 5/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 18ms/step - accuracy: 0.8324 - loss: 0.5098\n", - "Epoch 6/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8430 - loss: 0.4767\n", - "Epoch 7/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8507 - loss: 0.4554\n", - "Epoch 8/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8580 - loss: 0.4336\n", - "Epoch 9/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 18ms/step - accuracy: 0.8628 - loss: 0.4185\n", - "Epoch 10/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 20ms/step - accuracy: 0.8693 - loss: 0.4050\n", - "Epoch 11/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 19ms/step - accuracy: 0.8710 - loss: 0.3950\n", - "Epoch 12/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8703 - loss: 0.3822\n", - "Epoch 13/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 20ms/step - accuracy: 0.8775 - loss: 0.3726\n", - "Epoch 14/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 19ms/step - accuracy: 0.8788 - loss: 0.3669\n", - "Epoch 15/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 20ms/step - accuracy: 0.8810 - loss: 0.3625\n", - "Epoch 16/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8829 - loss: 0.3488\n", - "Epoch 17/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 20ms/step - accuracy: 0.8935 - loss: 0.3481\n", - "Epoch 18/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 18ms/step - accuracy: 0.8917 - loss: 0.3368\n", - "Epoch 19/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 18ms/step - accuracy: 0.8916 - loss: 0.3375\n", - "Epoch 20/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8912 - loss: 0.3302\n", - "Epoch 21/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8891 - loss: 0.3251\n", - "Epoch 22/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m11s\u001b[0m 19ms/step - accuracy: 0.8984 - loss: 0.3151\n", - "Epoch 23/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9010 - loss: 0.3181\n", - "Epoch 24/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8947 - loss: 0.3143\n", - "Epoch 25/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8999 - loss: 0.3072\n", - "Epoch 26/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m11s\u001b[0m 20ms/step - accuracy: 0.8994 - loss: 0.3079\n", - "Epoch 27/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 18ms/step - accuracy: 0.9001 - loss: 0.3081\n", - "Epoch 28/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 18ms/step - accuracy: 0.9059 - loss: 0.2971\n", - "Epoch 29/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 19ms/step - accuracy: 0.9012 - loss: 0.2983\n", - "Epoch 30/30\n", - "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m10s\u001b[0m 19ms/step - accuracy: 0.9056 - loss: 0.2938\n" - ] - }, - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "" - ] - }, - "metadata": {}, - "execution_count": 19 - } - ] - }, - { - "cell_type": "code", - "source": [ - "model_path = model_dir + '/model.h5'" - ], - "metadata": { - "id": "LpesSWrvrltJ" - }, - "execution_count": 20, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "model.save(model_path, save_format='h5')" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "ik4KqmJdUbKd", - "outputId": "d168634b-b029-4bf1-cf87-e280ace945fb" - }, - "execution_count": 21, - "outputs": [ - { - "output_type": "stream", - "name": "stderr", - "text": [ - "WARNING:absl:The `save_format` argument is deprecated in Keras 3. We recommend removing this argument as it can be inferred from the file path. Received: save_format=h5\n", - "WARNING:absl:You are saving your model as an HDF5 file via `model.save()` or `keras.saving.save_model(model)`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')` or `keras.saving.save_model(model, 'my_model.keras')`. \n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Evaluation" - ], - "metadata": { - "id": "qIGU25KNO1sp" - } - }, - { - "cell_type": "code", - "source": [ - "result = model.evaluate(test_ds)\n", - "print(f'Test accuracy: {result[1] * 100:3.2f}%')" - ], - "metadata": { - "id": "40b_QINGGF7Y", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "16936959-2cfe-4005-b038-43eab764abab" - }, - "execution_count": 22, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "\u001b[1m94/94\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m24s\u001b[0m 190ms/step - accuracy: 0.9264 - loss: 0.2314\n", - "Test accuracy: 89.20%\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "result2 = model.evaluate(test2_ds)\n", - "print(f'Test2 accuracy: {result2[1] * 100:3.2f}%')" - ], - "metadata": { - "id": "zyDqRJSEGM4L", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "09e78303-ee89-418f-cef9-f1a4900de3f2" - }, - "execution_count": 23, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "\u001b[1m20/20\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m125s\u001b[0m 5s/step - accuracy: 0.8283 - loss: 23.2442\n", - "Test2 accuracy: 84.04%\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "true_labels = []\n", - "predicted_classes = []\n", - "\n", - "for images, labels in test_ds:\n", - " # append true labels based on their format\n", - " if len(labels.shape) > 1: # if one-hot encoded\n", - " true_labels.append(np.argmax(labels.numpy(), axis=1))\n", - " else: # if integer labels\n", - " true_labels.append(labels.numpy())\n", - "\n", - " # predict classes\n", - " predictions = model.predict(images)\n", - " predicted_classes.append(np.argmax(predictions, axis=1))\n", - "\n", - "# combine all batches into single arrays\n", - "true_labels = np.concatenate(true_labels)\n", - "predicted_classes = np.concatenate(predicted_classes)" - ], - "metadata": { - "id": "hpMkylclPBAB", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "909e4490-b5b4-48ff-a2a6-71f42226d86e" - }, - "execution_count": 24, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 5s/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 66ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 66ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 69ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 67ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 69ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 68ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 69ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 68ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 66ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 66ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 68ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 66ms/step\n", - "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 7s/step\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "cm = confusion_matrix(true_labels, predicted_classes)\n", - "print('Confusion matrix:\\n', cm)" - ], - "metadata": { - "id": "vYjCERt3PNQX", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "a6eaab6b-1891-44a3-a150-8ef7a86474fc" - }, - "execution_count": 25, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Confusion matrix:\n", - " [[290 3 2 3 2]\n", - " [ 4 264 10 10 12]\n", - " [ 1 6 273 14 6]\n", - " [ 3 20 11 251 15]\n", - " [ 12 3 6 19 260]]\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "class_names = ['tiger', 'lynx', 'bear', 'deer', 'bird']\n", - "report = classification_report(true_labels, predicted_classes, target_names=class_names)\n", - "print('Classification report:\\n', report)" - ], - "metadata": { - "id": "9db2EW1LPRzc", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "2f0bc5bf-cf72-4972-8656-228d67f6161d" - }, - "execution_count": 26, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Classification report:\n", - " precision recall f1-score support\n", - "\n", - " tiger 0.94 0.97 0.95 300\n", - " lynx 0.89 0.88 0.89 300\n", - " bear 0.90 0.91 0.91 300\n", - " deer 0.85 0.84 0.84 300\n", - " bird 0.88 0.87 0.87 300\n", - "\n", - " accuracy 0.89 1500\n", - " macro avg 0.89 0.89 0.89 1500\n", - "weighted avg 0.89 0.89 0.89 1500\n", - "\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "plt.figure(figsize=(10, 8))\n", - "sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=class_names, yticklabels=class_names)\n", - "plt.xlabel('Predicted')\n", - "plt.ylabel('True')\n", - "plt.title('Confusion matrix')\n", - "confusion_matrix_path = media_dir + '/confusion_matrix.png'\n", - "plt.savefig(confusion_matrix_path, dpi=300, bbox_inches='tight')\n", - "plt.show()" - ], - "metadata": { - "id": "oc7KSHEBPV8o", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 718 - }, - "outputId": "d378ad2e-85be-46c7-914c-0bbf12c9ade0" - }, - "execution_count": 27, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": [ - "
" - ], - "image/png": "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AgCkLBIKAGmGr6+vJDl1sbmfEydOyM3NTSVLlnRqDwwMlL+/v06cOOHUXrhw4UT7CAgI0D///GMy4sSefvpp1a1bVz169FC+fPnUsWNHLV++/L7JxZ04g4ODEy0rW7asLly4kGiswL/PJSAgQJKSdC4FCxZMNO7Dz89PhQoVStT2731GR0dr5MiRKlSokDw9PZU7d27lyZNHly9f1pUrVx547DuKFSuW5HUlad68ebpx44aOHDmihQsXOiU2AABrkVAASDN8fX2VP39+/fnnny5t9+8/ju/lXrdoNZJw9+x7HSM+Pt7pefbs2bVp0yatXbtWzz33nPbs2aOnn35ajzzySKJ1/4v/ci732jYp++zXr5/Gjx+vp556SsuXL9fq1au1Zs0a5cqVK8kVGUkuJwQbNmywD7Tfu3evS9sCAFIWCQWANOXRRx9VeHi4tm7d+sB1ixQpooSEBB05csSp/ezZs7p8+bL9jk3JISAgQJcvX07U/u8qiCS5ubmpSZMmmjJlivbv36/x48dr3bp1Wr9+/V33fSfOQ4cOJVp28OBB5c6dO80MPv7888/VtWtXTZ482T7AvV69eolem6QmeUkRGRmpfv36qVmzZnr00Uc1ZMiQu77uAABrkFAASFNeffVVeXl5qUePHjp79myi5eHh4Zo2bZokqVWrVpKU6E5MU6ZMkSS1bt062eIqUaKErly5oj179tjbIiMj9eWXXzqtd+nSpUTb3rmD0b9vZXtHUFCQqlSpokWLFjn9Yf7nn39q9erV9vNMC9zd3RNVQWbMmJGo+nInAbpbEuaqnj17KiEhQfPmzdOcOXOUJUsWde/ePUnVGABAymNiOwBpSokSJbR06VI9/fTTKlu2rNNM2b/88os+++wz+zwFlStXVteuXTVnzhxdvnxZDRs21G+//aZFixapffv2aty4cbLF1bFjRw0dOlSPPfaY+vfvrxs3bmjWrFkqXbq002DksWPHatOmTWrdurWKFCmic+fO6f3331fBggVVr169e+5/0qRJatmypUJCQtS9e3dFR0drxowZ8vPz0+jRo5PtPP6rRx99VIsXL5afn5/KlSunrVu3au3atcqVK5fTelWqVJG7u7vefvttXblyRZ6ennr44YeVN29el463YMECffvtt1q4cKEKFiwo6XYC07lzZ82aNUsvv/xysp0bAMAcEgoAaU7b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saK8vLw0cODARANxeX+nfUm53lFRUXrppZfUv3//RNsXLlzY/jPXO/3jGiI9I6FIYzw8PO757YUkBQcHa/v27U5t/35erVo1HTp0SCVLlkyRGJGysmTJoq5du2rBggXy8PBQx44dlT17dpf2cenSJXXr1k1vvPGGIiMj1alTJ+3cudPl/SBlbNu2zen5r7/+qlKlSqlq1aqKj4/XuXPnVL9+/btuu2XLFrVr106dO3eWJCUkJOjw4cMqV65ciscN15QoUUJZs2bVtm3b7H/8//PPPzp8+LAaNmyYpOtdrVo17d+/n8/zdOhe7/N/J4/3UrZsWW3btk1dunRx2geQFpFQpDFFixbVtm3bdPz4cXl7eyf61rlfv35q0KCBpkyZojZt2mjdunX6/vvvncqqI0eO1KOPPqrChQvriSeekJubm3bv3q0///xT48aNS+1Tggk9evRQ2bJlJd3+A9JVvXr1UqFChTR8+HDFxMSoatWqGjJkiGbOnJncocKEiIgIhYaG6qWXXtLOnTs1Y8YMTZ48WaVLl1anTp3UpUsXTZ48WVWrVtX58+f1008/qVKlSmrdurVKlSqlzz//XL/88osCAgI0ZcoUnT17loQiDfL29lb37t31yiuvKFeuXMqbN6/eeOMNubnd7m2clOs9dOhQ1a5dW3379lWPHj3k5eWl/fv3a82aNXrvvfcsPkPcz73e50k1YMAAdevWTTVq1FDdunX18ccfa9++fSpevHgKRg2YwxiKNGbIkCFyd3dXuXLllCdPnkT9ouvWravZs2drypQpqly5sn744QcNGjTIqStT8+bNtWrVKq1evVoPPfSQateuralTp6pIkSKpfTowqVSpUqpTp47KlCmTqA/tg3z00Uf67rvvtHjxYmXJkkVeXl5asmSJPvzwQ33//fcpFDFc0aVLF0VHR6tmzZrq06ePBgwYYL/V54IFC9SlSxcNHjxYwcHBat++vbZv327/hnv48OGqVq2amjdvrkaNGikwMFDt27e38GxwP5MmTVL9+vXVpk0bNW3aVPXq1XMa3/Kg612pUiVt3LhRhw8fVv369VW1alWNHDlS+fPnt+qUkET3e58nxdNPP60RI0bo1VdfVfXq1XXixAn17t07BSMGzLMZxv/fFBnpVs+ePXXw4EH9/PPPVoeCZGIYhkqVKqWXX35ZoaGhVocDAABwT3R5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\n" - }, - "metadata": {} - } - ] - } - ] -} \ No newline at end of file +{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"colab":{"provenance":[],"gpuType":"T4"},"accelerator":"GPU","kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":210880785,"sourceType":"kernelVersion"}],"dockerImageVersionId":30805,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Training","metadata":{"id":"0goBcwsXEl7q"}},{"cell_type":"markdown","source":"## Setup","metadata":{"id":"_AciCyGkEpkC"}},{"cell_type":"code","source":"!pip install keras kimm -U","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"KVoOmsrBExwK","outputId":"266204f1-044a-49f4-cf32-5ce95a872f9b","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:02:44.127956Z","iopub.execute_input":"2024-12-03T21:02:44.128623Z","iopub.status.idle":"2024-12-03T21:02:55.241317Z","shell.execute_reply.started":"2024-12-03T21:02:44.128589Z","shell.execute_reply":"2024-12-03T21:02:55.240446Z"}},"outputs":[{"name":"stdout","text":"Requirement already satisfied: keras in /opt/conda/lib/python3.10/site-packages (3.3.3)\nCollecting keras\n Downloading keras-3.7.0-py3-none-any.whl.metadata (5.8 kB)\nCollecting kimm\n Downloading kimm-0.2.5-py3-none-any.whl.metadata (12 kB)\nRequirement already satisfied: absl-py in /opt/conda/lib/python3.10/site-packages (from keras) (1.4.0)\nRequirement already satisfied: numpy in /opt/conda/lib/python3.10/site-packages (from keras) (1.26.4)\nRequirement already satisfied: rich in /opt/conda/lib/python3.10/site-packages (from keras) (13.7.1)\nRequirement already satisfied: namex in /opt/conda/lib/python3.10/site-packages (from keras) (0.0.8)\nRequirement already satisfied: h5py in /opt/conda/lib/python3.10/site-packages (from keras) (3.11.0)\nRequirement already satisfied: optree in /opt/conda/lib/python3.10/site-packages (from keras) (0.11.0)\nRequirement already satisfied: ml-dtypes in /opt/conda/lib/python3.10/site-packages (from keras) (0.3.2)\nRequirement already satisfied: packaging in /opt/conda/lib/python3.10/site-packages (from keras) (21.3)\nRequirement already satisfied: typing-extensions>=4.0.0 in /opt/conda/lib/python3.10/site-packages (from optree->keras) (4.12.2)\nRequirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /opt/conda/lib/python3.10/site-packages (from packaging->keras) (3.1.2)\nRequirement already satisfied: markdown-it-py>=2.2.0 in /opt/conda/lib/python3.10/site-packages (from rich->keras) (3.0.0)\nRequirement already satisfied: pygments<3.0.0,>=2.13.0 in /opt/conda/lib/python3.10/site-packages (from rich->keras) (2.18.0)\nRequirement already satisfied: mdurl~=0.1 in /opt/conda/lib/python3.10/site-packages (from markdown-it-py>=2.2.0->rich->keras) (0.1.2)\nDownloading keras-3.7.0-py3-none-any.whl (1.2 MB)\n\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m24.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n\u001b[?25hDownloading kimm-0.2.5-py3-none-any.whl (123 kB)\n\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m123.4/123.4 kB\u001b[0m \u001b[31m9.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n\u001b[?25hInstalling collected packages: keras, kimm\n Attempting uninstall: keras\n Found existing installation: keras 3.3.3\n Uninstalling keras-3.3.3:\n Successfully uninstalled keras-3.3.3\nSuccessfully installed keras-3.7.0 kimm-0.2.5\n","output_type":"stream"}],"execution_count":1},{"cell_type":"code","source":"!git clone https://github.com/alexvmt/tiger_classification.git","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"eRkEBiiVEvBh","outputId":"866c5ae8-dff5-482e-ae46-c0f3588e00ea","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:02:55.243335Z","iopub.execute_input":"2024-12-03T21:02:55.243626Z","iopub.status.idle":"2024-12-03T21:02:57.126660Z","shell.execute_reply.started":"2024-12-03T21:02:55.243599Z","shell.execute_reply":"2024-12-03T21:02:57.125883Z"}},"outputs":[{"name":"stdout","text":"Cloning into 'tiger_classification'...\nremote: Enumerating objects: 111, done.\u001b[K\nremote: Counting objects: 100% (111/111), done.\u001b[K\nremote: Compressing objects: 100% (75/75), done.\u001b[K\nremote: Total 111 (delta 42), reused 97 (delta 31), pack-reused 0 (from 0)\u001b[K\nReceiving objects: 100% (111/111), 1.90 MiB | 16.49 MiB/s, done.\nResolving deltas: 100% (42/42), done.\n","output_type":"stream"}],"execution_count":2},{"cell_type":"code","source":"%cd ../../","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:02:57.127944Z","iopub.execute_input":"2024-12-03T21:02:57.128197Z","iopub.status.idle":"2024-12-03T21:02:57.134342Z","shell.execute_reply.started":"2024-12-03T21:02:57.128172Z","shell.execute_reply":"2024-12-03T21:02:57.133442Z"}},"outputs":[{"name":"stdout","text":"/\n","output_type":"stream"}],"execution_count":3},{"cell_type":"code","source":"project_dir = 'kaggle/working/tiger_classification'\n\n# set seed\nseed = 42\n\n# set n train and test images\nn_train_images = 1000\nn_test_images = 300\n\n# set batch size\nbatch_size = 16\n\n# set num classes\nnum_classes = 5\n\n# set class names\nclass_names = ['tiger', 'lynx', 'bear', 'deer', 'bird']\n\n# define paths to train and test images\nimages_input_dir = 'kaggle/input/preprocess-images/tiger_classification/images'\nimages_sampled_dir = 'images'\n!mkdir -p \"$images_sampled_dir\"\ntrain_dir = images_input_dir + '/train'\ntrain_dir_sampled = images_sampled_dir + '/train_sampled'\ntest_dir = images_input_dir + '/test'\ntest_dir_sampled = images_sampled_dir + '/test_sampled'\ntest2_dir = images_input_dir + '/test2'\n\n# define path to model dir\nmodel_dir = project_dir + '/model'\n!mkdir -p \"$model_dir\"\nmodel_path = model_dir + '/model.h5'\n\n# define path to media dir\nmedia_dir = project_dir + '/media'\n!mkdir -p \"$media_dir\"","metadata":{"id":"4bedI2X2QDdf","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:02:57.136370Z","iopub.execute_input":"2024-12-03T21:02:57.136607Z","iopub.status.idle":"2024-12-03T21:03:00.102871Z","shell.execute_reply.started":"2024-12-03T21:02:57.136584Z","shell.execute_reply":"2024-12-03T21:03:00.101796Z"}},"outputs":[],"execution_count":4},{"cell_type":"code","source":"import os\nimport random\nimport shutil\nimport numpy as np\n\nimport keras\nfrom keras import layers, optimizers, losses, callbacks\nimport kimm\nimport tensorflow as tf\nimport tensorflow_datasets as tfds\nfrom sklearn.metrics import confusion_matrix, classification_report\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"id":"WNSWKPrzEzy_","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:03:00.104060Z","iopub.execute_input":"2024-12-03T21:03:00.104342Z","iopub.status.idle":"2024-12-03T21:03:12.013428Z","shell.execute_reply.started":"2024-12-03T21:03:00.104316Z","shell.execute_reply":"2024-12-03T21:03:12.012745Z"}},"outputs":[],"execution_count":5},{"cell_type":"code","source":"def sample_images(source_dir, target_dir, samples_per_class, seed=42):\n \"\"\"\n Samples a fixed number of images per class from a directory structure.\n\n Args:\n source_dir (str): Path to the source dataset directory.\n target_dir (str): Path to the target dataset directory to store sampled data.\n samples_per_class (int): Number of images to sample per class.\n seed (int): Random seed for reproducibility.\n \"\"\"\n random.seed(seed)\n\n if not os.path.exists(target_dir):\n os.makedirs(target_dir)\n\n for class_name in os.listdir(source_dir):\n class_path = os.path.join(source_dir, class_name)\n if os.path.isdir(class_path):\n sampled_class_dir = os.path.join(target_dir, class_name)\n os.makedirs(sampled_class_dir, exist_ok=True)\n\n # list and shuffle all files in class directory\n all_images = os.listdir(class_path)\n random.shuffle(all_images)\n\n # select desired number of samples\n sampled_images = all_images[:samples_per_class]\n\n # copy sampled images to new directory\n for image_name in sampled_images:\n source_image_path = os.path.join(class_path, image_name)\n target_image_path = os.path.join(sampled_class_dir, image_name)\n shutil.copy(source_image_path, target_image_path)","metadata":{"id":"RjGj2LDNR15z","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:03:12.014443Z","iopub.execute_input":"2024-12-03T21:03:12.014897Z","iopub.status.idle":"2024-12-03T21:03:12.021132Z","shell.execute_reply.started":"2024-12-03T21:03:12.014870Z","shell.execute_reply":"2024-12-03T21:03:12.020261Z"}},"outputs":[],"execution_count":6},{"cell_type":"markdown","source":"## Prepare train and test datasets","metadata":{"id":"o-oFY9SuE8dT"}},{"cell_type":"code","source":"# create new directory with sampled train images\nsample_images(train_dir, train_dir_sampled, n_train_images)","metadata":{"id":"KewO2flaRgLu","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:03:12.022486Z","iopub.execute_input":"2024-12-03T21:03:12.022834Z","iopub.status.idle":"2024-12-03T21:03:39.520712Z","shell.execute_reply.started":"2024-12-03T21:03:12.022797Z","shell.execute_reply":"2024-12-03T21:03:39.519605Z"}},"outputs":[],"execution_count":7},{"cell_type":"code","source":"# create new directory with sampled test images\nsample_images(test_dir, test_dir_sampled, n_test_images)","metadata":{"id":"feQggHlSWEh4","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:03:39.521812Z","iopub.execute_input":"2024-12-03T21:03:39.522977Z","iopub.status.idle":"2024-12-03T21:03:46.725090Z","shell.execute_reply.started":"2024-12-03T21:03:39.522925Z","shell.execute_reply":"2024-12-03T21:03:46.724472Z"}},"outputs":[],"execution_count":8},{"cell_type":"code","source":"# create train dataset\ntrain_ds = tf.keras.preprocessing.image_dataset_from_directory(\n train_dir_sampled,\n label_mode='categorical',\n shuffle=True,\n seed=seed,\n)\n\n# create test dataset\ntest_ds = tf.keras.preprocessing.image_dataset_from_directory(\n test_dir_sampled,\n label_mode='categorical',\n shuffle=False,\n)\n\n# create test2 dataset\ntest2_ds = tf.keras.preprocessing.image_dataset_from_directory(\n test2_dir,\n label_mode='categorical',\n shuffle=False,\n)\n\n# we need to unbatch because there's somehow an unwanted additional dimension\ntrain_ds = train_ds.unbatch()\ntest_ds = test_ds.unbatch()\ntest2_ds = test2_ds.unbatch()\n\nprint(f'Number of train samples: {train_ds.cardinality()}')\nprint(f'Number of test samples: {test_ds.cardinality()}')","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"J5i-u-VSE74K","outputId":"cda0d93f-4445-41f3-bb1b-5b1942d838b6","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:04:58.555448Z","iopub.execute_input":"2024-12-03T21:04:58.556263Z","iopub.status.idle":"2024-12-03T21:05:01.856039Z","shell.execute_reply.started":"2024-12-03T21:04:58.556230Z","shell.execute_reply":"2024-12-03T21:05:01.855228Z"}},"outputs":[{"name":"stdout","text":"Found 5000 files belonging to 5 classes.\nFound 1500 files belonging to 5 classes.\nFound 303 files belonging to 1 classes.\nNumber of train samples: -2\nNumber of test samples: -2\n","output_type":"stream"}],"execution_count":14},{"cell_type":"code","source":"# check dimensions\nprint(train_ds.element_spec, test_ds.element_spec)","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"myqLQZuqFZkx","outputId":"1636afdc-4dcd-4ad9-9041-bedfc196f415","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T20:47:08.138434Z","iopub.execute_input":"2024-12-03T20:47:08.138881Z","iopub.status.idle":"2024-12-03T20:47:08.143314Z","shell.execute_reply.started":"2024-12-03T20:47:08.138852Z","shell.execute_reply":"2024-12-03T20:47:08.142449Z"}},"outputs":[{"name":"stdout","text":"(TensorSpec(shape=(256, 256, 3), dtype=tf.float32, name=None), TensorSpec(shape=(5,), dtype=tf.float32, name=None)) (TensorSpec(shape=(256, 256, 3), dtype=tf.float32, name=None), TensorSpec(shape=(5,), dtype=tf.float32, name=None))\n","output_type":"stream"}],"execution_count":10},{"cell_type":"code","source":"# setup dataset with tf.data\nresize_fn = keras.layers.Resizing(224, 224)\n\ntrain_ds = train_ds.map(lambda x, y: (resize_fn(x), y))\ntest_ds = test_ds.map(lambda x, y: (resize_fn(x), y))\ntest2_ds = test2_ds.map(lambda x, y: (resize_fn(x), y))\n\ntrain_ds = train_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE).cache()\ntest_ds = test_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE).cache()\ntest2_ds = test2_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE).cache()","metadata":{"id":"YCc38anvFgJc","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:05:15.826463Z","iopub.execute_input":"2024-12-03T21:05:15.827277Z","iopub.status.idle":"2024-12-03T21:05:15.911476Z","shell.execute_reply.started":"2024-12-03T21:05:15.827245Z","shell.execute_reply":"2024-12-03T21:05:15.910845Z"}},"outputs":[],"execution_count":15},{"cell_type":"markdown","source":"## Prepare model","metadata":{"id":"CdVE1QLMFtA5"}},{"cell_type":"code","source":"# create base model\nbase_model = kimm.models.EfficientNetV2B0(\n input_shape=(224, 224, 3),\n include_preprocessing=True,\n include_top=False,\n)\n\n# freeze base model\nbase_model.trainable = False\n\n# create new model on top\ninputs = keras.Input(shape=(224, 224, 3))\nx = inputs\n\n# The base model contains batchnorm layers. We want to keep them in inference mode\n# when we unfreeze the base model for fine-tuning, so we make sure that the\n# base_model is running in inference mode here.\nx = base_model(x, training=False)\nx = keras.layers.GlobalAveragePooling2D()(x)\nx = keras.layers.Dropout(0.2)(x) # regularize with dropout\noutputs = keras.layers.Dense(num_classes, activation='softmax')(x)\nmodel = keras.Model(inputs, outputs)\n\nmodel.summary(show_trainable=True)","metadata":{"id":"3mmwlJBDFf_6","colab":{"base_uri":"https://localhost:8080/","height":359},"outputId":"73087a5a-85e9-43f0-bdee-b067a8168bcb","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:05:22.433770Z","iopub.execute_input":"2024-12-03T21:05:22.434619Z","iopub.status.idle":"2024-12-03T21:05:27.947501Z","shell.execute_reply.started":"2024-12-03T21:05:22.434585Z","shell.execute_reply":"2024-12-03T21:05:27.946738Z"}},"outputs":[{"name":"stdout","text":"Downloading data from https://github.com/james77777778/keras-image-models/releases/download/0.1.0/efficientnetv2b0_tf_efficientnetv2_b0.in1k.keras\n\u001b[1m29451563/29451563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 0us/step\n","output_type":"stream"},{"output_type":"display_data","data":{"text/plain":"\u001b[1mModel: \"functional\"\u001b[0m\n","text/html":"
Model: \"functional\"\n
\n"},"metadata":{}},{"output_type":"display_data","data":{"text/plain":"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━┓\n┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mTrai…\u001b[0m\u001b[1m \u001b[0m┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━┩\n│ input_layer_1 (\u001b[38;5;33mInputLayer\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m224\u001b[0m, \u001b[38;5;34m224\u001b[0m, \u001b[38;5;34m3\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ \u001b[1m-\u001b[0m │\n├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n│ EfficientNetV2B0 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m7\u001b[0m, \u001b[38;5;34m7\u001b[0m, \u001b[38;5;34m1280\u001b[0m) │ \u001b[38;5;34m5,919,312\u001b[0m │ \u001b[1;91mN\u001b[0m │\n│ (\u001b[38;5;33mEfficientNetV2B0\u001b[0m) │ │ │ │\n├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n│ global_average_pooling2d │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1280\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ \u001b[1m-\u001b[0m │\n│ (\u001b[38;5;33mGlobalAveragePooling2D\u001b[0m) │ │ │ │\n├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n│ dropout (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1280\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ \u001b[1m-\u001b[0m │\n├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n│ dense (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m5\u001b[0m) │ \u001b[38;5;34m6,405\u001b[0m │ \u001b[1;38;5;34mY\u001b[0m │\n└─────────────────────────────┴───────────────────────┴────────────┴───────┘\n","text/html":"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━┓\n┃ Layer (type)                 Output Shape              Param #  Trai… ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━┩\n│ input_layer_1 (InputLayer)  │ (None, 224, 224, 3)   │          0-   │\n├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n│ EfficientNetV2B0            │ (None, 7, 7, 1280)    │  5,919,312N   │\n│ (EfficientNetV2B0)          │                       │            │       │\n├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n│ global_average_pooling2d    │ (None, 1280)          │          0-   │\n│ (GlobalAveragePooling2D)    │                       │            │       │\n├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n│ dropout (Dropout)           │ (None, 1280)          │          0-   │\n├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n│ dense (Dense)               │ (None, 5)             │      6,405Y   │\n└─────────────────────────────┴───────────────────────┴────────────┴───────┘\n
\n"},"metadata":{}},{"output_type":"display_data","data":{"text/plain":"\u001b[1m Total params: \u001b[0m\u001b[38;5;34m5,925,717\u001b[0m (22.60 MB)\n","text/html":"
 Total params: 5,925,717 (22.60 MB)\n
\n"},"metadata":{}},{"output_type":"display_data","data":{"text/plain":"\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m6,405\u001b[0m (25.02 KB)\n","text/html":"
 Trainable params: 6,405 (25.02 KB)\n
\n"},"metadata":{}},{"output_type":"display_data","data":{"text/plain":"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m5,919,312\u001b[0m (22.58 MB)\n","text/html":"
 Non-trainable params: 5,919,312 (22.58 MB)\n
\n"},"metadata":{}}],"execution_count":16},{"cell_type":"markdown","source":"## Training\n\nFollow [mewc-train](https://github.com/zaandahl/mewc-train)","metadata":{"id":"YcYVdF_1F9EQ"}},{"cell_type":"code","source":"# df_size = 2500\n\nepochs = 50\n\nlr_init = 1e-4\n# min_lr_frac = 1/5 # default minimum learning rate fraction of initial learning rate\n# steps_per_epoch = df_size // batch_size\n# total_steps = epochs * steps_per_epoch # total number of steps for monotonic exponential decay across all epochs\n# lr = optimizers.schedules.ExponentialDecay(initial_learning_rate=lr_init, decay_steps=total_steps, decay_rate=min_lr_frac, staircase=False)\namsgrad = True\nweight_decay = 1e-4\noptimizer = optimizers.AdamW(learning_rate=lr_init, amsgrad=amsgrad, weight_decay=weight_decay)\n\n# if num_classes == 2:\n# loss_f = losses.BinaryFocalCrossentropy() # use for binary classification tasks\n# act_f = 'sigmoid' # use for binary classification tasks\n# else:\n# loss_f = losses.CategoricalFocalCrossentropy() # use for unbalanced multi-class tasks (typical for wildlife datasets)\n# act_f = 'softmax' # use for multi-class classification tasks\nloss_f = losses.CategoricalCrossentropy()\n\nmetrics = ['accuracy']\n\ncallbacks = [callbacks.EarlyStopping(monitor='loss', mode='min', min_delta=0.001, patience=5, restore_best_weights=True)]","metadata":{"id":"Ho-88Fe_GxVd","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:05:27.948956Z","iopub.execute_input":"2024-12-03T21:05:27.949229Z","iopub.status.idle":"2024-12-03T21:05:27.958565Z","shell.execute_reply.started":"2024-12-03T21:05:27.949198Z","shell.execute_reply":"2024-12-03T21:05:27.957900Z"}},"outputs":[],"execution_count":17},{"cell_type":"code","source":"model.compile(\n optimizer=optimizer,\n loss=loss_f,\n metrics=metrics,\n)","metadata":{"id":"fAHCE7OrGCGF","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:05:27.959363Z","iopub.execute_input":"2024-12-03T21:05:27.959578Z","iopub.status.idle":"2024-12-03T21:05:27.980848Z","shell.execute_reply.started":"2024-12-03T21:05:27.959548Z","shell.execute_reply":"2024-12-03T21:05:27.980000Z"}},"outputs":[],"execution_count":18},{"cell_type":"code","source":"model.fit(train_ds, epochs=epochs, callbacks=callbacks)","metadata":{"id":"GZKd2EixF8yO","colab":{"base_uri":"https://localhost:8080/"},"outputId":"e8424e62-1116-4b52-90af-5fe25403927f","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:05:27.982341Z","iopub.execute_input":"2024-12-03T21:05:27.982584Z","iopub.status.idle":"2024-12-03T21:10:37.520153Z","shell.execute_reply.started":"2024-12-03T21:05:27.982561Z","shell.execute_reply":"2024-12-03T21:10:37.519373Z"}},"outputs":[{"name":"stdout","text":"Epoch 1/50\n","output_type":"stream"},{"name":"stderr","text":"WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\nI0000 00:00:1733259935.852964 213 service.cc:145] XLA service 0x7da8d0002050 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:\nI0000 00:00:1733259935.853039 213 service.cc:153] StreamExecutor device (0): Tesla T4, Compute Capability 7.5\nI0000 00:00:1733259935.853045 213 service.cc:153] StreamExecutor device (1): Tesla T4, Compute Capability 7.5\n","output_type":"stream"},{"name":"stdout","text":" 5/Unknown \u001b[1m16s\u001b[0m 33ms/step - accuracy: 0.1069 - loss: 1.8373","output_type":"stream"},{"name":"stderr","text":"I0000 00:00:1733259943.337190 213 device_compiler.h:188] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process.\n","output_type":"stream"},{"name":"stdout","text":" 313/Unknown \u001b[1m31s\u001b[0m 49ms/step - accuracy: 0.3650 - loss: 1.4763","output_type":"stream"},{"name":"stderr","text":"/opt/conda/lib/python3.10/site-packages/keras/src/trainers/epoch_iterator.py:151: UserWarning: Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches. You may need to use the `.repeat()` function when building your dataset.\n self._interrupted_warning()\n","output_type":"stream"},{"name":"stdout","text":"\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m31s\u001b[0m 50ms/step - accuracy: 0.3655 - loss: 1.4756\nEpoch 2/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.7534 - loss: 0.8291\nEpoch 3/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.8039 - loss: 0.6425\nEpoch 4/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.8151 - loss: 0.5599\nEpoch 5/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.8258 - loss: 0.5161\nEpoch 6/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.8463 - loss: 0.4793\nEpoch 7/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.8506 - loss: 0.4562\nEpoch 8/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.8517 - loss: 0.4407\nEpoch 9/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.8592 - loss: 0.4262\nEpoch 10/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 17ms/step - accuracy: 0.8608 - loss: 0.4123\nEpoch 11/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 18ms/step - accuracy: 0.8642 - loss: 0.4008\nEpoch 12/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 18ms/step - accuracy: 0.8612 - loss: 0.3954\nEpoch 13/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8732 - loss: 0.3854\nEpoch 14/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8698 - loss: 0.3788\nEpoch 15/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8812 - loss: 0.3677\nEpoch 16/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8761 - loss: 0.3664\nEpoch 17/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8789 - loss: 0.3598\nEpoch 18/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8814 - loss: 0.3565\nEpoch 19/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8795 - loss: 0.3504\nEpoch 20/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8821 - loss: 0.3434\nEpoch 21/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8875 - loss: 0.3414\nEpoch 22/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8864 - loss: 0.3364\nEpoch 23/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8895 - loss: 0.3311\nEpoch 24/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8911 - loss: 0.3272\nEpoch 25/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8926 - loss: 0.3252\nEpoch 26/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8879 - loss: 0.3222\nEpoch 27/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8927 - loss: 0.3184\nEpoch 28/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8947 - loss: 0.3164\nEpoch 29/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.8952 - loss: 0.3072\nEpoch 30/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8966 - loss: 0.3108\nEpoch 31/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8980 - loss: 0.3075\nEpoch 32/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.8990 - loss: 0.3033\nEpoch 33/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9059 - loss: 0.2954\nEpoch 34/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9017 - loss: 0.2956\nEpoch 35/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9044 - loss: 0.2987\nEpoch 36/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9033 - loss: 0.2920\nEpoch 37/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.9080 - loss: 0.2891\nEpoch 38/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9054 - loss: 0.2907\nEpoch 39/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.9067 - loss: 0.2880\nEpoch 40/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.9050 - loss: 0.2825\nEpoch 41/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9041 - loss: 0.2873\nEpoch 42/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9051 - loss: 0.2864\nEpoch 43/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9092 - loss: 0.2821\nEpoch 44/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.9100 - loss: 0.2785\nEpoch 45/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9085 - loss: 0.2797\nEpoch 46/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9093 - loss: 0.2782\nEpoch 47/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.9116 - loss: 0.2704\nEpoch 48/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 18ms/step - accuracy: 0.9096 - loss: 0.2710\nEpoch 49/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.9087 - loss: 0.2709\nEpoch 50/50\n\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 19ms/step - accuracy: 0.9112 - loss: 0.2671\n","output_type":"stream"},{"execution_count":19,"output_type":"execute_result","data":{"text/plain":""},"metadata":{}}],"execution_count":19},{"cell_type":"code","source":"model.save(model_path, save_format='h5')","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ik4KqmJdUbKd","outputId":"d168634b-b029-4bf1-cf87-e280ace945fb","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:10:37.521118Z","iopub.execute_input":"2024-12-03T21:10:37.521376Z","iopub.status.idle":"2024-12-03T21:10:37.757406Z","shell.execute_reply.started":"2024-12-03T21:10:37.521352Z","shell.execute_reply":"2024-12-03T21:10:37.756724Z"}},"outputs":[],"execution_count":20},{"cell_type":"markdown","source":"## Evaluation","metadata":{"id":"qIGU25KNO1sp"}},{"cell_type":"code","source":"result = model.evaluate(test_ds)\nprint(f'Test accuracy: {result[1] * 100:3.2f}%')","metadata":{"id":"40b_QINGGF7Y","colab":{"base_uri":"https://localhost:8080/"},"outputId":"16936959-2cfe-4005-b038-43eab764abab","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:10:37.758372Z","iopub.execute_input":"2024-12-03T21:10:37.758627Z","iopub.status.idle":"2024-12-03T21:10:50.981516Z","shell.execute_reply.started":"2024-12-03T21:10:37.758601Z","shell.execute_reply":"2024-12-03T21:10:50.980585Z"}},"outputs":[{"name":"stdout","text":"\u001b[1m94/94\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m13s\u001b[0m 96ms/step - accuracy: 0.9193 - loss: 0.2617\nTest accuracy: 88.13%\n","output_type":"stream"}],"execution_count":21},{"cell_type":"code","source":"result2 = model.evaluate(test2_ds)\nprint(f'Test2 accuracy: {result2[1] * 100:3.2f}%')","metadata":{"id":"zyDqRJSEGM4L","colab":{"base_uri":"https://localhost:8080/"},"outputId":"09e78303-ee89-418f-cef9-f1a4900de3f2","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:10:50.982509Z","iopub.execute_input":"2024-12-03T21:10:50.982798Z","iopub.status.idle":"2024-12-03T21:10:59.669602Z","shell.execute_reply.started":"2024-12-03T21:10:50.982771Z","shell.execute_reply":"2024-12-03T21:10:59.668778Z"}},"outputs":[{"name":"stdout","text":"\u001b[1m19/19\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m9s\u001b[0m 238ms/step - accuracy: 0.8517 - loss: 25.4893\nTest2 accuracy: 86.47%\n","output_type":"stream"}],"execution_count":22},{"cell_type":"code","source":"true_labels = []\npredicted_classes = []\n\nfor images, labels in test_ds:\n # append true labels based on their format\n if len(labels.shape) > 1: # if one-hot encoded\n true_labels.append(np.argmax(labels.numpy(), axis=1))\n else: # if integer labels\n true_labels.append(labels.numpy())\n\n # predict classes\n predictions = model.predict(images)\n predicted_classes.append(np.argmax(predictions, axis=1))\n\n# combine all batches into single arrays\ntrue_labels = np.concatenate(true_labels)\npredicted_classes = np.concatenate(predicted_classes)","metadata":{"id":"hpMkylclPBAB","colab":{"base_uri":"https://localhost:8080/"},"outputId":"909e4490-b5b4-48ff-a2a6-71f42226d86e","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:10:59.670941Z","iopub.execute_input":"2024-12-03T21:10:59.671326Z","iopub.status.idle":"2024-12-03T21:11:16.562551Z","shell.execute_reply.started":"2024-12-03T21:10:59.671287Z","shell.execute_reply":"2024-12-03T21:11:16.561899Z"}},"outputs":[{"name":"stdout","text":"\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 4s/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 66ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 62ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 61ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 57ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 60ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 69ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 65ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 59ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step\n\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 4s/step\n","output_type":"stream"}],"execution_count":23},{"cell_type":"code","source":"cm = confusion_matrix(true_labels, predicted_classes)\nprint('Confusion matrix:\\n', cm)","metadata":{"id":"vYjCERt3PNQX","colab":{"base_uri":"https://localhost:8080/"},"outputId":"a6eaab6b-1891-44a3-a150-8ef7a86474fc","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:11:16.563575Z","iopub.execute_input":"2024-12-03T21:11:16.563865Z","iopub.status.idle":"2024-12-03T21:11:16.571119Z","shell.execute_reply.started":"2024-12-03T21:11:16.563838Z","shell.execute_reply":"2024-12-03T21:11:16.570188Z"}},"outputs":[{"name":"stdout","text":"Confusion matrix:\n [[287 1 2 1 9]\n [ 0 262 9 12 17]\n [ 1 12 271 6 10]\n [ 2 22 13 245 18]\n [ 5 4 15 19 257]]\n","output_type":"stream"}],"execution_count":24},{"cell_type":"code","source":"report = classification_report(true_labels, predicted_classes, target_names=class_names)\nprint('Classification report:\\n', report)","metadata":{"id":"9db2EW1LPRzc","colab":{"base_uri":"https://localhost:8080/"},"outputId":"2f0bc5bf-cf72-4972-8656-228d67f6161d","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:11:16.573101Z","iopub.execute_input":"2024-12-03T21:11:16.573381Z","iopub.status.idle":"2024-12-03T21:11:16.588752Z","shell.execute_reply.started":"2024-12-03T21:11:16.573353Z","shell.execute_reply":"2024-12-03T21:11:16.588059Z"}},"outputs":[{"name":"stdout","text":"Classification report:\n precision recall f1-score support\n\n tiger 0.97 0.96 0.96 300\n lynx 0.87 0.87 0.87 300\n bear 0.87 0.90 0.89 300\n deer 0.87 0.82 0.84 300\n bird 0.83 0.86 0.84 300\n\n accuracy 0.88 1500\n macro avg 0.88 0.88 0.88 1500\nweighted avg 0.88 0.88 0.88 1500\n\n","output_type":"stream"}],"execution_count":25},{"cell_type":"code","source":"plt.figure(figsize=(10, 8))\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=class_names, yticklabels=class_names)\nplt.xlabel('Predicted')\nplt.ylabel('True')\nplt.title('Confusion matrix')\nconfusion_matrix_path = media_dir + '/confusion_matrix.png'\nplt.savefig(confusion_matrix_path, dpi=300, bbox_inches='tight')\nplt.show()","metadata":{"id":"oc7KSHEBPV8o","colab":{"base_uri":"https://localhost:8080/","height":718},"outputId":"d378ad2e-85be-46c7-914c-0bbf12c9ade0","trusted":true,"execution":{"iopub.status.busy":"2024-12-03T21:11:16.589628Z","iopub.execute_input":"2024-12-03T21:11:16.589879Z","iopub.status.idle":"2024-12-03T21:11:17.492361Z","shell.execute_reply.started":"2024-12-03T21:11:16.589855Z","shell.execute_reply":"2024-12-03T21:11:17.491443Z"}},"outputs":[{"output_type":"display_data","data":{"text/plain":"
","image/png":"iVBORw0KGgoAAAANSUhEUgAAAxQAAAK9CAYAAAC95yoDAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuNSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/xnp5ZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABx9UlEQVR4nO3dd3yN5//H8fdJyJBIgojE3rF3S+yi1FYd9Ks1ipbaoVTVHlGbDqpWUa1Wt7bUVrM2taVKqa1GQiLj/P7wc3qOBDl3k9yJvJ4e9+ORc93rc59bxud8ruu+LFar1SoAAAAAMMDF7AAAAAAApF8kFAAAAAAMI6EAAAAAYBgJBQAAAADDSCgAAAAAGEZCAQAAAMAwEgoAAAAAhpFQAAAAADCMhAIAAACAYSQUAHCf48ePq2HDhvL19ZXFYtG3336brMf/888/ZbFYtGDBgmQ97uOgYMGC6tixo9lhAACcQEIBIE0KDw/X66+/rsKFC8vDw0M+Pj6qUaOGpk+frtu3b6fouTt06KADBw5o7NixWrRokapUqZKi53scHTp0SCNGjNCff/5pdigAgBRmsVqtVrODAAB7P/74o1544QW5u7urffv2KlOmjO7cuaNNmzbpq6++UseOHTV79uwUOfft27eVJUsWDRkyRGPGjEmRc1itVkVHRytz5sxydXVNkXOYbdmyZXrhhRe0bt061a1bN8n7RUdHy8XFRZkzZ0654AAAySqT2QEAgL2TJ0+qbdu2KlCggNauXaugoCDbuh49eujEiRP68ccfU+z8ly5dkiT5+fml2DksFos8PDxS7PjpjdVqVVRUlDw9PeXu7m52OAAAJ9HlCUCaMmHCBEVERGju3LkOycQ9RYsWVZ8+fWyvY2NjNXr0aBUpUkTu7u4qWLCg3n77bUVHRzvsV7BgQTVr1kybNm3Sk08+KQ8PDxUuXFgLFy60bTNixAgVKFBAkvTmm2/KYrGoYMGCkqSOHTvavrY3YsQIWSwWh7ZVq1apZs2a8vPzk7e3t4KDg/X222/b1j9oDMXatWtVq1YteXl5yc/PTy1bttThw4cTPd+JEyfUsWNH+fn5ydfXV506ddKtW7ce/Mb+v7p166pMmTLav3+/6tSpoyxZsqho0aJatmyZJGnDhg2qWrWqPD09FRwcrNWrVzvsf+rUKb3xxhsKDg6Wp6encuTIoRdeeMGha9OCBQv0wgsvSJKeeuopWSwWWSwWrV+/XtK/92LlypWqUqWKPD099dFHH9nW3RtDYbVa9dRTTylnzpy6ePGi7fh37txR2bJlVaRIEUVGRj7ymgEAKYuEAkCa8sMPP6hw4cKqXr16krbv0qWLhg0bpkqVKmnq1KmqU6eOwsLC1LZt2wTbnjhxQs8//7yefvppTZ48WdmyZVPHjh118OBBSVLr1q01depUSdJLL72kRYsWadq0aU7Ff/DgQTVr1kzR0dEaNWqUJk+erBYtWmjz5s0P3W/16tVq1KiRLl68qBEjRig0NFRbtmxRjRo1Eh2H8OKLL+rmzZsKCwvTiy++qAULFmjkyJFJivGff/5Rs2bNVLVqVU2YMEHu7u5q27atli5dqrZt26pJkyYaP368IiMj9fzzz+vmzZu2fXfs2KEtW7aobdu2mjFjhrp166Y1a9aobt26toSmdu3a6t27tyTp7bff1qJFi7Ro0SKVLFnSdpyjR4/qpZde0tNPP63p06erQoUKCeK0WCyaN2+eoqKi1K1bN1v78OHDdfDgQc2fP19eXl5JumYAQAqyAkAacf36daska8uWLZO0/d69e62SrF26dHFoHzBggFWSde3atba2AgUKWCVZN27caGu7ePGi1d3d3dq/f39b28mTJ62SrBMnTnQ4ZocOHawFChRIEMPw4cOt9j9Kp06dapVkvXTp0gPjvneO+fPn29oqVKhgDQgIsF65csXWtm/fPquLi4u1ffv2Cc736quvOhzz2WeftebIkeOB57ynTp06VknWJUuW2NqOHDlilWR1cXGxbtu2zda+cuXKBHHeunUrwTG3bt1qlWRduHChre3LL7+0SrKuW7cuwfb37sWKFSsSXdehQweHto8++sgqybp48WLrtm3brK6urta+ffs+8loBAKmDCgWANOPGjRuSpKxZsyZp+59++kmSFBoa6tDev39/SUow1qJUqVKqVauW7XXOnDkVHBysP/74w3DM97s39uK7775TfHx8kvY5d+6c9u7dq44dOyp79uy29nLlyunpp5+2Xac9+0/sJalWrVq6cuWK7T18GG9vb4cKTnBwsPz8/FSyZElVrVrV1n7va/v3x9PT0/Z1TEyMrly5oqJFi8rPz0+7d+9OwtXeVahQITVq1ChJ27722mtq1KiRevXqpVdeeUVFihTRuHHjknwuAEDK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ebNatmypl19+WZIUHx+vY8eOqVSpUikeN5xTpEgRZc6cWdu3b7f98f/PP//o2LFjqlOnTpLud6VKlXTo0CF+nqdDD/o+vz95fJCSJUtq+/btat++vcMxgLSIhCKNKViwoLZv364///xT3t7eCT517tWrl2rXrq0pU6aoefPmWrt2rX7++WeHsuqwYcPUrFkz5c+fX88//7xcXFy0b98+/f777xozZkxqXxIM6NKli0qWLCnp7h+QzurWrZvy5cund955R9HR0apYsaIGDBigDz74ILlDhQGnT59WaGioXn/9de3evVvvvfeeJk+erOLFi6tdu3Zq3769Jk+erIoVK+rSpUtas2aNypUrp6ZNm6pYsWJatmyZtmzZomzZsmnKlCm6cOECCUUa5O3trc6dO+vNN99Ujhw5FBAQoCFDhsjF5W5v46Tc70GDBqlatWrq2bOnunTpIi8vLx06dEirVq3S+++/b/IV4mEe9H2eVH369FHHjh1VpUoV1ahRQ59++qkOHjyowoULp2DUgDGMoUhjBgwYIFdXV5UqVUo5c+ZM0C+6Ro0amjVrlqZMmaLy5ctrxYoV6tevn0NXpkaNGmn58uX65Zdf9MQTT6hatWqaOnWqChQokNqXA4OKFSum6tWrq0SJEgn60D7KwoUL9dNPP2nRokXKlCmTvLy8tHjxYn388cf6+eefUyhiOKN9+/a6ffu2nnzySfXo0UN9+vSxPepz/vz5at++vfr376/g4GC1atVKO3bssH3C/c4776hSpUpq1KiR6tatq8DAQLVq1crEq8HDTJw4UbVq1VLz5s3VoEED1axZ02F8y6Pud7ly5bRhwwYdO3ZMtWrVUsWKFTVs2DDlzp3brEtCEj3s+zwp2rRpo6FDh2rgwIGqXLmyTp06pe7du6dgxIBxFqv1/x+KjHSra9euOnLkiH799VezQ0EysVqtKlasmN544w2FhoaaHQ4AAMAD0eUpHZo0aZKefvppeXl56eeff9Ynn3yiDz/80OywkEwuXbqkzz//XOfPn1enTp3MDgcAAOChSCjSod9++00TJkzQzZs3VbhwYc2YMUNdunQxOywkk4CAAPn7+2v27NnKli2b2eEAAAA8FF2eAAAAABjGoGwAAAAAhpFQAAAAADCMhAIAAACAYSQUAAAAAAwjoQAAAABgGAkFAKQxHTt2dJj9um7duurbt2+qx7F+/XpZLBZdu3Yt1c8NAEg/SCgAIIk6duwoi8Uii8UiNzc3FS1aVKNGjVJsbGyKnvfrr7/W6NGjk7QtSQAAILUxsR0AOOGZZ57R/PnzFR0drZ9++kk9evRQ5syZNXjwYIft7ty5Izc3t2Q5Z/bs2ZPlOAAApAQqFADgBHd3dwUGBqpAgQLq3r27GjRooO+//97WTWns2LHKnTu3goODJUl//fWXXnzxRfn5+Sl79uxq2bKl/vzzT9vx4uLiFBoaKj8/P+XIkUMDBw7U/fON3t/lKTo6WoMGDVK+fPnk7u6uokWLau7cufrzzz/11FNPSZKyZcsmi8Wijh07SpLi4+MVFhamQoUKydPTU+XLl9eyZcsczvPTTz+pePHi8vT01FNPPeUQJwAAD0JCAQD/gaenp+7cuSNJWrNmjY4ePapVq1Zp+fLliomJUaNGjZQ1a1b9+uuv2rx5s7y9vfXMM8/Y9pk8ebIWLFigefPmadOmTbp69aq++eabh56zffv2+uyzzzRjxgwdPnxYH330kby9vZUvXz599dVXkqSjR4/q3Llzmj59uiQpLCxMCxcu1KxZs3Tw4EH169dPL7/8sjZs2CDpbuLTunVrNW/eXHv37lWXLl301ltvpdTbBgB4jNDlCQAMsFqtWrNmjVauXKlevXrp0qVL8vLy0pw5c2xdnRYvXqz4+HjNmTNHFotFkjR//nz5+flp/fr1atiwoaZNm6bBgwerdevWkqRZs2Zp5cqVDzzvsWPH9MUXX2jVqlVq0KCBJKlw4cK29fe6RwUEBMjPz0/S3YrGuHHjtHr1aoWEhNj22bRpkz766CPVqVNHM2fOVJEiRTR58mRJUnBwsA4cOKB33303Gd81AMDjiIQCAJywfPlyeXt7KyYmRvHx8frf//6nESNGqEePHipbtqzDuIl9+/bpxIkTypo1q8MxoqKiFB4eruvXr+vcuXOqWrWqbV2mTJlUpUqVBN2e7tm7d69cXV1Vp06dJMd84sQJ3bp1S08//bRD+507d1SxYkVJ0uHDhx3ikGRLPgAAeBgSCgBwwlNPPaWZM2fKzc1NuXPnVqZM//4Y9fLyctg2IiJClStX1qeffprgODlz5jR0fk9PT6f3iYiIkCT9+OOPypMnj8M6d3d3Q3EAAHAPCQUAOMHLy0tFixZN0raVKlXS0qVLFRAQIB8fn0S3CQoK0vbt21W7dm1JUmxsrHbt2qVKlSolun3ZsmUVHx+vDRs22Lo82btXIYmLi7O1lSpVSu7u7jp9+vQDKxslS5bU999/79C2bdu2R18kACDDY1A2AKSQdu3ayd/fXy1bttSvv/6qkydPav369erdu7fOnDkjSerTp4/Gjx+vb7/9VkeOHNEbb7zx0DkkChYsqA4dOujVV1/Vt99+azvmF198IUkqUKCALBaLli9frkuXLikiIkJZs2bVgAED1K9fP33yyScKDw/X7t279d577+mTTz6RJHXr1k3Hjx/Xm2++qaNHj2rJkiVasGBBSr9FAIDHAAkFAKSQLFmyaOPGjcqfP79at26tkiVLqnPnzoqKirJVLPr3769XXnlFHTp0UEhIiLJmzapnn332ocedOXOmnn/+eb3xxhsqUaKEunbtqsjISElSnjx5NHLkSL311lvKlSuXevbsKUkaPXq0hg4dqrCwMJUsWVLPPPOMfvzxRxUqVEiSlD9/fn311Vf69ttvVb58ec2aNUvjxo1LwXcHAPC4sFgfNPIPAAAAAB6BCgUAAAAAw0goAAAAABhGQgEAAADAMBIKAAAAAIaRUAAAAAAwjIQCAAAAgGEkFAAAAAAMI6EAAAAAYBgJBQAAAADDSCgAAAAAGEZCAQAAAMCw/wNAQ8msQB1A7gAAAABJRU5ErkJggg=="},"metadata":{}}],"execution_count":26}]} \ No newline at end of file