{"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":"none","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":31040,"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-07-16T16:17:26.839452Z","iopub.execute_input":"2025-07-16T16:17:26.839762Z","iopub.status.idle":"2025-07-16T16:17:26.850033Z","shell.execute_reply.started":"2025-07-16T16:17:26.839738Z","shell.execute_reply":"2025-07-16T16:17:26.848918Z"}},"outputs":[{"name":"stdout","text":"/kaggle/input/dogs-vs-cats/test1.zip\n/kaggle/input/dogs-vs-cats/train.zip\n/kaggle/input/dogs-vs-cats/sampleSubmission.csv\n","output_type":"stream"}],"execution_count":49},{"cell_type":"markdown","source":"## Unzip & Organize Images","metadata":{}},{"cell_type":"code","source":"import zipfile\nimport os\n\n# Unzip images into a new directory\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/dogs-vs-cats/train')\n\n# Check extracted image count\nimage_dir = '/kaggle/working/dogs-vs-cats/train/train'\nprint(\"Total images:\", len(os.listdir(image_dir)))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T16:17:26.851631Z","iopub.execute_input":"2025-07-16T16:17:26.851982Z","iopub.status.idle":"2025-07-16T16:17:35.002448Z","shell.execute_reply.started":"2025-07-16T16:17:26.851956Z","shell.execute_reply":"2025-07-16T16:17:35.001576Z"}},"outputs":[{"name":"stdout","text":"Total images: 25000\n","output_type":"stream"}],"execution_count":50},{"cell_type":"markdown","source":"## Create a PyTorch Dataset from Images\n","metadata":{}},{"cell_type":"code","source":"from torchvision import datasets, transforms\nfrom torch.utils.data import DataLoader, random_split\nfrom PIL import Image\n\n# Custom Dataset class\nfrom torch.utils.data import Dataset\nclass CatsDogsDataset(Dataset):\n    def __init__(self, image_dir, transform=None):\n        self.image_dir = image_dir\n        self.transform = transform\n        self.image_filenames = os.listdir(image_dir)\n\n    def __len__(self):\n        return len(self.image_filenames)\n\n    def __getitem__(self, idx):\n        img_name = self.image_filenames[idx]\n        img_path = os.path.join(self.image_dir, img_name)\n        image = Image.open(img_path).convert(\"RGB\")\n        label = 1 if \"dog\" in img_name else 0  # 1 for dog, 0 for cat\n\n        if self.transform:\n            image = self.transform(image)\n\n        return image, label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T16:17:35.003316Z","iopub.execute_input":"2025-07-16T16:17:35.003564Z","iopub.status.idle":"2025-07-16T16:17:35.011067Z","shell.execute_reply.started":"2025-07-16T16:17:35.003539Z","shell.execute_reply":"2025-07-16T16:17:35.009984Z"}},"outputs":[],"execution_count":51},{"cell_type":"markdown","source":"## Define Transforms and Dataloaders","metadata":{}},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize((128, 128)),\n    transforms.ToTensor()\n])\n\ndataset = CatsDogsDataset(image_dir, transform=transform)\n\n# Train/val split\ntrain_size = int(0.8 * len(dataset))\nval_size = len(dataset) - train_size\ntrain_ds, val_ds = random_split(dataset, [train_size, val_size])\n\ntrain_loader = DataLoader(train_ds, batch_size=32, shuffle=True)\nval_loader = DataLoader(val_ds, batch_size=32, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T16:17:35.011958Z","iopub.execute_input":"2025-07-16T16:17:35.012198Z","iopub.status.idle":"2025-07-16T16:17:35.052926Z","shell.execute_reply.started":"2025-07-16T16:17:35.012181Z","shell.execute_reply":"2025-07-16T16:17:35.052023Z"}},"outputs":[],"execution_count":52},{"cell_type":"markdown","source":"## Build a CNN Classifier","metadata":{}},{"cell_type":"code","source":"import torch.nn as nn\n\nclass CatDogCNN(nn.Module):\n    def __init__(self):\n        super(CatDogCNN, self).__init__()\n        self.conv_layer = nn.Sequential(\n            nn.Conv2d(3, 16, 3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2),\n            \n            nn.Conv2d(16, 32, 3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2),\n        )\n        self.fc_layer = nn.Sequential(\n            nn.Linear(32 * 32 * 32, 512),\n            nn.ReLU(),\n            nn.Linear(512, 2)  # 2 classes: cat & dog\n        )\n\n    def forward(self, x):\n        x = self.conv_layer(x)\n        x = x.view(x.size(0), -1)\n        x = self.fc_layer(x)\n        return x\n\nmodel = CatDogCNN()\nmodel","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T16:17:35.054971Z","iopub.execute_input":"2025-07-16T16:17:35.055256Z","iopub.status.idle":"2025-07-16T16:17:35.386907Z","shell.execute_reply.started":"2025-07-16T16:17:35.055235Z","shell.execute_reply":"2025-07-16T16:17:35.386068Z"}},"outputs":[{"execution_count":53,"output_type":"execute_result","data":{"text/plain":"CatDogCNN(\n  (conv_layer): Sequential(\n    (0): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n    (1): ReLU()\n    (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n    (3): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n    (4): ReLU()\n    (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n  )\n  (fc_layer): Sequential(\n    (0): Linear(in_features=32768, out_features=512, bias=True)\n    (1): ReLU()\n    (2): Linear(in_features=512, out_features=2, bias=True)\n  )\n)"},"metadata":{}}],"execution_count":53},{"cell_type":"markdown","source":"## Train the Model","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.optim as optim\n\n\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.01)\n\n# Training loop\nepochs = 10\nfor epoch in range(epochs):\n    model.train()\n    running_loss = 0.0\n    for inputs, labels in train_loader:\n        inputs, labels = inputs.to(device), labels.to(device)\n\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item()\n\n    print(f\"Epoch [{epoch+1}], Loss: {running_loss:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T16:17:35.387687Z","iopub.execute_input":"2025-07-16T16:17:35.387902Z","iopub.status.idle":"2025-07-16T17:12:57.264185Z","shell.execute_reply.started":"2025-07-16T16:17:35.387887Z","shell.execute_reply":"2025-07-16T17:12:57.262021Z"}},"outputs":[{"name":"stdout","text":"Epoch [1], Loss: 609.1506\nEpoch [2], Loss: 433.6398\nEpoch [4], Loss: 433.5198\nEpoch [5], Loss: 433.4652\nEpoch [6], Loss: 433.5603\nEpoch [7], Loss: 433.3631\nEpoch [8], Loss: 433.5938\nEpoch [9], Loss: 433.3631\nEpoch [10], Loss: 433.4627\n","output_type":"stream"}],"execution_count":54},{"cell_type":"markdown","source":"## Evaluate and Visualize Predictions","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nmodel.eval()\ncorrect, total = 0, 0\n\nwith torch.no_grad():\n    for images, labels in val_loader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        preds = torch.max(outputs, 1)\n        correct += (preds == labels).sum().item()\n        total += labels.size(0)\n\nprint(f\"Validation Accuracy: {100 * correct / total:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T17:26:03.335613Z","iopub.execute_input":"2025-07-16T17:26:03.335897Z","iopub.status.idle":"2025-07-16T17:26:03.501763Z","shell.execute_reply.started":"2025-07-16T17:26:03.335878Z","shell.execute_reply":"2025-07-16T17:26:03.50054Z"}},"outputs":[{"traceback":["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m","\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)","\u001b[0;32m/tmp/ipykernel_35/295230579.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      9\u001b[0m         \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimages\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     10\u001b[0m         \u001b[0mpreds\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0moutputs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m         \u001b[0mcorrect\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mpreds\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mlabels\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitem\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     12\u001b[0m         \u001b[0mtotal\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mlabels\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     13\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;31mAttributeError\u001b[0m: 'bool' object has no attribute 'item'"],"ename":"AttributeError","evalue":"'bool' object has no attribute 'item'","output_type":"error"}],"execution_count":60},{"cell_type":"markdown","source":"## Save Model","metadata":{}},{"cell_type":"code","source":"torch.save(model.state_dict(), \"cat_dog_classifier.pth\")\nprint(\"✅ Model saved as cat_dog_classifier.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T17:12:57.28104Z","iopub.status.idle":"2025-07-16T17:12:57.281412Z","shell.execute_reply.started":"2025-07-16T17:12:57.281233Z","shell.execute_reply":"2025-07-16T17:12:57.28125Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Transform the image and predic","metadata":{}},{"cell_type":"code","source":"# Apply the same transformations used for train/val\nimg_tensor = transform(img).unsqueeze(0).to(device)  # Add batch dimension\n\n# Predict\nmodel.eval()\nwith torch.no_grad():\n    output = model(img_tensor)\n    prediction = torch.argmax(output, dim=1).item()\n\n# Map prediction to label\nclasses = ['cat', 'dog']\nprint(\"Predicted label:\", classes[prediction])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T17:12:57.283498Z","iopub.status.idle":"2025-07-16T17:12:57.283837Z","shell.execute_reply.started":"2025-07-16T17:12:57.283705Z","shell.execute_reply":"2025-07-16T17:12:57.283718Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##  Plot Image Predictions (Cats vs Dogs)","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\n# Class names\nclass_names = ['Cat', 'Dog']\n\n# Set model to evaluation mode\nmodel.eval()\n\n# Plot sample predictions\ndef plot_predictions(model, dataloader, num_images=6):\n    model.eval()\n    images_so_far = 0\n    fig = plt.figure(figsize=(12, 8))\n\n    with torch.no_grad():\n        for inputs, labels in dataloader:\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n\n            outputs = model(inputs)\n            _, preds = torch.max(outputs, 1)\n\n            for j in range(inputs.size()[0]):\n                images_so_far += 1\n                ax = plt.subplot(num_images//3, 3, images_so_far)\n                ax.axis('off')\n                ax.set_title(f'Actual: {class_names[labels[j]]} | Predicted: {class_names[preds[j]]}')\n                img = inputs[j].cpu().permute(1, 2, 0).numpy()\n                ax.imshow(img)\n\n                if images_so_far == num_images:\n                    return\n\n# Call the function\nplot_predictions(model, val_loader, num_images=6)\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T17:12:57.285534Z","iopub.status.idle":"2025-07-16T17:12:57.285922Z","shell.execute_reply.started":"2025-07-16T17:12:57.285742Z","shell.execute_reply":"2025-07-16T17:12:57.285759Z"}},"outputs":[],"execution_count":null}]}