{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Introduction:\n*In this project, the goal is to classify dog and cat images using the Dogs vs. Cats dataset provided on Kaggle. A Convolutional Neural Network (CNN) model was trained to distinguish between the two classes using labeled image data.*\n\n*The dataset was preprocessed by resizing and normalizing the images, and a supervised learning approach was applied. The model was trained using a multi-layer CNN and evaluated on a validation set before generating predictions on the test set.*\n\n","metadata":{}},{"cell_type":"code","source":"# Required libraries\nimport os\nimport random\nimport numpy as np\nimport cv2\nimport zipfile\nimport matplotlib.pyplot as plt\nimport pandas as pd\n\n\nfrom imutils import paths\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:19:29.231325Z","iopub.execute_input":"2025-07-17T22:19:29.231792Z","iopub.status.idle":"2025-07-17T22:19:32.985635Z","shell.execute_reply.started":"2025-07-17T22:19:29.231765Z","shell.execute_reply":"2025-07-17T22:19:32.984967Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define paths\nzip_train_path = \"/kaggle/input/dogs-vs-cats/train.zip\"\nzip_test_path = \"/kaggle/input/dogs-vs-cats/test1.zip\"\nextract_train_path = \"/kaggle/working/train\"\nextract_test_path = \"/kaggle/working/test\"\n\n# Extract training data\nwith zipfile.ZipFile(zip_train_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_train_path)\n\n# Extract test data\nwith zipfile.ZipFile(zip_test_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_test_path)\n\nprint(\"Train and test zip files extracted successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:31.726206Z","iopub.execute_input":"2025-07-17T22:21:31.726527Z","iopub.status.idle":"2025-07-17T22:21:40.867303Z","shell.execute_reply.started":"2025-07-17T22:21:31.726503Z","shell.execute_reply":"2025-07-17T22:21:40.866664Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Data loading function\nclass_labels = {'cat': 0, 'dog': 1}  # Map class names to numeric labels\n\ndef load_dataset(path, target_size=(100, 100), max_samples=None):\n    \"\"\"\n    Load images from the given directory, preprocess them, and return image arrays with labels.\n\n    Parameters:\n        path (str): Directory containing the images\n        target_size (tuple): Desired image size (width, height) after resizing\n        max_samples (int or None): Maximum number of samples to load\n\n    Returns:\n        x (np.array): Array of preprocessed images normalized to [0, 1]\n        labels (np.array): Corresponding numeric labels\n    \"\"\"\n    x = []           # List to store images\n    labels = []      # List to store labels\n\n    # Get all image file paths and shuffle them randomly\n    image_paths = list(paths.list_images(path))\n    random.shuffle(image_paths)\n    \n    # Limit number of samples to 2000 for faster processing\n    image_paths = image_paths[:2000]\n    if max_samples:\n        image_paths = image_paths[:max_samples]\n\n    for image_path in image_paths:\n        img = cv2.imread(image_path)\n        if img is None:\n            print(f\"Warning: {image_path} could not be read, skipping.\")\n            continue\n\n        img = cv2.resize(img, target_size)  \n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n\n        x.append(img)\n\n        # Determine label from filename prefix\n        file_name = os.path.basename(image_path)\n        if file_name.startswith('cat'):\n            label_name = 'cat'\n        elif file_name.startswith('dog'):\n            label_name = 'dog'\n        else:\n            print(f\"Warning: Unknown file format {file_name}, skipping.\")\n            continue\n\n        labels.append(class_labels[label_name])\n\n    # Convert lists to numpy arrays and normalize pixel values to range [0, 1]\n    x = np.array(x, dtype=\"float32\") / 255.0\n    labels = np.array(labels)\n\n    print(f\"Loaded data shape: {x.shape}, Number of labels: {len(labels)}\")\n    return x, labels","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:40.868444Z","iopub.execute_input":"2025-07-17T22:21:40.868692Z","iopub.status.idle":"2025-07-17T22:21:40.875638Z","shell.execute_reply.started":"2025-07-17T22:21:40.868674Z","shell.execute_reply":"2025-07-17T22:21:40.874975Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def visualize_img(image_batch, label_batch, class_labels=class_labels):\n    \"\"\"\n    Displays a sample of images with their corresponding labels.\n    \n    Parameters:\n        image_batch (array-like): Batch of images (e.g., x_train)\n        label_batch (array-like): Corresponding labels (e.g., y_train)\n        class_labels (dict): Dictionary mapping class names to numeric labels\n    \"\"\"\n\n    plt.figure(figsize=(12, 6))  # Set the figure size\n    class_names = list(class_labels.keys())  # Get class names (e.g., ['cat', 'dog'])\n\n    # Select 10 random indices (or less if fewer images are available)\n    sample_size = min(10, len(image_batch))\n    idxs = np.random.choice(len(image_batch), size=sample_size, replace=False)\n\n    for i, idx in enumerate(idxs):\n        ax = plt.subplot(2, 5, i + 1)  # Arrange in 2 rows and 5 columns\n        plt.imshow(image_batch[idx])  # Show the image\n        plt.title(class_names[label_batch[idx]].title())  # Display the label\n        plt.axis('off')  # Hide axis ticks\n\n    plt.tight_layout()  # Adjust layout to prevent overlap\n    plt.show()  # Display the plot\n\n# Load the dataset\nx_train, y_train = load_dataset(extract_train_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:40.876413Z","iopub.execute_input":"2025-07-17T22:21:40.876696Z","iopub.status.idle":"2025-07-17T22:21:42.756467Z","shell.execute_reply.started":"2025-07-17T22:21:40.876671Z","shell.execute_reply":"2025-07-17T22:21:42.755761Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"visualize_img(x_train, y_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:42.758315Z","iopub.execute_input":"2025-07-17T22:21:42.758890Z","iopub.status.idle":"2025-07-17T22:21:43.773803Z","shell.execute_reply.started":"2025-07-17T22:21:42.758869Z","shell.execute_reply":"2025-07-17T22:21:43.772276Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X, y = load_dataset(extract_train_path, max_samples=2000)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:43.774685Z","iopub.execute_input":"2025-07-17T22:21:43.774943Z","iopub.status.idle":"2025-07-17T22:21:45.604204Z","shell.execute_reply.started":"2025-07-17T22:21:43.774923Z","shell.execute_reply":"2025-07-17T22:21:45.603551Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#  Load test dataset (without labels)\ntest_path = os.path.join(extract_test_path, \"test1\")\ntest_image_paths = sorted(list(paths.list_images(test_path)), key=lambda x: int(os.path.splitext(os.path.basename(x))[0]))\nX_test = []\n\n# Load and preprocess each test image\nfor img_path in test_image_paths:\n    img = cv2.imread(img_path)\n    img = cv2.resize(img, (100,100))\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    X_test.append(img)\n\nX_test = np.array(X_test, dtype=\"float32\") / 255.0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:45.604901Z","iopub.execute_input":"2025-07-17T22:21:45.605092Z","iopub.status.idle":"2025-07-17T22:21:56.734289Z","shell.execute_reply.started":"2025-07-17T22:21:45.605077Z","shell.execute_reply":"2025-07-17T22:21:56.733784Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Split the data into training and validation sets\nX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:56.735003Z","iopub.execute_input":"2025-07-17T22:21:56.735223Z","iopub.status.idle":"2025-07-17T22:21:56.787283Z","shell.execute_reply.started":"2025-07-17T22:21:56.735195Z","shell.execute_reply":"2025-07-17T22:21:56.786436Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Build the model\nIMG_SIZE = 100\n\n#Define a simple Convolutional Neural Network using the Sequential API\nmodel = Sequential([\n    Conv2D(8, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)),  # First convolutional layer\n    MaxPooling2D(2, 2),  # First max pooling layer\n\n    Conv2D(16, (3, 3), activation='relu'),  # Second convolutional layer\n    MaxPooling2D(2, 2),  # Second max pooling layer\n\n    Flatten(),  # Flatten the 3D feature maps to 1D\n    Dense(64, activation='relu'),  # Fully connected layer with 64 units\n    Dropout(0.5),  # Dropout layer to prevent overfitting\n\n    Dense(1, activation='sigmoid')  # Output layer with sigmoid activation for binary classification\n])\n\n# Compile the model with appropriate loss function and optimizer\nmodel.compile(optimizer=Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy'])\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:56.788253Z","iopub.execute_input":"2025-07-17T22:21:56.788537Z","iopub.status.idle":"2025-07-17T22:21:57.899943Z","shell.execute_reply.started":"2025-07-17T22:21:56.788512Z","shell.execute_reply":"2025-07-17T22:21:57.899248Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Train the model\nhistory = model.fit(\n    X_train, y_train,\n    validation_data=(X_val, y_val),\n    epochs=10,\n    batch_size=8,\n    verbose=2\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:21:57.900724Z","iopub.execute_input":"2025-07-17T22:21:57.900954Z","iopub.status.idle":"2025-07-17T22:22:09.840579Z","shell.execute_reply.started":"2025-07-17T22:21:57.900927Z","shell.execute_reply":"2025-07-17T22:22:09.839633Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Training Summary:**\n* The model starts with an accuracy near random chance (~50%) and improves steadily over the epochs. Training accuracy reaches around 93% by the 10th epoch, while validation accuracy plateaus around 67%.\n\n* The validation loss shows some fluctuations and increases toward the end, indicating possible overfitting. This suggests the model fits the training data well but generalizes moderately on unseen data.\n\n* To improve performance, techniques like EarlyStopping, data augmentation, or transfer learning could be applied.\n\n","metadata":{}},{"cell_type":"code","source":"# Plot training & validation accuracy values\nplt.figure(figsize=(12, 5))\n\nplt.subplot(1, 2, 1)\nplt.plot(history.history['accuracy'], label='Train Accuracy')\nplt.plot(history.history['val_accuracy'], label='Validation Accuracy')\nplt.title('Model Accuracy Over Epochs')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.grid(True)\n\n# Plot training & validation loss values\nplt.subplot(1, 2, 2)\nplt.plot(history.history['loss'], label='Train Loss')\nplt.plot(history.history['val_loss'], label='Validation Loss')\nplt.title('Model Loss Over Epochs')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend()\nplt.grid(True)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:22:25.959689Z","iopub.execute_input":"2025-07-17T22:22:25.959985Z","iopub.status.idle":"2025-07-17T22:22:26.378383Z","shell.execute_reply.started":"2025-07-17T22:22:25.959963Z","shell.execute_reply":"2025-07-17T22:22:26.377652Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Training results\nacc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs_range = range(len(acc))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:22:41.984427Z","iopub.execute_input":"2025-07-17T22:22:41.984746Z","iopub.status.idle":"2025-07-17T22:22:41.989098Z","shell.execute_reply.started":"2025-07-17T22:22:41.984724Z","shell.execute_reply":"2025-07-17T22:22:41.988362Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def predict_image(image_path, model, target_size=(100, 100)):\n    \"\"\"\n    Load an image, preprocess it, and predict whether it's a cat or dog using the trained model.\n    \n    Parameters:\n        image_path (str): Path to the image file.\n        model (keras.Model): Trained CNN model for prediction.\n        target_size (tuple): Desired image size for the model input.\n    \"\"\"\n\n    # Load the image and resize it to the target size\n    img = load_img(image_path, target_size=target_size)\n    img_array = img_to_array(img) / 255.0  # Normalize pixel values to [0,1]\n    img_array = np.expand_dims(img_array, axis=0)  # Add batch dimension: (1, IMG_SIZE, IMG_SIZE, 3)\n\n    # Make prediction using the model\n    prediction = model.predict(img_array)[0][0]\n\n    # Classification threshold set at 0.75\n    label = \"Dog\" if prediction > 0.75 else \"Cat\"\n    confidence = prediction if prediction > 0.75 else 1 - prediction\n\n    # Print the prediction and confidence percentage\n    print(f\"Prediction: {label} ({confidence * 100:.2f}%)\")\n\n    # Display the image with the predicted label as the title\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:22:42.209408Z","iopub.execute_input":"2025-07-17T22:22:42.209645Z","iopub.status.idle":"2025-07-17T22:22:42.214992Z","shell.execute_reply.started":"2025-07-17T22:22:42.209627Z","shell.execute_reply":"2025-07-17T22:22:42.214420Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predict_image('/kaggle/working/train/train/dog.310.jpg', model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:22:42.362020Z","iopub.execute_input":"2025-07-17T22:22:42.362223Z","iopub.status.idle":"2025-07-17T22:22:42.885333Z","shell.execute_reply.started":"2025-07-17T22:22:42.362210Z","shell.execute_reply":"2025-07-17T22:22:42.884561Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Predict probabilities on test set\npredictions = model.predict(X_test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:22:42.887351Z","iopub.execute_input":"2025-07-17T22:22:42.887547Z","iopub.status.idle":"2025-07-17T22:22:48.734758Z","shell.execute_reply.started":"2025-07-17T22:22:42.887533Z","shell.execute_reply":"2025-07-17T22:22:48.734032Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Convert probabilities to binary labels (0 = cat, 1 = dog)\nlabels = (predictions > 0.5).astype(int).flatten()\n\n# Extract image IDs from filenames\nimage_ids = [int(os.path.splitext(os.path.basename(path))[0]) for path in test_image_paths]\n\n# Prepare submission DataFrame\nsubmission = pd.DataFrame({\n    \"id\": image_ids,\n    \"label\": labels\n})\n\n# Sort by ID\nsubmission = submission.sort_values(by=\"id\")\n\n# Save to CSV\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\" submission.csv file created successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-17T22:22:48.736101Z","iopub.execute_input":"2025-07-17T22:22:48.736380Z","iopub.status.idle":"2025-07-17T22:22:48.774047Z","shell.execute_reply.started":"2025-07-17T22:22:48.736355Z","shell.execute_reply":"2025-07-17T22:22:48.773448Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Conclusion\nDespite training on a limited dataset, the model was able to make accurate predictions on the test images. The accuracy and loss curves indicate a balanced learning process without severe overfitting.\n\nWhile the model's performance is satisfactory, improvements could be made using deeper networks, transfer learning techniques, or data augmentation to increase generalization.\n\nThis project demonstrates the implementation of a basic CNN model for solving image classification problems effectively.\n","metadata":{}}]}