{"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":"import os\nimport math\nimport time\nimport random\nimport shutil\nfrom pathlib import Path\nfrom contextlib import contextmanager\nfrom collections import defaultdict, Counter\n\nimport scipy as sp\nimport numpy as np\nimport pandas as pd\n\nfrom sklearn import preprocessing\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.model_selection import StratifiedKFold\n\nfrom tqdm.auto import tqdm\nfrom functools import partial\n\nimport cv2\nfrom PIL import Image\n\nimport matplotlib\nimport matplotlib.pyplot as plt\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.optim import Adam, SGD\nimport torchvision.models as models\nfrom torch.nn.parameter import Parameter\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.optim.lr_scheduler import CosineAnnealingWarmRestarts, CosineAnnealingLR, ReduceLROnPlateau\n\nfrom albumentations import (\n    Compose, OneOf, Normalize, Resize, RandomResizedCrop, RandomCrop, HorizontalFlip, VerticalFlip, \n    RandomBrightness, RandomContrast, RandomBrightnessContrast, Rotate, ShiftScaleRotate, Cutout, \n    IAAAdditiveGaussianNoise, Transpose\n    )\nfrom albumentations.pytorch import ToTensorV2\nfrom albumentations import ImageOnlyTransform\n\nimport warnings \nwarnings.filterwarnings('ignore')\n\ndevice = torch.device('cuda:'+str(0) if torch.cuda.is_available() else 'cpu')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-03-14T08:34:14.957008Z","iopub.execute_input":"2022-03-14T08:34:14.957487Z","iopub.status.idle":"2022-03-14T08:34:18.667680Z","shell.execute_reply.started":"2022-03-14T08:34:14.957372Z","shell.execute_reply":"2022-03-14T08:34:18.666883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_img_path = os.listdir('../input/cassava-leaf-disease-classification/train_images')\nprint(len(train_img_path))\ndata_path = '../input/cassava-leaf-disease-classification'","metadata":{"execution":{"iopub.status.busy":"2022-03-14T08:34:35.177549Z","iopub.execute_input":"2022-03-14T08:34:35.177826Z","iopub.status.idle":"2022-03-14T08:34:35.635667Z","shell.execute_reply.started":"2022-03-14T08:34:35.177796Z","shell.execute_reply":"2022-03-14T08:34:35.634769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = pd.read_csv(data_path+'/sample_submission.csv')\nlabel_map = pd.read_json(data_path+'/label_num_to_disease_map.json', orient='index')","metadata":{"execution":{"iopub.status.busy":"2022-03-14T08:36:13.798942Z","iopub.execute_input":"2022-03-14T08:36:13.799218Z","iopub.status.idle":"2022-03-14T08:36:13.819766Z","shell.execute_reply.started":"2022-03-14T08:36:13.799187Z","shell.execute_reply":"2022-03-14T08:36:13.818967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TestDataset(Dataset):\n    def __init__(self, df, transform=None):\n        self.df = df\n        self.file_names = df['image_id'].values\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        file_name = self.file_names[idx]\n        file_path = data_path+'/test_images/'+str(file_name)\n        image = cv2.imread(file_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        if self.transform:\n            augmented = self.transform(image=image)\n            image = augmented['image']\n        return image","metadata":{"execution":{"iopub.status.busy":"2022-03-14T08:36:27.147319Z","iopub.execute_input":"2022-03-14T08:36:27.147621Z","iopub.status.idle":"2022-03-14T08:36:27.176130Z","shell.execute_reply.started":"2022-03-14T08:36:27.147588Z","shell.execute_reply":"2022-03-14T08:36:27.166348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_transforms(*, data):\n    if data == 'test':\n        return Compose([\n            Resize(380, 380),\n            Normalize(\n                mean=[0.485, 0.456, 0.406],\n                std=[0.229, 0.224, 0.225],\n            ),\n            ToTensorV2(),\n        ])","metadata":{"execution":{"iopub.status.busy":"2022-03-14T08:39:45.330397Z","iopub.execute_input":"2022-03-14T08:39:45.330667Z","iopub.status.idle":"2022-03-14T08:39:45.336961Z","shell.execute_reply.started":"2022-03-14T08:39:45.330637Z","shell.execute_reply":"2022-03-14T08:39:45.336252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BottleNeck(nn.Module):\n    expansion = 2\n\n    def __init__(self, in_channel, channel, stride=1, C=32, downsample=None):\n        super().__init__()\n        self.conv1 = nn.Sequential(\n            nn.Conv2d(in_channel, channel, kernel_size=1, stride=stride, bias=False),\n            nn.BatchNorm2d(channel),\n            nn.ReLU(inplace=True)\n        )\n\n        self.conv2 = nn.Sequential(\n            nn.Conv2d(channel, channel, kernel_size=3, padding=1, bias=False, stride=1, groups=C),\n            nn.BatchNorm2d(channel),\n            nn.ReLU(inplace=True)\n        )\n\n        self.conv3 = nn.Sequential(\n            nn.Conv2d(channel, channel * self.expansion, kernel_size=1, stride=1, bias=False),\n            nn.BatchNorm2d(channel * self.expansion),\n            nn.ReLU(inplace=True)\n        )\n\n        self.downsample = downsample\n        self.stride = stride\n        self.relu = nn.ReLU(inplace=True)\n\n    def forward(self, x):\n        residual = x\n        x = self.conv1(x)\n        x = self.conv2(x)\n        x = self.conv3(x)\n\n        # out = self.relu(self.bn1(self.conv1(x)))  # bs,c,h,w\n        # out = self.relu(self.bn2(self.conv2(out)))  # bs,c,h,w\n        # out = self.relu(self.bn3(self.conv3(out)))  # bs,4c,h,w\n\n        if self.downsample is not None:\n            residual = self.downsample(residual)\n\n        x = x + residual\n        x = self.relu(x)\n        return x\n\n\nclass ResNeXt(nn.Module):\n    def __init__(self, block, layers, num_classes=1000):\n        super().__init__()\n        # 定义输入模块的维度\n        self.in_channel = 64\n        # stem layer\n        self.layer0 = nn.Sequential(\n            nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False),\n            nn.BatchNorm2d(64),\n            nn.ReLU(inplace=True),\n            nn.MaxPool2d(kernel_size=3, stride=2, padding=1, ceil_mode=False)\n        )\n\n        # main layer\n        self.layer1 = self._make_layer(block, 128, layers[0])\n        self.layer2 = self._make_layer(block, 256, layers[1], stride=2)\n        self.layer3 = self._make_layer(block, 512, layers[2], stride=2)\n        self.layer4 = self._make_layer(block, 1024, layers[3], stride=2)\n\n        # classifier\n        self.avgpool = nn.AdaptiveAvgPool2d(1)\n        self.classifier = nn.Linear(1024 * block.expansion, num_classes)\n        self.downsample = None\n\n    def forward(self, x):\n        # stem layer\n        x = self.layer0(x)\n\n        # layers:\n        x = self.layer1(x)  # bs,56,56,128*2\n        x = self.layer2(x)  # bs,28,28,256*2\n        x = self.layer3(x)  # bs,14,14,512*2\n        x = self.layer4(x)  # bs,7,7,1024*2\n\n        # classifier\n        x = self.avgpool(x)  # bs,1,1,1024*2\n        x = x.reshape(x.shape[0], -1)  # bs,1024*2\n        x = self.classifier(x)  # bs,1000\n\n        return x\n\n    def _make_layer(self, block, channel, blocks, stride=1):\n        # downsample 主要用来处理H(x)=F(x)+x中F(x)和x的channel维度不匹配问题，即对残差结构的输入进行升维，在做残差相加的时候，必须保证残差的纬度与真正的输出维度（宽、高、以及深度）相同\n        # 比如步长！=1 或者 in_channel!=channel&self.expansion\n        downsample = None\n        if stride != 1 or self.in_channel != channel * block.expansion:\n            self.downsample = nn.Conv2d(self.in_channel, channel * block.expansion, stride=stride, kernel_size=1,\n                                        bias=False)\n        # 第一个conv部分，可能需要downsample\n        layers = list()\n        layers.append(block(self.in_channel, channel, downsample=self.downsample, stride=stride))\n        self.in_channel = channel * block.expansion\n        for _ in range(1, blocks):\n            layers.append(block(self.in_channel, channel))\n        return nn.Sequential(*layers)\n    \n    \ndef ResNeXt50(num_classes=1000):\n    return ResNeXt(BottleNeck, [3, 4, 6, 3], num_classes=num_classes)","metadata":{"execution":{"iopub.status.busy":"2022-03-14T08:40:03.814077Z","iopub.execute_input":"2022-03-14T08:40:03.814385Z","iopub.status.idle":"2022-03-14T08:40:03.839788Z","shell.execute_reply.started":"2022-03-14T08:40:03.814355Z","shell.execute_reply":"2022-03-14T08:40:03.839010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"chectpoint = torch.load('../input/resnext/resnext_0.pth', map_location='cuda:0')\n\npred=[]\ntest = pd.read_csv(data_path+'/sample_submission.csv')\nmodel = ResNeXt50(5)\nmodel.load_state_dict(chectpoint['model'])\n\ntest_dataset = TestDataset(test, transform=get_transforms(data='test'))\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=2, pin_memory=True)\n\ndef preds(model, dataloader, device):\n    model.eval()\n    model.to(device)\n    pred_list = []\n    with torch.no_grad():\n        tqbm_batch_iter = tqdm(dataloader)\n        for image in tqbm_batch_iter:\n            image = image.to(device)\n            outputs = model(image)\n\n            pred_y = torch.max(outputs, dim=1)[1]\n            pred_list.extend(outputs.argmax(dim=1).tolist())\n    return pred_list\n\n# test_bar = tqdm(test_loader)\n# for test_data in test_bar:\n#     outputs = model(test_data.to(device))\n#     predict_y = torch.max(outputs, dim=1)[1]\n#     pred.append(int(predict_y))\n# for image_id in test.image_id:\n#     image = Image.open(os.path.join(\"../input/cassava-leaf-disease-classification\",  \"test_images\", image_id))\n#     image = image.resize((224,224))\n#     image = np.expand_dims(image, axis = 0)\n#     pred.append(torch.max(model(image.to(device), dim=1)[1]))\npred = preds(model, test_loader, device)\npred","metadata":{"execution":{"iopub.status.busy":"2022-03-14T08:40:33.659220Z","iopub.execute_input":"2022-03-14T08:40:33.659978Z","iopub.status.idle":"2022-03-14T08:40:46.390608Z","shell.execute_reply.started":"2022-03-14T08:40:33.659940Z","shell.execute_reply":"2022-03-14T08:40:46.389900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test['label'] = pred\ntest\ntest.to_csv('submission.csv', index = False)","metadata":{"execution":{"iopub.status.busy":"2022-03-14T08:41:03.261156Z","iopub.execute_input":"2022-03-14T08:41:03.261628Z","iopub.status.idle":"2022-03-14T08:41:03.270360Z","shell.execute_reply.started":"2022-03-14T08:41:03.261591Z","shell.execute_reply":"2022-03-14T08:41:03.269704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.head()","metadata":{"execution":{"iopub.status.busy":"2022-03-14T08:41:16.521399Z","iopub.execute_input":"2022-03-14T08:41:16.522188Z","iopub.status.idle":"2022-03-14T08:41:16.534796Z","shell.execute_reply.started":"2022-03-14T08:41:16.522128Z","shell.execute_reply":"2022-03-14T08:41:16.533937Z"},"trusted":true},"execution_count":null,"outputs":[]}]}