{"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":7327,"databundleVersionId":861871,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import f1_score,classification_report\nimport torch\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nimport torch.nn as nn\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.594262Z","iopub.execute_input":"2025-07-06T15:52:45.594572Z","iopub.status.idle":"2025-07-06T15:52:45.599879Z","shell.execute_reply.started":"2025-07-06T15:52:45.594551Z","shell.execute_reply":"2025-07-06T15:52:45.599008Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dir = '../input/dog-breed-identification/train'\ntrain_size = len(os.listdir('../input/dog-breed-identification/train'))\n\ntrain_size","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.604238Z","iopub.execute_input":"2025-07-06T15:52:45.604808Z","iopub.status.idle":"2025-07-06T15:52:45.626321Z","shell.execute_reply.started":"2025-07-06T15:52:45.604785Z","shell.execute_reply":"2025-07-06T15:52:45.625576Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = (\"cuda\" if torch.cuda.is_available() else \"cpu\")\ndevice","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.627618Z","iopub.execute_input":"2025-07-06T15:52:45.627908Z","iopub.status.idle":"2025-07-06T15:52:45.641353Z","shell.execute_reply.started":"2025-07-06T15:52:45.627884Z","shell.execute_reply":"2025-07-06T15:52:45.640526Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv('../input/dog-breed-identification/labels.csv')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.642155Z","iopub.execute_input":"2025-07-06T15:52:45.642438Z","iopub.status.idle":"2025-07-06T15:52:45.667887Z","shell.execute_reply.started":"2025-07-06T15:52:45.642404Z","shell.execute_reply":"2025-07-06T15:52:45.667129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels = sorted(df['breed'].unique())\nn_classes = len(labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.669509Z","iopub.execute_input":"2025-07-06T15:52:45.669736Z","iopub.status.idle":"2025-07-06T15:52:45.674302Z","shell.execute_reply.started":"2025-07-06T15:52:45.669720Z","shell.execute_reply":"2025-07-06T15:52:45.673522Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class_to_num = dict(zip(labels,np.arange(n_classes)))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.675064Z","iopub.execute_input":"2025-07-06T15:52:45.675279Z","iopub.status.idle":"2025-07-06T15:52:45.690894Z","shell.execute_reply.started":"2025-07-06T15:52:45.675254Z","shell.execute_reply":"2025-07-06T15:52:45.690094Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(df.drop('breed', axis = 1), df['breed'], test_size=0.2, random_state=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.691688Z","iopub.execute_input":"2025-07-06T15:52:45.691921Z","iopub.status.idle":"2025-07-06T15:52:45.712787Z","shell.execute_reply.started":"2025-07-06T15:52:45.691897Z","shell.execute_reply":"2025-07-06T15:52:45.712089Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train['breed'] = y_train\nX_test['breed'] = y_test","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.713643Z","iopub.execute_input":"2025-07-06T15:52:45.713850Z","iopub.status.idle":"2025-07-06T15:52:45.727021Z","shell.execute_reply.started":"2025-07-06T15:52:45.713836Z","shell.execute_reply":"2025-07-06T15:52:45.726224Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nfrom PIL import Image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.727778Z","iopub.execute_input":"2025-07-06T15:52:45.728110Z","iopub.status.idle":"2025-07-06T15:52:45.741276Z","shell.execute_reply.started":"2025-07-06T15:52:45.728087Z","shell.execute_reply":"2025-07-06T15:52:45.740664Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img = Image.open(os.path.join(train_dir, df['id'][0] + '.jpg'))\noriginal_mode = img.mode\nprint(f\"The original color format (mode) of the image is: {original_mode}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.742213Z","iopub.execute_input":"2025-07-06T15:52:45.742496Z","iopub.status.idle":"2025-07-06T15:52:45.761321Z","shell.execute_reply.started":"2025-07-06T15:52:45.742452Z","shell.execute_reply":"2025-07-06T15:52:45.760498Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Standard image size for Resnet50 model\nimg_size = (224,224,3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.763504Z","iopub.execute_input":"2025-07-06T15:52:45.763734Z","iopub.status.idle":"2025-07-06T15:52:45.773722Z","shell.execute_reply.started":"2025-07-06T15:52:45.763713Z","shell.execute_reply":"2025-07-06T15:52:45.772930Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import Dataset\nfrom PIL import Image\n\nclass DogBreedDataset(Dataset):\n    def __init__(self, image_paths, labels, transform=None):\n        self.image_paths = image_paths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, index):\n        img_path = self.image_paths[index]\n        label = self.labels[index]\n\n        # Load image\n        image = Image.open(img_path).convert('RGB') # Ensure image is in RGB\n\n        # Apply transformations\n        if self.transform:\n            image = self.transform(image)\n\n        # Convert label to numerical format\n        label_num = class_to_num[label]\n\n        return image, label_num","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.774398Z","iopub.execute_input":"2025-07-06T15:52:45.774703Z","iopub.status.idle":"2025-07-06T15:52:45.792994Z","shell.execute_reply.started":"2025-07-06T15:52:45.774671Z","shell.execute_reply":"2025-07-06T15:52:45.792229Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize((img_size[0], img_size[1])),\n    transforms.ToTensor(),  # Converts image to [0,1] float tensor\n])\n\n# Create the datasets\n# We will use the paths and labels generated by the previous images_to_tensor function call\n# but we need to re-run that call to get the updated lists of paths and labels.\n# However, the previous call failed. Let's generate the paths and labels again,\n# but this time just return the lists, not the tensors as the original function did.\n\ndef get_image_paths_and_labels(data_dir, df):\n    image_names = list(df['id'])\n    image_labels = list(df['breed'])\n    image_paths = [os.path.join(data_dir, img_name + '.jpg') for img_name in image_names]\n    return image_paths, image_labels\n\ntrain_image_paths, train_labels_list = get_image_paths_and_labels(train_dir, X_train)\ntest_image_paths, test_labels_list = get_image_paths_and_labels(train_dir, X_test)\n\n\ntrain_dataset = DogBreedDataset(train_image_paths, train_labels_list, transform=transform)\ntest_dataset = DogBreedDataset(test_image_paths, test_labels_list, transform=transform)\n\nprint(f\"Train Dataset Size: {len(train_dataset)}\")\nprint(f\"Test Dataset Size: {len(test_dataset)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.794829Z","iopub.execute_input":"2025-07-06T15:52:45.795098Z","iopub.status.idle":"2025-07-06T15:52:45.823237Z","shell.execute_reply.started":"2025-07-06T15:52:45.795082Z","shell.execute_reply":"2025-07-06T15:52:45.822446Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_samples_to_plot = 9  # You can change this number\nindices_to_plot = np.random.choice(len(train_dataset), num_samples_to_plot, replace=False)\n\nplt.figure(figsize=(10, 10))\nfor i, idx in enumerate(indices_to_plot):\n    image, label_num = train_dataset[idx]\n\n    # Convert the tensor image to a format suitable for plotting (HxWx channels)\n    # and move it to CPU if it's on GPU\n    image_np = image.permute(1, 2, 0).cpu().numpy()\n\n    # Find the breed name from the label number\n    breed_name = labels[label_num]\n\n    plt.subplot(3, 3, i + 1)\n    plt.imshow(image_np)\n    plt.title(breed_name)\n    plt.axis('off')\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:45.824304Z","iopub.execute_input":"2025-07-06T15:52:45.824646Z","iopub.status.idle":"2025-07-06T15:52:47.136911Z","shell.execute_reply.started":"2025-07-06T15:52:45.824624Z","shell.execute_reply":"2025-07-06T15:52:47.135879Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\n# Create DataLoaders for the train and test data\nbatch_size = 64 # You can adjust this based on your GPU memory\ntrain_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n\ntest_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)\n\nprint(f\"Number of batches in train_dataloader: {len(train_dataloader)}\")\nprint(f\"Number of batches in test_dataloader: {len(test_dataloader)}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:47.137771Z","iopub.execute_input":"2025-07-06T15:52:47.138017Z","iopub.status.idle":"2025-07-06T15:52:47.143234Z","shell.execute_reply.started":"2025-07-06T15:52:47.137999Z","shell.execute_reply":"2025-07-06T15:52:47.142494Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision.models import resnet18\nmodel = models.resnet18(pretrained=True)\nmodel.to(device)\nloss_fn = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(params=model.parameters(), \n                             lr=0.001)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:47.143966Z","iopub.execute_input":"2025-07-06T15:52:47.144150Z","iopub.status.idle":"2025-07-06T15:52:47.989053Z","shell.execute_reply.started":"2025-07-06T15:52:47.144136Z","shell.execute_reply":"2025-07-06T15:52:47.988327Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"torch.manual_seed(42)\n\n# Measure time\nfrom tqdm.auto import tqdm\nimport time\n\n# Train and test model\ndef accuracy_fn(y_true, y_pred):\n    correct = torch.eq(y_true, y_pred).sum().item()\n    acc = (correct / len(y_pred)) * 100\n    return acc\n\n# Training loop\nepochs = 15\ntrain_loss_list = []\ntrain_accuracy_list = []\ntest_loss_list= []\ntest_accuracy_list= []\n\nstart_time = time.time()\n\nfor epoch in tqdm(range(epochs)):\n    ### Training\n    model.train() # set model to training mode\n    train_loss = 0\n    train_acc = 0\n    for batch, (X, y) in enumerate(train_dataloader):\n        X, y = X.to(device), y.to(device)\n\n        # 1. Forward pass\n        y_pred_logits = model(X)\n\n        # 2. Calculate loss (cross entropy loss requires target to be class indices)\n        loss = loss_fn(y_pred_logits,y) # y is already class index\n\n        train_loss += loss.item()\n\n        # 3. Optimizer zero grad\n        optimizer.zero_grad()\n\n        # 4. Loss backward\n        loss.backward()\n\n        # 5. Optimizer step\n        optimizer.step()\n\n        # Calculate accuracy\n        y_pred_prob = torch.softmax(y_pred_logits, dim=1)\n        y_pred = torch.argmax(y_pred_prob, dim=1)\n        train_acc += accuracy_fn(y_pred, y)\n\n\n    # Calculate average train loss and accuracy\n    train_loss /= len(train_dataloader)\n    train_acc /= len(train_dataloader)\n    train_loss_list.append(train_loss)\n    train_accuracy_list.append(train_acc)\n\n\n    ### Testing\n    model.eval() # set model to evaluation mode\n    test_loss = 0\n    test_acc = 0\n    with torch.no_grad():\n        for X,y in test_dataloader:\n            X,y = X.to(device), y.to(device)\n\n            test_pred_logits = model(X)\n            loss = loss_fn(test_pred_logits, y) # Calculate loss on test data\n            test_loss += loss.item()\n\n            test_pred_prob = torch.softmax(test_pred_logits, dim=1)\n            test_pred = torch.argmax(test_pred_prob, dim=1)\n            acc = accuracy_fn(y,test_pred) # Calculate accuracy on test data\n            test_acc += acc\n\n    # Calculate average loss and accuracy for the epoch\n    test_loss /= len(test_dataloader)\n    test_acc /= len(test_dataloader)\n\n    test_loss_list.append(test_loss)\n    test_accuracy_list.append(test_acc)\n\n\n    print(f\"Epoch: {epoch+1} | Train loss: {train_loss:.5f} | Train acc: {train_acc:.2f}% | Test loss: {test_loss:.5f} | Test acc: {test_acc:.2f}%\")\n\nend_time = time.time()\ntotal_time = end_time - start_time\nprint(f\"Total training time: {total_time:.2f} seconds\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T15:52:47.989821Z","iopub.execute_input":"2025-07-06T15:52:47.990052Z","iopub.status.idle":"2025-07-06T16:11:59.878320Z","shell.execute_reply.started":"2025-07-06T15:52:47.990034Z","shell.execute_reply":"2025-07-06T16:11:59.877501Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class PredictionDataset(Dataset):\n    def __init__(self, image_paths, transform=None):\n        self.image_paths = image_paths\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, index):\n        img_path = self.image_paths[index]\n\n        # Load image\n        image = Image.open(img_path) # Ensure image is in RGB\n\n        # Apply transformations\n        if self.transform:\n            image = self.transform(image)\n\n        return image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T16:12:21.194791Z","iopub.execute_input":"2025-07-06T16:12:21.195260Z","iopub.status.idle":"2025-07-06T16:12:21.199883Z","shell.execute_reply.started":"2025-07-06T16:12:21.195236Z","shell.execute_reply":"2025-07-06T16:12:21.199091Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_dir = '../input/dog-breed-identification/test'\ntest_size = len(os.listdir('../input/dog-breed-identification/test'))\n\ntest_size","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T16:12:25.389355Z","iopub.execute_input":"2025-07-06T16:12:25.389963Z","iopub.status.idle":"2025-07-06T16:12:25.399238Z","shell.execute_reply.started":"2025-07-06T16:12:25.389942Z","shell.execute_reply":"2025-07-06T16:12:25.398373Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_image_names = os.listdir(test_dir)\ntest_image_paths = [os.path.join(test_dir, img_name) for img_name in test_image_names]\n\nprediction_dataset = PredictionDataset(test_image_paths, transform=transform)\nbatch_size = 64 \ntestset = DataLoader(prediction_dataset, batch_size=batch_size, shuffle=False) # No need to shuffle for prediction\n\nprint(f\"Number of samples in prediction dataset: {len(prediction_dataset)}\")\nprint(f\"Number of batches in prediction_dataloader: {len(testset)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T16:12:28.108079Z","iopub.execute_input":"2025-07-06T16:12:28.108614Z","iopub.status.idle":"2025-07-06T16:12:28.126105Z","shell.execute_reply.started":"2025-07-06T16:12:28.108591Z","shell.execute_reply":"2025-07-06T16:12:28.125508Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\n\npredictions = []\nimage_ids = [img_name.split('.')[0] for img_name in test_image_names] # Assuming image names are like 'id.jpg'\n\nwith torch.no_grad():\n    for images in testset:\n        images = images.to(device)\n\n        # Forward pass\n        outputs = model(images)\n\n        # Get predicted class probabilities or indices\n        # For this competition, we need probabilities for each class\n        probabilities = torch.softmax(outputs, dim=1)\n\n        # Append predictions to the list\n        predictions.append(probabilities.cpu().numpy())\n\n# Concatenate predictions from all batches\npredictions = np.concatenate(predictions)\n\n# You now have the predictions in a numpy array.\n# The order of predictions corresponds to the order of images in test_image_paths.\n# The columns of the predictions array correspond to the classes in your 'labels' list.\nprint(f\"Shape of predictions array: {predictions.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T16:15:20.369246Z","iopub.execute_input":"2025-07-06T16:15:20.369974Z","iopub.status.idle":"2025-07-06T16:17:53.096272Z","shell.execute_reply.started":"2025-07-06T16:15:20.369948Z","shell.execute_reply":"2025-07-06T16:17:53.095504Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_class_indices = np.argmax(predictions, axis=1)\n\n# Convert the predicted class indices back to breed labels\npredicted_labels = [labels[i] for i in predicted_class_indices]\n\n# You now have a list of predicted breed labels for each image in the test set\nprint(f\"Number of predicted labels: {len(predicted_labels)}\")\nprint(f\"First 10 predicted labels: {predicted_labels[:10]}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T16:18:04.159592Z","iopub.execute_input":"2025-07-06T16:18:04.159863Z","iopub.status.idle":"2025-07-06T16:18:04.169361Z","shell.execute_reply.started":"2025-07-06T16:18:04.159845Z","shell.execute_reply":"2025-07-06T16:18:04.168616Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_df = pd.DataFrame({'id': image_ids, 'breed': predicted_labels})\n\n# Save the DataFrame to a CSV file\nsubmission_df.to_csv('submission.csv', index=False)\n\nprint(\"Submission file 'submission.csv' created successfully!\")\ndisplay(submission_df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-06T16:18:45.031978Z","iopub.execute_input":"2025-07-06T16:18:45.032584Z","iopub.status.idle":"2025-07-06T16:18:45.078016Z","shell.execute_reply.started":"2025-07-06T16:18:45.032563Z","shell.execute_reply":"2025-07-06T16:18:45.077275Z"}},"outputs":[],"execution_count":null}]}