{"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":"markdown","source":"## Importing packages","metadata":{}},{"cell_type":"code","source":"from pathlib import Path\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nfrom sklearn.preprocessing import LabelEncoder\nimport json\nfrom IPython import display\nfrom PIL import Image\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.utils.data as data\nimport torchvision.datasets as datasets\nimport torchvision.models as models\nimport torchvision.transforms as transforms\nimport albumentations\nfrom albumentations.pytorch import ToTensorV2\nfrom torch.utils.data import DataLoader\nimport gc\n# from pytorchtools import EarlyStopping\nimport glob\nfrom tqdm.notebook import tqdm\n\nBATCH_SIZE = 8\nSIZE = 512\nRESIZE = 256\nEPOCHS = 5","metadata":{"execution":{"iopub.status.busy":"2022-04-14T15:55:21.669786Z","iopub.execute_input":"2022-04-14T15:55:21.670038Z","iopub.status.idle":"2022-04-14T15:55:24.687518Z","shell.execute_reply.started":"2022-04-14T15:55:21.669969Z","shell.execute_reply":"2022-04-14T15:55:24.686684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preparing Data","metadata":{}},{"cell_type":"code","source":"class TrainDataset(data.Dataset):\n    def __init__(self, train_df, input_size, transform=None):\n        super().__init__()\n        \n        self.train_df = train_df\n        self.input_size = input_size\n        image_path = train_df['directory']\n        self.len = len(image_path)\n        self.transform = transform\n    \n    def __len__(self):\n        return self.len\n    \n    def __getitem__(self, index):\n        image_path = (train_df['directory']).to_list()[index]\n        \n        image = Image.open(image_path)\n        image = image.resize(self.input_size)\n        image = np.array(image).astype(np.float32)\n\n        if self.transform:\n            transformed = self.transform(image=image)\n            image = transformed['image']\n        \n        category = self.train_df['category'].to_list()[index]\n\n        return image, category","metadata":{"execution":{"iopub.status.busy":"2022-04-14T15:55:24.689071Z","iopub.execute_input":"2022-04-14T15:55:24.689326Z","iopub.status.idle":"2022-04-14T15:55:24.697868Z","shell.execute_reply.started":"2022-04-14T15:55:24.689263Z","shell.execute_reply":"2022-04-14T15:55:24.697194Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TestDataset(data.Dataset):\n    def __init__(self, test_df, input_size):\n        super().__init__()\n        \n        self.test_df = test_df\n        self.input_size = input_size\n        image_path = test_df['directory']\n        self.len = len(image_path)\n    \n    def __len__(self):\n        return self.len\n    \n    def __getitem__(self, index):\n        image_path = (self.test_df['directory']).to_list()[index]\n        \n        image = Image.open(image_path)\n        image = image.resize(self.input_size)\n        image = np.array(image).astype(np.float32)\n        \n\n        return image\n","metadata":{"execution":{"iopub.status.busy":"2022-04-14T15:55:24.699084Z","iopub.execute_input":"2022-04-14T15:55:24.699498Z","iopub.status.idle":"2022-04-14T15:55:24.708703Z","shell.execute_reply.started":"2022-04-14T15:55:24.699453Z","shell.execute_reply":"2022-04-14T15:55:24.708073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(\"../input/herbarium-2022-pandas/train.csv\")\nle  = LabelEncoder()\ntrain_df['category'] = le.fit_transform(train_df['category'])\ntrain_df['category'].max()","metadata":{"execution":{"iopub.status.busy":"2022-04-14T15:55:24.711126Z","iopub.execute_input":"2022-04-14T15:55:24.711606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(train_df['category'].unique()))\nout_dim = len(train_df['category'].unique())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transformer = albumentations.Compose(\n        [\n            albumentations.RandomCrop(width=RESIZE, height=RESIZE),\n            albumentations.RandomRotate90(p=0.5),\n            albumentations.HorizontalFlip(p=0.5),\n            albumentations.VerticalFlip(p=0.5),\n            albumentations.RandomBrightnessContrast(p=0.2),\n            albumentations.GaussianBlur(p=0.5),\n            albumentations.GaussNoise(p=0.5),\n            ToTensorV2()\n        ]\n    )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_dataset = TrainDataset(train_df, (SIZE, SIZE), transformer)\nlen(image_dataset)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(image_dataset))\nprint(int(len(image_dataset)*0.7), int(len(image_dataset)*0.3))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset, valid_dataset = torch.utils.data.random_split(\n    image_dataset, \n    [int(len(image_dataset)*0.8), int(len(image_dataset)*0.2)+1]\n)\n\nprint(len(train_dataset), len(valid_dataset))\ndel image_dataset\ngc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataloader = DataLoader(\n    train_dataset, \n    batch_size=BATCH_SIZE, \n    shuffle=True,\n    num_workers=0, \n    drop_last=True,\n    pin_memory=True\n)\n\nvalid_dataloader = DataLoader(\n    train_dataset, \n    batch_size=BATCH_SIZE, \n    shuffle=True,\n    num_workers=0, \n    drop_last=True,\n    pin_memory=True\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = models.resnet18(pretrained=False)\nmodel.fc = nn.Linear(in_features=512, out_features=out_dim, bias=True)\n\nprint(model)\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nmodel = model.to(DEVICE)\nprint(DEVICE)\noptimizer = optim.Adam(model.parameters())\ncriterion = nn.CrossEntropyLoss()\n\ntorch.backends.cudnn.benchmark = True\ntrn_loss = []\nval_loss = []","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for epoch in tqdm(range(EPOCHS)):\n        # 学習\n        model.train()\n        train_loss = 0\n        n_train = 0\n        acc_train = 0\n        for batch, category in tqdm(train_dataloader):\n            n_train += category.size()[0]\n            for param in model.parameters():\n                param.grad = None\n\n            batch = batch.float()\n\n            batch = batch.to(DEVICE)\n            cat_t = torch.eye(out_dim)[category]\n            category = category.to(DEVICE)\n            cat_t = cat_t.to(DEVICE)\n\n            preds = model(batch)\n            loss = -(cat_t*torch.log_softmax(preds, dim=-1)).sum(axis=1).mean()\n            # loss = criterion(preds, category)\n            loss.backward()\n            optimizer.step()\n\n            preds = preds.argmax(1)\n            acc_train += (preds==category).float().sum().item()\n            losses_train.append(loss.tolist())\n\n        # Validation\n        model.eval()\n        n_val = 0\n        acc_val = 0\n        with torch.inference_mode():\n            for batch, category in tqdm(valid_dataloader):\n                n_val += category.size()[0]\n                batch = batch.float()\n\n                batch = batch.to(DEVICE)\n                cat_t = torch.eye(out_dim)[category]\n                category = category.to(DEVICE)\n                cat_t = cat_t.to(DEVICE)\n\n                preds = model(batch)\n                loss = -(cat_t*torch.log_softmax(preds, dim=-1)).sum(axis=1).mean()\n                losses_valid.append(loss.tolist())\n\n        # if (epoch + 1) % 10 == 0:\n        print('EPOCH: {}, Train [Loss: {:.3f}, Accuracy: {:.3f}], Valid [Loss: {:.3f}, Accuracy: {:.3f}]'.format(\n        epoch + 1,\n        np.mean(train_loss),\n        acc_train/n_train,\n        np.mean(losses_valid),\n        acc_val/n_val\n    ))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.read_csv(\"../input/herbarium-2022-pandas/test.csv\")\ntest_dataset = TrainDataset(test_df, (SIZE, SIZE))\n\ntest_dataloader = DataLoader(\n        test_dataset,\n        batch_size=BATCH_SIZE,\n        shuffle=True,\n        num_workers=0,\n        pin_memory=True\n    )\ndel test_dataset\ngc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\npreds_list = []","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with torch.inference_mode():\n    for image in tqdm(test_dataloader):\n\n        for param in model.parameters():\n            param.grad = None\n\n        image = image.float()\n        image = image.to(DEVICE)\n\n        preds = model(image)\n        preds = preds.to('cpu')\n\n        preds_list = preds_list + preds.argmax(dim=1).tolist()\ndel model, test_dataloader\ngc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds_list = le.inverse_transform(preds_list)\n\nprint(preds_list)\nsub = pd.read_csv(\"../input/herbarium-2022-fgvc9/sample_submission.csv\", names=['ID', 'Predicted'])\nsub.loc[:, 'Predicted'] = preds_list\nsub.to_csv(\"./submission.csv\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}