{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"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        pass\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":"2022-12-29T03:59:02.299771Z","iopub.execute_input":"2022-12-29T03:59:02.300419Z","iopub.status.idle":"2022-12-29T03:59:29.123257Z","shell.execute_reply.started":"2022-12-29T03:59:02.300323Z","shell.execute_reply":"2022-12-29T03:59:29.121469Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom PIL import Image\nimport torch\nfrom torch.utils.data import Dataset,DataLoader\nimport torchvision\nimport torchvision.transforms as transforms","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:29.124671Z","iopub.execute_input":"2022-12-29T03:59:29.124973Z","iopub.status.idle":"2022-12-29T03:59:30.884727Z","shell.execute_reply.started":"2022-12-29T03:59:29.124943Z","shell.execute_reply":"2022-12-29T03:59:30.883777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('../input/classify-leaves/train.csv')\ntest = pd.read_csv('../input/classify-leaves/test.csv')\n\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:30.886328Z","iopub.execute_input":"2022-12-29T03:59:30.886867Z","iopub.status.idle":"2022-12-29T03:59:30.943798Z","shell.execute_reply.started":"2022-12-29T03:59:30.886830Z","shell.execute_reply":"2022-12-29T03:59:30.942762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = train['label'].unique()\nlabel2num = {}\nfor idx,label in enumerate(labels):\n    label2num[label] = idx\nprint('label2num:',label2num)\nnum2label = { a : b for b, a in label2num.items()}\nprint('num2label:',num2label)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:30.946597Z","iopub.execute_input":"2022-12-29T03:59:30.946953Z","iopub.status.idle":"2022-12-29T03:59:30.959655Z","shell.execute_reply.started":"2022-12-29T03:59:30.946918Z","shell.execute_reply":"2022-12-29T03:59:30.958585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class MyDataset(Dataset):\n    def __init__(self, mode='train', valid_ratio=0.2, resize_height=256, resize_width=256):\n        self.resize_height = resize_height\n        self.resize_width = resize_width\n        self.mode = mode\n        \n        \n        if mode == 'train':\n            data = pd.read_csv('/kaggle/input/classify-leaves/train.csv')\n            self.train_len = int(data.shape[0] * (1 - valid_ratio))\n            self.train_image = np.asarray(data.loc[:self.train_len, 'image'])\n            self.train_label = np.asarray(data.loc[:self.train_len, 'label'])\n            self.image_arr = self.train_image\n            self.label_arr = self.train_label\n        elif mode == 'valid':\n            data = pd.read_csv('/kaggle/input/classify-leaves/train.csv')\n            self.train_len = int(data.shape[0] * (1 - valid_ratio))\n            self.valid_image = np.asarray(data.loc[self.train_len:, 'image'])\n            self.valid_label = np.asarray(data.loc[self.train_len:, 'label'])\n            self.image_arr = self.valid_image\n            self.label_arr = self.valid_label\n        elif mode == 'test':\n            data = pd.read_csv('/kaggle/input/classify-leaves/test.csv')\n            self.test_image = np.asarray(data.loc[:, 'image'])\n            self.image_arr = self.test_image\n        self._len = len(self.image_arr)\n    \n    def __getitem__(self, index):\n        image_path = self.image_arr[index]\n        image = Image.open(os.path.join('/kaggle/input/classify-leaves/', image_path))\n        if self.mode == 'train':\n            transform = transforms.Compose([transforms.RandomResizedCrop(224),\n                                 transforms.RandomHorizontalFlip(),\n                                 transforms.ToTensor(),\n                                 transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])\n        else:\n            transform = transforms.Compose([transforms.Resize(256),\n                               transforms.CenterCrop(224),\n                               transforms.ToTensor(),\n                               transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])\n            \n        image = transform(image)\n        \n        if self.mode == 'test':\n            return image\n        \n        label = self.label_arr[index]\n        label_num = label2num[label]\n        return image, label_num\n    \n    def __len__(self):\n        return self._len","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:30.962290Z","iopub.execute_input":"2022-12-29T03:59:30.962743Z","iopub.status.idle":"2022-12-29T03:59:30.977534Z","shell.execute_reply.started":"2022-12-29T03:59:30.962708Z","shell.execute_reply":"2022-12-29T03:59:30.976572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = MyDataset()\n# print(data._x)\nfirst = next(iter(data))\nprint(first)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:30.980735Z","iopub.execute_input":"2022-12-29T03:59:30.981124Z","iopub.status.idle":"2022-12-29T03:59:31.071531Z","shell.execute_reply.started":"2022-12-29T03:59:30.981002Z","shell.execute_reply":"2022-12-29T03:59:31.070405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = MyDataset(mode='train')\nvalid_dataset = MyDataset(mode='valid')\ntest_dataset =  MyDataset(mode='test')","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:31.072825Z","iopub.execute_input":"2022-12-29T03:59:31.073095Z","iopub.status.idle":"2022-12-29T03:59:31.111783Z","shell.execute_reply.started":"2022-12-29T03:59:31.073071Z","shell.execute_reply":"2022-12-29T03:59:31.110910Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loader = DataLoader(train_dataset, batch_size=10, shuffle=True, num_workers=2)\nvalid_loader = DataLoader(valid_dataset, batch_size=10, shuffle=True, num_workers=2)\ntest_loader = DataLoader(test_dataset, batch_size=10, shuffle=False, num_workers=2)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:31.113219Z","iopub.execute_input":"2022-12-29T03:59:31.113600Z","iopub.status.idle":"2022-12-29T03:59:31.119199Z","shell.execute_reply.started":"2022-12-29T03:59:31.113537Z","shell.execute_reply":"2022-12-29T03:59:31.118133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_loader(loader):\n    for (x, y) in loader:\n        print(x)\n        print(y)\n        break\nshow_loader(valid_loader)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:31.120809Z","iopub.execute_input":"2022-12-29T03:59:31.121149Z","iopub.status.idle":"2022-12-29T03:59:31.380792Z","shell.execute_reply.started":"2022-12-29T03:59:31.121113Z","shell.execute_reply":"2022-12-29T03:59:31.378651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nfrom torch import nn\nfrom torch.nn import functional as F\n\n\nclass Residual(nn.Module):  #@save\n    def __init__(self, input_channels, num_channels,\n                 use_1x1conv=False, strides=1):\n        super().__init__()\n        self.conv1 = nn.Conv2d(input_channels, num_channels,\n                               kernel_size=3, padding=1, stride=strides)\n        self.conv2 = nn.Conv2d(num_channels, num_channels,\n                               kernel_size=3, padding=1)\n        if use_1x1conv:\n            self.conv3 = nn.Conv2d(input_channels, num_channels,\n                                   kernel_size=1, stride=strides)\n        else:\n            self.conv3 = None\n        self.bn1 = nn.BatchNorm2d(num_channels)\n        self.bn2 = nn.BatchNorm2d(num_channels)\n\n    def forward(self, X):\n        Y = F.relu(self.bn1(self.conv1(X)))\n        Y = self.bn2(self.conv2(Y))\n        if self.conv3:\n            X = self.conv3(X)\n        Y += X\n        return F.relu(Y)\n    \nb1 = nn.Sequential(nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),\n                   nn.BatchNorm2d(64), nn.ReLU(),\n                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))\n\ndef resnet_block(input_channels, num_channels, num_residuals,\n                 first_block=False):\n    blk = []\n    for i in range(num_residuals):\n        if i == 0 and not first_block:\n            blk.append(Residual(input_channels, num_channels,\n                                use_1x1conv=True, strides=2))\n        else:\n            blk.append(Residual(num_channels, num_channels))\n    return blk\n\nb2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))\nb3 = nn.Sequential(*resnet_block(64, 128, 2))\nb4 = nn.Sequential(*resnet_block(128, 256, 2))\nb5 = nn.Sequential(*resnet_block(256, 512, 2))\n\nnet = nn.Sequential(b1, b2, b3, b4, b5,\n                    nn.AdaptiveAvgPool2d((1,1)),\n                    nn.Flatten(), nn.Linear(512, 176))\n\nnet","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:31.384926Z","iopub.execute_input":"2022-12-29T03:59:31.385241Z","iopub.status.idle":"2022-12-29T03:59:31.520532Z","shell.execute_reply.started":"2022-12-29T03:59:31.385208Z","shell.execute_reply":"2022-12-29T03:59:31.519422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\nEPOCH = 100\nLR = 1e-4\n\n\noptimizer = torch.optim.Adam(net.parameters(), lr=LR)\nloss_func = nn.CrossEntropyLoss()\nmetric_func = lambda y_test, y_pred: accuracy_score(y_test.cpu().data.numpy(), y_pred.cpu().data.numpy())","metadata":{"execution":{"iopub.status.busy":"2022-12-29T03:59:31.522201Z","iopub.execute_input":"2022-12-29T03:59:31.522881Z","iopub.status.idle":"2022-12-29T03:59:32.031358Z","shell.execute_reply.started":"2022-12-29T03:59:31.522838Z","shell.execute_reply":"2022-12-29T03:59:32.030112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = \"cuda:0\"\nnet.to(device)\nbest_acc = 0\nfor epoch in range(EPOCH):\n    for step, (x, y) in enumerate(train_loader, 1):\n        net.train()\n        x = x.to(device)\n        y = y.to(device)\n        output = net(x)\n        loss = loss_func(output, y)\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        if step % 50 == 0 or step == 1:\n            net.eval()\n            with torch.no_grad():\n                accuracy = []\n                for (valid_x, valid_y) in valid_loader:\n                    valid_x = valid_x.to(device)\n                    valid_y = valid_y.to(device)\n                    output = net(valid_x)\n#                     print('output:',output)\n                    acc = metric_func(valid_y, torch.max(output, 1)[1])\n                    accuracy.append(acc)\n                accuracy = np.mean(accuracy)\n                print('Epoch: {}, step: {}, loss:{:.4f}, valid_accuracy: {:.4f}'.format(epoch, step, loss.cpu().data.numpy(), accuracy))\n                if step == 1 and epoch == 0:\n                    best_acc = accuracy\n    if accuracy >= best_acc:\n        best_acc = accuracy\n        torch.save(net.state_dict(), './net.ckpt')\n        print('Saving net with an accuracy of {}'.format(best_acc))\n    else:\n        print('The accuracy of this epoch is not good as the last epoch : {}. Kernel shut down.'.format(best_acc))\n        break","metadata":{"execution":{"iopub.status.busy":"2022-12-29T04:00:48.273393Z","iopub.execute_input":"2022-12-29T04:00:48.274008Z","iopub.status.idle":"2022-12-29T04:18:56.123050Z","shell.execute_reply.started":"2022-12-29T04:00:48.273963Z","shell.execute_reply":"2022-12-29T04:18:56.121099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"net.load_state_dict(torch.load('./net.ckpt'))\nnet.eval()\ntest_labels = []\nwith torch.no_grad():\n    for test_x in test_loader:\n        test_x = test_x.to(device)\n        output = net(test_x)\n        for label in torch.max(output, 1)[1]:\n#             print('label:',)\n            test_labels.append(num2label[label.item()])\n\n","metadata":{"execution":{"iopub.status.busy":"2022-12-29T04:24:17.825220Z","iopub.execute_input":"2022-12-29T04:24:17.825622Z","iopub.status.idle":"2022-12-29T04:25:06.735751Z","shell.execute_reply.started":"2022-12-29T04:24:17.825575Z","shell.execute_reply":"2022-12-29T04:25:06.734473Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = test.copy()\nsubmission['label'] = pd.Series(test_labels)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T04:27:12.886526Z","iopub.execute_input":"2022-12-29T04:27:12.887087Z","iopub.status.idle":"2022-12-29T04:27:12.894918Z","shell.execute_reply.started":"2022-12-29T04:27:12.887050Z","shell.execute_reply":"2022-12-29T04:27:12.893794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('./submission.csv',index=0)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T04:28:31.211533Z","iopub.execute_input":"2022-12-29T04:28:31.211915Z","iopub.status.idle":"2022-12-29T04:28:31.230886Z","shell.execute_reply.started":"2022-12-29T04:28:31.211883Z","shell.execute_reply":"2022-12-29T04:28:31.229967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}