{"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":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31011,"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":"2025-04-23T01:13:20.443435Z","iopub.execute_input":"2025-04-23T01:13:20.443686Z","iopub.status.idle":"2025-04-23T01:13:20.453484Z","shell.execute_reply.started":"2025-04-23T01:13:20.443665Z","shell.execute_reply":"2025-04-23T01:13:20.452632Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'\n\nimport warnings\nwarnings.filterwarnings('ignore')\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models, optimizers\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications import MobileNetV2, InceptionResNetV2, InceptionV3\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras import Model\nfrom sklearn.model_selection import train_test_split\nimport zipfile\nimport shutil","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:13:23.435618Z","iopub.execute_input":"2025-04-23T01:13:23.436081Z","iopub.status.idle":"2025-04-23T01:13:38.111901Z","shell.execute_reply.started":"2025-04-23T01:13:23.436060Z","shell.execute_reply":"2025-04-23T01:13:38.111390Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Clean up working directory\nworkspace_path = \"/kaggle/working\"\n\nfor item in os.listdir(workspace_path):\n    target = os.path.join(workspace_path, item)\n    try:\n        if os.path.isfile(target) or os.path.islink(target):\n            os.unlink(target)\n        elif os.path.isdir(target):\n            shutil.rmtree(target)\n    except Exception as error:\n        print(f\"Could not delete {target}. Reason: {error}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T23:03:26.972361Z","iopub.execute_input":"2025-04-22T23:03:26.972913Z","iopub.status.idle":"2025-04-22T23:03:28.081041Z","shell.execute_reply.started":"2025-04-22T23:03:26.972884Z","shell.execute_reply":"2025-04-22T23:03:28.080222Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Unzip data and organize structure\n\n# Input zip file locations\npath_to_train_zip = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip'\npath_to_test_zip = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip'\n\n# Output directory structure\nproject_dir = '/kaggle/working/pet-classifier'\nraw_train_dir = os.path.join(project_dir, 'unzipped_train')\ntrain_split_dir = os.path.join(project_dir, 'training')\nval_split_dir = os.path.join(project_dir, 'validation')\ntest_output_dir = os.path.join(project_dir, 'testing')\n\nos.makedirs(raw_train_dir, exist_ok=True)\nwith zipfile.ZipFile(path_to_train_zip, 'r') as archive:\n    archive.extractall(raw_train_dir)\n\nos.makedirs(test_output_dir, exist_ok=True)\nwith zipfile.ZipFile(path_to_test_zip, 'r') as archive:\n    archive.extractall(test_output_dir)\n\nimage_directory = os.path.join(raw_train_dir, 'train')\nall_filenames = os.listdir(image_directory)\n\n# Create directories for categorized split\nfor species in ['cats', 'dogs']:\n    os.makedirs(os.path.join(train_split_dir, species), exist_ok=True)\n    os.makedirs(os.path.join(val_split_dir, species), exist_ok=True)\n\n# Split 80/20 per class\ntrain_ratio = 0.8\ncat_files = sorted([img for img in all_filenames if 'cat' in img])\ndog_files = sorted([img for img in all_filenames if 'dog' in img])\n\ncat_train_count = int(len(cat_files) * train_ratio)\ndog_train_count = int(len(dog_files) * train_ratio)\n\n# Move files accordingly\nfor img in cat_files[:cat_train_count]:\n    shutil.move(os.path.join(image_directory, img), os.path.join(train_split_dir, 'cats', img))\nfor img in cat_files[cat_train_count:]:\n    shutil.move(os.path.join(image_directory, img), os.path.join(val_split_dir, 'cats', img))\n\nfor img in dog_files[:dog_train_count]:\n    shutil.move(os.path.join(image_directory, img), os.path.join(train_split_dir, 'dogs', img))\nfor img in dog_files[dog_train_count:]:\n    shutil.move(os.path.join(image_directory, img), os.path.join(val_split_dir, 'dogs', img))\n\nprint(\"Split complete. Images placed into training/, validation/, and testing/ folders.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:13:49.633884Z","iopub.execute_input":"2025-04-23T01:13:49.634625Z","iopub.status.idle":"2025-04-23T01:14:03.462496Z","shell.execute_reply.started":"2025-04-23T01:13:49.634598Z","shell.execute_reply":"2025-04-23T01:14:03.461723Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check how many images remain\nif os.path.exists(raw_train_dir):\n    leftover_imgs = os.listdir(raw_train_dir)\n    rem_dogs = len([i for i in leftover_imgs if 'dog' in i])\n    rem_cats = len([i for i in leftover_imgs if 'cat' in i])\nelse:\n    rem_dogs = rem_cats = 0\n\nprint(f\"Remaining in original folder: Dogs = {rem_dogs}, Cats = {rem_cats}\")\n\n# Count split images\ndogs_train = len(os.listdir(os.path.join(train_split_dir, 'dogs')))\ncats_train = len(os.listdir(os.path.join(train_split_dir, 'cats')))\ndogs_val = len(os.listdir(os.path.join(val_split_dir, 'dogs')))\ncats_val = len(os.listdir(os.path.join(val_split_dir, 'cats')))\n\nprint(\"\\nTraining Split:\")\nprint(f\"Dogs: {dogs_train}\")\nprint(f\"Cats: {cats_train}\")\n\nprint(\"\\nValidation Split:\")\nprint(f\"Dogs: {dogs_val}\")\nprint(f\"Cats: {cats_val}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:14:07.630898Z","iopub.execute_input":"2025-04-23T01:14:07.631165Z","iopub.status.idle":"2025-04-23T01:14:07.651480Z","shell.execute_reply.started":"2025-04-23T01:14:07.631145Z","shell.execute_reply":"2025-04-23T01:14:07.650771Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Image generators\n\ntrain_aug = ImageDataGenerator(rescale=1./255)\nval_aug = ImageDataGenerator(rescale=1./255)\n\ntrain_flow = train_aug.flow_from_directory(\n    train_split_dir,\n    target_size=(299, 299),\n    batch_size=32,\n    class_mode='binary'\n)\n\nval_flow = val_aug.flow_from_directory(\n    val_split_dir,\n    target_size=(299, 299),\n    batch_size=32,\n    class_mode='binary'\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:14:10.989472Z","iopub.execute_input":"2025-04-23T01:14:10.989753Z","iopub.status.idle":"2025-04-23T01:14:11.226633Z","shell.execute_reply.started":"2025-04-23T01:14:10.989731Z","shell.execute_reply":"2025-04-23T01:14:11.226082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === Constants ===\nINPUT_SHAPE = (299, 299)\nBATCH_SIZE = 32\nEPOCHS = 10\n\n# === Plot Training History ===\ndef plot_training_metrics(history, chart_title=\"Model Performance Overview\"):\n    epochs_ran = history.epoch\n    metrics = history.history\n\n    plt.figure(figsize=(14, 5))\n\n    # Accuracy curve\n    plt.subplot(1, 2, 1)\n    plt.plot(epochs_ran, metrics['accuracy'], label='Training Accuracy')\n    plt.plot(epochs_ran, metrics['val_accuracy'], linestyle='--', label='Validation Accuracy')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.title('Accuracy per Epoch')\n    plt.legend()\n    plt.grid(True)\n\n    # Loss curve\n    plt.subplot(1, 2, 2)\n    plt.plot(epochs_ran, metrics['loss'], label='Training Loss')\n    plt.plot(epochs_ran, metrics['val_loss'], linestyle='--', label='Validation Loss')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.title('Loss per Epoch')\n    plt.legend()\n    plt.grid(True)\n\n    plt.suptitle(chart_title)\n    plt.tight_layout()\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:14:59.591293Z","iopub.execute_input":"2025-04-23T01:14:59.591850Z","iopub.status.idle":"2025-04-23T01:14:59.597553Z","shell.execute_reply.started":"2025-04-23T01:14:59.591828Z","shell.execute_reply":"2025-04-23T01:14:59.596910Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras import layers, models, optimizers\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\n\ndef create_transfer_model(base_architecture, image_dim=299, dropout_prob=0.5, freeze_base=True):\n    base_model = base_architecture(\n        weights='imagenet',\n        include_top=False,\n        input_shape=(image_dim, image_dim, 3)\n    )\n    base_model.trainable = not freeze_base\n\n    x = base_model.output\n    x = layers.GlobalAveragePooling2D()(x)\n    x = layers.Dense(128, activation='relu')(x)\n    x = layers.Dropout(dropout_prob)(x)\n    output_layer = layers.Dense(1, activation='sigmoid')(x)\n\n    model = Model(inputs=base_model.input, outputs=output_layer)\n    model.compile(\n        optimizer=optimizers.Adam(learning_rate=0.001),\n        loss='binary_crossentropy',\n        metrics=['accuracy']\n    )\n    return model\n\n# === Callbacks ===\ntraining_callbacks = [\n    EarlyStopping(\n        monitor='val_loss',\n        patience=3,\n        restore_best_weights=True,\n        verbose=1),\n    ReduceLROnPlateau(\n        monitor='val_loss',\n        factor=0.2,\n        patience=2,\n        min_lr=1e-6,\n        verbose=1)\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:15:02.285387Z","iopub.execute_input":"2025-04-23T01:15:02.286082Z","iopub.status.idle":"2025-04-23T01:15:02.292304Z","shell.execute_reply.started":"2025-04-23T01:15:02.286045Z","shell.execute_reply":"2025-04-23T01:15:02.291546Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === Custom CNN Builder ===\ndef create_custom_cnn():\n    model = models.Sequential([\n        layers.Input(shape=(INPUT_SHAPE[0], INPUT_SHAPE[1], 3)),\n        layers.Conv2D(32, (3, 3), activation='relu'),\n        layers.MaxPooling2D(pool_size=(2, 2)),\n        layers.Conv2D(64, (3, 3), activation='relu'),\n        layers.MaxPooling2D(pool_size=(2, 2)),\n        layers.Flatten(),\n        layers.Dropout(0.5),\n        layers.Dense(64, activation='relu'),\n        layers.Dense(1, activation='sigmoid')\n    ])\n    model.compile(\n        optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),\n        loss='binary_crossentropy',\n        metrics=['accuracy']\n    )\n    return model\n\n# === Train CNN ===\ncustom_cnn_model = create_custom_cnn()\ncustom_cnn_history = custom_cnn_model.fit(\n    train_flow,\n    validation_data=val_flow,\n    epochs=EPOCHS,\n    callbacks=training_callbacks)\n\n# === Plot Results ===\nplot_training_metrics(custom_cnn_history, \"Custom CNN Performance\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:15:04.244891Z","iopub.execute_input":"2025-04-23T01:15:04.245170Z","iopub.status.idle":"2025-04-23T01:25:36.305005Z","shell.execute_reply.started":"2025-04-23T01:15:04.245148Z","shell.execute_reply":"2025-04-23T01:25:36.304353Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === Build and Train MobileNetV2 ===\nmobilenet_model = create_transfer_model(\n    base_architecture=MobileNetV2,\n    image_dim=INPUT_SHAPE[0],\n    dropout_prob=0.5,\n    freeze_base=True)\n\nmobilenet_history = mobilenet_model.fit(\n    train_flow,\n    validation_data=val_flow,\n    epochs=EPOCHS,\n    callbacks=training_callbacks)\n\n# === Plot Performance ===\nplot_training_metrics(mobilenet_history, \"MobileNetV2 Transfer Learning\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T23:10:42.702528Z","iopub.execute_input":"2025-04-22T23:10:42.702907Z","iopub.status.idle":"2025-04-22T23:21:51.584418Z","shell.execute_reply.started":"2025-04-22T23:10:42.702883Z","shell.execute_reply":"2025-04-22T23:21:51.583691Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === Build and Train InceptionV3 ===\ninceptionv3_model = create_transfer_model(\n    base_architecture=InceptionV3,\n    image_dim=INPUT_SHAPE[0],\n    dropout_prob=0.5,\n    freeze_base=True)\n\ninceptionv3_history = inceptionv3_model.fit(\n    train_flow,\n    validation_data=val_flow,\n    epochs=EPOCHS,\n    callbacks=training_callbacks)\n\n# === Plot Performance ===\nplot_training_metrics(inceptionv3_history, \"InceptionV3 Transfer Learning\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:27:23.784665Z","iopub.execute_input":"2025-04-23T01:27:23.785167Z","iopub.status.idle":"2025-04-23T01:43:40.880937Z","shell.execute_reply.started":"2025-04-23T01:27:23.785143Z","shell.execute_reply":"2025-04-23T01:43:40.880278Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# FROM HERE\n# === Path to Test Images ===\ntest_image_dir = '/kaggle/working/pet-classifier/testing/test'\n\n# === Load Test Filenames ===\ntest_files = sorted([file for file in os.listdir(test_image_dir) if file.endswith('.jpg')])\ntest_dataframe = pd.DataFrame({'filename': test_files})\n\n# === Test Data Generator ===\ntest_datagen = ImageDataGenerator(rescale=1./255)\ntest_data_generator = test_datagen.flow_from_dataframe(\n    dataframe=test_dataframe,\n    directory=test_image_dir,\n    x_col='filename',\n    y_col=None,\n    target_size=INPUT_SHAPE,\n    class_mode=None,\n    batch_size=BATCH_SIZE,\n    shuffle=False)\n\n# === Make Predictions ===\ntest_predictions = inceptionv3_model.predict(test_data_generator, verbose=1).flatten()\npredicted_labels = (test_predictions > 0.5).astype(int)\n\n# === Extract Image IDs ===\nimage_ids = [int(name.split('.')[0]) for name in test_files]\n\n# === Create Submission File ===\nsubmission = pd.DataFrame({\n    'id': image_ids,\n    'label': test_predictions\n})\n\nsubmission = submission.sort_values('id')\nsubmission.to_csv('submission.csv', index=False)\n\nprint(\"submission.csv with probabilities created successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T01:43:49.406817Z","iopub.execute_input":"2025-04-23T01:43:49.407354Z","iopub.status.idle":"2025-04-23T01:44:50.687143Z","shell.execute_reply.started":"2025-04-23T01:43:49.407331Z","shell.execute_reply":"2025-04-23T01:44:50.686286Z"}},"outputs":[],"execution_count":null}]}