{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":30198,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<div style=\"border-radius:10px;\n            border : #015a2c solid;\n            background-color:#ecfff5;\n           font-size:110%;\n           letter-spacing:0.5px;\n            text-align: center\">\n\n<center><h1 style=\"padding: 25px 0px; color:#015a2c; font-weight: bold; font-family: Cursive\">\n🐱 Cats vs. Dogs 🐶</h1></center>\n<center><h3 style=\"padding-bottom: 25px; color:#015a2c; font-weight: bold; font-style:italic; font-family: Cursive\">\n(CNN model - Image augmentation - Transfer learning)</h3></center>     \n\n</div>","metadata":{}},{"cell_type":"code","source":"import os, shutil\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2026-01-29T18:31:55.361523Z","iopub.execute_input":"2026-01-29T18:31:55.362170Z","iopub.status.idle":"2026-01-29T18:31:55.389406Z","shell.execute_reply.started":"2026-01-29T18:31:55.362075Z","shell.execute_reply":"2026-01-29T18:31:55.388592Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Import Libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport zipfile\nimport matplotlib.pyplot as plt\n\nfrom tensorflow import keras\nfrom keras import layers\nfrom keras.models import Sequential\n\nfrom tensorflow.keras.optimizers import RMSprop\nfrom keras.preprocessing import image\nfrom keras.preprocessing.image import ImageDataGenerator\n\nfrom tensorflow.keras.applications import VGG16\nfrom tensorflow.keras.callbacks import EarlyStopping","metadata":{"execution":{"iopub.status.busy":"2026-01-29T18:36:59.464763Z","iopub.execute_input":"2026-01-29T18:36:59.465133Z","iopub.status.idle":"2026-01-29T18:37:05.165791Z","shell.execute_reply.started":"2026-01-29T18:36:59.465104Z","shell.execute_reply":"2026-01-29T18:37:05.165031Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Define Functions","metadata":{}},{"cell_type":"code","source":"def plot_loss_accuracy(history):\n    acc = history.history['accuracy']\n    val_acc = history.history['val_accuracy']\n    loss = history.history['loss']\n    val_loss = history.history['val_loss']\n\n    epochs = range(len(acc))\n\n    plt.plot(epochs, acc, 'bo', label='Training accuracy')\n    plt.plot(epochs, val_acc, 'b', label='Validation accuracy')\n    plt.title('Training and validation accuracy')\n    plt.legend()\n    plt.figure()\n\n    plt.plot(epochs, loss, 'bo', label='Training Loss')\n    plt.plot(epochs, val_loss, 'b', label='Validation Loss')\n    plt.title('Training and validation loss')\n    plt.legend()\n\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2026-01-29T18:46:49.183876Z","iopub.execute_input":"2026-01-29T18:46:49.184290Z","iopub.status.idle":"2026-01-29T18:46:49.190868Z","shell.execute_reply.started":"2026-01-29T18:46:49.184256Z","shell.execute_reply":"2026-01-29T18:46:49.189871Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Import & organize Data","metadata":{}},{"cell_type":"code","source":"zip_df = zipfile.ZipFile(\"/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip\", 'r')\nzip_df.extractall(\"/kaggle/working/\")\nzip_df.close()","metadata":{"execution":{"iopub.status.busy":"2026-01-29T18:46:58.746423Z","iopub.execute_input":"2026-01-29T18:46:58.746818Z","iopub.status.idle":"2026-01-29T18:47:07.431104Z","shell.execute_reply.started":"2026-01-29T18:46:58.746785Z","shell.execute_reply":"2026-01-29T18:47:07.430185Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"original_dataset_dir = '/kaggle/working/train'\nbase_dir = '/kaggle/working/catVsdog'\nos.mkdir(base_dir)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T18:47:30.690398Z","iopub.execute_input":"2026-01-29T18:47:30.691128Z","iopub.status.idle":"2026-01-29T18:47:30.695580Z","shell.execute_reply.started":"2026-01-29T18:47:30.691083Z","shell.execute_reply":"2026-01-29T18:47:30.694397Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dir = os.path.join(base_dir, 'train')\nos.mkdir(train_dir)\nvalidation_dir = os.path.join(base_dir, 'validation')\nos.mkdir(validation_dir)\n\n# ------------------------------------\ntrain_cats_dir = os.path.join(train_dir, 'cats')\nos.mkdir(train_cats_dir)\ntrain_dogs_dir = os.path.join(train_dir, 'dogs')\nos.mkdir(train_dogs_dir)\n\n# ------------------------------------\nvalidation_cats_dir = os.path.join(validation_dir, 'cats')\nos.mkdir(validation_cats_dir)\nvalidation_dogs_dir = os.path.join(validation_dir, 'dogs')\nos.mkdir(validation_dogs_dir)\n","metadata":{"execution":{"iopub.status.busy":"2026-01-29T18:47:35.810463Z","iopub.execute_input":"2026-01-29T18:47:35.811373Z","iopub.status.idle":"2026-01-29T18:47:35.821129Z","shell.execute_reply.started":"2026-01-29T18:47:35.811334Z","shell.execute_reply":"2026-01-29T18:47:35.820377Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('total training cat images:', len(os.listdir(train_cats_dir)))","metadata":{"execution":{"iopub.status.busy":"2026-01-29T18:58:16.309406Z","iopub.execute_input":"2026-01-29T18:58:16.309815Z","iopub.status.idle":"2026-01-29T18:58:16.321544Z","shell.execute_reply.started":"2026-01-29T18:58:16.309784Z","shell.execute_reply":"2026-01-29T18:58:16.320587Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fnames = ['cat.{}.jpg'.format(i) for i in range(10000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(train_cats_dir, fname)\n    shutil.copyfile(src, dst)\n\nfnames = ['cat.{}.jpg'.format(i) for i in range(10000, 12500)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(validation_cats_dir, fname)\n    shutil.copyfile(src, dst)\n    \n# --------------------------------------------------------------\nfnames = ['dog.{}.jpg'.format(i) for i in range(10000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(train_dogs_dir, fname)\n    shutil.copyfile(src, dst)\n    \nfnames = ['dog.{}.jpg'.format(i) for i in range(10000, 12500)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(validation_dogs_dir, fname)\n    shutil.copyfile(src, dst)\n","metadata":{"execution":{"iopub.status.busy":"2026-01-29T18:58:17.719048Z","iopub.execute_input":"2026-01-29T18:58:17.719754Z","iopub.status.idle":"2026-01-29T18:58:21.555271Z","shell.execute_reply.started":"2026-01-29T18:58:17.719722Z","shell.execute_reply":"2026-01-29T18:58:21.554517Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('total training cat images:', len(os.listdir(train_cats_dir)))\nprint('total training dog images:', len(os.listdir(train_dogs_dir)))\nprint('total validation cat images:', len(os.listdir(validation_cats_dir)))\nprint('total validation dog images:', len(os.listdir(validation_dogs_dir)))","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:15:59.347397Z","iopub.execute_input":"2026-01-29T19:15:59.347849Z","iopub.status.idle":"2026-01-29T19:15:59.367809Z","shell.execute_reply.started":"2026-01-29T19:15:59.347805Z","shell.execute_reply":"2026-01-29T19:15:59.366963Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 1. CNN","metadata":{}},{"cell_type":"code","source":"model = Sequential()\nmodel.add(layers.Conv2D(32, (3,3), activation='relu', input_shape=(150, 150, 3)))\nmodel.add(layers.MaxPooling2D(2, 2))\nmodel.add(layers.Conv2D(64, (3,3), activation='relu'))\nmodel.add(layers.MaxPooling2D(2,2))\nmodel.add(layers.Conv2D(128, (3,3), activation='relu'))\nmodel.add(layers.MaxPooling2D(2,2))\n\nmodel.add(layers.Flatten())\nmodel.add(layers.Dense(512, activation='relu'))\nmodel.add(layers.Dense(1, activation='sigmoid'))\n\nmodel.compile(loss='binary_crossentropy',\n            optimizer=RMSprop(learning_rate=1e-4),\n            metrics=['accuracy'])\n","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2026-01-29T19:16:04.408229Z","iopub.execute_input":"2026-01-29T19:16:04.408873Z","iopub.status.idle":"2026-01-29T19:16:07.151136Z","shell.execute_reply.started":"2026-01-29T19:16:04.408841Z","shell.execute_reply":"2026-01-29T19:16:07.150498Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:17:33.561709Z","iopub.execute_input":"2026-01-29T19:17:33.562093Z","iopub.status.idle":"2026-01-29T19:17:33.567990Z","shell.execute_reply.started":"2026-01-29T19:17:33.562063Z","shell.execute_reply":"2026-01-29T19:17:33.567083Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1./255)\nvalidation_datagen = ImageDataGenerator(rescale=1./255)\n\n# --------------------------------------\ntrain_generator = train_datagen.flow_from_directory(\n        train_dir,  \n        target_size=(150, 150),  \n        batch_size=100,\n        class_mode='binary')\n\n# --------------------------------------\nvalidation_generator = validation_datagen.flow_from_directory(\n        validation_dir,\n        target_size=(150, 150),\n        batch_size=50,\n        class_mode='binary')","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:22:39.223371Z","iopub.execute_input":"2026-01-29T19:22:39.223769Z","iopub.status.idle":"2026-01-29T19:22:39.728539Z","shell.execute_reply.started":"2026-01-29T19:22:39.223736Z","shell.execute_reply":"2026-01-29T19:22:39.727686Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit_generator(\n      train_generator,\n      steps_per_epoch=200,  # 20000 train images = batch_size * steps\n      epochs=20,\n      validation_data=validation_generator,\n      validation_steps=100  # 5000 validation images = batch_size * steps\n)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:22:41.119552Z","iopub.execute_input":"2026-01-29T19:22:41.120375Z","iopub.status.idle":"2026-01-29T19:44:16.430898Z","shell.execute_reply.started":"2026-01-29T19:22:41.120341Z","shell.execute_reply":"2026-01-29T19:44:16.430056Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_loss_accuracy(history)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:44:16.432693Z","iopub.execute_input":"2026-01-29T19:44:16.433231Z","iopub.status.idle":"2026-01-29T19:44:16.726365Z","shell.execute_reply.started":"2026-01-29T19:44:16.433192Z","shell.execute_reply":"2026-01-29T19:44:16.725527Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<div style=\"font-family: Cursive; font-size:16px; background-color:#ecfff5; padding: 25px 20px\">\nThe plot above shows the pattern of overfitting.\n</div>","metadata":{}},{"cell_type":"markdown","source":"# 2. Data augmentation and Dropout layer ","metadata":{}},{"cell_type":"markdown","source":"<div style=\"padding: 10px; font-family: Cursive; border: solid 2px #015a2c;\n            font-size:15.5px;padding: 25px 10px; border-radius:8px;\">\n<p>There are several ways to prevent overfitting, two of which are:</p>\n<ol>\n    <li>Dropout layer</li>\n    <li>Data augmentation</li>\n</ol>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div style=\"padding: 10px; font-family: Cursive; border: solid 2px #015a2c;\n            font-size:15.5px;padding: 25px 10px; border-radius:8px;\">\n<h3>What is Dropout? 🤔</h3>\n<p>A single model can be used to simulate having a large number of different network architectures by randomly dropping out nodes during training. This is called dropout and offers a very computationally cheap and remarkably effective regularization method to reduce overfitting and improve generalization error in deep neural networks of all kinds. <a href =\"https://machinelearningmastery.com/dropout-for-regularizing-deep-neural-networks/\">ref</a>\n<br><br> The following figure shows a network with dropout.\n</p>    \n<img width =90% src=\"https://miro.medium.com/max/1400/1*iWQzxhVlvadk6VAJjsgXgg.png\" alt=\"dropout\"  class=\"center\"> \n<center><a href = \"https://medium.com/@amarbudhiraja/https-medium-com-amarbudhiraja-learning-less-to-learn-better-dropout-in-deep-machine-learning-74334da4bfc5\">image source</a></center>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div style=\"padding: 10px; font-family: Cursive; border: solid 2px #015a2c;\n            font-size:15.5px;padding: 25px 10px; border-radius:8px;\">\n<h3>What is image data augmentation? 🧐</h3>\n<p>image data augmentation is a technique that can be used to artificially expand the size of a training dataset by creating modified versions of images in the dataset.<br> Training deep learning neural network models on more data can result in more skillful models, and the augmentation techniques can create variations of the images that can improve the ability of the fit models to generalize what they have learned to new images. <a href =\"https://machinelearningmastery.com/how-to-configure-image-data-augmentation-when-training-deep-learning-neural-networks/\">ref</a></p>\n<p>Some image augmentation techniques include:</p>\n<ul>\n    <li>Image shifts</li>    \n    <li>Image flips</li>\n    <li>Image rotations</li>\n    <li>Image zoom</li>\n    <li>and ...</li>\n</ul>\n<p>The following figure shows the augmentation of a cat image.</p>\n<img src=\"https://929687.smushcdn.com/2633864/wp-content/uploads/2021/05/tf_data_data_aug_sequential.png?lossy=1&strip=1&webp=1\" alt=\"augmentation\"  class=\"center\" height=100%> \n<center><a href = \"https://pyimagesearch.com/2021/06/28/data-augmentation-with-tf-data-and-tensorflow/\">image source</a></center>\n\n</div>","metadata":{}},{"cell_type":"code","source":"train_datagen_augmentation = ImageDataGenerator(rescale=1./255,\n                                                rotation_range=50,\n                                                width_shift_range=0.2,\n                                                height_shift_range=0.2,\n                                                shear_range=0.25,\n                                                zoom_range=0.2,\n                                                horizontal_flip=True,\n                                                fill_mode='nearest')\n\n\ntrain_generator = train_datagen_augmentation.flow_from_directory(\n        train_dir,  \n        target_size=(150, 150),  \n        batch_size=100,\n        class_mode='binary')","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:45:16.833169Z","iopub.execute_input":"2026-01-29T19:45:16.833660Z","iopub.status.idle":"2026-01-29T19:45:17.180802Z","shell.execute_reply.started":"2026-01-29T19:45:16.833599Z","shell.execute_reply":"2026-01-29T19:45:17.180061Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fname_cat = [os.path.join(train_cats_dir, fname) for fname in os.listdir(train_cats_dir)]\n\nimg_path = fname_cat[20]\nimg = image.load_img(img_path, target_size=(150, 150))\nx = image.img_to_array(img)\nx = x.reshape((1,) + x.shape)\ni = 0\nfor batch in train_datagen_augmentation.flow(x, batch_size=1):\n    plt.figure(i)\n    imgplot = plt.imshow(image.array_to_img(batch[0]))\n    i += 1\n    if i % 4 == 0:\n        break\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:45:19.400468Z","iopub.execute_input":"2026-01-29T19:45:19.401302Z","iopub.status.idle":"2026-01-29T19:45:20.280745Z","shell.execute_reply.started":"2026-01-29T19:45:19.401271Z","shell.execute_reply":"2026-01-29T19:45:20.279912Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fname_dog = [os.path.join(train_dogs_dir, fname) for fname in os.listdir(train_dogs_dir)]\n\nimg_path = fname_dog[25]\nimg = image.load_img(img_path, target_size=(150, 150))\nx = image.img_to_array(img)\nx = x.reshape((1,) + x.shape)\ni = 0\nfor batch in train_datagen_augmentation.flow(x, batch_size=1):\n    plt.figure(i)\n    imgplot = plt.imshow(image.array_to_img(batch[0]))\n    i += 1\n    if i % 4 == 0:\n        break\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:45:24.481915Z","iopub.execute_input":"2026-01-29T19:45:24.482563Z","iopub.status.idle":"2026-01-29T19:45:25.173491Z","shell.execute_reply.started":"2026-01-29T19:45:24.482531Z","shell.execute_reply":"2026-01-29T19:45:25.172779Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_2 = Sequential()\nmodel_2.add(layers.Conv2D(32, (3,3), activation='relu', input_shape=(150, 150, 3)))\nmodel_2.add(layers.MaxPooling2D(2, 2))\nmodel_2.add(layers.Conv2D(64, (3,3), activation='relu'))\nmodel_2.add(layers.MaxPooling2D(2,2))\nmodel_2.add(layers.Conv2D(128, (3,3), activation='relu'))\nmodel_2.add(layers.MaxPooling2D(2,2))\n\nmodel_2.add(layers.Flatten())\nmodel_2.add(layers.Dropout(0.5))\nmodel_2.add(layers.Dense(512, activation='relu'))\nmodel_2.add(layers.Dense(1, activation='sigmoid'))\n\nmodel_2.compile(loss='binary_crossentropy',\n            optimizer=RMSprop(learning_rate=1e-4),\n            metrics=['accuracy'])\n","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:45:29.647537Z","iopub.execute_input":"2026-01-29T19:45:29.648385Z","iopub.status.idle":"2026-01-29T19:45:29.709248Z","shell.execute_reply.started":"2026-01-29T19:45:29.648339Z","shell.execute_reply":"2026-01-29T19:45:29.708636Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model_2.fit_generator(\n      train_generator,\n      steps_per_epoch=200,  # 20000 train images = batch_size * steps\n      epochs=20,\n      validation_data=validation_generator,\n      validation_steps=100  # 5000 validation images = batch_size * steps\n)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T19:45:39.064096Z","iopub.execute_input":"2026-01-29T19:45:39.064796Z","iopub.status.idle":"2026-01-29T20:35:24.598219Z","shell.execute_reply.started":"2026-01-29T19:45:39.064761Z","shell.execute_reply":"2026-01-29T20:35:24.597371Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_loss_accuracy(history)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:44:35.552307Z","iopub.execute_input":"2026-01-29T20:44:35.553827Z","iopub.status.idle":"2026-01-29T20:44:36.123561Z","shell.execute_reply.started":"2026-01-29T20:44:35.553785Z","shell.execute_reply":"2026-01-29T20:44:36.122840Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<div style=\"font-family: Cursive; font-size:16px; background-color:#ecfff5; padding: 25px 20px\">\nTo increase accuracy, we can use transfer learning.\n</div>","metadata":{}},{"cell_type":"markdown","source":"# 3. Transfer learning","metadata":{}},{"cell_type":"markdown","source":"<div style=\"padding: 10px; font-family: Cursive; border: solid 2px #015a2c;\n            font-size:15.5px;padding: 25px 10px; border-radius:8px;\">\n<h3>What is Transfer Learning?</h3>\n<p>Transfer learning is a machine learning technique where a model trained on one task is re-purposed on a second related task. <a href =\"https://machinelearningmastery.com/transfer-learning-for-deep-learning/\">ref</a> <br> We can use 2 below strategies  for doing transfer learning:</p>\n<ol>\n    <li>Feature extraction</li>\n    <p>Instead of using the model end-to-end as in the previous example, we can treat the pre-trained neural network as a feature extractor by discarding the last fully-connected output layer. This approach allows us to directly apply new dataset to solve an entirely different problem. <a href =\"https://towardsdatascience.com/what-is-deep-transfer-learning-and-why-is-it-becoming-so-popular-91acdcc2717a\">ref</a></p>\n    <li>Fine-tuning</li>\n    <p>Unfreeze a few of the top layers of a frozen model base and jointly train both the newly-added classifier layers and the last layers of the base model. This allows us to \"fine-tune\" the higher-order feature representations in the base model in order to make them more relevant for the specific task. <a href =\"https://www.tensorflow.org/tutorials/images/transfer_learning\">ref</a></p>\n</ol>\n\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div style=\"border-radius:10px;\n            background-color:#ffffff;\n            border-style: solid;\n            border-color: #015a2c;\n            letter-spacing:0.5px;\">\n\n<center><h3 style=\"padding: 5px 0px; color:#015a2c; font-weight: bold; font-family: Cursive\">\n1. Feature extraction</h3></center>\n</div>","metadata":{}},{"cell_type":"code","source":"base_model = VGG16(weights='imagenet',\n                  include_top=False,\n                  input_shape=(150, 150, 3))","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:46:16.059836Z","iopub.execute_input":"2026-01-29T20:46:16.060596Z","iopub.status.idle":"2026-01-29T20:46:16.626021Z","shell.execute_reply.started":"2026-01-29T20:46:16.060564Z","shell.execute_reply":"2026-01-29T20:46:16.625358Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_model.summary()","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:46:38.491125Z","iopub.execute_input":"2026-01-29T20:46:38.491841Z","iopub.status.idle":"2026-01-29T20:46:38.497637Z","shell.execute_reply.started":"2026-01-29T20:46:38.491809Z","shell.execute_reply":"2026-01-29T20:46:38.496835Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_3 = Sequential()\nmodel_3.add(base_model)\nmodel_3.add(layers.Flatten())\nmodel_3.add(layers.Dense(512, activation='relu'))\nmodel_3.add(layers.Dense(1, activation='sigmoid'))\n\nmodel_3.compile(loss='binary_crossentropy',\n            optimizer=RMSprop(learning_rate=1e-4),\n            metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:47:13.982409Z","iopub.execute_input":"2026-01-29T20:47:13.983293Z","iopub.status.idle":"2026-01-29T20:47:14.049806Z","shell.execute_reply.started":"2026-01-29T20:47:13.983259Z","shell.execute_reply":"2026-01-29T20:47:14.048995Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_3.summary()","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:47:17.891630Z","iopub.execute_input":"2026-01-29T20:47:17.892408Z","iopub.status.idle":"2026-01-29T20:47:17.897920Z","shell.execute_reply.started":"2026-01-29T20:47:17.892365Z","shell.execute_reply":"2026-01-29T20:47:17.897137Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('This is the number of trainable weights '\n      'before freezing the base model:', len(model_3.trainable_weights))","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:47:34.128694Z","iopub.execute_input":"2026-01-29T20:47:34.129262Z","iopub.status.idle":"2026-01-29T20:47:34.133295Z","shell.execute_reply.started":"2026-01-29T20:47:34.129233Z","shell.execute_reply":"2026-01-29T20:47:34.132527Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_model.trainable = False","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:47:43.010902Z","iopub.execute_input":"2026-01-29T20:47:43.011254Z","iopub.status.idle":"2026-01-29T20:47:43.015537Z","shell.execute_reply.started":"2026-01-29T20:47:43.011224Z","shell.execute_reply":"2026-01-29T20:47:43.014788Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('This is the number of trainable weights '\n      'after freezing the base model:', len(model.trainable_weights))","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:48:05.216465Z","iopub.execute_input":"2026-01-29T20:48:05.216851Z","iopub.status.idle":"2026-01-29T20:48:05.221194Z","shell.execute_reply.started":"2026-01-29T20:48:05.216821Z","shell.execute_reply":"2026-01-29T20:48:05.220335Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model_3.fit_generator(\n      train_generator,\n      steps_per_epoch=200,  # 20000 train images = batch_size * steps\n      epochs=20,\n      validation_data=validation_generator,\n      validation_steps=100  # 5000 validation images = batch_size * steps\n)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T20:48:07.612422Z","iopub.execute_input":"2026-01-29T20:48:07.612793Z","iopub.status.idle":"2026-01-29T21:37:10.636970Z","shell.execute_reply.started":"2026-01-29T20:48:07.612760Z","shell.execute_reply":"2026-01-29T21:37:10.636109Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_loss_accuracy(history)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T21:37:24.053065Z","iopub.execute_input":"2026-01-29T21:37:24.053391Z","iopub.status.idle":"2026-01-29T21:37:24.443937Z","shell.execute_reply.started":"2026-01-29T21:37:24.053362Z","shell.execute_reply":"2026-01-29T21:37:24.443157Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<div style=\"border-radius:10px;\n            background-color:#ffffff;\n            border-style: solid;\n            border-color: #015a2c;\n            letter-spacing:0.5px;\">\n\n<center><h3 style=\"padding: 5px 0px; color:#015a2c; font-weight: bold; font-family: Cursive\">\n2. Fine-Tuning</h3></center>\n</div>","metadata":{}},{"cell_type":"code","source":"for l in base_model.layers:\n    print(\"layer name is : \",l.name,\" ** trainable is \", l.trainable)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T21:37:34.311357Z","iopub.execute_input":"2026-01-29T21:37:34.312139Z","iopub.status.idle":"2026-01-29T21:37:34.316835Z","shell.execute_reply.started":"2026-01-29T21:37:34.312103Z","shell.execute_reply":"2026-01-29T21:37:34.315993Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_model.trainable = True\ntmp = False\nfor l in base_model.layers:\n    if l.name == \"block5_conv1\":\n        tmp = True\n    if tmp:\n        l.trainable = True\n    else:\n        l.trainable = False","metadata":{"execution":{"iopub.status.busy":"2026-01-29T21:37:35.967258Z","iopub.execute_input":"2026-01-29T21:37:35.968101Z","iopub.status.idle":"2026-01-29T21:37:35.973333Z","shell.execute_reply.started":"2026-01-29T21:37:35.968064Z","shell.execute_reply":"2026-01-29T21:37:35.972484Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_3.compile(loss='binary_crossentropy',\n            optimizer=RMSprop(learning_rate=1e-4),\n            metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2026-01-29T21:37:38.889253Z","iopub.execute_input":"2026-01-29T21:37:38.889597Z","iopub.status.idle":"2026-01-29T21:37:38.900395Z","shell.execute_reply.started":"2026-01-29T21:37:38.889568Z","shell.execute_reply":"2026-01-29T21:37:38.899688Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"early_stopping = EarlyStopping(patience=3, monitor='val_loss')","metadata":{"execution":{"iopub.status.busy":"2026-01-29T21:37:39.635951Z","iopub.execute_input":"2026-01-29T21:37:39.636491Z","iopub.status.idle":"2026-01-29T21:37:39.640298Z","shell.execute_reply.started":"2026-01-29T21:37:39.636461Z","shell.execute_reply":"2026-01-29T21:37:39.639542Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model_3.fit_generator(\n      train_generator,\n      steps_per_epoch=200,  # 20000 train images = batch_size * steps\n      epochs=20,\n      validation_data=validation_generator,\n      validation_steps=100,  # 5000 validdation images = batch_size * steps\n      callbacks=[early_stopping])","metadata":{"execution":{"iopub.status.busy":"2026-01-29T21:37:41.479109Z","iopub.execute_input":"2026-01-29T21:37:41.479457Z","iopub.status.idle":"2026-01-29T21:49:48.300347Z","shell.execute_reply.started":"2026-01-29T21:37:41.479427Z","shell.execute_reply":"2026-01-29T21:49:48.299497Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_loss_accuracy(history)","metadata":{"execution":{"iopub.status.busy":"2026-01-29T21:49:48.301607Z","iopub.execute_input":"2026-01-29T21:49:48.301986Z","iopub.status.idle":"2026-01-29T21:49:48.691151Z","shell.execute_reply.started":"2026-01-29T21:49:48.301959Z","shell.execute_reply":"2026-01-29T21:49:48.690400Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# References:\n* https://machinelearningmastery.com/dropout-for-regularizing-deep-neural-networks/\n* https://machinelearningmastery.com/how-to-configure-image-data-augmentation-when-training-deep-learning-neural-networks/\n* https://www.tensorflow.org/tutorials/images/data_augmentation\n* https://machinelearningmastery.com/transfer-learning-for-deep-learning/\n* https://towardsdatascience.com/what-is-deep-transfer-learning-and-why-is-it-becoming-so-popular-91acdcc2717a\n* https://www.tensorflow.org/tutorials/images/transfer_learning","metadata":{}},{"cell_type":"markdown","source":"<div style=\"border-radius:10px;\n            background-color:#ffffff;\n            border-style: solid;\n            border-color: #015a2c;\n            letter-spacing:0.5px;\">\n\n<center><h4 style=\"padding: 5px 0px; color:#015a2c; font-weight: bold; font-family: Cursive\">\n    Thanks for your attention and for reviewing my notebook.🙌 <br><br>Please write your comments for me.📝</h4></center>\n<center><h4 style=\"padding: 5px 0px; color:#015a2c; font-weight: bold; font-family: Cursive\">\nIf you liked my work and found it useful, please upvote. Thank you🙏</h4></center>\n</div>","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}