{"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 numpy as np\nimport pandas as pd","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-05-25T21:40:48.966124Z","iopub.execute_input":"2021-05-25T21:40:48.966548Z","iopub.status.idle":"2021-05-25T21:40:48.971258Z","shell.execute_reply.started":"2021-05-25T21:40:48.966499Z","shell.execute_reply":"2021-05-25T21:40:48.970307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install detectron2 -f \\\n  https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.7/index.html","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:27:20.154260Z","iopub.execute_input":"2021-05-25T21:27:20.154610Z","iopub.status.idle":"2021-05-25T21:27:43.133222Z","shell.execute_reply.started":"2021-05-25T21:27:20.154532Z","shell.execute_reply":"2021-05-25T21:27:43.132363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import detectron2\nfrom detectron2.utils.logger import setup_logger\nsetup_logger()\n\nimport numpy as np\nimport cv2\nimport random\n\nfrom detectron2 import model_zoo\nfrom detectron2.engine import DefaultPredictor\nfrom detectron2.config import get_cfg\nfrom detectron2.utils.visualizer import Visualizer\nfrom detectron2.data import MetadataCatalog","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:28:43.369169Z","iopub.execute_input":"2021-05-25T21:28:43.369482Z","iopub.status.idle":"2021-05-25T21:28:45.309670Z","shell.execute_reply.started":"2021-05-25T21:28:43.369454Z","shell.execute_reply":"2021-05-25T21:28:45.308735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from PIL import Image\nimport cv2\nimport os\nimport torch\nimport math\n\ndef get_predictor():\n\n\n    cfg = get_cfg()\n    cfg.merge_from_file(model_zoo.get_config_file(\"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml\"))\n    cfg.DATASETS.TRAIN = ()\n    cfg.DATALOADER.NUM_WORKERS = 16\n\n    cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = (8)  # faster, and good enough for this toy dataset\n    cfg.MODEL.ROI_HEADS.NUM_CLASSES = 2  # 3 classes (data, fig, hazelnut)\n\n    os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)\n    \n    cfg.MODEL.WEIGHTS = \"../input/image-segmentation-using-detectron2/model.pth\"\n    cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7   # set the testing threshold for this model\n    predictor = DefaultPredictor(cfg)\n    return predictor\n\ndef get_cropped_leaf(img,predictor):\n    \n    #get prediction\n    outputs = predictor(img)\n    \n    #get boxes and masks\n    ins = outputs[\"instances\"]\n    pred_masks = ins.get_fields()[\"pred_masks\"]\n    boxes = ins.get_fields()[\"pred_boxes\"]    \n    \n    #get main leaf mask if the area is >= the mean area of boxes and is closes to the centre \n    \n    masker = pred_masks[np.argmin([calculateDistance(x[0], x[1], int(img.shape[1]/2), int(img.shape[0]/2)) for i,x in enumerate(boxes.get_centers()) if (boxes[i].area()>=torch.mean(boxes.area()).to(\"cpu\")).item()])].to(\"cpu\").numpy().astype(np.uint8)\n\n    #mask image\n    mask_out = cv2.bitwise_and(img, img, mask=masker)\n    \n    #find contours and boxes\n    contours, hierarchy = cv2.findContours(masker.copy() ,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\n    contour = contours[np.argmax([cv2.contourArea(x) for x in contours])]\n    rotrect = cv2.minAreaRect(contour)\n    box = cv2.boxPoints(rotrect)\n    box = np.int0(box)\n    \n\n    #crop image\n    resized = get_cropped(rotrect,box,mask_out)\n    \n    return resized\n\n#function to crop the image to boxand rotate\n\ndef get_cropped(rotrect,box,image):\n    \n    width = int(rotrect[1][0])\n    height = int(rotrect[1][1])\n\n    src_pts = box.astype(\"float32\")\n    # corrdinate of the points in box points after the rectangle has been\n    # straightened\n    dst_pts = np.array([[0, height-1],\n                        [0, 0],\n                        [width-1, 0],\n                        [width-1, height-1]], dtype=\"float32\")\n\n    # the perspective transformation matrix\n    M = cv2.getPerspectiveTransform(src_pts, dst_pts)\n\n    # directly warp the rotated rectangle to get the straightened rectangle\n    warped = cv2.warpPerspective(image, M, (width, height))\n    return warped\n\ndef calculateDistance(x1,y1,x2,y2):  \n    dist = math.hypot(x2 - x1, y2 - y1)\n    return dist  ","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:48:23.253088Z","iopub.execute_input":"2021-05-25T21:48:23.253464Z","iopub.status.idle":"2021-05-25T21:48:23.268072Z","shell.execute_reply.started":"2021-05-25T21:48:23.253434Z","shell.execute_reply":"2021-05-25T21:48:23.267216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictor = get_predictor()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:43:12.949472Z","iopub.execute_input":"2021-05-25T21:43:12.949895Z","iopub.status.idle":"2021-05-25T21:43:12.956246Z","shell.execute_reply.started":"2021-05-25T21:43:12.949855Z","shell.execute_reply":"2021-05-25T21:43:12.955130Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = get_cropped_leaf(plt.imread(\"../input/plant2021-downscaled-images-dataset/831436bf0e15e5e9.jpg\"),predictor)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:48:37.981426Z","iopub.execute_input":"2021-05-25T21:48:37.981732Z","iopub.status.idle":"2021-05-25T21:48:38.094419Z","shell.execute_reply.started":"2021-05-25T21:48:37.981704Z","shell.execute_reply":"2021-05-25T21:48:38.093434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:48:38.605294Z","iopub.execute_input":"2021-05-25T21:48:38.605608Z","iopub.status.idle":"2021-05-25T21:48:38.613316Z","shell.execute_reply.started":"2021-05-25T21:48:38.605579Z","shell.execute_reply":"2021-05-25T21:48:38.612496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(img)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:48:57.136984Z","iopub.execute_input":"2021-05-25T21:48:57.137299Z","iopub.status.idle":"2021-05-25T21:48:57.331739Z","shell.execute_reply.started":"2021-05-25T21:48:57.137269Z","shell.execute_reply":"2021-05-25T21:48:57.328204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv('../input/plant-pathology-2021-fgvc8/train.csv').sample(frac=1, random_state=666)\ntrain_df['path'] =  train_df['image'].apply(lambda x: '../input/plant2021-downscaled-images-dataset/' + x)\ntrain_df.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:40:57.420293Z","iopub.execute_input":"2021-05-25T21:40:57.420606Z","iopub.status.idle":"2021-05-25T21:40:57.479926Z","shell.execute_reply.started":"2021-05-25T21:40:57.420576Z","shell.execute_reply":"2021-05-25T21:40:57.478865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#train_df.drop_duplicates(['image']).shape","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:40:58.982626Z","iopub.execute_input":"2021-05-25T21:40:58.982975Z","iopub.status.idle":"2021-05-25T21:40:58.986610Z","shell.execute_reply.started":"2021-05-25T21:40:58.982946Z","shell.execute_reply":"2021-05-25T21:40:58.985619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['label_id'] = train_df['labels'].str.replace('scab', '1').str.replace('rust', '2') \\\n    .str.replace('healthy', '0').str.replace('frog_eye_leaf_spot', '3') \\\n    .str.replace('complex', '4').str.replace('powdery_mildew', '5').str.split(\" \")","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:40:59.344829Z","iopub.execute_input":"2021-05-25T21:40:59.345119Z","iopub.status.idle":"2021-05-25T21:40:59.442090Z","shell.execute_reply.started":"2021-05-25T21:40:59.345092Z","shell.execute_reply":"2021-05-25T21:40:59.441377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['label_id'] = [[int(j) for j in i] for i in train_df['label_id'].values]","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:40:59.588040Z","iopub.execute_input":"2021-05-25T21:40:59.588299Z","iopub.status.idle":"2021-05-25T21:40:59.719384Z","shell.execute_reply.started":"2021-05-25T21:40:59.588275Z","shell.execute_reply":"2021-05-25T21:40:59.718184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from random import sample","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:41:01.029246Z","iopub.execute_input":"2021-05-25T21:41:01.029560Z","iopub.status.idle":"2021-05-25T21:41:01.034488Z","shell.execute_reply.started":"2021-05-25T21:41:01.029530Z","shell.execute_reply":"2021-05-25T21:41:01.033186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df = train_df.iloc[17000:, :]\ntrain_df = train_df.iloc[:17000, :]#.sample(200000, replace=True).groupby('labels').head(4500)#.shape","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:41:01.265827Z","iopub.execute_input":"2021-05-25T21:41:01.266107Z","iopub.status.idle":"2021-05-25T21:41:01.270429Z","shell.execute_reply.started":"2021-05-25T21:41:01.266080Z","shell.execute_reply":"2021-05-25T21:41:01.269573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#from sklearn.preprocessing import LabelEncoder\n\n#label = LabelEncoder()\n#label.fit(train_df['labels'])\n#train_df['label_id'] = label.transform(train_df['labels'])\n#label_dic = dict(sorted(train_df[['label_id', 'labels']].values.tolist())) #save for submission\nlabel_dic = {\n    0: 'healthy', \n    1: 'scab',\n    2: 'rust',\n    3: 'frog_eye_leaf_spot',\n    4: 'complex', \n    5: 'powdery_mildew'\n}\nprint(label_dic)\nclasses = 6#len(train_df['labels'].value_counts()) #12\n\ndel train_df['labels'] \n\nimage_labels = np.array(train_df['label_id'].values)\nimage_list = np.array(train_df['path'].values)\n\nimage_labels_v = np.array(valid_df['label_id'].values)\nimage_list_v = np.array(valid_df['path'].values)\n\nprint(image_list.shape) #18632","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:41:01.982351Z","iopub.execute_input":"2021-05-25T21:41:01.982673Z","iopub.status.idle":"2021-05-25T21:41:01.995173Z","shell.execute_reply.started":"2021-05-25T21:41:01.982644Z","shell.execute_reply":"2021-05-25T21:41:01.994380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classes","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:41:03.129173Z","iopub.execute_input":"2021-05-25T21:41:03.129488Z","iopub.status.idle":"2021-05-25T21:41:03.134385Z","shell.execute_reply.started":"2021-05-25T21:41:03.129460Z","shell.execute_reply":"2021-05-25T21:41:03.133459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"[5193 / sum([j in i for i in list(image_labels)]) for j in range(6)]","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:41:03.745431Z","iopub.execute_input":"2021-05-25T21:41:03.745736Z","iopub.status.idle":"2021-05-25T21:41:03.762985Z","shell.execute_reply.started":"2021-05-25T21:41:03.745707Z","shell.execute_reply":"2021-05-25T21:41:03.761919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cls_weight = [1.24, 1.0001, 2.72, 1.31, 2.61, 4.4]\ncls_weight","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:41:04.419430Z","iopub.execute_input":"2021-05-25T21:41:04.419769Z","iopub.status.idle":"2021-05-25T21:41:04.425556Z","shell.execute_reply.started":"2021-05-25T21:41:04.419725Z","shell.execute_reply":"2021-05-25T21:41:04.424507Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!apt install ../input/pyturbojpeg/libturbojpeg_1.4.2-0ubuntu3.4_amd64.deb\n!pip install ../input/pyturbojpeg/PyTurboJPEG-1.4.1","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:41:06.365357Z","iopub.execute_input":"2021-05-25T21:41:06.365704Z","iopub.status.idle":"2021-05-25T21:41:17.461912Z","shell.execute_reply.started":"2021-05-25T21:41:06.365673Z","shell.execute_reply":"2021-05-25T21:41:17.461102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport albumentations as A\nimport cv2, torch\nimport torchvision.transforms as transforms\nfrom tqdm.notebook import tqdm\nfrom torch.utils.data import Dataset, DataLoader\nfrom turbojpeg import TurboJPEG\n\ndevice = torch.device('cuda' if torch.cuda.is_available else 'cpu')\n\n#######################################\n\nfrom albumentations.pytorch import ToTensor\n\ndef get_training_augmentation():\n    \n    augmentation_pipeline = A.Compose(\n        [\n            A.OneOf([\n                A.Compose([\n                    A.SmallestMaxSize(224),\n                    A.RandomCrop(224, 224),\n                ], p=1),\n                A.Compose([\n                    A.SmallestMaxSize(400),\n                    A.RandomCrop(224, 224),\n                ], p=1)\n            ], p=1),\n            \n            A.OneOf(\n                [\n                    A.RandomGamma(), \n                    A.RandomBrightness(), \n                    A.RandomContrast(), \n                    A.Blur(blur_limit=10),\n                    A.GaussNoise()\n                ],\n                p = 0.3\n            ),\n            A.OneOf(\n                [\n                    A.Rotate(limit = 360), \n                    A.Flip(p = 0.5),\n                ],\n                p = 0.3\n            ),\n            A.Normalize(\n                mean=[0.485, 0.456, 0.406],\n                std=[0.229, 0.224, 0.225]\n                ),\n            ToTensor() \n        ],\n        p = 1\n    )\n    return lambda img:augmentation_pipeline(image=np.array(img))['image']\n\n\n\ndef transform_valid():\n    \n    augmentation_pipeline = A.Compose(\n        [\n            A.SmallestMaxSize(224),\n            A.RandomCrop(224, 224),\n            A.Normalize(\n                mean=[0.485, 0.456, 0.406],\n                std=[0.229, 0.224, 0.225]\n                ),\n            ToTensor() \n        ],\n        p = 1\n    )\n    return lambda img:augmentation_pipeline(image=np.array(img))['image']\n\n######################################\n\njpeg_reader = TurboJPEG()\n\ndef read_img(img):\n    with open(img, \"rb\") as f:\n        return jpeg_reader.decode(f.read(), 0) \n    \n\nclass dataset(Dataset) :\n    def __init__(self, image_list, image_labels, transform, device) :\n        self.image_list = image_list\n        self.image_labels = image_labels\n        self.transform = transform\n    \n    def __len__(self) :\n        return len(self.image_list)\n    \n    def __getitem__(self, index) :\n        x = read_img(self.image_list[index])\n        try:\n            x = get_cropped_leaf(x, predictor)\n        except:\n            x = read_img(self.image_list[index])\n        x = self.transform(x).to(device)\n        \n        y = self.image_labels[index]\n        y = torch.nn.functional.one_hot(torch.tensor(y), 6).sum(0).to(device)\n        \n        return x, y\n\n\ntrain_data = dataset(image_list, image_labels, get_training_augmentation(), device)\n\nprint(len(train_data))\n\ntrain_data = DataLoader(train_data, batch_size = 32, shuffle = True)\n\n##########\n# validation loader\nvalid_data = dataset(image_list_v, image_labels_v, transform_valid(), device)\nprint(len(valid_data))\nvalid_data = DataLoader(valid_data, batch_size = 32, shuffle = True)\n########","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:56:59.597862Z","iopub.execute_input":"2021-05-25T21:56:59.598187Z","iopub.status.idle":"2021-05-25T21:56:59.657766Z","shell.execute_reply.started":"2021-05-25T21:56:59.598158Z","shell.execute_reply":"2021-05-25T21:56:59.656720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.nn.functional.one_hot(torch.tensor([1,5]),6).sum(0).view(1,6)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:49:45.589562Z","iopub.execute_input":"2021-05-25T21:49:45.589904Z","iopub.status.idle":"2021-05-25T21:49:45.597125Z","shell.execute_reply.started":"2021-05-25T21:49:45.589871Z","shell.execute_reply":"2021-05-25T21:49:45.595957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#next(iter(train_data))","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:49:46.122272Z","iopub.execute_input":"2021-05-25T21:49:46.122613Z","iopub.status.idle":"2021-05-25T21:49:46.126797Z","shell.execute_reply.started":"2021-05-25T21:49:46.122581Z","shell.execute_reply":"2021-05-25T21:49:46.125602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataloaders = {\n    'train': train_data , \n    'val': valid_data\n}\n\ndataset_sizes = {\n    'train': 17000, \n    'val': 1632\n}","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:03.509150Z","iopub.execute_input":"2021-05-25T21:57:03.509477Z","iopub.status.idle":"2021-05-25T21:57:03.514165Z","shell.execute_reply.started":"2021-05-25T21:57:03.509446Z","shell.execute_reply":"2021-05-25T21:57:03.513036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def gallery(array, ncols=3):\n    nindex, height, width, intensity = array.shape\n    nrows = nindex//ncols\n    assert nindex == nrows*ncols\n    result = (array.reshape(nrows, ncols, height, width, intensity)\n              .swapaxes(1,2)\n              .reshape(height*nrows, width*ncols, intensity))\n    return result","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:49:48.654266Z","iopub.execute_input":"2021-05-25T21:49:48.654574Z","iopub.status.idle":"2021-05-25T21:49:48.661684Z","shell.execute_reply.started":"2021-05-25T21:49:48.654545Z","shell.execute_reply":"2021-05-25T21:49:48.660982Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#get_training_augmentation()(image).numpy().reshape(1,3,224,224).shape","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:49:51.869367Z","iopub.execute_input":"2021-05-25T21:49:51.869713Z","iopub.status.idle":"2021-05-25T21:49:51.873371Z","shell.execute_reply.started":"2021-05-25T21:49:51.869685Z","shell.execute_reply":"2021-05-25T21:49:51.872453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image = read_img('../input/plant2021-downscaled-images-dataset/800edef467d27c15.jpg')\n\nimages_aug = np.array([(get_training_augmentation()(image)).permute((1,2,0)).numpy() for _ in range(25)])\n\nplt.figure(figsize=(10,10))\nplt.axis('off')\nplt.imshow(gallery(images_aug, ncols = 5))\nplt.title('Augmentation pipeline examples')","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:49:52.505534Z","iopub.execute_input":"2021-05-25T21:49:52.505859Z","iopub.status.idle":"2021-05-25T21:49:53.107796Z","shell.execute_reply.started":"2021-05-25T21:49:52.505830Z","shell.execute_reply":"2021-05-25T21:49:53.107003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(image)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:50:04.237694Z","iopub.execute_input":"2021-05-25T21:50:04.238075Z","iopub.status.idle":"2021-05-25T21:50:04.455470Z","shell.execute_reply.started":"2021-05-25T21:50:04.238038Z","shell.execute_reply":"2021-05-25T21:50:04.454587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\n\nsys.path.append(\"../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master\")\n\nfrom efficientnet_pytorch import model as enet","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:10.245863Z","iopub.execute_input":"2021-05-25T21:57:10.246190Z","iopub.status.idle":"2021-05-25T21:57:10.251956Z","shell.execute_reply.started":"2021-05-25T21:57:10.246161Z","shell.execute_reply":"2021-05-25T21:57:10.250930Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = enet.EfficientNet.from_name('efficientnet-b0')\n\nmodel.load_state_dict(torch.load('../input/efficientnet-pytorch/efficientnet-b0-08094119.pth'))","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:10.533667Z","iopub.execute_input":"2021-05-25T21:57:10.533959Z","iopub.status.idle":"2021-05-25T21:57:10.646884Z","shell.execute_reply.started":"2021-05-25T21:57:10.533933Z","shell.execute_reply":"2021-05-25T21:57:10.646027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#model\n\n\n#np.array([0.99, 0.9, 0.92, 0.2, 0.7, 0.6]).mean()","metadata":{"execution":{"iopub.status.busy":"2021-05-22T18:59:44.642095Z","iopub.execute_input":"2021-05-22T18:59:44.642403Z","iopub.status.idle":"2021-05-22T18:59:44.646187Z","shell.execute_reply.started":"2021-05-22T18:59:44.642373Z","shell.execute_reply":"2021-05-22T18:59:44.645209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\n\nclass FocalLoss(nn.Module):\n    \"\"\"\n    The focal loss for fighting against class-imbalance\n    \"\"\"\n    def __init__(self, alpha=1, gamma=2):\n        super(FocalLoss, self).__init__()\n        self.alpha = alpha\n        self.gamma = gamma\n        self.epsilon = 1e-12  # prevent training from Nan-loss error\n        self.cls_weights = torch.tensor([cls_weight],dtype=torch.float, requires_grad=False, device=device)\n\n    def forward(self, logits, target):\n        \"\"\"\n        logits & target should be tensors with shape [batch_size, num_classes]\n        \"\"\"\n        probs = torch.sigmoid(logits)\n        one_subtract_probs = 1.0 - probs\n        # add epsilon\n        probs_new = probs + self.epsilon\n        one_subtract_probs_new = one_subtract_probs + self.epsilon\n        # calculate focal loss\n        log_pt = target * torch.log(probs_new) + (1.0 - target) * torch.log(one_subtract_probs_new)\n        pt = torch.exp(log_pt)\n        focal_loss = -1.0 * (self.alpha * (1 - pt) ** self.gamma) * log_pt\n        focal_loss = focal_loss * self.cls_weights\n        return torch.mean(focal_loss)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:13.513278Z","iopub.execute_input":"2021-05-25T21:57:13.513593Z","iopub.status.idle":"2021-05-25T21:57:13.523629Z","shell.execute_reply.started":"2021-05-25T21:57:13.513564Z","shell.execute_reply":"2021-05-25T21:57:13.522311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import f1_score","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:13.821065Z","iopub.execute_input":"2021-05-25T21:57:13.821348Z","iopub.status.idle":"2021-05-25T21:57:13.827452Z","shell.execute_reply.started":"2021-05-25T21:57:13.821322Z","shell.execute_reply":"2021-05-25T21:57:13.826494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model._fc.in_features","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:14.071102Z","iopub.execute_input":"2021-05-25T21:57:14.071396Z","iopub.status.idle":"2021-05-25T21:57:14.076457Z","shell.execute_reply.started":"2021-05-25T21:57:14.071370Z","shell.execute_reply":"2021-05-25T21:57:14.075597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model._fc = nn.Linear(in_features=model._fc.in_features, out_features=6).cuda()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:14.316398Z","iopub.execute_input":"2021-05-25T21:57:14.316675Z","iopub.status.idle":"2021-05-25T21:57:14.324595Z","shell.execute_reply.started":"2021-05-25T21:57:14.316648Z","shell.execute_reply":"2021-05-25T21:57:14.323763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(list(model.parameters()))","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:14.968071Z","iopub.execute_input":"2021-05-25T21:57:14.968391Z","iopub.status.idle":"2021-05-25T21:57:14.979308Z","shell.execute_reply.started":"2021-05-25T21:57:14.968362Z","shell.execute_reply":"2021-05-25T21:57:14.978603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nfrom torch.optim import Adam\nfrom torch.optim import lr_scheduler\n\n#model._fc.out_features = classes #change the last FC layer\n\nmodel = model.to(device)\ncriterion = FocalLoss().to(device) #nn.CrossEntropyLoss().to(device) nn.BCEWithLogitsLoss().to(device)#\noptimizer = torch.optim.Adam(model.parameters(), lr = 0.0001) # lr, SGD\n\nexp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:15.315354Z","iopub.execute_input":"2021-05-25T21:57:15.315685Z","iopub.status.idle":"2021-05-25T21:57:15.348184Z","shell.execute_reply.started":"2021-05-25T21:57:15.315656Z","shell.execute_reply":"2021-05-25T21:57:15.347495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset_sizes","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:15.825404Z","iopub.execute_input":"2021-05-25T21:57:15.825709Z","iopub.status.idle":"2021-05-25T21:57:15.830997Z","shell.execute_reply.started":"2021-05-25T21:57:15.825681Z","shell.execute_reply":"2021-05-25T21:57:15.829998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion((model(next(iter(train_data))[0])), next(iter(train_data))[1].float())","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:16.294282Z","iopub.execute_input":"2021-05-25T21:57:16.294629Z","iopub.status.idle":"2021-05-25T21:57:23.145874Z","shell.execute_reply.started":"2021-05-25T21:57:16.294597Z","shell.execute_reply":"2021-05-25T21:57:23.145135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def to_lab(preds):\n    return ((preds > 0) + torch.nn.functional.one_hot(preds.argmax(1), 6) != 0).long()\n\na, b = next(iter(train_data))\n\npreds = to_lab(model(a))\n((preds == b).sum(1)==6).sum(), f1_score(preds.cpu(), b.cpu(), average='macro', zero_division=True)#/72\n#preds\n#(preds == next(iter(train_data))[1]).sum()/72,torch.sum((preds == next(iter(train_data))[1]).float().mean()*6)/12\n#","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:25.515744Z","iopub.execute_input":"2021-05-25T21:57:25.516116Z","iopub.status.idle":"2021-05-25T21:57:28.840876Z","shell.execute_reply.started":"2021-05-25T21:57:25.516087Z","shell.execute_reply":"2021-05-25T21:57:28.840126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(preds+torch.nn.functional.one_hot(model(a).argmax(1), 6) != 0).long()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:31.683187Z","iopub.execute_input":"2021-05-25T21:57:31.683504Z","iopub.status.idle":"2021-05-25T21:57:31.734469Z","shell.execute_reply.started":"2021-05-25T21:57:31.683473Z","shell.execute_reply":"2021-05-25T21:57:31.733635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(model(a) > 0).sum(1)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:33.828491Z","iopub.execute_input":"2021-05-25T21:57:33.828824Z","iopub.status.idle":"2021-05-25T21:57:33.874714Z","shell.execute_reply.started":"2021-05-25T21:57:33.828793Z","shell.execute_reply":"2021-05-25T21:57:33.873866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(preds*b).sum(dim=0)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:35.393426Z","iopub.execute_input":"2021-05-25T21:57:35.393747Z","iopub.status.idle":"2021-05-25T21:57:35.400372Z","shell.execute_reply.started":"2021-05-25T21:57:35.393715Z","shell.execute_reply":"2021-05-25T21:57:35.399453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import time\nimport copy\n\ndef train_model(model, criterion, optimizer, scheduler, num_epochs=25):\n    since = time.time()\n\n    best_model_wts = copy.deepcopy(model.state_dict())\n    best_acc = 0.0\n\n    for epoch in range(num_epochs):\n        print('Epoch {}/{}'.format(epoch, num_epochs - 1))\n        print('-' * 10)\n\n        # Each epoch has a training and validation phase\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                optimizer.step()\n                scheduler.step()\n                model.train()  # Set model to training mode\n            else:\n                model.eval()   # Set model to evaluate mode\n\n            running_loss = 0.0\n            running_corrects = 0\n            f1l = 0\n\n            # Iterate over data.\n            for inputs, labels in tqdm(dataloaders[phase]):\n                inputs = inputs.to(device)\n                labels = labels.to(device) #\n                #print(labels)\n                # zero the parameter gradients\n                optimizer.zero_grad()\n\n                # forward\n                # track history if only in train\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = model(inputs)\n                    #outputs = torch.nn.Sigmoid()(outputs)\n                    #_, preds = torch.max(outputs, 1)\n                    preds = to_lab(outputs)\n                    loss = criterion(outputs, labels.float())\n\n                    # backward + optimize only if in training phase\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n                        \n                #torch.cuda.empty_cache()\n\n                # statistics\n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += ((preds == labels.data).sum(1)==6).sum()\n                f1l += f1_score(preds.cpu().numpy(), labels.cpu().numpy(), average='macro', zero_division=True) * inputs.size(0)\n\n            epoch_loss = running_loss / dataset_sizes[phase]\n            epoch_acc = running_corrects.double() / dataset_sizes[phase]\n            epoch_f1 = f1l / dataset_sizes[phase]\n\n            print('{} Loss: {:.4f} Acc: {:.4f} F1: {:.4f}'.format(phase, epoch_loss, epoch_acc, epoch_f1))\n\n            # deep copy the model\n            if phase == 'val' and epoch_acc > best_acc:\n                best_acc = epoch_acc\n                best_model_wts = copy.deepcopy(model.state_dict())\n                torch.save(model.state_dict(), 'best_model.pth')\n\n        print()\n\n    time_elapsed = time.time() - since\n    print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))\n    print('Best val Acc: {:4f}'.format(best_acc))\n\n    # load best model weights\n    model.load_state_dict(best_model_wts)\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:36.233172Z","iopub.execute_input":"2021-05-25T21:57:36.233479Z","iopub.status.idle":"2021-05-25T21:57:36.246341Z","shell.execute_reply.started":"2021-05-25T21:57:36.233450Z","shell.execute_reply":"2021-05-25T21:57:36.245461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = train_model(model, criterion, optimizer, exp_lr_scheduler, num_epochs=6)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T21:57:37.268746Z","iopub.execute_input":"2021-05-25T21:57:37.269087Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#nn.functional.one_hot(torch.tensor([]), 6)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T15:06:48.957866Z","iopub.execute_input":"2021-05-22T15:06:48.958172Z","iopub.status.idle":"2021-05-22T15:06:48.963916Z","shell.execute_reply.started":"2021-05-22T15:06:48.958145Z","shell.execute_reply":"2021-05-22T15:06:48.963152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from glob import glob\n\nvalid_image_list = glob('../input/plant-pathology-2021-fgvc8/test_images/*.jpg')\n\nmodel.eval()\npredict_list = []\nimage_name_list = []\nfor i, image in tqdm(enumerate(valid_image_list)) :\n    image_name = image[48:]\n    \n    img = read_img(image)\n    img = transform_valid()(img)\n    \n    result_list = torch.FloatTensor(np.zeros((classes))).to(device)\n    img = img.to(device)\n    img = img.reshape(-1, 3, 224, 224)\n    with torch.set_grad_enabled(False):\n        predict = model(img)\n    predict_list.append(list(to_lab(predict).reshape(-1).nonzero().reshape(-1).cpu().numpy()))\n    #predict_list.append(result_list)\n    image_name_list.append(image_name)\n    \n#predict_list = np.array(predict_list)\nimage_name_list = np.array(image_name_list)\nprint(image_name_list)\n\nsubmission_df = pd.DataFrame()\nsubmission_df['image'] = image_name_list\nsubmission_df['label_id'] = predict_list\nsubmission_df['labels'] = submission_df['label_id'].apply(lambda x: \" \".join([label_dic[i] for i in x]))\ndel submission_df['label_id']\nsubmission_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-22T17:55:33.787794Z","iopub.execute_input":"2021-05-22T17:55:33.788303Z","iopub.status.idle":"2021-05-22T17:55:34.320465Z","shell.execute_reply.started":"2021-05-22T17:55:33.788256Z","shell.execute_reply":"2021-05-22T17:55:34.318932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df.to_csv(\"submission.csv\", index = False)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T17:55:37.234858Z","iopub.execute_input":"2021-05-22T17:55:37.235219Z","iopub.status.idle":"2021-05-22T17:55:37.573962Z","shell.execute_reply.started":"2021-05-22T17:55:37.235179Z","shell.execute_reply":"2021-05-22T17:55:37.573071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}