{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","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":30732,"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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-15T09:44:02.045535Z","iopub.execute_input":"2024-06-15T09:44:02.045875Z","iopub.status.idle":"2024-06-15T09:44:03.065881Z","shell.execute_reply.started":"2024-06-15T09:44:02.045844Z","shell.execute_reply":"2024-06-15T09:44:03.064999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# install the unzip package\n!pip install py7zr","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:44:03.067488Z","iopub.execute_input":"2024-06-15T09:44:03.067841Z","iopub.status.idle":"2024-06-15T09:44:19.430873Z","shell.execute_reply.started":"2024-06-15T09:44:03.067818Z","shell.execute_reply":"2024-06-15T09:44:19.429966Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import essential package\nimport torch\nimport py7zr\nimport torchvision.models as models\nimport torch.nn as nn\nimport os\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\nfrom torchvision import transforms\nimport torch.optim as optim\nimport pandas as pd\nimport torchvision\nimport shutil","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:44:19.432359Z","iopub.execute_input":"2024-06-15T09:44:19.432655Z","iopub.status.idle":"2024-06-15T09:44:24.500832Z","shell.execute_reply.started":"2024-06-15T09:44:19.432627Z","shell.execute_reply":"2024-06-15T09:44:24.499921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# unzip the file, only once will be ok\noutput_dir = \"/kaggle/working/cifar-10\"\nos.makedirs(output_dir, exist_ok=True)\n\nwith py7zr.SevenZipFile('/kaggle/input/cifar-10/train.7z', mode='r') as archive:\n    archive.extractall(path=output_dir)\nwith py7zr.SevenZipFile('/kaggle/input/cifar-10/test.7z', mode='r') as archive:\n    archive.extractall(path=output_dir)\nshutil.copyfile('/kaggle/input/cifar-10/trainLabels.csv', '/kaggle/working/cifar-10/trainLabels.csv')\n","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:44:24.503473Z","iopub.execute_input":"2024-06-15T09:44:24.505286Z","iopub.status.idle":"2024-06-15T09:47:57.625473Z","shell.execute_reply.started":"2024-06-15T09:44:24.505256Z","shell.execute_reply":"2024-06-15T09:47:57.624492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"\nuse resnet and finetune\nresnet34\n\"\"\"\nmodel = torchvision.models.resnet34('IMAGENET1K_V1')\n# change the fully-connected layer, and initialize it\nmodel.fc = nn.Linear(model.fc.in_features, 10)\ntorch.nn.init.xavier_uniform_(model.fc.weight)\nfor param in model.parameters():\n    param.requires_grad = True\nmodel = model.cuda()","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:47:57.626709Z","iopub.execute_input":"2024-06-15T09:47:57.627005Z","iopub.status.idle":"2024-06-15T09:47:59.213929Z","shell.execute_reply.started":"2024-06-15T09:47:57.626980Z","shell.execute_reply":"2024-06-15T09:47:59.212808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define the class and id mapping\nclass2id = {\n    'airplane': 0,\n    'automobile': 1, \n    'bird': 2, \n    'cat': 3, \n    'deer': 4, \n    'dog': 5, \n    'frog': 6, \n    'horse': 7, \n    'ship': 8, \n    'truck': 9\n}\nid2class = {val:key for key, val in class2id.items()}","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:47:59.215558Z","iopub.execute_input":"2024-06-15T09:47:59.215900Z","iopub.status.idle":"2024-06-15T09:47:59.221567Z","shell.execute_reply.started":"2024-06-15T09:47:59.215869Z","shell.execute_reply":"2024-06-15T09:47:59.220578Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define the indexs of training dataset, validation dataset, trainval dataset and test dataset\ntrainval_idx_list = np.arange(1, 50001, dtype = np.int32)\ntest_idx_list = np.arange(1, 300001, dtype = np.int32)\n\np = 0.9 # use 90% data for training and 10% for validation\nMX = 50000\nTRAIN_LEN = int(MX * p)\ntrain_idx_list = trainval_idx_list[:TRAIN_LEN]\nval_idx_list = trainval_idx_list[TRAIN_LEN:]\n\n# calculate the mean and std for training dataset(used for train and validation)\ntrain_pics = []\nfor idx in train_idx_list:\n    img = Image.open(os.path.join(\"/kaggle/working/cifar-10/train\", '{}.png'.format(idx)))\n    train_pics.append(np.array(img)[None, ...])\ntrain_total = np.concatenate(train_pics, axis=0).reshape(-1, 3)\ntrain_total = train_total/ 255.0\ntrain_mean = np.mean(train_total, 0)\ntrain_std = np.std(train_total, 0)\n\n# calculate the mean and std for trainval dataset(used for test)\ntrainval_pics = []\nfor idx in trainval_idx_list:\n    img = Image.open(os.path.join(\"/kaggle/working/cifar-10/train\", '{}.png'.format(idx)))\n    trainval_pics.append(np.array(img)[None, ...])\ntrainval_total = np.concatenate(trainval_pics, axis=0).reshape(-1, 3)\ntrainval_total = trainval_total/ 255.0\ntrainval_mean = np.mean(trainval_total, 0)\ntrainval_std = np.std(trainval_total, 0)","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:47:59.222955Z","iopub.execute_input":"2024-06-15T09:47:59.223693Z","iopub.status.idle":"2024-06-15T09:48:23.800838Z","shell.execute_reply.started":"2024-06-15T09:47:59.223659Z","shell.execute_reply":"2024-06-15T09:48:23.799741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define the dataset\nclass CIFAR10(Dataset):\n    def __init__(self, root_path, split = 'train'):\n        super().__init__()\n        #*  root path\n        self.data_path = root_path\n        \n        #* sub dataset path\n        if split=='train' or split=='val' or split=='trainval':\n            self.split_data_path = os.path.join(self.data_path, 'train')\n        else:\n            self.split_data_path = os.path.join(self.data_path, 'test')\n        self.split = split\n        \n        #* label info\n        self.label_data = pd.read_csv(os.path.join(self.data_path, 'trainLabels.csv'))\n        \n        # index_list\n        if split == 'train':\n            idxs_list = train_idx_list\n        elif split == 'val':\n            idxs_list = val_idx_list\n        elif split == 'trainval':\n            idxs_list = trainval_idx_list\n        else:\n            idxs_list = test_idx_list\n        self.idxs_list = idxs_list\n        \n        #* data augmentation\n        if self.split == 'train':\n            self.transforms = transforms.Compose([\n                transforms.Resize(128),  # the resize operation will boost the performance a lot\n                transforms.RandomHorizontalFlip(p=0.5),\n                transforms.ToTensor(),        \n                transforms.Normalize(train_mean, train_std),\n                # transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2),\n            ])\n        elif self.split == 'val':\n            self.transforms = transforms.Compose([\n                transforms.Resize(128),\n                transforms.ToTensor(),        \n                transforms.Normalize(train_mean, train_std)\n            ])\n        elif self.split == 'trainval':\n            self.transforms = transforms.Compose([\n                transforms.Resize(128),            \n                transforms.RandomHorizontalFlip(p=0.5),\n                transforms.ToTensor(),        \n                transforms.Normalize(trainval_mean, trainval_std),\n            ])\n        else:\n            self.transforms = transforms.Compose([\n                transforms.Resize(128),\n                transforms.ToTensor(),        \n                transforms.Normalize(trainval_mean, trainval_std)\n            ])\n        \n    def __getitem__(self, index):\n        img_idx = self.idxs_list[index]\n        #* read the image \n        img = Image.open(os.path.join(self.split_data_path, '{}.png'.format(img_idx)))\n        \n        #* data augmentation\n        img = self.transforms(img)\n        if self.split != 'test':\n            #* get the number label\n            label = self.label_data.iloc[img_idx-1]['label']\n            label = class2id[label]\n            return img.cuda(), torch.tensor([label]).cuda()\n        else:\n            return img.cuda()\n        \n    def __len__(self):\n        return len(self.idxs_list)","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:48:23.802146Z","iopub.execute_input":"2024-06-15T09:48:23.802506Z","iopub.status.idle":"2024-06-15T09:48:23.817484Z","shell.execute_reply.started":"2024-06-15T09:48:23.802470Z","shell.execute_reply":"2024-06-15T09:48:23.816557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# some hyper-parameters\nLR = 1e-4\nWEIGHT_DECAY = 5e-4\nEPOCH = 20\nBATCH_SIZE = 128","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:48:23.818679Z","iopub.execute_input":"2024-06-15T09:48:23.818963Z","iopub.status.idle":"2024-06-15T09:48:23.833004Z","shell.execute_reply.started":"2024-06-15T09:48:23.818938Z","shell.execute_reply":"2024-06-15T09:48:23.832108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loss function\ncriterion = nn.CrossEntropyLoss()\n\n# optimizer\noptimizer = optim.Adam(model.parameters(), lr=LR, weight_decay=WEIGHT_DECAY)\n    \n# lr_scheduler\nlr_scheduler = optim.lr_scheduler.OneCycleLR(optimizer, LR, epochs = EPOCH, steps_per_epoch=(50000+BATCH_SIZE-1)//BATCH_SIZE)","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:48:23.836028Z","iopub.execute_input":"2024-06-15T09:48:23.836335Z","iopub.status.idle":"2024-06-15T09:48:23.844996Z","shell.execute_reply.started":"2024-06-15T09:48:23.836309Z","shell.execute_reply":"2024-06-15T09:48:23.844147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = CIFAR10('/kaggle/working/cifar-10', split='train')\nval_dataset = CIFAR10('/kaggle/working/cifar-10', split='val')\ntrain_dataloader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle = True)\nval_dataloader = DataLoader(val_dataset, batch_size=BATCH_SIZE, shuffle = False)","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:48:23.846126Z","iopub.execute_input":"2024-06-15T09:48:23.846399Z","iopub.status.idle":"2024-06-15T09:48:23.892827Z","shell.execute_reply.started":"2024-06-15T09:48:23.846367Z","shell.execute_reply":"2024-06-15T09:48:23.892027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train and validate, save the best model\nbest_acc = 0\nfor epoch_idx in range(EPOCH):\n    model.train()\n    running_loss = 0\n    for batch_idx, (img, label) in enumerate(train_dataloader):\n        output = model(img)\n        loss = criterion(output, label.squeeze())\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        lr_scheduler.step()\n        running_loss += loss.item()\n    print(\"Epoch{} Loss: {}\".format(epoch_idx, running_loss/len(train_dataloader.dataset)))\n    with torch.no_grad():\n        model.eval()\n        right_cnt = 0\n        for batch_idx, (img, label) in enumerate(val_dataloader):\n            output = model(img)\n            results = torch.argmax(output, dim=-1)\n            right_cnt += (results == label.squeeze()).sum()\n        acc = right_cnt / len(val_dataset)\n        print(\"Epoch{} ACC: {}\".format(epoch_idx, acc))\n    if acc > best_acc:\n        best_acc = acc\n        torch.save(model.state_dict(), 'model_params.pth')","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:48:23.894128Z","iopub.execute_input":"2024-06-15T09:48:23.894498Z","iopub.status.idle":"2024-06-15T09:50:05.404405Z","shell.execute_reply.started":"2024-06-15T09:48:23.894465Z","shell.execute_reply":"2024-06-15T09:50:05.403397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = torchvision.models.resnet34('IMAGENET1K_V1')\nmodel.fc = nn.Linear(512, 10)\nmodel.load_state_dict(torch.load('model_params.pth'))\nmodel = model.cuda()\ntest_dataset = CIFAR10('/kaggle/working/cifar-10', split='test')\ntest_dataloader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle = False)\nresults = []\nwith torch.no_grad():\n    model.eval()\n    batch_size = test_dataloader.batch_size\n    for batch_idx, img in enumerate(test_dataloader):\n        output = model(img)\n        res = torch.argmax(output, dim=-1).detach().cpu().numpy()\n        for idx, r in enumerate(res):\n            results.append({'id': batch_idx * batch_size + idx+1, 'label': id2class[r]})\n    df = pd.DataFrame(results)\n\n    csv_file = 'submission.csv'\n\n    df.to_csv(csv_file, index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:50:05.405837Z","iopub.execute_input":"2024-06-15T09:50:05.406485Z","iopub.status.idle":"2024-06-15T09:56:22.231977Z","shell.execute_reply.started":"2024-06-15T09:50:05.406448Z","shell.execute_reply":"2024-06-15T09:56:22.231102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shutil.rmtree('/kaggle/working/cifar-10')\nos.remove('/kaggle/working/model_params.pth')","metadata":{"execution":{"iopub.status.busy":"2024-06-15T09:57:53.724112Z","iopub.execute_input":"2024-06-15T09:57:53.724497Z","iopub.status.idle":"2024-06-15T09:57:53.742163Z","shell.execute_reply.started":"2024-06-15T09:57:53.724460Z","shell.execute_reply":"2024-06-15T09:57:53.741285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}