{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"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}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install py7zr","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-10-19T19:16:36.365738Z","iopub.execute_input":"2024-10-19T19:16:36.366249Z","iopub.status.idle":"2024-10-19T19:16:52.395788Z","shell.execute_reply.started":"2024-10-19T19:16:36.366206Z","shell.execute_reply":"2024-10-19T19:16:52.394824Z"}},"outputs":[],"execution_count":null},{"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":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T19:16:52.397902Z","iopub.execute_input":"2024-10-19T19:16:52.398231Z","iopub.status.idle":"2024-10-19T19:16:55.425428Z","shell.execute_reply.started":"2024-10-19T19:16:52.398194Z","shell.execute_reply":"2024-10-19T19:16:55.424098Z"}},"outputs":[],"execution_count":null},{"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":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T19:16:55.426872Z","iopub.execute_input":"2024-10-19T19:16:55.427215Z","iopub.status.idle":"2024-10-19T19:17:02.585233Z","shell.execute_reply.started":"2024-10-19T19:16:55.427174Z","shell.execute_reply":"2024-10-19T19:17:02.584348Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 1. Print all the files in the input directory to verify paths\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T19:23:10.288644Z","iopub.execute_input":"2024-10-19T19:23:10.289442Z","iopub.status.idle":"2024-10-19T19:23:10.301559Z","shell.execute_reply.started":"2024-10-19T19:23:10.289399Z","shell.execute_reply":"2024-10-19T19:23:10.300551Z"}},"outputs":[],"execution_count":null},{"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/'\nextracted_test_path = '/kaggle/working/cifar-10/'\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":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T19:23:40.378366Z","iopub.execute_input":"2024-10-19T19:23:40.378891Z","iopub.status.idle":"2024-10-19T19:26:31.367150Z","shell.execute_reply.started":"2024-10-19T19:23:40.378841Z","shell.execute_reply":"2024-10-19T19:26:31.366262Z"}},"outputs":[],"execution_count":null},{"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/cifar-10/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":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T19:34:00.176366Z","iopub.execute_input":"2024-10-19T19:34:00.177258Z","iopub.status.idle":"2024-10-19T19:34:00.337030Z","shell.execute_reply.started":"2024-10-19T19:34:00.177215Z","shell.execute_reply":"2024-10-19T19:34:00.335983Z"}},"outputs":[],"execution_count":null},{"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 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])# Define a simpler transform for test data\ntest_transform = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize(*stats)\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T19:34:00.339472Z","iopub.execute_input":"2024-10-19T19:34:00.340551Z","iopub.status.idle":"2024-10-19T19:34:00.349904Z","shell.execute_reply.started":"2024-10-19T19:34:00.340495Z","shell.execute_reply":"2024-10-19T19:34:00.348889Z"}},"outputs":[],"execution_count":null},{"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":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T19:34:00.351144Z","iopub.execute_input":"2024-10-19T19:34:00.351491Z","iopub.status.idle":"2024-10-19T19:34:00.368160Z","shell.execute_reply.started":"2024-10-19T19:34:00.351454Z","shell.execute_reply":"2024-10-19T19:34:00.367337Z"}},"outputs":[],"execution_count":null},{"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":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T21:21:53.449462Z","iopub.execute_input":"2024-10-19T21:21:53.450263Z","iopub.status.idle":"2024-10-19T21:21:53.661853Z","shell.execute_reply.started":"2024-10-19T21:21:53.450221Z","shell.execute_reply":"2024-10-19T21:21:53.661056Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.optim as optim\nimport torch.optim.lr_scheduler as lr_scheduler\n\nclass WarmupCosineAnnealingScheduler(lr_scheduler._LRScheduler):\n    def __init__(self, optimizer, warmup_epochs, max_epochs, eta_min=0, last_epoch=-1):\n        self.warmup_epochs = warmup_epochs\n        self.max_epochs = max_epochs\n        self.eta_min = eta_min\n        super(WarmupCosineAnnealingScheduler, self).__init__(optimizer, last_epoch)\n    \n    def get_lr(self):\n        if self.last_epoch < self.warmup_epochs:\n            # Linear warmup\n            return [base_lr * (self.last_epoch + 1) / self.warmup_epochs for base_lr in self.base_lrs]\n        else:\n            # Cosine annealing\n            cosine_epoch = self.last_epoch - self.warmup_epochs\n            cosine_max_epoch = self.max_epochs - self.warmup_epochs\n            return [self.eta_min + (base_lr - self.eta_min) * \n                    (1 + math.cos(math.pi * cosine_epoch / cosine_max_epoch)) / 2 \n                    for base_lr in self.base_lrs]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T21:21:53.969862Z","iopub.execute_input":"2024-10-19T21:21:53.970524Z","iopub.status.idle":"2024-10-19T21:21:53.978207Z","shell.execute_reply.started":"2024-10-19T21:21:53.970487Z","shell.execute_reply":"2024-10-19T21:21:53.977335Z"}},"outputs":[],"execution_count":null},{"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 = 40\n#lr_scheduler = CosineAnnealingLR(optimizer, T_max=max_epochs)  # Learning rate scheduler\nwarmup_epochs = 20\n\nlr_scheduler = WarmupCosineAnnealingScheduler(optimizer, warmup_epochs, max_epochs)\n\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":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T21:22:04.327969Z","iopub.execute_input":"2024-10-19T21:22:04.328706Z","iopub.status.idle":"2024-10-19T21:53:36.251025Z","shell.execute_reply.started":"2024-10-19T21:22:04.328666Z","shell.execute_reply":"2024-10-19T21:53:36.249894Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Prepare filenames for the test \ntest_image_paths = [os.path.join('/kaggle/working/cifar-10/test', img_file) for img_file in os.listdir('/kaggle/working/cifar-10/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-challange2.csv', index=False)  # Save the file in CSV format\n\nprint(\"Predictions saved to AsmaFinalSubmission-challange2.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T21:54:07.379886Z","iopub.execute_input":"2024-10-19T21:54:07.380887Z","iopub.status.idle":"2024-10-19T21:55:36.470611Z","shell.execute_reply.started":"2024-10-19T21:54:07.380812Z","shell.execute_reply":"2024-10-19T21:55:36.469417Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!kaggle competitions submit -c cifar-10 -f AsmaFinalSubmission-challange2.csv -m \"Message\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-19T21:55:36.472620Z","iopub.execute_input":"2024-10-19T21:55:36.472981Z","iopub.status.idle":"2024-10-19T21:55:42.102479Z","shell.execute_reply.started":"2024-10-19T21:55:36.472944Z","shell.execute_reply":"2024-10-19T21:55:42.101348Z"}},"outputs":[],"execution_count":null}]}