{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!unzip -qq /kaggle/input/dogs-vs-cats/train.zip","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:27:43.270784Z","iopub.execute_input":"2025-06-11T20:27:43.271017Z","iopub.status.idle":"2025-06-11T20:27:58.484793Z","shell.execute_reply.started":"2025-06-11T20:27:43.270993Z","shell.execute_reply":"2025-06-11T20:27:58.483765Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, shutil, pathlib\noriginal_dir = pathlib.Path(\"train\")\nnew_base_dir = pathlib.Path(\"cats_vs_dogs_small\")\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)\n        fnames = [f\"{category}.{i}.jpg\" for i in range(start_index, end_index)]\n        for fname in fnames:\n            shutil.copyfile(src=original_dir / fname, dst=dir / fname)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:27:58.485715Z","iopub.execute_input":"2025-06-11T20:27:58.485920Z","iopub.status.idle":"2025-06-11T20:27:58.491899Z","shell.execute_reply.started":"2025-06-11T20:27:58.485898Z","shell.execute_reply":"2025-06-11T20:27:58.490942Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"make_subset(\"train\", start_index=0, end_index=1000)\nmake_subset(\"validation\", start_index=1000, end_index=1500)\nmake_subset(\"test\", start_index=1500, end_index=2500)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:27:58.493645Z","iopub.execute_input":"2025-06-11T20:27:58.493815Z","iopub.status.idle":"2025-06-11T20:27:59.215737Z","shell.execute_reply.started":"2025-06-11T20:27:58.493802Z","shell.execute_reply":"2025-06-11T20:27:59.214926Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.utils import image_dataset_from_directory\n\ntrain_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\ntest_dataset = image_dataset_from_directory(\n    new_base_dir / \"test\",\n    image_size=(180, 180),\n    batch_size=32)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:27:59.216654Z","iopub.execute_input":"2025-06-11T20:27:59.216890Z","iopub.status.idle":"2025-06-11T20:28:18.068049Z","shell.execute_reply.started":"2025-06-11T20:27:59.216862Z","shell.execute_reply":"2025-06-11T20:28:18.067259Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow import keras\n\nconv_base = keras.applications.vgg16.VGG16(\n    weights=\"imagenet\",\n    include_top=False,\n    input_shape=(180, 180, 3))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:28:18.068932Z","iopub.execute_input":"2025-06-11T20:28:18.069202Z","iopub.status.idle":"2025-06-11T20:28:19.645685Z","shell.execute_reply.started":"2025-06-11T20:28:18.069173Z","shell.execute_reply":"2025-06-11T20:28:19.645071Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"conv_base.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:28:19.646398Z","iopub.execute_input":"2025-06-11T20:28:19.646683Z","iopub.status.idle":"2025-06-11T20:28:19.670520Z","shell.execute_reply.started":"2025-06-11T20:28:19.646653Z","shell.execute_reply":"2025-06-11T20:28:19.669967Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\ndef get_features_and_labels(dataset):\n    all_features = []\n    all_labels = []\n    for images, labels in dataset:\n        preprocessed_images = keras.applications.vgg16.preprocess_input(images)\n        features = conv_base.predict(preprocessed_images)\n        all_features.append(features)\n        all_labels.append(labels)\n    return np.concatenate(all_features), np.concatenate(all_labels)\n    \ntrain_features, train_labels = get_features_and_labels(train_dataset)\nval_features, val_labels = get_features_and_labels(validation_dataset)\ntest_features, test_labels = get_features_and_labels(test_dataset)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:28:19.671190Z","iopub.execute_input":"2025-06-11T20:28:19.671439Z","iopub.status.idle":"2025-06-11T20:29:08.263736Z","shell.execute_reply.started":"2025-06-11T20:28:19.671410Z","shell.execute_reply":"2025-06-11T20:29:08.263098Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_features.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:29:08.264691Z","iopub.execute_input":"2025-06-11T20:29:08.264963Z","iopub.status.idle":"2025-06-11T20:29:08.270267Z","shell.execute_reply.started":"2025-06-11T20:29:08.264939Z","shell.execute_reply":"2025-06-11T20:29:08.269451Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras import layers\n\ninputs = keras.Input(shape=(5, 5, 512))\nx = layers.Flatten()(inputs)\nx = layers.Dense(256)(x)\nx = layers.Dropout(0.5)(x)\noutputs = layers.Dense(1, activation=\"sigmoid\")(x)\nmodel = keras.Model(inputs, outputs)\n\nmodel.compile(loss=\"binary_crossentropy\",\n    optimizer=\"rmsprop\",\n    metrics=[\"accuracy\"])\n\ncallbacks = [\n    keras.callbacks.ModelCheckpoint(\n    filepath=\"feature_extraction.keras\",\n    save_best_only=True,\n    monitor=\"val_loss\")\n]\n\nhistory = model.fit(\n    train_features, train_labels,\n    epochs=20,\n    validation_data=(val_features, val_labels),\n    callbacks=callbacks)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:29:08.272189Z","iopub.execute_input":"2025-06-11T20:29:08.272417Z","iopub.status.idle":"2025-06-11T20:29:18.876409Z","shell.execute_reply.started":"2025-06-11T20:29:08.272396Z","shell.execute_reply":"2025-06-11T20:29:18.875678Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nacc = history.history[\"accuracy\"]\nval_acc = history.history[\"val_accuracy\"]\nloss = history.history[\"loss\"]\nval_loss = history.history[\"val_loss\"]\nepochs = range(1, len(acc) + 1)\nplt.plot(epochs, acc, \"bo\", label=\"Training accuracy\")\nplt.plot(epochs, val_acc, \"b\", label=\"Validation accuracy\")\nplt.title(\"Training and validation accuracy\")\nplt.legend()\nplt.figure()\nplt.plot(epochs, loss, \"bo\", label=\"Training loss\")\nplt.plot(epochs, val_loss, \"b\", label=\"Validation loss\")\nplt.title(\"Training and validation loss\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:29:18.877446Z","iopub.execute_input":"2025-06-11T20:29:18.877695Z","iopub.status.idle":"2025-06-11T20:29:19.300849Z","shell.execute_reply.started":"2025-06-11T20:29:18.877675Z","shell.execute_reply":"2025-06-11T20:29:19.299843Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"conv_base = keras.applications.vgg16.VGG16(\n    weights=\"imagenet\",\n    include_top=False)\nconv_base.trainable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:29:19.301841Z","iopub.execute_input":"2025-06-11T20:29:19.302132Z","iopub.status.idle":"2025-06-11T20:29:19.551934Z","shell.execute_reply.started":"2025-06-11T20:29:19.302090Z","shell.execute_reply":"2025-06-11T20:29:19.551402Z"}},"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)\n\ninputs = keras.Input(shape=(180, 180, 3))\nx = data_augmentation(inputs)\nx = keras.applications.vgg16.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)\nmodel.compile(loss=\"binary_crossentropy\",\n    optimizer=\"rmsprop\",\n    metrics=[\"accuracy\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:29:19.552619Z","iopub.execute_input":"2025-06-11T20:29:19.552802Z","iopub.status.idle":"2025-06-11T20:29:19.597959Z","shell.execute_reply.started":"2025-06-11T20:29:19.552788Z","shell.execute_reply":"2025-06-11T20:29:19.597388Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"callbacks = [\n    keras.callbacks.ModelCheckpoint(\n    filepath=\"feature_extraction_with_data_augmentation.keras\",\n    save_best_only=True,\n    monitor=\"val_loss\")\n]\nhistory = model.fit(\n    train_dataset,\n    epochs=50,\n    validation_data=validation_dataset,\n    callbacks=callbacks)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:29:19.598623Z","iopub.execute_input":"2025-06-11T20:29:19.598817Z","iopub.status.idle":"2025-06-11T20:37:34.014980Z","shell.execute_reply.started":"2025-06-11T20:29:19.598803Z","shell.execute_reply":"2025-06-11T20:37:34.014391Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nacc = history.history[\"accuracy\"]\nval_acc = history.history[\"val_accuracy\"]\nloss = history.history[\"loss\"]\nval_loss = history.history[\"val_loss\"]\nepochs = range(1, len(acc) + 1)\nplt.plot(epochs, acc, \"bo\", label=\"Training accuracy\")\nplt.plot(epochs, val_acc, \"b\", label=\"Validation accuracy\")\nplt.title(\"Training and validation accuracy\")\nplt.legend()\nplt.figure()\nplt.plot(epochs, loss, \"bo\", label=\"Training loss\")\nplt.plot(epochs, val_loss, \"b\", label=\"Validation loss\")\nplt.title(\"Training and validation loss\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:37:34.016037Z","iopub.execute_input":"2025-06-11T20:37:34.016357Z","iopub.status.idle":"2025-06-11T20:37:34.343315Z","shell.execute_reply.started":"2025-06-11T20:37:34.016338Z","shell.execute_reply":"2025-06-11T20:37:34.342605Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_model = keras.models.load_model(\n    \"feature_extraction_with_data_augmentation.keras\")\ntest_loss, test_acc = test_model.evaluate(test_dataset)\nprint(f\"Test accuracy: {test_acc:.3f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:37:34.344137Z","iopub.execute_input":"2025-06-11T20:37:34.344763Z","iopub.status.idle":"2025-06-11T20:37:42.039753Z","shell.execute_reply.started":"2025-06-11T20:37:34.344744Z","shell.execute_reply":"2025-06-11T20:37:42.039126Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"conv_base.trainable = True\nfor layer in conv_base.layers[:-4]:\n    layer.trainable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:42:19.372475Z","iopub.execute_input":"2025-06-11T20:42:19.372766Z","iopub.status.idle":"2025-06-11T20:42:19.377427Z","shell.execute_reply.started":"2025-06-11T20:42:19.372745Z","shell.execute_reply":"2025-06-11T20:42:19.376825Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(loss=\"binary_crossentropy\",\n    optimizer=keras.optimizers.RMSprop(learning_rate=1e-5),\n    metrics=[\"accuracy\"])\n\ncallbacks = [\n    keras.callbacks.ModelCheckpoint(\n    filepath=\"fine_tuning.keras\",\n    save_best_only=True,\n    monitor=\"val_loss\")\n]\n\nhistory = model.fit(\n    train_dataset,\n    epochs=30,\n    validation_data=validation_dataset,\n    callbacks=callbacks)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:42:58.496182Z","iopub.execute_input":"2025-06-11T20:42:58.496515Z","iopub.status.idle":"2025-06-11T20:48:42.883067Z","shell.execute_reply.started":"2025-06-11T20:42:58.496493Z","shell.execute_reply":"2025-06-11T20:48:42.882350Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = keras.models.load_model(\"fine_tuning.keras\")\ntest_loss, test_acc = model.evaluate(test_dataset)\nprint(f\"Test accuracy: {test_acc:.3f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-11T20:51:35.260580Z","iopub.execute_input":"2025-06-11T20:51:35.261202Z","iopub.status.idle":"2025-06-11T20:51:42.687412Z","shell.execute_reply.started":"2025-06-11T20:51:35.261179Z","shell.execute_reply":"2025-06-11T20:51:42.686793Z"}},"outputs":[],"execution_count":null}]}