{"metadata":{"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"},{"sourceId":9550777,"sourceType":"datasetVersion","datasetId":5819135}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.14"},"papermill":{"default_parameters":{},"duration":976.602337,"end_time":"2024-10-05T12:54:07.848187","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2024-10-05T12:37:51.245850","version":"2.6.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install py7zr","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":15.922024,"end_time":"2024-10-05T12:38:10.769987","exception":false,"start_time":"2024-10-05T12:37:54.847963","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-10-05T19:05:32.481309Z","iopub.execute_input":"2024-10-05T19:05:32.482115Z","iopub.status.idle":"2024-10-05T19:05:44.231644Z","shell.execute_reply.started":"2024-10-05T19:05:32.482069Z","shell.execute_reply":"2024-10-05T19:05:44.230457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch.optim.lr_scheduler import CosineAnnealingLR, LambdaLR\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import datasets, transforms\nfrom torchvision.transforms import RandomErasing\nfrom tqdm import tqdm\nimport math\nimport os\nimport pandas as pd\nfrom PIL import Image\nimport py7zr","metadata":{"papermill":{"duration":8.637569,"end_time":"2024-10-05T12:38:19.413815","exception":false,"start_time":"2024-10-05T12:38:10.776246","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-10-05T19:05:44.234011Z","iopub.execute_input":"2024-10-05T19:05:44.234366Z","iopub.status.idle":"2024-10-05T19:05:44.240779Z","shell.execute_reply.started":"2024-10-05T19:05:44.234332Z","shell.execute_reply":"2024-10-05T19:05:44.239687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import py7zr\nimport os\ntrain_archive_path = '/kaggle/input/cifar-10/train.7z'\ntest_archive_path = '/kaggle/input/cifar-10/test.7z'\nextracted_train_path = '/kaggle/working/cifar-10/train'\nextracted_test_path = '/kaggle/working/cifar-10/test'\n\nwith py7zr.SevenZipFile(train_archive_path, mode='r') as z:\n    z.extractall(path=extracted_train_path)\n\nwith py7zr.SevenZipFile(test_archive_path, mode='r') as z:\n    z.extractall(path=extracted_test_path)","metadata":{"papermill":{"duration":173.480309,"end_time":"2024-10-05T12:41:12.899165","exception":false,"start_time":"2024-10-05T12:38:19.418856","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-10-05T19:05:44.242103Z","iopub.execute_input":"2024-10-05T19:05:44.242887Z","iopub.status.idle":"2024-10-05T19:08:46.459495Z","shell.execute_reply.started":"2024-10-05T19:05:44.242843Z","shell.execute_reply":"2024-10-05T19:08:46.458670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load the training labels using pandas\nlabels_df = pd.read_csv('/kaggle/input/cifar-10/trainLabels.csv')  # Read CSV file containing image IDs and their respective labels\n\n# Create a list of image file paths by mapping filenames with labels\nimage_file_paths = [os.path.join('/kaggle/working/train_images/train', f\"{img_id}.png\") for img_id in labels_df['id']]  # Image paths for training data\nimage_labels = labels_df['label'].values  # Extract the labels from the dataframe\n\n# Define CIFAR-10 classes and convert string labels to corresponding index values\ncifar_classes = ('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')\nclass_to_index = {category: index for index, category in enumerate(cifar_classes)}  # Map class names to integer indices\nimage_labels = [class_to_index[label] for label in image_labels]  # Convert string labels to their respective indices","metadata":{"papermill":{"duration":0.174576,"end_time":"2024-10-05T12:41:13.079078","exception":false,"start_time":"2024-10-05T12:41:12.904502","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-10-05T19:08:46.460731Z","iopub.execute_input":"2024-10-05T19:08:46.461050Z","iopub.status.idle":"2024-10-05T19:08:46.598173Z","shell.execute_reply.started":"2024-10-05T19:08:46.461012Z","shell.execute_reply":"2024-10-05T19:08:46.597338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define stats for normalization (CIFAR-10 statistics)\nstats = ((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))\n# Data Augmentation with CutOut (RandomErasing) for training data\ntrain_transform = transforms.Compose([\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomCrop(32, padding=4),\n    transforms.ToTensor(),\n    transforms.Normalize(*stats),\n    RandomErasing(scale=(0.02, 0.33))\n])\n\n# Define a simpler transform for test data\ntest_transform = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize(*stats)\n])","metadata":{"execution":{"iopub.status.busy":"2024-10-05T19:08:46.601139Z","iopub.execute_input":"2024-10-05T19:08:46.601541Z","iopub.status.idle":"2024-10-05T19:08:46.608141Z","shell.execute_reply.started":"2024-10-05T19:08:46.601506Z","shell.execute_reply":"2024-10-05T19:08:46.607083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Custom dataset class for CIFAR-10 training data\nclass CustomCIFAR10Dataset(Dataset):\n    def __init__(self, image_file_paths, image_labels, transform=None):\n        self.image_file_paths = image_file_paths  # Store the paths of training images\n        self.image_labels = image_labels  # Store the labels of training images\n        self.transform = transform  # Store any transformation function applied to the images\n\n    def __len__(self):\n        return len(self.image_file_paths)  # Return the total number of images\n\n    def __getitem__(self, idx):\n        img_path = self.image_file_paths[idx]  # Get the path of the image at the specified index\n        image = Image.open(img_path)  # Open the image file\n        label = self.image_labels[idx]  # Get the label corresponding to the image\n\n        if self.transform:  # Apply the transformation, if provided\n            image = self.transform(image)\n\n        return image, label  # Return the image and its label\n\n# Create the dataset and data loader for training data\ntrain_dataset = CustomCIFAR10Dataset(image_file_paths, image_labels, transform=train_transform)  # Initialize dataset with images, labels, and transformations\ntrain_loader = DataLoader(dataset=train_dataset, batch_size=128, shuffle=True, num_workers=2)  # Load data in batches, shuffling data with multiple workers","metadata":{"papermill":{"duration":0.015654,"end_time":"2024-10-05T12:41:13.100067","exception":false,"start_time":"2024-10-05T12:41:13.084413","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-10-05T19:08:46.609272Z","iopub.execute_input":"2024-10-05T19:08:46.609568Z","iopub.status.idle":"2024-10-05T19:08:46.625354Z","shell.execute_reply.started":"2024-10-05T19:08:46.609537Z","shell.execute_reply":"2024-10-05T19:08:46.624465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\n\n# Define a Residual Block for the ResNet architecture\nclass ResBlock(nn.Module):\n    def __init__(self, in_channels, out_channels, stride=1, downsample=None):\n        super(ResBlock, self).__init__()\n        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(out_channels)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1, bias=False)\n        self.bn2 = nn.BatchNorm2d(out_channels)\n        self.downsample = downsample\n\n    def forward(self, x):\n        residual = x\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n        out = self.conv2(out)\n        out = self.bn2(out)\n\n        if self.downsample:\n            residual = self.downsample(x)\n\n        out = torch.add(out, residual)\n        out = self.relu(out)\n        return out\n\n# ResNet Model with refactored initialization and layer creation\nclass ResNetModel(nn.Module):\n    def __init__(self, block, layers, num_classes=10):\n        super(ResNetModel, self).__init__()\n        self.in_channels = 64\n\n        # Create initial convolution, batch norm, and ReLU\n        self.conv = self.build_conv_layer(3, 64)\n        self.bn = nn.BatchNorm2d(64)\n        self.relu = nn.ReLU(inplace=True)\n\n        # Create the residual layers\n        self.layer1 = self.make_layer(block, 64, layers[0])\n        self.layer2 = self.make_layer(block, 128, layers[1], stride=2)\n        self.layer3 = self.make_layer(block, 256, layers[2], stride=2)\n        self.layer4 = self.make_layer(block, 512, layers[3], stride=2)\n\n        # Global pooling and fully connected layer\n        self.avg_pool = nn.AdaptiveAvgPool2d((1, 1))\n        self.fc = nn.Linear(512, num_classes)\n\n        # Initialize weights\n        self.initialize_weights()\n\n    def build_conv_layer(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1):\n        return nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding=padding, bias=False)\n\n    def make_layer(self, block, out_channels, blocks, stride=1):\n        downsample = None\n        if stride != 1 or self.in_channels != out_channels:\n            downsample = nn.Sequential(\n                self.build_conv_layer(self.in_channels, out_channels, kernel_size=1, stride=stride, padding=0),\n                nn.BatchNorm2d(out_channels)\n            )\n\n        layers = [block(self.in_channels, out_channels, stride, downsample)]\n        self.in_channels = out_channels\n        for _ in range(1, blocks):\n            layers.append(block(out_channels, out_channels))\n\n        return nn.Sequential(*layers)\n\n    def initialize_weights(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n            elif isinstance(m, nn.BatchNorm2d):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n    def forward(self, x):\n        x = self.conv(x)\n        x = self.bn(x)\n        x = self.relu(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avg_pool(x)\n        x = torch.flatten(x, 1)\n        x = self.fc(x)\n\n        return x\n\n# Instantiate the model, loss function, and optimizer\nresnet_model = ResNetModel(ResBlock, [2, 2, 2, 2]).cuda()\nloss_function = nn.CrossEntropyLoss()\noptimizer = optim.AdamW(resnet_model.parameters(), lr=0.001, weight_decay=1e-4)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T19:08:46.626491Z","iopub.execute_input":"2024-10-05T19:08:46.626811Z","iopub.status.idle":"2024-10-05T19:08:46.828679Z","shell.execute_reply.started":"2024-10-05T19:08:46.626768Z","shell.execute_reply":"2024-10-05T19:08:46.827669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to train the model\ndef train_model(network, data_loader, loss_function, optim, lr_scheduler):\n    network.train()  # Set the model to training mode\n    total_loss = 0.0\n    correct_predictions = 0\n    total_samples = 0\n    # Loop over the training data\n    for images, labels in tqdm(data_loader):\n        images, labels = images.cuda(), labels.cuda()  # Move images and labels to GPU\n        optim.zero_grad()  # Clear previous gradients\n        outputs = network(images)  # Forward pass\n        loss = loss_function(outputs, labels)  # Calculate the loss\n        loss.backward()  # Backpropagate the gradients\n        optim.step()  # Update model parameters\n        total_loss += loss.item()  # Accumulate total loss\n        _, predicted_labels = outputs.max(1)  # Get predicted labels\n        total_samples += labels.size(0)  # Keep track of total samples processed\n        correct_predictions += predicted_labels.eq(labels).sum().item()  # Count correct predictions\n    lr_scheduler.step()  # Adjust learning rate based on scheduler\n    print(f\"Training Loss: {total_loss/len(data_loader)}, Training Accuracy: {100 * correct_predictions/total_samples:.2f}%\")\n\n# Function to test the model\ndef test_model(network, test_data_loader, loss_function):\n    network.eval()  # Set the model to evaluation mode\n    total_loss = 0.0\n    correct_predictions = 0\n    total_samples = 0\n    with torch.no_grad():  # Disable gradient calculation for evaluation\n        for images, labels in tqdm(test_data_loader):\n            images, labels = images.cuda(), labels.cuda()  # Move images and labels to GPU\n            outputs = network(images)  # Forward pass\n            loss = loss_function(outputs, labels)  # Calculate loss\n            total_loss += loss.item()  # Accumulate total loss\n            _, predicted_labels = outputs.max(1)  # Get predicted labels\n            total_samples += labels.size(0)  # Keep track of total samples processed\n            correct_predictions += predicted_labels.eq(labels).sum().item()  # Count correct predictions\n    print(f\"Testing Loss: {total_loss/len(test_data_loader)}, Testing Accuracy: {100 * correct_predictions/total_samples:.2f}%\")\n    return 100 * correct_predictions/total_samples  # Return accuracy\n\n# Main training loop\nmax_epochs = 20  # Maximum number of training iterations\nlr_scheduler = CosineAnnealingLR(optimizer, T_max=max_epochs)  # Learning rate scheduler\nbest_accuracy = 0  # Initialize variable to track the best accuracy\nfor epoch in range(max_epochs):\n    print(f\"Epoch {epoch+1}/{max_epochs}\")\n    train_model(resnet_model, train_loader, loss_function, optimizer, lr_scheduler)  # Train the model\n    accuracy = test_model(resnet_model, train_loader, loss_function)  # Test the model\n    if accuracy > best_accuracy:  # If current accuracy is the best so far\n        best_accuracy = accuracy  # Update best accuracy\n        torch.save(resnet_model.state_dict(), \"best_resnet_model.pth\")  # Save the best model weights","metadata":{"papermill":{"duration":669.30185,"end_time":"2024-10-05T12:52:22.853981","exception":false,"start_time":"2024-10-05T12:41:13.552131","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-10-05T19:08:46.830148Z","iopub.execute_input":"2024-10-05T19:08:46.830470Z","iopub.status.idle":"2024-10-05T19:24:19.708201Z","shell.execute_reply.started":"2024-10-05T19:08:46.830438Z","shell.execute_reply":"2024-10-05T19:24:19.707000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prepare filenames for the test dataset\ntest_image_paths = [os.path.join('/kaggle/working/test_images/test', img_file) for img_file in os.listdir('/kaggle/working/test_images/test')]  # List of test image paths\ntest_image_paths.sort(key=lambda x: int(x.split('/')[-1].split('.')[0]))  # Sort filenames by the numeric part of the filename\n\n# Custom dataset class for CIFAR-10 test data\nclass CustomCIFAR10TestDataset(Dataset):\n    def __init__(self, image_paths, transform):\n        self.image_paths = image_paths  # Store the list of test image paths\n        self.transform = transform  # Store any transformation function\n\n    def __len__(self):\n        return len(self.image_paths)  # Return the total number of test images\n\n    def __getitem__(self, idx):\n        img = Image.open(self.image_paths[idx])  # Open the image at the specified index\n        if self.transform:\n            img = self.transform(img)  # Apply transformation if provided\n        return img  # Return the transformed image\n\n# Initialize the test dataset and dataloader\ntest_dataset = CustomCIFAR10TestDataset(test_image_paths, test_transform)  # Create the test dataset\ntest_loader = DataLoader(test_dataset, batch_size=128, shuffle=False, num_workers=2)  # Load test data in batches without shuffling\n\n# Load the best model for prediction\nresnet_model.load_state_dict(torch.load('best_resnet_model.pth'))  # Load the saved model weights\nresnet_model = resnet_model.cuda()  # Move the model to GPU\n\n# Predict on the test dataset\npredictions = []\nwith torch.no_grad():  # Disable gradient calculation for prediction\n    resnet_model.eval()  # Set the model to evaluation mode\n    for images in tqdm(test_loader):\n        images = images.cuda()  # Move images to GPU\n        outputs = resnet_model(images)  # Perform forward pass\n        preds = torch.argmax(outputs, 1)  # Get the predicted class labels\n        preds = preds.cpu().numpy()  # Move predictions to CPU and convert to numpy array\n        predictions.extend([cifar_classes[i] for i in preds])  # Map predictions to class names\n\n# Load the sample submission file and save predictions\nsubmission_file = pd.read_csv('/kaggle/input/cifar-10/sampleSubmission.csv')  # Load the sample submission file\nsubmission_file['label'] = predictions  # Assign predicted labels to the submission file\nsubmission_file.to_csv('./AsmaFinalSubmission.csv', index=False)  # Save the file in CSV format\n\nprint(\"Predictions saved to AsmaFinalSubmission.csv\")","metadata":{"execution":{"iopub.status.busy":"2024-10-05T19:27:52.805318Z","iopub.execute_input":"2024-10-05T19:27:52.806101Z","iopub.status.idle":"2024-10-05T19:29:15.800469Z","shell.execute_reply.started":"2024-10-05T19:27:52.806048Z","shell.execute_reply":"2024-10-05T19:29:15.799408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create the .kaggle directory (if it doesn't already exist)\n!mkdir -p ~/.kaggle\n\n# Move the kaggle.json from your dataset to the .kaggle directory\n!cp /kaggle/input/kaggle/kaggle.json ~/.kaggle/\n\n# Set appropriate permissions\n!chmod 600 ~/.kaggle/kaggle.json","metadata":{"execution":{"iopub.status.busy":"2024-10-05T19:29:40.744839Z","iopub.execute_input":"2024-10-05T19:29:40.745750Z","iopub.status.idle":"2024-10-05T19:29:43.877391Z","shell.execute_reply.started":"2024-10-05T19:29:40.745702Z","shell.execute_reply":"2024-10-05T19:29:43.876227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!kaggle competitions submit -c cifar-10 -f AsmaFinalSubmission.csv -m \"Message\"","metadata":{"execution":{"iopub.status.busy":"2024-10-05T19:30:51.072855Z","iopub.execute_input":"2024-10-05T19:30:51.073696Z","iopub.status.idle":"2024-10-05T19:30:54.084365Z","shell.execute_reply.started":"2024-10-05T19:30:51.073655Z","shell.execute_reply":"2024-10-05T19:30:54.083304Z"},"trusted":true},"execution_count":null,"outputs":[]}]}