{"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":"none","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31153,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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-10-20T15:01:01.582956Z","iopub.execute_input":"2025-10-20T15:01:01.583400Z","iopub.status.idle":"2025-10-20T15:01:01.940794Z","shell.execute_reply.started":"2025-10-20T15:01:01.583375Z","shell.execute_reply":"2025-10-20T15:01:01.939833Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# unzip the train and test folders","metadata":{}},{"cell_type":"code","source":"!unzip -qq /kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip\n!unzip -qq /kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:01.942689Z","iopub.execute_input":"2025-10-20T15:01:01.943318Z","iopub.status.idle":"2025-10-20T15:01:18.043472Z","shell.execute_reply.started":"2025-10-20T15:01:01.943280Z","shell.execute_reply":"2025-10-20T15:01:18.041822Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom tensorflow import keras \nfrom tensorflow.keras import layers\nfrom tensorflow.keras.utils import image_dataset_from_directory\nimport os, shutil, pathlib\n\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:18.045365Z","iopub.execute_input":"2025-10-20T15:01:18.045805Z","iopub.status.idle":"2025-10-20T15:01:36.891091Z","shell.execute_reply.started":"2025-10-20T15:01:18.045756Z","shell.execute_reply":"2025-10-20T15:01:36.890043Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Organizing the Dataset into Train, Validation, and Test Sets","metadata":{}},{"cell_type":"code","source":"# Define the base directory\nbase_dir = pathlib.Path(\"/kaggle/working/\")\n\n# Define the source directory\noriginal_dir = base_dir / \"train\"\n\n# Define the destination directories\ntrain_dir = base_dir / \"train_organized\" # Changed directory name for subset\nvalidation_dir = base_dir / \"validation_organized\"\ntest_dir = base_dir / \"test_organized\"\n\n# Create the main destination directories\nfor directory in [train_dir, validation_dir, test_dir]:\n    os.makedirs(directory, exist_ok=True)\n\n# Create subdirectories for cats and dogs within each destination directory\nfor directory in [train_dir, validation_dir, test_dir]:\n    os.makedirs(directory / \"cats\", exist_ok=True)\n    os.makedirs(directory / \"dogs\", exist_ok=True)\n# Function to get category from filename\ndef get_category(filename):\n    if \"cat\" in filename:\n        return \"cats\"\n    elif \"dog\" in filename:\n        return \"dogs\"\n    else:\n        return None\n\n# Get list of all image files\nall_files = list(original_dir.glob(\"*.jpg\")) # Assuming all images are jpg\n\n# Separate cat and dog files\ncat_files = [f for f in all_files if \"cat\" in f.name]\ndog_files = [f for f in all_files if \"dog\" in f.name]\n\n# Shuffle files to create random train/validation/test splits\nnp.random.shuffle(cat_files)\nnp.random.shuffle(dog_files)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:36.891891Z","iopub.execute_input":"2025-10-20T15:01:36.892463Z","iopub.status.idle":"2025-10-20T15:01:36.974712Z","shell.execute_reply.started":"2025-10-20T15:01:36.892431Z","shell.execute_reply":"2025-10-20T15:01:36.973513Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# check if the classes in the data is balanced","metadata":{}},{"cell_type":"code","source":"# Count the number of cat and dog files\nnum_cats = len(cat_files)\nnum_dogs = len(dog_files)\n\n# Create a bar plot to visualize class balance\nlabels = ['Cats', 'Dogs']\ncounts = [num_cats, num_dogs]\n\nplt.bar(labels, counts, color=['blue', 'orange'])\nplt.title('Class Balance: Cats vs Dogs')\nplt.ylabel('Number of Images')\nplt.xlabel('Classes')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:36.976816Z","iopub.execute_input":"2025-10-20T15:01:36.977124Z","iopub.status.idle":"2025-10-20T15:01:37.288401Z","shell.execute_reply.started":"2025-10-20T15:01:36.977105Z","shell.execute_reply":"2025-10-20T15:01:37.287370Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Splitting the train Dataset Files (training, validation, and test sets)","metadata":{}},{"cell_type":"code","source":"# Define split sizes for each label in training\ntrain_split = 5500\nvalidation_split = 2000\ntest_split = 5000     \n\ntrain_cat_files = cat_files[:train_split]\ntrain_dog_files = dog_files[:train_split]\n\nvalidation_cat_files = cat_files[train_split : train_split + validation_split]\nvalidation_dog_files = dog_files[train_split : train_split + validation_split]\n\ntest_cat_files = cat_files[train_split + validation_split : train_split + validation_split + test_split]\ntest_dog_files = dog_files[train_split + validation_split : train_split + validation_split + test_split]\n\n\n# Function to copy files to their respective directories\ndef copy_files(file_list, destination_dir):\n    for f in file_list:\n        category = get_category(f.name)\n        if category:\n            shutil.copy(f, destination_dir / category / f.name)\n\n# Copy files to train, validation, and test directories\nprint(\"Copying training files (subset)...\")\ncopy_files(train_cat_files + train_dog_files, train_dir)\nprint(\"Copying validation files...\")\ncopy_files(validation_cat_files + validation_dog_files, validation_dir)\nprint(\"Copying test files...\")\ncopy_files(test_cat_files + test_dog_files, test_dir)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:37.289410Z","iopub.execute_input":"2025-10-20T15:01:37.289656Z","iopub.status.idle":"2025-10-20T15:01:40.473781Z","shell.execute_reply.started":"2025-10-20T15:01:37.289639Z","shell.execute_reply":"2025-10-20T15:01:40.472826Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# load and preprocess the organized image data into dataset objects for training, validation, and testing.","metadata":{}},{"cell_type":"code","source":"train_dataset = image_dataset_from_directory(\n    train_dir, # Use the new training directory\n    image_size=(224, 224),\n    batch_size=64)\nvalidation_dataset = image_dataset_from_directory(\n    validation_dir ,\n    image_size=(224, 224),\n    batch_size=64)\ntest_dataset = image_dataset_from_directory(\n    test_dir ,\n    image_size=(224, 224),\n    batch_size=64)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:40.474574Z","iopub.execute_input":"2025-10-20T15:01:40.474859Z","iopub.status.idle":"2025-10-20T15:01:41.422507Z","shell.execute_reply.started":"2025-10-20T15:01:40.474838Z","shell.execute_reply":"2025-10-20T15:01:41.421518Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Visualizing a random Training Images with its corresponding class label","metadata":{}},{"cell_type":"code","source":"# Take one batch from the training dataset\nfor images, labels in train_dataset.take(1):\n    plt.figure(figsize=(12, 12))\n    for i in range(20):\n        ax = plt.subplot(5, 4, i + 1)\n        plt.imshow(images[i].numpy().astype(\"uint8\"))\n        plt.title(train_dataset.class_names[labels[i]])\n        plt.axis(\"off\")\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:41.423438Z","iopub.execute_input":"2025-10-20T15:01:41.423762Z","iopub.status.idle":"2025-10-20T15:01:43.290649Z","shell.execute_reply.started":"2025-10-20T15:01:41.423736Z","shell.execute_reply":"2025-10-20T15:01:43.289199Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Building the ResNet50-Based Model Architecture","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.applications import ResNet50\nfrom tensorflow.keras import layers, models\n\n\n\n# Load base model (exclude top layers)\nbase_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))\n\n# Freeze base layers initially\nbase_model.trainable = False\n\n# Build model with embedded normalization\nmodel = models.Sequential([\n    base_model,\n    layers.GlobalAveragePooling2D(),\n    layers.Dropout(0.5),  # Regularization\n    layers.Dense(512, activation='relu'),\n    layers.Dense(1, activation='sigmoid')  # Binary classification\n])\n\nmodel.summary()  # Check architecture\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:43.291801Z","iopub.execute_input":"2025-10-20T15:01:43.292079Z","iopub.status.idle":"2025-10-20T15:01:48.182990Z","shell.execute_reply.started":"2025-10-20T15:01:43.292051Z","shell.execute_reply":"2025-10-20T15:01:48.181961Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Compiling the Model and Configuring Training Callbacks","metadata":{}},{"cell_type":"code","source":"model.compile(\n    optimizer='sgd', loss='binary_crossentropy', metrics=['accuracy'] \n)\n\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True),\n    tf.keras.callbacks.ModelCheckpoint('ResNet50-Based Model.h5', monitor='val_accuracy', save_best_only=True)\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:48.184021Z","iopub.execute_input":"2025-10-20T15:01:48.184426Z","iopub.status.idle":"2025-10-20T15:01:48.202670Z","shell.execute_reply.started":"2025-10-20T15:01:48.184395Z","shell.execute_reply":"2025-10-20T15:01:48.201543Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# fit the model\n\n**⚠️ Warning :  the model take too much time to fit**\n\n\n","metadata":{}},{"cell_type":"code","source":"history = model.fit(\n    train_dataset,\n    validation_data=validation_dataset,\n    epochs=10,  \n    callbacks=callbacks\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T15:01:48.203689Z","iopub.execute_input":"2025-10-20T15:01:48.204066Z","iopub.status.idle":"2025-10-20T18:54:00.607775Z","shell.execute_reply.started":"2025-10-20T15:01:48.204037Z","shell.execute_reply":"2025-10-20T18:54:00.604292Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Visualizing the model performance","metadata":{}},{"cell_type":"code","source":" import matplotlib.pyplot as plt\n acc = history.history[\"accuracy\"]\n val_acc = history.history[\"val_accuracy\"]\n loss = history.history[\"loss\"]\n val_loss = history.history[\"val_loss\"]\n epochs = range(1, len(acc) + 1)\n plt.plot(epochs, acc, \"bo\", label=\"Training accuracy\")\n plt.plot(epochs, val_acc, \"b\", label=\"Validation accuracy\")\n plt.title(\"Training and validation accuracy\")\n plt.legend()\n plt.figure()\n plt.plot(epochs, loss, \"bo\", label=\"Training loss\")\n plt.plot(epochs, val_loss, \"b\", label=\"Validation loss\")\n plt.title(\"Training and validation loss\")\n plt.legend()\n plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T18:54:00.612976Z","iopub.execute_input":"2025-10-20T18:54:00.613595Z","iopub.status.idle":"2025-10-20T18:54:01.053425Z","shell.execute_reply.started":"2025-10-20T18:54:00.613564Z","shell.execute_reply":"2025-10-20T18:54:01.051910Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# load the model","metadata":{}},{"cell_type":"code","source":" test_model = keras.models.load_model(\n \"/kaggle/working/ResNet50-Based Model.h5\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T18:57:29.639226Z","iopub.execute_input":"2025-10-20T18:57:29.640032Z","iopub.status.idle":"2025-10-20T18:57:31.143441Z","shell.execute_reply.started":"2025-10-20T18:57:29.640000Z","shell.execute_reply":"2025-10-20T18:57:31.142577Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Evaluating the Trained Model performance on the Test Dataset","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\n\n# Get predictions\ny_true = np.concatenate([y for x, y in test_dataset], axis=0)\ny_pred_probs = test_model.predict(test_dataset)\ny_pred = (y_pred_probs > 0.5).astype(int).flatten()\n\nprint(classification_report(y_true, y_pred))\nprint(confusion_matrix(y_true, y_pred))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T18:57:35.697825Z","iopub.execute_input":"2025-10-20T18:57:35.698263Z","iopub.status.idle":"2025-10-20T19:15:08.160925Z","shell.execute_reply.started":"2025-10-20T18:57:35.698233Z","shell.execute_reply":"2025-10-20T19:15:08.157449Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_loss, test_acc = test_model.evaluate(test_dataset)\nprint(f\"Test accuracy: {test_acc:.3f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T19:15:08.166093Z","iopub.execute_input":"2025-10-20T19:15:08.166549Z","iopub.status.idle":"2025-10-20T19:32:19.033315Z","shell.execute_reply.started":"2025-10-20T19:15:08.166525Z","shell.execute_reply":"2025-10-20T19:32:19.031732Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Visualizing Model Predictions on Random Test Images\n","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport tensorflow as tf\nimport random\n\n# Get the filenames from the test directory\ntest_images_dir = pathlib.Path(\"/kaggle/working/test\")\ntest_image_files = list(test_images_dir.glob(\"*.jpg\")) # Get all files\n\n\nimages_to_show = [random.randint(0, 5000) for _ in range(20)]\nimages_to_display = []\nfilenames_to_display = []\nplt.figure(figsize=(12, 12))\nfor idx, i in enumerate(images_to_show):\n    img_path = test_image_files[i]\n    img = tf.keras.utils.load_img(img_path, target_size=(224, 224))\n    img_array = tf.keras.utils.img_to_array(img)\n    img_array = tf.expand_dims(img_array, 0)  # Create a batch\n\n    images_to_display.append(img)\n    filenames_to_display.append(img_path.name)\n\n    # Make prediction for this single image\n    prediction = test_model.predict(img_array)\n    predicted_label = \"Dog\" if prediction[0][0] > 0.5 else \"Cat\"\n    confidence = prediction[0][0] if predicted_label == \"Dog\" else 1 - prediction[0][0]\n    plt.subplot(4, 5, idx + 1)\n    plt.imshow(images_to_display[idx])\n    plt.title(f\"{predicted_label}: {confidence:.2f}\")\n    plt.axis(\"off\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T19:32:19.035476Z","iopub.execute_input":"2025-10-20T19:32:19.035807Z","iopub.status.idle":"2025-10-20T19:32:30.009467Z","shell.execute_reply.started":"2025-10-20T19:32:19.035784Z","shell.execute_reply":"2025-10-20T19:32:30.007449Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Preprocessing Images for Competition Submission Predictions (test images)","metadata":{}},{"cell_type":"code","source":"test_images_dir = pathlib.Path(\"/kaggle/working/test\")\n\ntest_data = image_dataset_from_directory(\n    test_images_dir,\n    image_size=(224, 224),\n    batch_size=64,\n    shuffle=False,\n    labels=None\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T19:32:30.012480Z","iopub.execute_input":"2025-10-20T19:32:30.012809Z","iopub.status.idle":"2025-10-20T19:32:30.483854Z","shell.execute_reply.started":"2025-10-20T19:32:30.012787Z","shell.execute_reply":"2025-10-20T19:32:30.482104Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Preparing the Submission File","metadata":{}},{"cell_type":"code","source":"import os\n\n# Get the file paths from the dataset\nfile_paths = test_data.file_paths\n\n# Extract just the filenames\nfilenames = [os.path.basename(path) for path in file_paths]\n\n# Now filenames contains the name of each image file\nprint(f\"Found {len(filenames)} images\")\nprint(\"First 5 filenames:\", filenames[:5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T19:32:30.484667Z","iopub.execute_input":"2025-10-20T19:32:30.484955Z","iopub.status.idle":"2025-10-20T19:32:30.498814Z","shell.execute_reply.started":"2025-10-20T19:32:30.484933Z","shell.execute_reply":"2025-10-20T19:32:30.496853Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"id = [int(filename.split('.')[0]) for filename in filenames]\nprint(f\"Found {len(id)} images\")\nprint(\"First 5 filenames:\", id[:5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T19:32:30.500962Z","iopub.execute_input":"2025-10-20T19:32:30.501465Z","iopub.status.idle":"2025-10-20T19:32:30.543526Z","shell.execute_reply.started":"2025-10-20T19:32:30.501426Z","shell.execute_reply":"2025-10-20T19:32:30.541179Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred = test_model.predict(test_data, steps = len(test_data), verbose = 1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T19:32:30.545533Z","iopub.execute_input":"2025-10-20T19:32:30.546140Z","iopub.status.idle":"2025-10-20T19:53:58.638522Z","shell.execute_reply.started":"2025-10-20T19:32:30.546085Z","shell.execute_reply":"2025-10-20T19:53:58.634511Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"id_fd=pd.Series(id,name = \"id\")\nid_lb=pd.DataFrame(pred, columns=['label'])\nsubmission = pd.concat([id_fd,id_lb],axis = 1)\nsubmission.to_csv(\"submission.csv\",index=False)\nsrt_sub=submission.sort_values(by=['id'])\nsrt_sub.head(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-20T19:53:58.643782Z","iopub.execute_input":"2025-10-20T19:53:58.644372Z","iopub.status.idle":"2025-10-20T19:53:58.808804Z","shell.execute_reply.started":"2025-10-20T19:53:58.644345Z","shell.execute_reply":"2025-10-20T19:53:58.807661Z"}},"outputs":[],"execution_count":null}]}