{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.10.12","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"}],"dockerImageVersionId":30635,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2024-01-22T20:31:14.857216Z","iopub.execute_input":"2024-01-22T20:31:14.857999Z","iopub.status.idle":"2024-01-22T20:31:15.268760Z","shell.execute_reply.started":"2024-01-22T20:31:14.857962Z","shell.execute_reply":"2024-01-22T20:31:15.267735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Import everything needed","metadata":{}},{"cell_type":"code","source":"import glob\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport collections\nimport math\nimport os\nimport shutil\nfrom sklearn.model_selection import train_test_split\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision\nfrom torchvision import datasets, transforms\nfrom torchvision.models import resnet18, ResNet18_Weights\nnp.random.seed(0)\ntorch.manual_seed(0)\ntorch.cuda.manual_seed(0)","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:31:17.566120Z","iopub.execute_input":"2024-01-22T20:31:17.566662Z","iopub.status.idle":"2024-01-22T20:31:22.056218Z","shell.execute_reply.started":"2024-01-22T20:31:17.566629Z","shell.execute_reply":"2024-01-22T20:31:22.055105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\n\nconfig = {\n    'device': 'cuda' if torch.cuda.is_available() else 'cpu',\n    'lr': 1e-4,\n    'batch': 128,\n    'epochs': 50,\n    'loss_fn': 'CrossEntropyLoss', # CrossEntropyLoss, NLLLoss\n    'optimizer': 'Adam', # Adam, SGD\n    'momentum': 0.9,\n    'fine_tune_full': True\n}\n\nprint(config['device'])\nwandb.init(project='CIFAR10', save_code=True, config=config, mode='disabled')","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:31:22.058027Z","iopub.execute_input":"2024-01-22T20:31:22.058546Z","iopub.status.idle":"2024-01-22T20:31:23.909125Z","shell.execute_reply.started":"2024-01-22T20:31:22.058517Z","shell.execute_reply":"2024-01-22T20:31:23.908079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Unzip datasets","metadata":{}},{"cell_type":"code","source":"!pip install py7zr","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:31:23.910491Z","iopub.execute_input":"2024-01-22T20:31:23.910999Z","iopub.status.idle":"2024-01-22T20:31:42.760015Z","shell.execute_reply.started":"2024-01-22T20:31:23.910968Z","shell.execute_reply":"2024-01-22T20:31:42.758788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# WARNING: It can take a lot of time to uncompress!","metadata":{}},{"cell_type":"code","source":"!python -m py7zr x /kaggle/input/cifar-10/train.7z","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:31:42.763784Z","iopub.execute_input":"2024-01-22T20:31:42.764271Z","iopub.status.idle":"2024-01-22T20:32:49.217054Z","shell.execute_reply.started":"2024-01-22T20:31:42.764228Z","shell.execute_reply":"2024-01-22T20:32:49.215741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python -m py7zr x /kaggle/input/cifar-10/test.7z","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:32:49.219353Z","iopub.execute_input":"2024-01-22T20:32:49.219818Z","iopub.status.idle":"2024-01-22T20:55:15.297426Z","shell.execute_reply.started":"2024-01-22T20:32:49.219777Z","shell.execute_reply":"2024-01-22T20:55:15.295769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = '/kaggle/working/'","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:55:15.299425Z","iopub.execute_input":"2024-01-22T20:55:15.299882Z","iopub.status.idle":"2024-01-22T20:55:15.305358Z","shell.execute_reply.started":"2024-01-22T20:55:15.299846Z","shell.execute_reply":"2024-01-22T20:55:15.304225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_csv_labels(fname):\n    \"\"\"Read `fname` to return a filename to label dictionary.\"\"\"\n    with open(fname, 'r') as f:\n        # Skip the file header line (column name)\n        lines = f.readlines()[1:]\n    tokens = [l.rstrip().split(',') for l in lines]\n    return dict(((name, label) for name, label in tokens))\n\nlabels = read_csv_labels(os.path.join(data_dir, '/kaggle/input/cifar-10/trainLabels.csv'))\nprint(f'Number training examples: {len(labels)}')\nprint(f'Number classes: {len(set(labels.values()))}')","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:55:15.306852Z","iopub.execute_input":"2024-01-22T20:55:15.307247Z","iopub.status.idle":"2024-01-22T20:55:15.425064Z","shell.execute_reply.started":"2024-01-22T20:55:15.307207Z","shell.execute_reply":"2024-01-22T20:55:15.423736Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def copyfile(filename, target_dir):\n    \"\"\"Copy a file into a target directory.\"\"\"\n    os.makedirs(target_dir, exist_ok=True)\n    shutil.copy(filename, target_dir)\n\ndef reorg_train_valid(data_dir, labels, valid_ratio):\n    \"\"\"Split the validation set out of the original training set.\"\"\"\n    # The number of examples of the class that has the fewest examples in the\n    # training dataset\n    n = collections.Counter(labels.values()).most_common()[-1][1]\n    # The number of examples per class for the validation set\n    n_valid_per_label = max(1, math.floor(n * valid_ratio))\n    label_count = {}\n    for train_file in os.listdir(os.path.join(data_dir, 'train')):\n        label = labels[train_file.split('.')[0]]\n        fname = os.path.join(data_dir, 'train', train_file)\n        copyfile(fname, os.path.join(data_dir, 'train_valid_test',\n                                     'train_valid', label))\n        if label not in label_count or label_count[label] < n_valid_per_label:\n            copyfile(fname, os.path.join(data_dir, 'train_valid_test',\n                                         'valid', label))\n            label_count[label] = label_count.get(label, 0) + 1\n        else:\n            copyfile(fname, os.path.join(data_dir, 'train_valid_test',\n                                         'train', label))\n    return n_valid_per_label\n\ndef reorg_test(data_dir):\n    \"\"\"Organize the testing set for data loading during prediction.\"\"\"\n    for test_file in os.listdir(os.path.join(data_dir, 'test')):\n        copyfile(os.path.join(data_dir, 'test', test_file),\n                 os.path.join(data_dir, 'train_valid_test', 'test',\n                              'unknown'))\n        \ndef reorg_cifar10_data(data_dir, valid_ratio):\n    labels = read_csv_labels('/kaggle/input/cifar-10/trainLabels.csv')\n    reorg_train_valid(data_dir, labels, valid_ratio)\n    reorg_test(data_dir)","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:55:15.426573Z","iopub.execute_input":"2024-01-22T20:55:15.426910Z","iopub.status.idle":"2024-01-22T20:55:15.441264Z","shell.execute_reply.started":"2024-01-22T20:55:15.426880Z","shell.execute_reply":"2024-01-22T20:55:15.439960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_ratio = 0.1\nreorg_cifar10_data(data_dir, valid_ratio)","metadata":{"execution":{"iopub.status.busy":"2024-01-22T20:55:15.442758Z","iopub.execute_input":"2024-01-22T20:55:15.443166Z","iopub.status.idle":"2024-01-22T20:56:26.128966Z","shell.execute_reply.started":"2024-01-22T20:55:15.443135Z","shell.execute_reply":"2024-01-22T20:56:26.127917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Transformations\n- Pre-trained networks usually apply some transformations to their inputs\n- TODOs:\n    - Check the transformations in the pre-trained ResNet and sync with yours! \n    - Consider adding more transformations, like HorizontalFlip, mnRandomSizeCrop","metadata":{}},{"cell_type":"code","source":"transform_train = torchvision.transforms.Compose([\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomVerticalFlip(),\n    transforms.RandomRotation((-180, 180)),\n    transforms.RandomPerspective(0.25),\n    transforms.RandomAutocontrast(),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\ntransform_test = torchvision.transforms.Compose([\n    torchvision.transforms.ToTensor(),\n    torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:02:20.787848Z","iopub.execute_input":"2024-01-22T21:02:20.788871Z","iopub.status.idle":"2024-01-22T21:02:20.796930Z","shell.execute_reply.started":"2024-01-22T21:02:20.788831Z","shell.execute_reply":"2024-01-22T21:02:20.795728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds, train_valid_ds = [torchvision.datasets.ImageFolder(\n    os.path.join(data_dir, 'train_valid_test', folder),\n    transform=transform_train) for folder in ['train', 'train_valid']]\n\nvalid_ds, test_ds = [torchvision.datasets.ImageFolder(\n    os.path.join(data_dir, 'train_valid_test', folder),\n    transform=transform_test) for folder in ['valid', 'test']]\n\ntrain_loader, train_valid_loader = [torch.utils.data.DataLoader(\n    dataset, config['batch'], shuffle=True, drop_last=True)\n    for dataset in (train_ds, train_valid_ds)]\n\nvalid_loader = torch.utils.data.DataLoader(valid_ds, config['batch'], shuffle=False, drop_last=True)\n\ntest_loader = torch.utils.data.DataLoader(test_ds, config['batch'], shuffle=False, drop_last=False)","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:02:21.721095Z","iopub.execute_input":"2024-01-22T21:02:21.721858Z","iopub.status.idle":"2024-01-22T21:02:23.921353Z","shell.execute_reply.started":"2024-01-22T21:02:21.721817Z","shell.execute_reply":"2024-01-22T21:02:23.920459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = []\ntrian_valid = []\nvalid = []\n\nfor _ in range(10):\n    train.append(0)\n    valid.append(0)\n    trian_valid.append(0)\n\nfor _, label in train_ds:\n    train[label] += 1\n    \nfor _, label in train_valid_ds:\n    trian_valid[label] += 1\n    \nfor _, label in valid_ds:\n    valid[label] += 1\n    \n    \nprint('Label -> Train, Train Validation, Validation')\nfor i, (a, b, c) in enumerate(zip(train, trian_valid, valid)):\n    print(f\"{i} -> {a}({100 * a/sum(train):.2f}%), {b}({100 * b/sum(trian_valid):.2f}%), {c}({100 * c/sum(valid):.2f}%)\")","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:02:23.923100Z","iopub.execute_input":"2024-01-22T21:02:23.923391Z","iopub.status.idle":"2024-01-22T21:04:34.080757Z","shell.execute_reply.started":"2024-01-22T21:02:23.923365Z","shell.execute_reply":"2024-01-22T21:04:34.079583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TODO: \n* Define the data augmentation technique \n* Fine-tune a pre-trained ResNet-18 on CIFAR-10\n* Submit your submission file to Kaggle (as described in the competition rules) and get your accuracy on the test set","metadata":{}},{"cell_type":"code","source":"def _weights_init(m):\n    if isinstance(m, nn.Linear):\n        nn.init.xavier_normal_(m.weight)\n        nn.init.constant_(m.bias, 0)\n    return m\n\nclass Model(nn.Module):\n    def __init__(self):\n        super(Model, self).__init__()\n        self.resnet = resnet18(weights=ResNet18_Weights.DEFAULT)\n        \n        for params in self.resnet.parameters():\n            params.requires_grad = config['fine_tune_full']\n                \n        self.resnet.fc = nn.Sequential(\n            _weights_init(nn.Linear(self.resnet.fc.in_features, 10)),\n        )\n        self.resnet.fc.requires_grad = True\n        \n        self.log_softmax = nn.LogSoftmax(dim=1)\n        self.sigmoid = nn.Sigmoid()\n        \n    def forward(self, x):\n        out = self.resnet(x)\n        \n        if config['loss_fn'] == 'NLLLoss':\n            out = self.log_softmax(out)\n        if config['loss_fn'] == 'CrossEntropyLoss':\n            out = self.sigmoid(out)\n            \n        return out","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:04:34.081932Z","iopub.execute_input":"2024-01-22T21:04:34.082303Z","iopub.status.idle":"2024-01-22T21:04:34.093664Z","shell.execute_reply.started":"2024-01-22T21:04:34.082273Z","shell.execute_reply":"2024-01-22T21:04:34.092367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_weights_from_model(model):\n    data = {}\n    for name, layer in model.resnet.named_parameters():\n        if not layer.requires_grad:\n            continue\n        try:\n            data[f'{name}_mean'] = layer.grad.mean().item()\n            data[f'{name}_max'] = layer.grad.max().item()\n        except:\n            data[f'{name}_mean'] = 0\n            data[f'{name}_max'] = 0\n    return data","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:04:34.096142Z","iopub.execute_input":"2024-01-22T21:04:34.096545Z","iopub.status.idle":"2024-01-22T21:04:34.108481Z","shell.execute_reply.started":"2024-01-22T21:04:34.096512Z","shell.execute_reply":"2024-01-22T21:04:34.107216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Model().to(config['device'])\n\nif config['loss_fn'] == 'CrossEntropyLoss':\n    loss_fn = nn.CrossEntropyLoss()\nelif config['loss_fn'] == 'NLLLoss':\n    loss_fn = nn.NLLLoss()\nelse:\n    raise Exception('Invalid Loss function')\n\nif config['optimizer'] == 'Adam':\n    optimizer = optim.Adam(model.parameters(), lr=config['lr'])\nelif config['optimizer'] == 'SGD':\n    optimizer = optim.SGD(model.parameters(), lr=config['lr'], momentum=config['momentum'])\nelse:\n    raise Exception('Invalid Optimizer')\n\nscheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=3, verbose=True, min_lr=1e-8, factor=0.5)","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:04:34.109951Z","iopub.execute_input":"2024-01-22T21:04:34.110331Z","iopub.status.idle":"2024-01-22T21:04:34.892065Z","shell.execute_reply.started":"2024-01-22T21:04:34.110300Z","shell.execute_reply":"2024-01-22T21:04:34.890961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loss = []\nval_loss = []\ntrain_accuracy = []\nval_accuracy = []\ngradients_data = []\nlrs = []\nmin_val_loss = 1e10","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:04:34.893291Z","iopub.execute_input":"2024-01-22T21:04:34.893624Z","iopub.status.idle":"2024-01-22T21:04:34.898639Z","shell.execute_reply.started":"2024-01-22T21:04:34.893596Z","shell.execute_reply":"2024-01-22T21:04:34.897683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for e in range(config['epochs']): \n    \n    print(f\"{e+1}/{config['epochs']}\")\n    \n    current_lr = scheduler.optimizer.param_groups[0]['lr']\n    lrs.append(current_lr)\n    wandb.log({\n        'learning_rate': current_lr\n    }, commit=False)\n    \n    model.train()\n    running_loss = 0\n    running_correct = 0\n    for image, label in train_loader:\n        image, label = image.to(config['device']), label.to(config['device'])\n        optimizer.zero_grad()\n        pred = model(image)\n        loss = loss_fn(pred, label)\n        loss.backward()\n        optimizer.step()\n        \n        running_correct += (pred.argmax(dim=1) == label).float().sum().item()\n        running_loss += loss.item()\n    \n    grads = get_weights_from_model(model)\n    train_loss.append(running_loss / len(train_ds))\n    train_accuracy.append(100 * running_correct / len(train_ds))\n    gradients_data.append(grads)\n    grads['epoch'] = e\n    grads['training_loss'] = running_loss / len(train_ds)\n    grads['training_accuracy'] = 100 * running_correct / len(train_ds)\n    wandb.log(grads, commit=False)\n    \n    print(f'Train Loss: {running_loss / len(train_ds):.5f}')\n    print(f'Train Acc: {100 * running_correct / len(train_ds):.3f}%')\n    \n    model.eval()\n    running_loss = 0\n    running_correct = 0\n    with torch.no_grad():\n        for image, label in train_valid_loader:\n            image, label = image.to(config['device']), label.to(config['device'])\n            pred = model(image)\n            loss = loss_fn(pred, label)\n            \n            running_correct += (pred.argmax(dim=1) == label).float().sum().item()\n            running_loss += loss.item()\n            \n    val_loss.append(running_loss / len(train_valid_ds))\n    val_accuracy.append(100 * running_correct / len(train_valid_ds))\n    scheduler.step(running_loss / len(train_valid_ds))\n    \n    print(f'Val Loss: {running_loss / len(train_valid_ds):.5f}')\n    print(f'Val Acc: {100 * running_correct / len(train_valid_ds):.3f}%')\n    \n    wandb.log({\n        'validation_loss': running_loss / len(train_valid_ds), \n        'validation_accuracy': 100 * running_correct / len(train_valid_ds)\n    })\n\n    if running_loss < min_val_loss:\n        print('saving model')\n        torch.save(model.state_dict(), 'model.pt')\n        min_val_loss = running_loss","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:04:34.899864Z","iopub.execute_input":"2024-01-22T21:04:34.900181Z","iopub.status.idle":"2024-01-22T21:30:21.390915Z","shell.execute_reply.started":"2024-01-22T21:04:34.900155Z","shell.execute_reply":"2024-01-22T21:30:21.389807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(3, 1, figsize=(10, 10))\n\nax[0].plot(list(range(len(train_loss))), train_loss, list(range(len(val_loss))), val_loss)\nax[0].legend([\"Train\", \"Validation\"])\nax[0].set_title(\"Loss\")\nax[0].grid()\n\nax[1].plot(list(range(len(train_accuracy))), train_accuracy, list(range(len(val_accuracy))), val_accuracy)\nax[1].set_title(\"Accuracy\")\nax[1].axis(ymin=0,ymax=105)\nax[1].grid()\n\nax[2].plot(list(range(len(lrs))), lrs)\nax[2].set_title(\"Learning Rate\")\nax[2].grid()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:30:21.392566Z","iopub.execute_input":"2024-01-22T21:30:21.393418Z","iopub.status.idle":"2024-01-22T21:30:22.160853Z","shell.execute_reply.started":"2024-01-22T21:30:21.393376Z","shell.execute_reply":"2024-01-22T21:30:22.159803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for name, layer in model.resnet.named_parameters():\n    try:\n        maxs = [grad[f'{name}_max'] for grad in gradients_data]\n        means = [grad[f'{name}_mean'] for grad in gradients_data]\n        \n        fig, ax = plt.subplots(1, 2, figsize=(15, 5))\n        \n        ax[0].plot(list(range(len(maxs))), maxs)\n        ax[1].plot(list(range(len(means))), means)\n\n        ax[0].set_title(f\"{name} Max\")\n        ax[1].set_title(f\"{name} Mean\")\n\n        ax[0].grid()\n        ax[1].grid()\n\n        plt.show()\n    except: \n        pass","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:30:22.163792Z","iopub.execute_input":"2024-01-22T21:30:22.164170Z","iopub.status.idle":"2024-01-22T21:30:56.662054Z","shell.execute_reply.started":"2024-01-22T21:30:22.164139Z","shell.execute_reply":"2024-01-22T21:30:56.660944Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_state_dict(torch.load('model.pt'))","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:30:56.663667Z","iopub.execute_input":"2024-01-22T21:30:56.664143Z","iopub.status.idle":"2024-01-22T21:30:56.731429Z","shell.execute_reply.started":"2024-01-22T21:30:56.664102Z","shell.execute_reply":"2024-01-22T21:30:56.730327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\ntotal_loss = 0\ntotal_correct = 0\nwith torch.no_grad():\n    for image, label in valid_loader:\n        image, label = image.to(config['device']), label.to(config['device'])\n        pred = model(image)\n        loss = loss_fn(pred, label)\n        total_correct += (pred.argmax(dim=1) == label).float().sum().item()\n        total_loss += loss.item()\n        \nprint(f'Overall Accuracy: {100 * total_correct/len(valid_ds):.4f}%')\nprint(f'Average Loss: {total_loss/len(valid_ds)}')","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:30:56.732756Z","iopub.execute_input":"2024-01-22T21:30:56.733108Z","iopub.status.idle":"2024-01-22T21:30:59.717074Z","shell.execute_reply.started":"2024-01-22T21:30:56.733077Z","shell.execute_reply":"2024-01-22T21:30:59.715963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_names = [\"airplane\", \"automobile\", \"bird\", \"cat\", \"deer\", \"dog\", \"frog\", \"horse\", \"ship\", \"truck\"]\n\ntest_loader = torch.utils.data.DataLoader(test_ds, batch_size=1, shuffle=False, drop_last=False)\n\nout_data = []\n\nmodel.eval()\nwith torch.no_grad():\n    for i, (image, label) in enumerate(test_loader):\n        image, label = image.to(config['device']), label.to(config['device'])\n        pred = model(image).argmax(dim=1).cpu().item()\n        \n        out_data.append([i+1, class_names[pred]])\n\nout_df = pd.DataFrame(out_data, columns=[\"id\", \"label\"])\nout_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-01-19T15:53:57.445951Z","iopub.execute_input":"2024-01-19T15:53:57.446323Z","iopub.status.idle":"2024-01-19T15:55:52.406225Z","shell.execute_reply.started":"2024-01-19T15:53:57.446288Z","shell.execute_reply":"2024-01-19T15:55:52.404691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_names = [\"airplane\", \"automobile\", \"bird\", \"cat\", \"deer\", \"dog\", \"frog\", \"horse\", \"ship\", \"truck\"]\ntest_loader = torch.utils.data.DataLoader(test_ds, batch_size=1, shuffle=False, drop_last=False)\n\nout_df = pd.read_csv('/kaggle/input/cifar-10/sampleSubmission.csv')\n\nlabels = []\n\nmodel.eval()\nwith torch.no_grad():\n    for i, (image, label) in enumerate(test_loader):\n        image, label = image.to(config['device']), label.to(config['device'])\n        pred = model(image).argmax(dim=1).cpu().item()\n        labels.append(class_names[pred])\n\nout_df['label'] = labels","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:34:46.472589Z","iopub.execute_input":"2024-01-22T21:34:46.473015Z","iopub.status.idle":"2024-01-22T21:54:35.433798Z","shell.execute_reply.started":"2024-01-22T21:34:46.472980Z","shell.execute_reply":"2024-01-22T21:54:35.432602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"out_df.to_csv('submission.csv', index = False)","metadata":{"execution":{"iopub.status.busy":"2024-01-22T21:56:57.768599Z","iopub.execute_input":"2024-01-22T21:56:57.768994Z","iopub.status.idle":"2024-01-22T21:56:58.486306Z","shell.execute_reply.started":"2024-01-22T21:56:57.768964Z","shell.execute_reply":"2024-01-22T21:56:58.485253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}