{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"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"},"colab":{"provenance":[],"authorship_tag":"ABX9TyNP+NVsnQuRfGBc+sqXeDj5"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"isSourceIdPinned":false,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Fine tune Densenet on cat-dog","metadata":{"id":"FOE5ZrT7hQjk"}},{"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":{"id":"BAkxXIRhhNB9","trusted":true,"execution":{"iopub.status.busy":"2025-07-12T17:29:35.329433Z","iopub.execute_input":"2025-07-12T17:29:35.329662Z","iopub.status.idle":"2025-07-12T17:29:48.568995Z","shell.execute_reply.started":"2025-07-12T17:29:35.329631Z","shell.execute_reply":"2025-07-12T17:29:48.568357Z"}},"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-12T17:29:53.564094Z","iopub.execute_input":"2025-07-12T17:29:53.564379Z","iopub.status.idle":"2025-07-12T17:30:07.638623Z","shell.execute_reply.started":"2025-07-12T17:29:53.564351Z","shell.execute_reply":"2025-07-12T17:30:07.637804Z"}},"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":"code","source":"original_train_dir = pathlib.Path('/kaggle/working/train')  # Now a Path object\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-12T17:32:27.159591Z","iopub.execute_input":"2025-07-12T17:32:27.160511Z","iopub.status.idle":"2025-07-12T17:32:29.779610Z","shell.execute_reply.started":"2025-07-12T17:32:27.160471Z","shell.execute_reply":"2025-07-12T17:32:29.778753Z"}},"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-12T17:32:35.011883Z","iopub.execute_input":"2025-07-12T17:32:35.012506Z","iopub.status.idle":"2025-07-12T17:32:38.711010Z","shell.execute_reply.started":"2025-07-12T17:32:35.012473Z","shell.execute_reply":"2025-07-12T17:32:38.710435Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image_dataset_from_directory\n\ntest_dir = \"/kaggle/working/test1\"  \nimg_size = (180, 180)  \nbatch_size = 32\n\n# Load test dataset (unlabeled)\ntest_dataset = image_dataset_from_directory(\n    directory=test_dir,\n    labels=None,            # No labels available\n    image_size=img_size,    \n    batch_size=batch_size,\n    shuffle=False,          # Keep original order for submission\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-12T17:33:19.252067Z","iopub.execute_input":"2025-07-12T17:33:19.252787Z","iopub.status.idle":"2025-07-12T17:33:19.520887Z","shell.execute_reply.started":"2025-07-12T17:33:19.252761Z","shell.execute_reply":"2025-07-12T17:33:19.520352Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras import layers\n\nconv_base = keras.applications.DenseNet121(\n    weights='imagenet',\n    include_top=False\n)\nconv_base.trainable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-12T17:34:54.614188Z","iopub.execute_input":"2025-07-12T17:34:54.614568Z","iopub.status.idle":"2025-07-12T17:34:57.715729Z","shell.execute_reply.started":"2025-07-12T17:34:54.614543Z","shell.execute_reply":"2025-07-12T17:34:57.715149Z"}},"outputs":[],"execution_count":null},{"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-12T17:35:50.279433Z","iopub.execute_input":"2025-07-12T17:35:50.279731Z","iopub.status.idle":"2025-07-12T17:35:50.295008Z","shell.execute_reply.started":"2025-07-12T17:35:50.279713Z","shell.execute_reply":"2025-07-12T17:35:50.294469Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inputs = keras.Input(shape=(180, 180, 3))\nx = data_augmentation(inputs)\nx = keras.applications.densenet.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-12T17:36:50.532782Z","iopub.execute_input":"2025-07-12T17:36:50.533524Z","iopub.status.idle":"2025-07-12T17:36:50.621879Z","shell.execute_reply.started":"2025-07-12T17:36:50.533498Z","shell.execute_reply":"2025-07-12T17:36:50.621303Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(loss='binary_crossentropy',\n              optimizer=keras.optimizers.Nadam(learning_rate=0.001),\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-12T17:38:57.515602Z","iopub.execute_input":"2025-07-12T17:38:57.515889Z","iopub.status.idle":"2025-07-12T17:38:57.532068Z","shell.execute_reply.started":"2025-07-12T17:38:57.515870Z","shell.execute_reply":"2025-07-12T17:38:57.531578Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_dataset,\n    epochs=9,\n    validation_data=validation_dataset,\n    callbacks=callbacks\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-12T17:39:45.921167Z","iopub.execute_input":"2025-07-12T17:39:45.921867Z","iopub.status.idle":"2025-07-12T17:52:14.799033Z","shell.execute_reply.started":"2025-07-12T17:39:45.921842Z","shell.execute_reply":"2025-07-12T17:52:14.798362Z"}},"outputs":[],"execution_count":null},{"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":{"id":"WXe_dNzEhcG6","trusted":true,"execution":{"iopub.status.busy":"2025-07-12T17:55:06.541518Z","iopub.execute_input":"2025-07-12T17:55:06.541769Z","iopub.status.idle":"2025-07-12T17:55:06.547117Z","shell.execute_reply.started":"2025-07-12T17:55:06.541752Z","shell.execute_reply":"2025-07-12T17:55:06.546331Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_history(history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-12T17:55:08.858855Z","iopub.execute_input":"2025-07-12T17:55:08.859551Z","iopub.status.idle":"2025-07-12T17:55:09.193221Z","shell.execute_reply.started":"2025-07-12T17:55:08.859520Z","shell.execute_reply":"2025-07-12T17:55:09.192475Z"}},"outputs":[],"execution_count":null}]}