{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":31260,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:25.634696Z","iopub.execute_input":"2026-02-05T10:26:25.634985Z","iopub.status.idle":"2026-02-05T10:26:25.642989Z","shell.execute_reply.started":"2026-02-05T10:26:25.634961Z","shell.execute_reply":"2026-02-05T10:26:25.642395Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Creating a project folder\nimport os\nos.makedirs('/kaggle/working/dogs-vs-cats', exist_ok=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:26.706912Z","iopub.execute_input":"2026-02-05T10:26:26.707168Z","iopub.status.idle":"2026-02-05T10:26:26.710889Z","shell.execute_reply.started":"2026-02-05T10:26:26.707146Z","shell.execute_reply":"2026-02-05T10:26:26.710187Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"I created a directory named dogs-vs-cats inside kaggle's working directory and set exist_ok = True ensures no error if the folder already exists.","metadata":{}},{"cell_type":"code","source":"# Unzip the train.zip file\nimport zipfile\n\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/dogs-vs-cats')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:27.094729Z","iopub.execute_input":"2026-02-05T10:26:27.095269Z","iopub.status.idle":"2026-02-05T10:26:31.465196Z","shell.execute_reply.started":"2026-02-05T10:26:27.095247Z","shell.execute_reply":"2026-02-05T10:26:31.464628Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"just opened the train.zip from kaggle's input directory and extracted all training images into my working directory","metadata":{}},{"cell_type":"code","source":"os.listdir('/kaggle/working/dogs-vs-cats')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:34.281103Z","iopub.execute_input":"2026-02-05T10:26:34.281777Z","iopub.status.idle":"2026-02-05T10:26:34.286639Z","shell.execute_reply.started":"2026-02-05T10:26:34.281748Z","shell.execute_reply":"2026-02-05T10:26:34.285767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"os.listdir('/kaggle/working/dogs-vs-cats/train')[:5]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:34.650686Z","iopub.execute_input":"2026-02-05T10:26:34.651353Z","iopub.status.idle":"2026-02-05T10:26:34.667494Z","shell.execute_reply.started":"2026-02-05T10:26:34.651308Z","shell.execute_reply":"2026-02-05T10:26:34.666970Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Creating a class folder\nbase_dir = '/kaggle/working/dogs-vs-cats/train'\n\nos.makedirs(base_dir + '/cats', exist_ok=True)\nos.makedirs(base_dir + '/dogs', exist_ok=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:36.337711Z","iopub.execute_input":"2026-02-05T10:26:36.337987Z","iopub.status.idle":"2026-02-05T10:26:36.342161Z","shell.execute_reply.started":"2026-02-05T10:26:36.337964Z","shell.execute_reply":"2026-02-05T10:26:36.341500Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Moving images into correct folders\nimport shutil\n\nfor file in os.listdir(base_dir):\n    path = os.path.join(base_dir, file)\n\n    if os.path.isdir(path):\n        continue\n\n    if file.startswith('cat'):\n        shutil.move(path, base_dir + '/cats/' + file)\n    elif file.startswith('dog'):\n        shutil.move(path, base_dir + '/dogs/' + file)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:37.150652Z","iopub.execute_input":"2026-02-05T10:26:37.150895Z","iopub.status.idle":"2026-02-05T10:26:38.954089Z","shell.execute_reply.started":"2026-02-05T10:26:37.150874Z","shell.execute_reply":"2026-02-05T10:26:38.953507Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Looping through all files in trian/ and moves cat.jpg -> cats/ and dog.jpg -> dogs/","metadata":{}},{"cell_type":"code","source":"os.listdir('/kaggle/working/dogs-vs-cats/train')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:38.955188Z","iopub.execute_input":"2026-02-05T10:26:38.955419Z","iopub.status.idle":"2026-02-05T10:26:38.960098Z","shell.execute_reply.started":"2026-02-05T10:26:38.955400Z","shell.execute_reply":"2026-02-05T10:26:38.959589Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Creating training and validation dataset\nimport tensorflow as tf\n\nDATA_DIR = '/kaggle/working/dogs-vs-cats/train'\n\ntrain_ds = tf.keras.utils.image_dataset_from_directory(\n    DATA_DIR,\n    image_size=(150, 150),\n    batch_size=64,\n    labels='inferred',\n    label_mode='int',\n    validation_split=0.2,\n    subset='training',\n    seed=42\n)\n\nval_ds = tf.keras.utils.image_dataset_from_directory(\n    DATA_DIR,\n    image_size=(150, 150),\n    batch_size=64,\n    labels='inferred',\n    label_mode='int',\n    validation_split=0.2,\n    subset='validation',\n    seed=42\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:39.608503Z","iopub.execute_input":"2026-02-05T10:26:39.608726Z","iopub.status.idle":"2026-02-05T10:26:40.875056Z","shell.execute_reply.started":"2026-02-05T10:26:39.608706Z","shell.execute_reply":"2026-02-05T10:26:40.874514Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers\nfrom tensorflow import keras\nfrom keras import Sequential\nfrom keras.layers import Flatten, Conv2D , MaxPooling2D , GlobalAveragePooling2D , Dense , BatchNormalization , Dropout\nfrom keras.applications.vgg16 import VGG16","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:22.125706Z","iopub.execute_input":"2026-02-05T09:49:22.125977Z","iopub.status.idle":"2026-02-05T09:49:22.131009Z","shell.execute_reply.started":"2026-02-05T09:49:22.125935Z","shell.execute_reply":"2026-02-05T09:49:22.130350Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Applying transfer learning\nconv_base = VGG16(\n    weights='imagenet',\n    include_top = False, # Keeping only Conv part \n    input_shape = (150 , 150 , 3)\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:22.131800Z","iopub.execute_input":"2026-02-05T09:49:22.132058Z","iopub.status.idle":"2026-02-05T09:49:23.600200Z","shell.execute_reply.started":"2026-02-05T09:49:22.132038Z","shell.execute_reply":"2026-02-05T09:49:23.599634Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"conv_base.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:23.601010Z","iopub.execute_input":"2026-02-05T09:49:23.601263Z","iopub.status.idle":"2026-02-05T09:49:23.622877Z","shell.execute_reply.started":"2026-02-05T09:49:23.601242Z","shell.execute_reply":"2026-02-05T09:49:23.622392Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = Sequential()\n\nmodel.add(conv_base)\nmodel.add(Flatten())\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(1, activation='sigmoid'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:23.623599Z","iopub.execute_input":"2026-02-05T09:49:23.623849Z","iopub.status.idle":"2026-02-05T09:49:23.650209Z","shell.execute_reply.started":"2026-02-05T09:49:23.623829Z","shell.execute_reply":"2026-02-05T09:49:23.649758Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:23.650968Z","iopub.execute_input":"2026-02-05T09:49:23.651229Z","iopub.status.idle":"2026-02-05T09:49:23.664505Z","shell.execute_reply.started":"2026-02-05T09:49:23.651201Z","shell.execute_reply":"2026-02-05T09:49:23.663773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# we train only the Fully Connected layer and Freeze the Convulational layers\nconv_base.trainable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:23.665353Z","iopub.execute_input":"2026-02-05T09:49:23.666008Z","iopub.status.idle":"2026-02-05T09:49:23.672685Z","shell.execute_reply.started":"2026-02-05T09:49:23.665985Z","shell.execute_reply":"2026-02-05T09:49:23.672025Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:23.673486Z","iopub.execute_input":"2026-02-05T09:49:23.673808Z","iopub.status.idle":"2026-02-05T09:49:23.687233Z","shell.execute_reply.started":"2026-02-05T09:49:23.673779Z","shell.execute_reply":"2026-02-05T09:49:23.686740Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process(image, label):\n    image = tf.cast(image, tf.float32) / 255.0\n    return image, label\n\n\ntrain_ds = train_ds.map(process)\nval_ds = val_ds.map(process)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:23.687920Z","iopub.execute_input":"2026-02-05T09:49:23.688179Z","iopub.status.idle":"2026-02-05T09:49:23.746924Z","shell.execute_reply.started":"2026-02-05T09:49:23.688148Z","shell.execute_reply":"2026-02-05T09:49:23.746150Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(optimizer='adam' , loss='binary_crossentropy', metrics=['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:23.747948Z","iopub.execute_input":"2026-02-05T09:49:23.748418Z","iopub.status.idle":"2026-02-05T09:49:23.761548Z","shell.execute_reply.started":"2026-02-05T09:49:23.748387Z","shell.execute_reply":"2026-02-05T09:49:23.760846Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(train_ds , epochs=10 , validation_data = val_ds)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T09:49:23.762288Z","iopub.execute_input":"2026-02-05T09:49:23.762532Z","iopub.status.idle":"2026-02-05T10:04:02.302780Z","shell.execute_reply.started":"2026-02-05T09:49:23.762513Z","shell.execute_reply":"2026-02-05T10:04:02.302215Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Accuracy Graph \nimport matplotlib.pyplot as plt\n\nplt.plot(history.history['accuracy'], color='red' , label='train')\nplt.plot(history.history['val_accuracy'], color='blue', label='validation')\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:04:41.350582Z","iopub.execute_input":"2026-02-05T10:04:41.350865Z","iopub.status.idle":"2026-02-05T10:04:41.565958Z","shell.execute_reply.started":"2026-02-05T10:04:41.350842Z","shell.execute_reply":"2026-02-05T10:04:41.565401Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Loss Function Graph\nplt.plot(history.history['loss'], color='red' , label='train')\nplt.plot(history.history['val_loss'], color='blue', label='validation')\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:04:45.129417Z","iopub.execute_input":"2026-02-05T10:04:45.130089Z","iopub.status.idle":"2026-02-05T10:04:45.231791Z","shell.execute_reply.started":"2026-02-05T10:04:45.130061Z","shell.execute_reply":"2026-02-05T10:04:45.231066Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Transfer Learning + Data Augmentation","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications import VGG16\nfrom tensorflow.keras.applications.vgg16 import preprocess_input\nfrom tensorflow.keras import layers, models\nimport tensorflow as tf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:45.169872Z","iopub.execute_input":"2026-02-05T10:26:45.170153Z","iopub.status.idle":"2026-02-05T10:26:45.173944Z","shell.execute_reply.started":"2026-02-05T10:26:45.170130Z","shell.execute_reply":"2026-02-05T10:26:45.173230Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"IMG_SIZE =150\n\n# Data Augmentation\ndata_augmentation = tf.keras.Sequential([\n    layers.RandomFlip(\"horizontal\"),\n    layers.RandomRotation(0.1),\n    layers.RandomZoom(0.1),\n])\n\n# Pretrained base\nconv_base_aug = VGG16(\n    weights='imagenet',\n    include_top = False,\n    input_shape=(IMG_SIZE, IMG_SIZE , 3)\n)\nconv_base_aug.trainable = False\n\n# Model\nmodel_aug = models.Sequential([\n    layers.Input(shape=(IMG_SIZE , IMG_SIZE , 3)),\n\n    data_augmentation,\n    layers.Lambda(preprocess_input),\n\n    conv_base_aug,\n\n    layers.GlobalAveragePooling2D(),\n    layers.Dense(256, activation='relu'),\n    layers.BatchNormalization(),\n    layers.Dropout(0.5),\n\n    layers.Dense(1, activation='sigmoid')\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:45.701071Z","iopub.execute_input":"2026-02-05T10:26:45.701788Z","iopub.status.idle":"2026-02-05T10:26:45.980441Z","shell.execute_reply.started":"2026-02-05T10:26:45.701753Z","shell.execute_reply":"2026-02-05T10:26:45.979908Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_aug.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:48.232196Z","iopub.execute_input":"2026-02-05T10:26:48.232886Z","iopub.status.idle":"2026-02-05T10:26:48.248730Z","shell.execute_reply.started":"2026-02-05T10:26:48.232857Z","shell.execute_reply":"2026-02-05T10:26:48.248145Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = tf.keras.optimizers.Adam(learning_rate=1e-4)\n\nmodel_aug.compile(\n    optimizer=optimizer,\n    loss='binary_crossentropy',\n    metrics=['accuracy']\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:48.634273Z","iopub.execute_input":"2026-02-05T10:26:48.634829Z","iopub.status.idle":"2026-02-05T10:26:48.641912Z","shell.execute_reply.started":"2026-02-05T10:26:48.634809Z","shell.execute_reply":"2026-02-05T10:26:48.641251Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"callbacks = [\n    tf.keras.callbacks.EarlyStopping(\n        monitor='val_loss',\n        patience=3,\n        restore_best_weights=True\n    ),\n    tf.keras.callbacks.ReduceLROnPlateau(\n        monitor='val_loss',\n        factor=0.2,\n        patience=2\n    )\n]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:50.281661Z","iopub.execute_input":"2026-02-05T10:26:50.282089Z","iopub.status.idle":"2026-02-05T10:26:50.285532Z","shell.execute_reply.started":"2026-02-05T10:26:50.282065Z","shell.execute_reply":"2026-02-05T10:26:50.284968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import time\n\nstart = time.time()\n\nhistory_aug = model_aug.fit(\n    train_ds,\n    validation_data=val_ds,\n    epochs=20,\n    callbacks=callbacks\n)\n\nend = time.time()\n\nprint(f\"Training time: {end - start:.2f} seconds\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:26:51.256797Z","iopub.execute_input":"2026-02-05T10:26:51.257067Z","iopub.status.idle":"2026-02-05T10:45:52.648746Z","shell.execute_reply.started":"2026-02-05T10:26:51.257043Z","shell.execute_reply":"2026-02-05T10:45:52.648116Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.plot(history_aug.history['accuracy'], color='red' , label='train')\nplt.plot(history_aug.history['val_accuracy'], color='blue', label='validation')\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:45:52.649887Z","iopub.execute_input":"2026-02-05T10:45:52.650132Z","iopub.status.idle":"2026-02-05T10:45:52.759291Z","shell.execute_reply.started":"2026-02-05T10:45:52.650110Z","shell.execute_reply":"2026-02-05T10:45:52.758744Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.plot(history_aug.history['loss'], color='red' , label='train')\nplt.plot(history_aug.history['val_loss'], color='blue', label='validation')\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:45:52.760180Z","iopub.execute_input":"2026-02-05T10:45:52.760447Z","iopub.status.idle":"2026-02-05T10:45:52.859811Z","shell.execute_reply.started":"2026-02-05T10:45:52.760427Z","shell.execute_reply":"2026-02-05T10:45:52.859137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_aug.layers","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:19:44.427299Z","iopub.execute_input":"2026-02-05T11:19:44.427613Z","iopub.status.idle":"2026-02-05T11:19:44.432699Z","shell.execute_reply.started":"2026-02-05T11:19:44.427589Z","shell.execute_reply":"2026-02-05T11:19:44.432024Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Fine Tuning\nconv_base = model_aug.layers[2]  # data_aug(0), preprocess(1), VGG16(2)\n\nconv_base.trainable = True\n\nfor layer in conv_base.layers:\n    if layer.name.startswith(\"block5\"):\n        layer.trainable = True\n    else:\n        layer.trainable = False\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:25:11.096581Z","iopub.status.idle":"2026-02-05T10:25:11.096824Z","shell.execute_reply.started":"2026-02-05T10:25:11.096715Z","shell.execute_reply":"2026-02-05T10:25:11.096728Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_aug.compile(\n    optimizer=tf.keras.optimizers.Adam(learning_rate=1e-5),\n    loss='binary_crossentropy',\n    metrics=['accuracy']\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:54:31.850238Z","iopub.execute_input":"2026-02-05T10:54:31.850979Z","iopub.status.idle":"2026-02-05T10:54:31.867547Z","shell.execute_reply.started":"2026-02-05T10:54:31.850950Z","shell.execute_reply":"2026-02-05T10:54:31.866899Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history_fine = model_aug.fit(\n    train_ds,\n    epochs=10,\n    validation_data=val_ds,\n    callbacks=callbacks\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T10:54:44.335765Z","iopub.execute_input":"2026-02-05T10:54:44.336047Z","iopub.status.idle":"2026-02-05T11:00:03.917563Z","shell.execute_reply.started":"2026-02-05T10:54:44.336024Z","shell.execute_reply":"2026-02-05T11:00:03.916955Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"conv_base.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:16:22.050777Z","iopub.execute_input":"2026-02-05T11:16:22.051451Z","iopub.status.idle":"2026-02-05T11:16:22.072883Z","shell.execute_reply.started":"2026-02-05T11:16:22.051422Z","shell.execute_reply":"2026-02-05T11:16:22.072378Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.plot(history_fine.history['accuracy'], color='red' , label='train')\nplt.plot(history_fine.history['val_accuracy'], color='blue', label='validation')\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:29:56.732166Z","iopub.execute_input":"2026-02-05T11:29:56.732471Z","iopub.status.idle":"2026-02-05T11:29:56.832088Z","shell.execute_reply.started":"2026-02-05T11:29:56.732446Z","shell.execute_reply":"2026-02-05T11:29:56.831395Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.plot(history_fine.history['loss'], color='red' , label='train')\nplt.plot(history_fine.history['val_loss'], color='blue', label='validation')\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:29:57.392289Z","iopub.execute_input":"2026-02-05T11:29:57.393019Z","iopub.status.idle":"2026-02-05T11:29:57.494844Z","shell.execute_reply.started":"2026-02-05T11:29:57.392986Z","shell.execute_reply":"2026-02-05T11:29:57.494391Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Fine-Tuning Results (VGG16 + Data Augmentation)\n\nAfter applying fine-tuning by unfreezing the top convolutional block\n(Block5) of the pretrained VGG16 model, the network achieved the\nfollowing performance:\n\n- Training Accuracy: ~96%\n- Validation Accuracy: ~97.7%\n- Validation Loss: ~0.06\n\nThe validation accuracy remained consistently higher than the training\naccuracy due to strong data augmentation and regularization, indicating\nexcellent generalization and no overfitting.\n\nThe learning rate was kept very low (1e-5 → 2e-6) to prevent damaging\npretrained weights. Fine-tuning resulted in marginal but stable\nperformance improvements, confirming that the pretrained features were\nsuccessfully adapted to the Dogs vs Cats classification task.\n","metadata":{}},{"cell_type":"code","source":"#Unzip test.zip file\nimport zipfile, os\n\nos.makedirs('/kaggle/working/dogs-vs-cats/test', exist_ok=True)\n\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/test1.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/dogs-vs-cats/test')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:29:09.777523Z","iopub.execute_input":"2026-02-05T11:29:09.777836Z","iopub.status.idle":"2026-02-05T11:29:13.607143Z","shell.execute_reply.started":"2026-02-05T11:29:09.777810Z","shell.execute_reply":"2026-02-05T11:29:13.606420Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TEST_DIR = \"/kaggle/working/dogs-vs-cats/test/test1\"\nIMG_SIZE = 150     # same as training\nBATCH_SIZE = 64","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:31:04.567900Z","iopub.execute_input":"2026-02-05T11:31:04.568183Z","iopub.status.idle":"2026-02-05T11:31:04.571767Z","shell.execute_reply.started":"2026-02-05T11:31:04.568159Z","shell.execute_reply":"2026-02-05T11:31:04.571057Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_ds = tf.keras.utils.image_dataset_from_directory(\n    TEST_DIR,\n    image_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    shuffle=False,      \n    labels=None\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:31:17.534733Z","iopub.execute_input":"2026-02-05T11:31:17.535396Z","iopub.status.idle":"2026-02-05T11:31:17.782815Z","shell.execute_reply.started":"2026-02-05T11:31:17.535369Z","shell.execute_reply":"2026-02-05T11:31:17.782090Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nimage_files = sorted(\n    [f for f in os.listdir(TEST_DIR) if f.endswith(\".jpg\")],\n    key=lambda x: int(x.split(\".\")[0])\n)\n\nimage_ids = [int(f.split(\".\")[0]) for f in image_files]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:32:02.366699Z","iopub.execute_input":"2026-02-05T11:32:02.367395Z","iopub.status.idle":"2026-02-05T11:32:02.388873Z","shell.execute_reply.started":"2026-02-05T11:32:02.367366Z","shell.execute_reply":"2026-02-05T11:32:02.388158Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predictions = model_aug.predict(test_ds)\npredicted_labels = (predictions > 0.5).astype(int).reshape(-1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:36:14.921536Z","iopub.execute_input":"2026-02-05T11:36:14.921830Z","iopub.status.idle":"2026-02-05T11:36:48.482293Z","shell.execute_reply.started":"2026-02-05T11:36:14.921805Z","shell.execute_reply":"2026-02-05T11:36:48.481673Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_map = {\n    0: \"Cat\",\n    1: \"Dog\"\n}\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:36:59.441418Z","iopub.execute_input":"2026-02-05T11:36:59.442147Z","iopub.status.idle":"2026-02-05T11:36:59.445290Z","shell.execute_reply.started":"2026-02-05T11:36:59.442116Z","shell.execute_reply":"2026-02-05T11:36:59.444711Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import random\n\nindices = random.sample(range(len(image_files)), 5)\n\nplt.figure(figsize=(15, 5))\n\nfor i, idx in enumerate(indices):\n    img_path = os.path.join(TEST_DIR, image_files[idx])\n    img = plt.imread(img_path)\n\n    plt.subplot(1, 5, i + 1)\n    plt.imshow(img)\n    plt.axis(\"off\")\n    plt.title(f\"ID: {image_ids[idx]}\\nPred: {label_map[predicted_labels[idx]]}\")\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-05T11:44:34.573185Z","iopub.execute_input":"2026-02-05T11:44:34.573693Z","iopub.status.idle":"2026-02-05T11:44:34.897737Z","shell.execute_reply.started":"2026-02-05T11:44:34.573663Z","shell.execute_reply":"2026-02-05T11:44:34.896968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}