{ "cells": [ { "cell_type": "markdown", "id": "dabed352-d637-47d9-b1c0-b99c407f2f8d", "metadata": {}, "source": [ "# Data Exploration and Preparation" ] }, { "cell_type": "code", "execution_count": 1, "id": "bc1b7bf2-84da-495d-939a-358c94859631", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-01-19 20:47:16.372082: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:485] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n", "2025-01-19 20:47:16.396318: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:8454] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n", "2025-01-19 20:47:16.402421: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1452] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n", "2025-01-19 20:47:16.420317: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n", "To enable the following instructions: SSE4.1 SSE4.2 AVX AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n" ] } ], "source": [ "import tensorflow as tf\n", "from tensorflow import keras\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from keras.datasets import mnist\n", "from keras import Sequential\n", "from keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, Dropout" ] }, { "cell_type": "code", "execution_count": 2, "id": "f19a0fc3-be77-44a4-a013-a5c46e967c55", "metadata": {}, "outputs": [], "source": [ "mnist = mnist\n", "(train_images, train_labels), (test_images, test_labels) = mnist.load_data()" ] }, { "cell_type": "markdown", "id": "4044a79e-b763-422c-a555-c7fa258b1f66", "metadata": {}, "source": [ "## Inspection of the dataset" ] }, { "cell_type": "code", "execution_count": 3, "id": "41ba16c1-b75f-4cd9-adf5-41506b733598", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "train set dimensions (60000, 28, 28)\n", "train set labels [5 0 4 ... 5 6 8]\n", "-------------------\n", "test set dimensions (10000, 28, 28)\n" ] } ], "source": [ "print('train set dimensions ', train_images.shape)\n", "print('train set labels', train_labels)\n", "print('-------------------')\n", "print('test set dimensions',test_images.shape)" ] }, { "cell_type": "code", "execution_count": 4, "id": "a9100043-9679-4ad1-9e7b-14e34d68c4fa", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Unique classes in the MNIST train set [0 1 2 3 4 5 6 7 8 9]\n", "Frequency of unique classes in MNIST train set (array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8), array([5923, 6742, 5958, 6131, 5842, 5421, 5918, 6265, 5851, 5949]))\n" ] } ], "source": [ "print ('Unique classes in the MNIST train set', np. unique(train_labels))\n", "print ('Frequency of unique classes in MNIST train set', np. unique(train_labels, return_counts=True))" ] }, { "cell_type": "code", "execution_count": 5, "id": "8936b73d-00c0-40dd-bd36-e0f19ee52992", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Unique classes in the MNIST test set [0 1 2 3 4 5 6 7 8 9]\n", "Frequency of unique classes in MNIST test set (array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8), array([ 980, 1135, 1032, 1010, 982, 892, 958, 1028, 974, 1009]))\n" ] } ], "source": [ "print ('Unique classes in the MNIST test set', np. unique(test_labels))\n", "print ('Frequency of unique classes in MNIST test set', np. unique(test_labels, return_counts=True))" ] }, { "cell_type": "code", "execution_count": 6, "id": "4c550e46-f950-425d-9ae9-debdaa8971f2", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAB8YAAADbCAYAAAAf6PubAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAse0lEQVR4nO3de7zWY7o/8HtlJcUUKoWmQg6RLIQy7TIkpKHROI0ipxqn2FthaAzjfNwvNM7kUNvhJQkbaUgYldrt2AlTISWpQQdJyXp+f+zf2Ez3vaxnrWetZ/Xt/f7LfK6u7/dapnt9n/VcPSrJ5XK5AAAAAAAAAAAZVa/YAwAAAAAAAABATbIYBwAAAAAAACDTLMYBAAAAAAAAyDSLcQAAAAAAAAAyzWIcAAAAAAAAgEyzGAcAAAAAAAAg0yzGAQAAAAAAAMg0i3EAAAAAAAAAMs1iHAAAAAAAAIBMsxgvgLZt24aZM2dW+td/9NFHoVmzZnnf55VXXgmdOnWq9Ey77LJLKCsrC2VlZeGxxx7L+35QHXXxXMyePTvsv//+Yaeddgr77rtvmDVrVt73g+qqi2fjHy6//PJQUlKS13xQCHXxXAwePDi0bdvWmaCo6uLZeOGFF0KnTp1Cx44dQ+fOncNbb72V9/2gOuraufjmm29Cnz59wk477RTKysrCoYceGj766KO87wfVVdfORgheT1F8dfFc9OzZM3Ts2DGUlZWFf/mXfwkzZszI+35QXXXxbHhmUGx18Vz8g/dsC8tiPMOeeOKJMGPGjDBjxoxw7LHHFnscKLpBgwaFgQMHhr/97W/hggsuCKeeemqxR4I6Y/r06WHy5MmhdevWxR4F6oTf/OY34fXXXw9t2rQp9ihQZ3z55ZehX79+4eGHHw5vv/12uO6668IJJ5xQ7LGg6AYOHBjef//9MGPGjNC7d+8wcODAYo8EdYLXU7Cuxx9/PLz99tthxowZ4fzzzw+nnHJKsUeCOsEzA+K8Z1t4FuM1aOjQoWGfffYJZWVloXv37mH27Nk/qg8ZMiTst99+Ybfddgsvv/zy9/m4ceNC165dw9577x3222+/8Oqrr9b26FBjinUuFi9eHKZPnx769esXQgihb9++4cMPP/RpDuqMYj4zVq9eHc4666xw++23h5KSkmp/LVAoxTwX3bp1C61atar21wA1oVhnY+7cuWGrrbYK7du3DyGE0L179zBv3rwwffr06n9RUE3FOhebbLJJ6NWr1/evoTp37hw++OCD6n9BUCBeT8G6inkuNt988+//edmyZaFePW/PU3d4ZsC6vGebQTmqrU2bNrn/+Z//WSdfsmTJ9//8yCOP5A4//PBcLpfLffjhh7kQQu6BBx7I5XK53KRJk3ItWrTIffXVV7m5c+fmunTpklu2bFkul8vlZs+endtmm21ya9asyU2YMCG39957f3/Nww47LDd16tTkTB07dsx16NAhd+qpp+YWL15csK8XKqOunYtp06bl2rdv/6Nsn332yU2cOLH6Xyzkoa6djVwul7vgggtyw4cPr3A+qEl18Vz81GxQG+ra2Vi6dGmuWbNmuUmTJuVyuVzuySefzIUQcqNHjy7cFw0/oa6di3/Wv3//3HnnnVetrxGqoi6fDa+nKJa6ei769++fa9WqVa5Vq1a5mTNnFuRrhXzU1bNR0WxQ0+riufCebc0oLdI+foPw4osvhttuuy2sWLEilJeXh+XLl39f23jjjUP//v1DCP/7J8pbtmwZ3nrrrTBjxowwZ86c0K1btx9da/78+etc/7nnnkve+9VXXw2tW7cO3377bRg2bFg46aSTKvz1UFuKeS7++U9V5XK56nwpUFDFOhuTJk0KU6dODddee20BvxoojGI+M6AuK9bZaNKkSRg9enS46KKLwooVK0LXrl3DrrvuGurXr1/Arw6qpi48M66++uowe/bscOedd1bzq4HCqQtnA+qaYp+Lhx56KIQQwoMPPhiGDh3qHFFnFPtsQF3kPdvssRivIR9//HEYPHhwePPNN8P2228f3n777XDggQdW2FNSUhJyuVw49NBDv3+B9M/XrKx//H0D9evXD+edd17Yaaed8vsCoAYU81z8/Oc/DwsWLAhr164NpaWlIZfLhfnz5/u7OagTink2Jk6cGN57772w3XbbhRBCWLBgQTjkkEPCvffeGw477LD8vxgokGK/loK6qthno1u3buGVV14JIfzvf9atZcuW3/+n1aFYin0uQgjhxhtvDE8++WT4y1/+Eho1apRXL9SUunA2oK6pS+fipJNOCr/73e/C559/Hpo2bVqla0Ch1KWzAXWF92yzyV9iUkOWLVsWNt5449CyZcuQy+XC8OHDf1Rfs2ZNGDVqVAghhDfffDMsWrQodOzYMfTs2TO88MIL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FVdckawtXbo07+vBP6vo93LHjh3zvt5LL72UrN1yyy15X4/12+abb56snXnmmcla6jX2uHHjkj19+vSp7Fg/qV27dsnaqFGjkrW9994773s98cQT0fz666/P+1pQ0wYPHpysbbrppgW91+677553zxtvvBHNJ02aVN1xIKm8vDxZ854RdVHbtm2Ttf79+0fzHj16FHSGrl27JmuFPDfLly9P1i666KJo/txzzyV7Vq1aVe2ZANYnHTp0SNbGjBkTzZs1a5bsue2226J5oXcgQ4YMSdYGDBiQ9/WuuuqqakyTPT4xDgAAAAAAAECmWYwDAAAAAAAAkGkW4wAAAAAAAABkmsU4AAAAAAAAAJlmMQ4AAAAAAABAplmMAwAAAAAAAJBppcUeYEMwd+7caD5gwIBkz4gRI5K1/v3755WHEMKmm24azR966KFkz6effpqssf67+eabk7WSkpJoPnHixGRPRbUNRb166T9rVF5eXouTEEIIW265Za3cZ4899kjWUmepR48eyZ5WrVpF84033jjZc8IJJyRrqd+Xq1atSvZMmTIlmq9evTrZU1oaf0nxX//1X8keyEefPn2i+bXXXlul673++uvR/KSTTkr2LFu2rEr3Yv1V0ffeZs2a5X29wYMHJ2tbbbVVND/55JOTPUcccUQ079ChQ7Jns802S9ZyuVxeeQghjBw5MpqvXLky2QP5aNSoUTTfddddkz1//OMfo3mvXr2qNEPq9VRVXuMvXLgwWUud9++++y7v+wCs71KvZ55++ulkT+vWrWtqnKJ47bXXkrW77767FieB6mnatGmxRyADUu89hhBCv379ovl9992X7KnKa/wuXbpE89///vfJnor2MKn3r48++uhkT+r95op2fXfddVeytiHyiXEAAAAAAAAAMs1iHAAAAAAAAIBMsxgHAAAAAAAAINMsxgEAAAAAAADINItxAAAAAAAAADLNYhwAAAAAAACATCst9gAbsjFjxiRrs2fPTtZuvvnmaH7QQQcle66++upo3qZNm2TPVVddFc0/+eSTZA91S+/evZO1srKyZC2Xy0Xzp59+urojZVp5eXmylvp3GkIIM2bMqIFpsmXVqlXRvKJ/r3feeWc0v/jiiwsy0z907NgxWSspKYnma9euTfZ8/fXX0XzWrFnJnvvvvz9ZmzZtWjSfOHFisuezzz6L5gsWLEj2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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(20, 4))\n", "\n", "# Loop through the first 10 images to get an idea of the dataset\n", "for i in range(10):\n", " plt.subplot(1, 10, i + 1)\n", " plt.imshow(train_images[i], cmap='gray')\n", " plt.axis('off') \n", " plt.title(f\"Label: {train_labels[i]}\", fontsize=8)\n", "\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 7, "id": "88206a02-ddf5-4f3b-94ba-3157733920fb", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure()\n", "plt.imshow(train_images[0])\n", "plt.colorbar()\n", "plt.grid(False)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "9e5d5a9d-326c-410a-ad78-02eb3c235d09", "metadata": {}, "source": [ "## Data preprocessing" ] }, { "cell_type": "code", "execution_count": 8, "id": "9715b5e8-6223-4114-8416-476834e99133", "metadata": {}, "outputs": [], "source": [ "def preprocess_data(train_images, test_images):\n", " train_images = train_images / 255.0\n", " test_images = test_images / 255.0\n", " train_images = np.expand_dims(train_images, axis=-1)\n", " test_images = np.expand_dims(test_images, axis=-1)\n", " return train_images, test_images" ] }, { "cell_type": "code", "execution_count": 9, "id": "838d3810-00a7-4c69-935c-c4c59fb30306", "metadata": {}, "outputs": [], "source": [ "train_images, test_images = preprocess_data(train_images, test_images)" ] }, { "cell_type": "code", "execution_count": 10, "id": "c707e0a3-6bf5-49f3-b7e6-1b765f3c22b4", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure()\n", "plt.imshow(train_images[0])\n", "plt.colorbar()\n", "plt.grid(False)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "3fc16921-a9e1-4cfe-aee8-a28c3b980678", "metadata": {}, "source": [ "# A simple CNN, trained with the original data" ] }, { "cell_type": "code", "execution_count": 11, "id": "53f60557-8a54-47f1-a031-8ffcdf99fee8", "metadata": {}, "outputs": [], "source": [ "model = Sequential([\n", " Flatten(),\n", " Dense(128, activation=tf.nn.relu),\n", " Dense(10, activation=tf.nn.softmax)\n", "])" ] }, { "cell_type": "code", "execution_count": 12, "id": "f7a5bf92-cbe4-47f2-8c6f-62a96adf570d", "metadata": {}, "outputs": [], "source": [ "model.compile(optimizer='adam',\n", " loss='sparse_categorical_crossentropy',\n", " metrics=['accuracy'])" ] }, { "cell_type": "code", "execution_count": 13, "id": "c5c5e756-0735-4e6d-86a5-33009a44e199", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 8ms/step - accuracy: 0.8804 - loss: 0.4226\n", "Epoch 2/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 9ms/step - accuracy: 0.9634 - loss: 0.1228\n", "Epoch 3/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 9ms/step - accuracy: 0.9766 - loss: 0.0772\n", "Epoch 4/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 8ms/step - accuracy: 0.9813 - loss: 0.0627\n", "Epoch 5/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 9ms/step - accuracy: 0.9869 - loss: 0.0447\n", "Epoch 6/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 8ms/step - accuracy: 0.9893 - loss: 0.0332\n", "Epoch 7/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 9ms/step - accuracy: 0.9926 - loss: 0.0250\n", "Epoch 8/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 8ms/step - accuracy: 0.9936 - loss: 0.0224\n", "Epoch 9/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 8ms/step - accuracy: 0.9942 - loss: 0.0187\n", "Epoch 10/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 8ms/step - accuracy: 0.9962 - loss: 0.0132\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.fit(train_images, train_labels, epochs=10)" ] }, { "cell_type": "code", "execution_count": 14, "id": "3d879a06-4779-450b-a730-2fd403409392", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 3ms/step - accuracy: 0.9739 - loss: 0.0968\n", "Test accuracy: 0.9768999814987183\n" ] } ], "source": [ "test_loss, test_acc = model.evaluate(test_images, test_labels)\n", "print('Test accuracy:', test_acc)" ] }, { "cell_type": "markdown", "id": "55770481-81cd-4d9c-855f-2a4ad026d5c5", "metadata": {}, "source": [ "# Dataset augmentation" ] }, { "cell_type": "code", "execution_count": 15, "id": "5cc13e61-aebf-46e1-94b1-a20d369e0f7d", "metadata": {}, "outputs": [], "source": [ "from keras.src.legacy.preprocessing.image import ImageDataGenerator\n", "\n", "datagen = ImageDataGenerator(\n", " rotation_range=40,\n", " width_shift_range=0.2,\n", " height_shift_range=0.2,\n", " shear_range=0.1,\n", " zoom_range=0.2,\n", " horizontal_flip=False, #because of 6 and 9\n", " fill_mode='nearest'\n", ")\n", "\n", "datagen.fit(train_images)" ] }, { "cell_type": "markdown", "id": "e9acbf8f-be21-4c07-8904-2b97262e7922", "metadata": {}, "source": [ "### Explore some of the augmented images" ] }, { "cell_type": "code", "execution_count": 16, "id": "51fdf7c3-0016-4bd6-a99f-9ffebfffd6cf", "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABcAAAAExCAYAAABbMgFNAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAp70lEQVR4nO3da7CV5X03/muzT5zPiJzBjSAKCqIRFBMFDyN14okGbdPEUzVjGnsw6ZhJmrQeMknrNJN2mmo1g0NjEocEwRjiAUlIoyJqAwaNCggKAhsRRGAf2If1f/H8H/rYxFw/w4a9uPl8Znghfvf3uvbaa13rXj9upaJUKpUSAAAAAAAUTJfO3gAAAAAAABwKBuAAAAAAABSSATgAAAAAAIVkAA4AAAAAQCEZgAMAAAAAUEgG4AAAAAAAFJIBOAAAAAAAhWQADgAAAABAIRmAAwAAAABQSAbgR6j7778/VVRUpOeff75D+ioqKtJf/MVfdEjX/9v593//93/Q177wwgvps5/9bJo0aVLq1atXGjx4cDrvvPPSsmXLOnSPwKHhjALKmTMKKGfOKKCcOaM4EhmAU5a+//3vp5UrV6Zrr702LV68ON13332ptrY2zZo1K82fP7+ztwcc5ZxRQDlzRgHlzBkFlDNnVDFVdfYG4Hf527/923TXXXe97/dmz56dTj311HTbbbelT33qU520MwBnFFDenFFAOXNGAeXMGVVM7gAvsKampnTLLbekyZMnpz59+qT+/fun6dOnp8WLF3/g19xzzz1p3Lhxqba2Np144onpBz/4wW9ltm3blm688cY0fPjwVFNTk8aMGZP+4R/+IbW2tnbY3o855pjf+r3Kyso0derUtGnTpg5bB+g8ziignDmjgHLmjALKmTOKcuMO8AJrbm5OO3fuTJ///OfTsGHD0v79+9PSpUvT5ZdfnubNm/dbf2r18MMPp5/97GfptttuSz169Ejf/va301VXXZWqqqrSnDlzUkr/57D5yEc+krp06ZK+8pWvpLq6uvTMM8+kO+64I23cuDHNmzfv9+5p9OjRKaWUNm7c+KG/n9bW1vRf//Vf6aSTTvrQXwuUH2cUUM6cUUA5c0YB5cwZRdkpcUSaN29eKaVUeu6558Jf09raWmppaSldd911pSlTprzv36WUSt26dStt27btffkTTjihNHbs2AO/d+ONN5Z69uxZeuONN9739XfddVcppVR66aWX3tf51a9+9X25urq6Ul1dXXjP/68vfelLpZRSadGiRX/Q1wOHjzMKKGfOKKCcOaOAcuaM4kjkf4FScAsWLEhnnXVW6tmzZ6qqqkrV1dXpO9/5TvrNb37zW9lZs2alwYMHH/jnysrKNHfu3LRu3bq0efPmlFJKjzzySDr33HPT0KFDU2tr64FfF110UUoppeXLl//e/axbty6tW7fuQ38f9913X7rzzjvTLbfcki655JIP/fVAeXJGAeXMGQWUM2cUUM6cUZQTA/ACW7hwYfrEJz6Rhg0blr773e+mZ555Jj333HPp2muvTU1NTb+VP/bYYz/w9955552UUkr19fXpxz/+caqurn7fr//7n4Hs2LGjw7+PefPmpRtvvDHdcMMN6Z/+6Z86vB/oHM4ooJw5o4By5owCypkzinLj/wFeYN/97nfTmDFj0oMPPpgqKioO/H5zc/PvzG/btu0Df2/AgAEppZQGDhyYTj755HTnnXf+zo6hQ4ce7LbfZ968een6669Pn/70p9Pdd9/9vu8DOLI5o4By5owCypkzCihnzijKjQF4gVVUVKSampr3vUi3bdv2gX/r7pNPPpnq6+sP/GcnbW1t6cEHH0x1dXVp+PDhKaWULr744rRkyZJUV1eX+vXrd0j3f//996frr78+ffKTn0z33XefwwYKxhkFlDNnFFDOnFFAOXNGUW4MwI9wy5Yt+51/g+3s2bPTxRdfnBYuXJhuuummNGfOnLRp06Z0++23pyFDhqS1a9f+1tcMHDgwzZw5M/3d3/3dgb9195VXXkk/+MEPDmRuu+229MQTT6Qzzzwz3XzzzWn8+PGpqakpbdy4MS1ZsiTdfffdBw6n32Xs2LEppZT9/y4tWLAgXXfddWny5MnpxhtvTCtXrnzfv58yZUqqra39vR1A53NGAeXMGQWUM2cUUM6cURxROvtv4eQP83//1t0P+rVhw4ZSqVQqff3rXy+NHj26VFtbW5owYULp3nvvLX31q18t/e8ffUqp9NnPfrb07W9/u1RXV1eqrq4unXDCCaUHHnjgt9Z+++23SzfffHNpzJgxperq6lL//v1LU6dOLX3pS18q7d27932d//tv3R01alRp1KhR2e/v05/+dOj7A8qTM2rDh33IgMPIGbXhwz5kwGHkjNrwYR8y4DByRm34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176WzVx77bWhriuvvDKbGTp0aKhr48aN2Uzk89L3vve90HqvvvpqNhN9TFevXp3NvPvuu6GuNWvWZDN79uwJdb333nvZzI4dO0JdRecOcAAAAAAACskAHAAAAACAQjIABwAAAACgkAzAAQAAAAAoJANwAAAAAAAKyQAcAAAAAIBCMgAHAAAAAKCQDMABAAAAACikqo4sa2xsDOVmzpyZzZx44omhrsrKylDuSFYqlbKZ3bt3h7qeffbZbObuu+/OZl5//fXQelu2bMlmrr/++lBX3759Q7mIyPOma9euoa5Zs2ZlMy+88EKoiyNH9OwZP358NvOpT30q1HXhhRdmMz169Ah1HW7Nzc2h3MqVK7OZf//3f89mdu3aFVpv9erV2Ux9fX2oCzhydevWLZTbtGlTNrNnz55sJnomLl26NJv55S9/Gerav39/NhO55kwppSFDhmQz0bMz8j45evToUFefPn1COaBjRM67p59+OtT1sY99LJsZMGBAqCtyPVxVFRuFtLS0hHJwOETnCnfeeWc2c8YZZ4S6pk2bls3U1NSEuh577LFsZvHixdnM5s2bQ+tF7Ny5M5SLzMkqKipCXdHZKR3LHeAAAAAAABSSATgAAAAAAIVkAA4AAAAAQCEZgAMAAAAAUEgG4AAAAAAAFJIBOAAAAAAAhWQADgAAAABAIRmAAwAAAABQSAbgAAAAAAAUUlVHlr355puh3D333JPNzJkzJ9Q1bdq0bGbEiBGhrnK1cePGbObJJ58MdX3rW9/KZtasWRPqiujTp082c9FFF4W6jjnmmGymd+/eoa6ampps5sUXXwx1bdq0KZSjWAYNGhTKzZ07N5u54oorQl19+/YN5Q63V199NZu59957Q10PPPBANrN9+/ZQF0BUY2NjKLdhw4Zs5p//+Z+zmSlTpoTWW7hwYTbz85//PNTVkVavXp3NNDU1hbqam5uzmV27doW69u/fn81069atw7qi2traOqwLyknkdf7ss8+GuiKv84EDB4a6Lr300mwmekYtWLAgm+nZs2eoa9u2baEcfJDo+8nPfvazbCb62vyP//iPbGbnzp2hriNZ9MygfLkDHAAAAACAQjIABwAAAACgkAzAAQAAAAAoJANwAAAAAAAKyQAcAAAAAIBCMgAHAAAAAKCQDMABAAAAACgkA3AAAAAAAAqpolQqlULBiooOW7RP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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Filter the images to get only those with label '2' for better understanding and comparison\n", "label_of_interest = 2\n", "filtered_images = train_images[train_labels == label_of_interest]\n", "filtered_labels = train_labels[train_labels == label_of_interest]\n", "\n", "augmented_images = datagen.flow(filtered_images, batch_size=5)\n", "images = next(augmented_images) \n", "\n", "# Plot 5 augmented images\n", "fig, axes = plt.subplots(1, 5, figsize=(15, 3)) # 1 row, 5 images\n", "axes = axes.flatten()\n", "\n", "for i in range(5):\n", " axes[i].imshow(images[i].squeeze(), cmap='gray')\n", " axes[i].axis('off') \n", " axes[i].set_title(f\"Label: {label_of_interest}\")\n", "\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "a49fee01-6270-4afa-8568-525f43978467", "metadata": {}, "source": [ "# Simple CNN with augmented dataset" ] }, { "cell_type": "code", "execution_count": 17, "id": "0e468ad2-5c10-461d-b39f-38ef3a56b826", "metadata": {}, "outputs": [], "source": [ "model.compile(optimizer='adam',\n", " loss='sparse_categorical_crossentropy',\n", " metrics=['accuracy'])" ] }, { "cell_type": "code", "execution_count": 19, "id": "bb11d7d9-d7a9-495d-ae64-f4609fdbdfbd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m58s\u001b[0m 31ms/step - accuracy: 0.6399 - loss: 1.1305\n", "Epoch 2/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m57s\u001b[0m 30ms/step - accuracy: 0.7456 - loss: 0.8298\n", "Epoch 3/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m59s\u001b[0m 31ms/step - accuracy: 0.7830 - loss: 0.6953\n", "Epoch 4/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m58s\u001b[0m 31ms/step - accuracy: 0.8088 - loss: 0.6210\n", "Epoch 5/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m57s\u001b[0m 30ms/step - accuracy: 0.8225 - loss: 0.5732\n", "Epoch 6/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m56s\u001b[0m 30ms/step - accuracy: 0.8357 - loss: 0.5396\n", "Epoch 7/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m59s\u001b[0m 31ms/step - accuracy: 0.8414 - loss: 0.5202\n", "Epoch 8/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m53s\u001b[0m 28ms/step - accuracy: 0.8482 - loss: 0.5012\n", "Epoch 9/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m54s\u001b[0m 29ms/step - accuracy: 0.8566 - loss: 0.4772\n", "Epoch 10/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m57s\u001b[0m 30ms/step - accuracy: 0.8574 - loss: 0.4629\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Train the model using the augmented data generator\n", "model.fit(datagen.flow(train_images, train_labels, batch_size=32), epochs=10)" ] }, { "cell_type": "code", "execution_count": 20, "id": "5d4bbd2a-9e18-49dd-a555-d1841d5d68f2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 3ms/step - accuracy: 0.9229 - loss: 0.2424\n", "Augmented test accuracy: 0.932200014591217\n" ] } ], "source": [ "# Evaluate the model on the test set\n", "augmented_test_loss, augmented_test_acc = model.evaluate(test_images, test_labels)\n", "print('Augmented test accuracy:', augmented_test_acc)" ] }, { "cell_type": "code", "execution_count": 21, "id": "9a788df7-c878-49f6-86b5-e385be7bf842", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Simple test accuracy: 0.9768999814987183\n", "Simple augmented test accuracy: 0.932200014591217\n" ] } ], "source": [ "# Compare the model accuracy on the original set vs the augmented set\n", "print('Simple test accuracy:', test_acc)\n", "print('Simple augmented test accuracy:', augmented_test_acc)" ] }, { "cell_type": "markdown", "id": "213269a1-95be-4f45-ae13-76ceaac35828", "metadata": {}, "source": [ "# More advanced CNN with augmented dataset" ] }, { "cell_type": "code", "execution_count": 22, "id": "89cca745-bda4-4a8a-92f0-8d31d508cc8e", "metadata": {}, "outputs": [], "source": [ "# more layers are added\n", "def build_advanced_model():\n", " model = Sequential([\n", " Input(shape=(28, 28, 1)),\n", " Conv2D(32, (3, 3), activation='relu'),\n", " MaxPooling2D((2, 2)),\n", " Conv2D(64, (3, 3), activation='relu'),\n", " MaxPooling2D((2, 2)),\n", " Flatten(),\n", " Dense(128, activation='relu'),\n", " Dropout(0.5),\n", " Dense(10, activation='softmax')\n", " ])\n", " model.compile(optimizer='adam',\n", " loss='sparse_categorical_crossentropy',\n", " metrics=['accuracy'])\n", " return model" ] }, { "cell_type": "code", "execution_count": 23, "id": "c1dfe2cf-86f9-4f36-8184-1dd566ece339", "metadata": {}, "outputs": [], "source": [ "advanced_model = build_advanced_model()" ] }, { "cell_type": "code", "execution_count": 24, "id": "93ba283c-6a0f-49c8-adf6-505ac51cbece", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m251s\u001b[0m 133ms/step - accuracy: 0.5385 - loss: 1.3305 - val_accuracy: 0.9559 - val_loss: 0.1485\n", "Epoch 2/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m246s\u001b[0m 131ms/step - accuracy: 0.8474 - loss: 0.4887 - val_accuracy: 0.9647 - val_loss: 0.1102\n", "Epoch 3/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m241s\u001b[0m 129ms/step - accuracy: 0.8866 - loss: 0.3713 - val_accuracy: 0.9685 - val_loss: 0.0905\n", "Epoch 4/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m241s\u001b[0m 128ms/step - accuracy: 0.9064 - loss: 0.3077 - val_accuracy: 0.9735 - val_loss: 0.0727\n", "Epoch 5/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m245s\u001b[0m 130ms/step - accuracy: 0.9166 - loss: 0.2790 - val_accuracy: 0.9762 - val_loss: 0.0756\n", "Epoch 6/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m243s\u001b[0m 129ms/step - accuracy: 0.9195 - loss: 0.2690 - val_accuracy: 0.9792 - val_loss: 0.0639\n", "Epoch 7/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m245s\u001b[0m 130ms/step - accuracy: 0.9270 - loss: 0.2395 - val_accuracy: 0.9804 - val_loss: 0.0569\n", "Epoch 8/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m240s\u001b[0m 128ms/step - accuracy: 0.9340 - loss: 0.2231 - val_accuracy: 0.9774 - val_loss: 0.0704\n", "Epoch 9/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m243s\u001b[0m 130ms/step - accuracy: 0.9356 - loss: 0.2144 - val_accuracy: 0.9844 - val_loss: 0.0496\n", "Epoch 10/10\n", "\u001b[1m1875/1875\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m240s\u001b[0m 128ms/step - accuracy: 0.9395 - loss: 0.2053 - val_accuracy: 0.9827 - val_loss: 0.0538\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "advanced_model.fit(datagen.flow(train_images, train_labels, batch_size=32),\n", " validation_data=(test_images, test_labels),\n", " epochs=10)" ] }, { "cell_type": "code", "execution_count": 25, "id": "ba5a04bc-f912-45ee-8c38-f860ae59687a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m9s\u001b[0m 28ms/step - accuracy: 0.9814 - loss: 0.0564\n", "Simple test accuracy: 0.9768999814987183\n", "Simple augmented test accuracy: 0.932200014591217\n", "Advanced test accuracy: 0.982699990272522\n" ] } ], "source": [ "advanced_test_loss, advanced_test_acc = advanced_model.evaluate(test_images, test_labels)\n", "print('Simple test accuracy:', test_acc)\n", "print('Simple augmented test accuracy:', augmented_test_acc)\n", "print('Advanced test accuracy:', advanced_test_acc)" ] }, { "cell_type": "code", "execution_count": 26, "id": "2178138b-5388-45a0-9e01-5cbae10e5bb9", "metadata": {}, "outputs": [], "source": [ "# Export functions to make them importable\n", "if __name__ == \"__main__\":\n", " pass # Prevent unintended execution during import" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel) *", "language": "python", "name": "conda-base-py" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.9" } }, "nbformat": 4, "nbformat_minor": 5 }