{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","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":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np \nfrom tensorflow import keras\nimport os, shutil, pathlib\nfrom tensorflow.keras.utils import image_dataset_from_directory","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:06:27.174403Z","iopub.execute_input":"2025-07-16T08:06:27.174557Z","iopub.status.idle":"2025-07-16T08:06:41.727867Z","shell.execute_reply.started":"2025-07-16T08:06:27.174541Z","shell.execute_reply":"2025-07-16T08:06:41.727276Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!unzip -qq /kaggle/input/dogs-vs-cats/train.zip","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:07:01.800836Z","iopub.execute_input":"2025-07-16T08:07:01.801462Z","iopub.status.idle":"2025-07-16T08:07:13.226752Z","shell.execute_reply.started":"2025-07-16T08:07:01.801438Z","shell.execute_reply":"2025-07-16T08:07:13.225680Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!unzip -qq /kaggle/input/dogs-vs-cats/test1.zip","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load Train data","metadata":{}},{"cell_type":"code","source":"original_train_dir = pathlib.Path('/kaggle/working/train')  \nnew_base_dir = pathlib.Path('cats_vs_dogs_train')\n\ndef make_subset(subset_name, start_index, end_index):\n  for category in ('cat', 'dog'):\n    dir = new_base_dir / subset_name / category\n    os.makedirs(dir, exist_ok=True)\n    fnames = [f\"{category}.{i}.jpg\" for i in range(start_index, end_index)]\n    for fname in fnames:\n      shutil.copyfile(src=original_train_dir / fname,\n                      dst=dir / fname)\n      \nmake_subset('train', start_index=0, end_index=10000)\nmake_subset('validation', start_index=10000, end_index=12500)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:14:14.574680Z","iopub.execute_input":"2025-07-16T08:14:14.574948Z","iopub.status.idle":"2025-07-16T08:14:17.157361Z","shell.execute_reply.started":"2025-07-16T08:14:14.574929Z","shell.execute_reply":"2025-07-16T08:14:17.156789Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = image_dataset_from_directory(\n    new_base_dir / 'train',\n    image_size=(180, 180),\n    batch_size=32\n)\nvalidation_dataset = image_dataset_from_directory(\n    new_base_dir / 'validation',\n    image_size=(180, 180),\n    batch_size=32\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:16:19.010938Z","iopub.execute_input":"2025-07-16T08:16:19.011542Z","iopub.status.idle":"2025-07-16T08:16:23.510784Z","shell.execute_reply.started":"2025-07-16T08:16:19.011518Z","shell.execute_reply":"2025-07-16T08:16:23.510236Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load Test data","metadata":{}},{"cell_type":"code","source":"test_dir = \"/kaggle/working/test1\"  \nimg_size = (180, 180)  \nbatch_size = 32\n\ntest_dataset = image_dataset_from_directory(\n    directory=test_dir,\n    labels=None,            \n    image_size=img_size,    \n    batch_size=batch_size,\n    shuffle=False,         \n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:16:41.811655Z","iopub.execute_input":"2025-07-16T08:16:41.811927Z","iopub.status.idle":"2025-07-16T08:16:42.082900Z","shell.execute_reply.started":"2025-07-16T08:16:41.811906Z","shell.execute_reply":"2025-07-16T08:16:42.082399Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load ResNet101V2 as Convolution Base","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras import layers\n\nconv_base = keras.applications.ResNet101V2(\n    weights='imagenet',\n    include_top=False\n)\nconv_base.trianable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:25:43.230278Z","iopub.execute_input":"2025-07-16T08:25:43.231105Z","iopub.status.idle":"2025-07-16T08:25:45.413710Z","shell.execute_reply.started":"2025-07-16T08:25:43.231073Z","shell.execute_reply":"2025-07-16T08:25:45.412825Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Data Augmentation layer","metadata":{}},{"cell_type":"code","source":"data_augmentation = keras.Sequential(\n    [\n layers.RandomFlip(\"horizontal\"),\n layers.RandomRotation(0.1),\n layers.RandomZoom(0.2),\n    ]\n )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:25:45.830862Z","iopub.execute_input":"2025-07-16T08:25:45.831118Z","iopub.status.idle":"2025-07-16T08:25:45.844645Z","shell.execute_reply.started":"2025-07-16T08:25:45.831099Z","shell.execute_reply":"2025-07-16T08:25:45.843881Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Model Building","metadata":{}},{"cell_type":"code","source":"inputs = keras.Input(shape=(180, 180, 3))\nx = data_augmentation(inputs)\nx = keras.applications.resnet_v2.preprocess_input(x)\nx = conv_base(x)\nx = layers.Flatten()(x)\nx = layers.Dense(256)(x)\nx = layers.Dropout(0.5)(x)\noutputs = layers.Dense(1, activation='sigmoid')(x)\nmodel = keras.Model(inputs, outputs)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:25:49.028582Z","iopub.execute_input":"2025-07-16T08:25:49.029081Z","iopub.status.idle":"2025-07-16T08:25:49.109063Z","shell.execute_reply.started":"2025-07-16T08:25:49.029055Z","shell.execute_reply":"2025-07-16T08:25:49.108489Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Make the last 5 layers trainable","metadata":{}},{"cell_type":"code","source":"conv_base.trainable = True\nfor layer in conv_base.layers[:-5]:\n  layer.trainable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:25:51.468251Z","iopub.execute_input":"2025-07-16T08:25:51.468534Z","iopub.status.idle":"2025-07-16T08:25:51.476113Z","shell.execute_reply.started":"2025-07-16T08:25:51.468513Z","shell.execute_reply":"2025-07-16T08:25:51.475544Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(loss='binary_crossentropy',\n              optimizer=keras.optimizers.Adam(),\n              metrics=['accuracy'])\ncallbacks = [\n    keras.callbacks.ModelCheckpoint(\n    filepath=\"fine_tuning.keras\",\n    save_best_only=True,\n    monitor=\"val_loss\")\n ]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:25:52.860962Z","iopub.execute_input":"2025-07-16T08:25:52.861259Z","iopub.status.idle":"2025-07-16T08:25:52.871878Z","shell.execute_reply.started":"2025-07-16T08:25:52.861209Z","shell.execute_reply":"2025-07-16T08:25:52.871001Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Model Training","metadata":{}},{"cell_type":"code","source":"history = model.fit(\n    train_dataset,\n    epochs=10,\n    validation_data=validation_dataset,\n    callbacks=callbacks\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:25:57.030073Z","iopub.execute_input":"2025-07-16T08:25:57.030799Z","iopub.status.idle":"2025-07-16T08:46:33.804151Z","shell.execute_reply.started":"2025-07-16T08:25:57.030775Z","shell.execute_reply":"2025-07-16T08:46:33.803213Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Plot model history","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ndef plot_history(history):\n  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))\n  ax1.plot(history.history['loss'], label='loss')\n  ax1.plot(history.history['val_loss'], label='val_loss')\n  ax1.set_title(\"Loss\")\n  ax1.set_xlabel('Epoch')\n  ax1.set_ylabel('binary_crossentropy')\n  ax1.legend()\n  ax1.grid(True)\n\n\n  ax2.plot(history.history['accuracy'], label='accuracy')\n  ax2.plot(history.history['val_accuracy'], label='val_accuracy')\n  ax2.set_title(\"Accuracy\")\n  ax2.set_xlabel('Epoch')\n  ax2.set_ylabel('Accuracy')\n  ax2.grid(True)\n  ax2.legend()\n  plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:24:51.864698Z","iopub.execute_input":"2025-07-16T08:24:51.865548Z","iopub.status.idle":"2025-07-16T08:24:51.870822Z","shell.execute_reply.started":"2025-07-16T08:24:51.865515Z","shell.execute_reply":"2025-07-16T08:24:51.870272Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_history(history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T08:53:13.292592Z","iopub.execute_input":"2025-07-16T08:53:13.292872Z","iopub.status.idle":"2025-07-16T08:53:13.709289Z","shell.execute_reply.started":"2025-07-16T08:53:13.292851Z","shell.execute_reply":"2025-07-16T08:53:13.708544Z"}},"outputs":[],"execution_count":null}]}