{"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"},{"sourceId":11506652,"sourceType":"datasetVersion","datasetId":7214680},{"sourceId":11507788,"sourceType":"datasetVersion","datasetId":7215481}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\n\nos.listdir(\"/kaggle/input\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T02:50:44.933086Z","iopub.execute_input":"2025-04-22T02:50:44.933360Z","iopub.status.idle":"2025-04-22T02:50:44.938966Z","shell.execute_reply.started":"2025-04-22T02:50:44.933342Z","shell.execute_reply":"2025-04-22T02:50:44.938064Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for folder in ['kaggle-json', 'dogs-vs-cats', 'dogs-vs-cats-redux-kernels-edition']:\n    print(f\"\\nContents of: /kaggle/input/{folder}\")\n    print(os.listdir(f\"/kaggle/input/{folder}\")[:5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T02:50:44.939980Z","iopub.execute_input":"2025-04-22T02:50:44.940182Z","iopub.status.idle":"2025-04-22T02:50:44.960343Z","shell.execute_reply.started":"2025-04-22T02:50:44.940168Z","shell.execute_reply":"2025-04-22T02:50:44.959730Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import ResNet50, EfficientNetB0, MobileNetV2\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.optimizers import Adam, SGD\nimport matplotlib.pyplot as plt\nimport time","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T03:55:14.756770Z","iopub.execute_input":"2025-04-22T03:55:14.757351Z","iopub.status.idle":"2025-04-22T03:55:14.761514Z","shell.execute_reply.started":"2025-04-22T03:55:14.757329Z","shell.execute_reply":"2025-04-22T03:55:14.760558Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Paths\nDATA_DIR = \"/kaggle/working/split_dataset\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T02:50:44.971419Z","iopub.execute_input":"2025-04-22T02:50:44.971595Z","iopub.status.idle":"2025-04-22T02:50:44.989339Z","shell.execute_reply.started":"2025-04-22T02:50:44.971582Z","shell.execute_reply":"2025-04-22T02:50:44.988713Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\ndata_dir = \"/kaggle/input/dogs-vs-cats/train/train\"\nprint(\"Sample files:\", os.listdir(data_dir)[:5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T02:50:44.990763Z","iopub.execute_input":"2025-04-22T02:50:44.990981Z","iopub.status.idle":"2025-04-22T02:50:45.012373Z","shell.execute_reply.started":"2025-04-22T02:50:44.990967Z","shell.execute_reply":"2025-04-22T02:50:45.011637Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, shutil\n\ndata_dir = \"/kaggle/input/dogs-vs-cats/train/train\"\nsplit_dir = \"/kaggle/working/split_dataset\"\ncat_dir = os.path.join(split_dir, \"cats\")\ndog_dir = os.path.join(split_dir, \"dogs\")\n\nos.makedirs(cat_dir, exist_ok=True)\nos.makedirs(dog_dir, exist_ok=True)\n\nfor fname in os.listdir(data_dir):\n    src = os.path.join(data_dir, fname)\n    if fname.startswith(\"cat\"):\n        shutil.copy(src, os.path.join(cat_dir, fname))\n    elif fname.startswith(\"dog\"):\n        shutil.copy(src, os.path.join(dog_dir, fname))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T02:50:45.013105Z","iopub.execute_input":"2025-04-22T02:50:45.013316Z","iopub.status.idle":"2025-04-22T02:51:36.658560Z","shell.execute_reply.started":"2025-04-22T02:50:45.013301Z","shell.execute_reply":"2025-04-22T02:51:36.657728Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Cats:\", len(os.listdir(cat_dir)))\nprint(\"Dogs:\", len(os.listdir(dog_dir)))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T02:51:36.659445Z","iopub.execute_input":"2025-04-22T02:51:36.659999Z","iopub.status.idle":"2025-04-22T02:51:36.676711Z","shell.execute_reply.started":"2025-04-22T02:51:36.659976Z","shell.execute_reply":"2025-04-22T02:51:36.676192Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.utils import image_dataset_from_directory\n\ntrain_ds = image_dataset_from_directory(\n    split_dir,\n    labels=\"inferred\",\n    label_mode=\"binary\",\n    batch_size=32,\n    image_size=(224, 224),\n    validation_split=0.2,\n    subset=\"training\",\n    seed=42\n)\n\nval_ds = image_dataset_from_directory(\n    split_dir,\n    labels=\"inferred\",\n    label_mode=\"binary\",\n    batch_size=32,\n    image_size=(224, 224),\n    validation_split=0.2,\n    subset=\"validation\",\n    seed=42\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T02:51:36.677427Z","iopub.execute_input":"2025-04-22T02:51:36.678129Z","iopub.status.idle":"2025-04-22T02:51:38.119597Z","shell.execute_reply.started":"2025-04-22T02:51:36.678112Z","shell.execute_reply":"2025-04-22T02:51:38.119101Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## MODEL EXPLORATION","metadata":{}},{"cell_type":"code","source":"AUTOTUNE = tf.data.AUTOTUNE\ntrain_ds = train_ds.prefetch(buffer_size=AUTOTUNE)\nval_ds = val_ds.prefetch(buffer_size=AUTOTUNE)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T02:54:21.254304Z","iopub.execute_input":"2025-04-22T02:54:21.254965Z","iopub.status.idle":"2025-04-22T02:54:21.261688Z","shell.execute_reply.started":"2025-04-22T02:54:21.254914Z","shell.execute_reply":"2025-04-22T02:54:21.261145Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"from tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import *\n\ndef build_model(model_name):\n    input_shape = (224, 224, 3)\n    \n    if model_name == \"SimpleCNN\":\n        model = models.Sequential([\n            layers.Rescaling(1./255, input_shape=input_shape),\n            layers.Conv2D(32, 3, activation='relu'),\n            layers.MaxPooling2D(),\n            layers.Conv2D(64, 3, activation='relu'),\n            layers.MaxPooling2D(),\n            layers.Conv2D(128, 3, activation='relu'),\n            layers.GlobalAveragePooling2D(),\n            layers.Dense(1, activation='sigmoid')\n        ])\n    \n    else:\n        base_model_map = {\n            \"EfficientNetB0\": EfficientNetB0,\n            \"MobileNetV2\": MobileNetV2,\n            \"ResNet50\": ResNet50,\n            \"InceptionV3\": InceptionV3,\n            \"VGG16\": VGG16\n        }\n\n        base_model = base_model_map[model_name](include_top=False, weights=\"imagenet\", input_shape=input_shape)\n        base_model.trainable = False\n\n        inputs = layers.Input(shape=input_shape)\n        x = base_model(inputs, training=False)\n        x = layers.GlobalAveragePooling2D()(x)\n        x = layers.Dropout(0.2)(x)\n        outputs = layers.Dense(1, activation='sigmoid')(x)\n\n        model = models.Model(inputs, outputs)\n\n    model.compile(optimizer=tf.keras.optimizers.Adam(1e-4),\n                  loss='binary_crossentropy',\n                  metrics=['accuracy'])\n    return model\n","metadata":{"execution":{"iopub.status.busy":"2025-04-22T02:57:10.033138Z","iopub.execute_input":"2025-04-22T02:57:10.033671Z","iopub.status.idle":"2025-04-22T02:57:10.047504Z","shell.execute_reply.started":"2025-04-22T02:57:10.033649Z","shell.execute_reply":"2025-04-22T02:57:10.046963Z"}}},{"cell_type":"markdown","source":"def train_model(model_name, train_ds, val_ds, epochs=5):\n    print(f\"\\n🚀 Training model: {model_name}\")\n    model = build_model(model_name)\n    \n    history = model.fit(\n        train_ds,\n        validation_data=val_ds,\n        epochs=epochs,\n        verbose=1\n    )\n    \n    return model, history\n","metadata":{"execution":{"iopub.status.busy":"2025-04-22T02:57:20.939497Z","iopub.execute_input":"2025-04-22T02:57:20.940251Z","iopub.status.idle":"2025-04-22T02:57:20.944670Z","shell.execute_reply.started":"2025-04-22T02:57:20.940228Z","shell.execute_reply":"2025-04-22T02:57:20.943929Z"}}},{"cell_type":"markdown","source":"model_names = [\"SimpleCNN\", \"EfficientNetB0\", \"MobileNetV2\", \"ResNet50\", \"InceptionV3\", \"VGG16\"]\ntrained_models = {}\ntraining_histories = {}\n\nfor name in model_names:\n    model, history = train_model(name, train_ds, val_ds)\n    trained_models[name] = model\n    training_histories[name] = history\n","metadata":{"execution":{"iopub.status.busy":"2025-04-22T02:57:53.676613Z","iopub.execute_input":"2025-04-22T02:57:53.676892Z","iopub.status.idle":"2025-04-22T03:29:34.529231Z","shell.execute_reply.started":"2025-04-22T02:57:53.676871Z","shell.execute_reply":"2025-04-22T03:29:34.528621Z"}}},{"cell_type":"markdown","source":"# ✅ Model-specific hyperparameters\nmodel_params = {\n    \"SimpleCNN\": {\"dense_units\": 128, \"dropout\": 0.3, \"lr\": 1e-4, \"optimizer\": \"adam\"},\n    \"EfficientNetB0\": {\"dense_units\": 128, \"dropout\": 0.2, \"lr\": 1e-4, \"optimizer\": \"adam\"},\n    \"MobileNetV2\": {\"dense_units\": 128, \"dropout\": 0.3, \"lr\": 1e-4, \"optimizer\": \"adam\"},\n    \"ResNet50\": {\"dense_units\": 128, \"dropout\": 0.2, \"lr\": 1e-4, \"optimizer\": \"sgd\"}\n}","metadata":{"execution":{"iopub.status.busy":"2025-04-22T04:01:38.677582Z","iopub.execute_input":"2025-04-22T04:01:38.678086Z","iopub.status.idle":"2025-04-22T04:01:38.682420Z","shell.execute_reply.started":"2025-04-22T04:01:38.678064Z","shell.execute_reply":"2025-04-22T04:01:38.681596Z"}}},{"cell_type":"markdown","source":"# ✅ Model builder\n\ndef build_model(model_name, use_pretrained=True):\n    input_shape = (224, 224, 3)\n    params = model_params[model_name]\n    dropout = params[\"dropout\"]\n    dense_units = params[\"dense_units\"]\n    lr = params[\"lr\"]\n    opt_type = params[\"optimizer\"]\n    \n    if model_name == \"SimpleCNN\":\n        model = models.Sequential([\n            layers.Rescaling(1./255, input_shape=input_shape),\n            layers.Conv2D(32, 3, activation='relu'),\n            layers.MaxPooling2D(),\n            layers.Conv2D(64, 3, activation='relu'),\n            layers.MaxPooling2D(),\n            layers.Conv2D(128, 3, activation='relu'),\n            layers.GlobalAveragePooling2D(),\n            layers.Dropout(dropout),\n            layers.Dense(dense_units, activation='relu'),\n            layers.Dense(1, activation='sigmoid')\n        ])\n    else:\n        base_model_map = {\n            \"EfficientNetB0\": EfficientNetB0,\n            \"MobileNetV2\": MobileNetV2,\n            \"ResNet50\": ResNet50,\n            \"InceptionV3\": InceptionV3,\n            \"VGG16\": VGG16\n        }\n        base_model = base_model_map[model_name](include_top=False, weights='imagenet' if use_pretrained else None, input_shape=input_shape, pooling='avg')\n        base_model.trainable = not use_pretrained  # freeze if pretrained\n\n        model = models.Sequential([\n            layers.Rescaling(1./255, input_shape=input_shape),\n            base_model,\n            layers.Dropout(dropout),\n            layers.Dense(dense_units, activation='relu'),\n            layers.Dense(1, activation='sigmoid')\n        ])\n\n    optimizer = Adam(learning_rate=lr) if opt_type == \"adam\" else SGD(learning_rate=lr)\n    model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy'])\n    return model","metadata":{"execution":{"iopub.status.busy":"2025-04-22T04:02:03.746578Z","iopub.execute_input":"2025-04-22T04:02:03.747348Z","iopub.status.idle":"2025-04-22T04:02:03.754557Z","shell.execute_reply.started":"2025-04-22T04:02:03.747323Z","shell.execute_reply":"2025-04-22T04:02:03.753705Z"}}},{"cell_type":"markdown","source":"# ✅ Training loop\nmodels_to_train = [\"SimpleCNN\", \"EfficientNetB0\", \"MobileNetV2\", \"ResNet50\"]\nhistories = {}\ntimes = {}\n\nfor model_name in models_to_train:\n    for pretrained in [False, True]:\n        if model_name == \"SimpleCNN\" and pretrained:\n            continue  # Skip pretrained simple model\n\n        key = f\"{model_name}_{'pretrained' if pretrained else 'scratch'}\"\n        print(f\"\\n🚀 Training: {key}\")\n        model = build_model(model_name, use_pretrained=pretrained)\n\n        start = time.time()\n        history = model.fit(train_ds, epochs=5, validation_data=val_ds, verbose=1)\n        duration = time.time() - start\n\n        histories[key] = history\n        times[key] = duration\n\n        print(f\"✅ {key} completed in {duration/60:.2f} minutes\")\n\n# ✅ Plot training curves\nfor key, history in histories.items():\n    plt.figure()\n    plt.plot(history.history['accuracy'], label='Train Acc')\n    plt.plot(history.history['val_accuracy'], label='Val Acc')\n    plt.title(f'{key} Accuracy')\n    plt.xlabel('Epochs')\n    plt.ylabel('Accuracy')\n    plt.legend()\n    plt.grid(True)\n    plt.show()\n\n# ✅ Print training time summary\nprint(\"\\n⏱️ Training Time Summary:\")\nfor key, t in times.items():\n    print(f\"{key}: {t/60:.2f} minutes\")","metadata":{"execution":{"iopub.status.busy":"2025-04-22T04:02:27.492364Z","iopub.execute_input":"2025-04-22T04:02:27.492631Z","iopub.status.idle":"2025-04-22T04:49:12.287430Z","shell.execute_reply.started":"2025-04-22T04:02:27.492609Z","shell.execute_reply":"2025-04-22T04:49:12.286670Z"}}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"BEST MODEL IS EFFIECIENTNET","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nimport numpy as np\nimport pandas as pd\nimport os\nimport matplotlib.pyplot as plt\nfrom tensorflow.keras.applications import MobileNetV2\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T05:20:23.809539Z","iopub.execute_input":"2025-04-22T05:20:23.810123Z","iopub.status.idle":"2025-04-22T05:20:23.815742Z","shell.execute_reply.started":"2025-04-22T05:20:23.810097Z","shell.execute_reply":"2025-04-22T05:20:23.814731Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === MODEL SETUP ===\ndef build_final_mobilenetv2():\n    base_model = MobileNetV2(include_top=False, weights=\"imagenet\", input_shape=(224, 224, 3))\n    base_model.trainable = True  # Enable fine-tuning\n\n    # Freeze bottom layers (optional)\n    for layer in base_model.layers[:-20]:\n        layer.trainable = False\n\n    inputs = layers.Input(shape=(224, 224, 3))\n    x = layers.Rescaling(1./255)(inputs)\n    x = base_model(x, training=True)\n    x = layers.GlobalAveragePooling2D()(x)\n    x = layers.Dropout(0.3)(x)\n    x = layers.Dense(128, activation='relu')(x)\n    x = layers.Dense(1, activation='sigmoid')(x)\n\n    model = models.Model(inputs, x)\n    model.compile(optimizer=Adam(1e-4), loss='binary_crossentropy', metrics=['accuracy'])\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T05:20:34.651044Z","iopub.execute_input":"2025-04-22T05:20:34.651302Z","iopub.status.idle":"2025-04-22T05:20:34.656895Z","shell.execute_reply.started":"2025-04-22T05:20:34.651284Z","shell.execute_reply":"2025-04-22T05:20:34.656013Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === TRAINING ===\nfinal_model = build_final_mobilenetv2()\n\nearly_stop = EarlyStopping(patience=3, restore_best_weights=True)\n\nhistory = final_model.fit(\n    train_ds,\n    validation_data=val_ds,\n    epochs=15,\n    callbacks=[early_stop],\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T05:20:42.580839Z","iopub.execute_input":"2025-04-22T05:20:42.581113Z","iopub.status.idle":"2025-04-22T05:23:06.956982Z","shell.execute_reply.started":"2025-04-22T05:20:42.581093Z","shell.execute_reply":"2025-04-22T05:23:06.956370Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nimport numpy as np\nimport pandas as pd\nimport os\n\n# === Define test directory path ===\ntest_dir = \"/kaggle/input/dogs-vs-cats/test/test\"\n\n# === Get sorted list of .jpg test filenames ===\ntest_filenames = sorted(\n    [f for f in os.listdir(test_dir) if f.endswith('.jpg')],\n    key=lambda x: int(x.split('.')[0])\n)\n\n# === Preprocessing function for test images ===\ndef preprocess_test_image(file_path):\n    img = tf.io.read_file(file_path)\n    img = tf.image.decode_jpeg(img, channels=3)\n    img = tf.image.resize(img, [224, 224])\n    img = tf.cast(img, tf.float32) / 255.0\n    return img\n\n# === Create dataset from file paths ===\nfile_paths = [os.path.join(test_dir, fname) for fname in test_filenames]\nfile_paths_tensor = tf.constant(file_paths, dtype=tf.string)\ntest_ds = tf.data.Dataset.from_tensor_slices(file_paths_tensor)\ntest_ds = test_ds.map(preprocess_test_image).batch(32)\n\n# === Predict using final model ===\npreds = final_model.predict(test_ds, verbose=1).squeeze()\n\n# === Extract IDs from filenames ===\nids = [int(fname.split('.')[0]) for fname in test_filenames]\n\n# === Create submission DataFrame and save ===\nsubmission = pd.DataFrame({\"id\": ids, \"label\": preds})\nsubmission.to_csv(\"submission.csv\", index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T05:29:47.879497Z","iopub.execute_input":"2025-04-22T05:29:47.880027Z","iopub.status.idle":"2025-04-22T05:30:23.500494Z","shell.execute_reply.started":"2025-04-22T05:29:47.880006Z","shell.execute_reply":"2025-04-22T05:30:23.499931Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T05:30:58.245103Z","iopub.execute_input":"2025-04-22T05:30:58.245369Z","iopub.status.idle":"2025-04-22T05:30:58.281794Z","shell.execute_reply.started":"2025-04-22T05:30:58.245349Z","shell.execute_reply":"2025-04-22T05:30:58.281108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}