{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport os\nimport time\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport albumentations as alb\nfrom albumentations.pytorch.transforms import ToTensorV2\nimport torch\nfrom torch.utils.data import DataLoader,Dataset\nfrom torch.utils.data import SubsetRandomSampler\nimport torchvision \nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection.rpn import AnchorGenerator\nfrom torchvision.models.detection import FasterRCNN\nimport cv2\nfrom tqdm.notebook import tqdm\nimport torch.nn as nn\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train_path = '/kaggle/input/global-wheat-detection/train.csv'\ntrain_img_path = '/kaggle/input/global-wheat-detection/train'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train = pd.read_csv(train_path)\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train['image_id'] = train['image_id'].apply(lambda x: str(x) + '.jpg')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"bboxes = np.stack(train['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep = ',')))\nfor i, col in enumerate(['x_min', 'y_min', 'w', 'h']):\n    train[col] = bboxes[:,i]\n\ntrain.drop(columns = ['bbox'], inplace = True)\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train['bbox_area'] = train['w']*train['h']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"max_area = 100000\nmin_area = 40\ntrain_clean = train[(train['bbox_area'] < max_area) & (train['bbox_area'] > min_area)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_split = 0.8\n\nimage_ids = train_clean['image_id'].unique()\ntrain_ids = image_ids[0:int(train_split*len(image_ids))]\nval_ids = image_ids[int(train_split*len(image_ids)):]\n\nprint('Length of training ids', len(train_ids))\nprint('Length of validation ids', len(val_ids))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = train_clean[train_clean['image_id'].isin(train_ids)]\nvalid_df = train_clean[train_clean['image_id'].isin(val_ids)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class WheatDataset(Dataset):\n    def __init__(self, df, image_dir,transform = None):\n        super().__init__()\n        self.df = df\n        self.img_ids = df['image_id'].unique()\n        self.image_dir = image_dir\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.img_ids)\n    \n    def __getitem__(self, idx: int):\n        image_id = self.img_ids[idx]\n        pts = self.df[self.df['image_id'] == image_id]\n        \n        image = cv2.imread(os.path.join(self.image_dir, image_id), cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image = image/255.0\n        \n        boxes = pts[['x_min', 'y_min', 'w', 'h']].values\n        \n        boxes[:, 2] = boxes[:, 0] + boxes[:, 2]\n        boxes[:, 3] = boxes[:, 1] + boxes[:, 3]\n        \n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]) \n        area = torch.as_tensor(area, dtype = torch.float32)\n        \n        labels = torch.ones((pts.shape[0],), dtype=torch.int64)\n        \n        iscrowd = torch.zeros((pts.shape[0],), dtype=torch.int32)\n        \n        target = {}\n        target[\"boxes\"] = boxes\n        target[\"labels\"] = labels\n        target[\"image_id\"] = torch.tensor(idx)\n        target[\"area\"] = area\n        target[\"iscrowd\"] = iscrowd\n\n        if self.transform:\n            sample = {\n                'image': image,\n                'bboxes': target['boxes'],\n                'labels': target['labels']\n            }\n            sample = self.transform(**sample)\n            image = sample['image']\n            \n            if len(sample['bboxes']) > 0:\n                target['boxes'] = torch.as_tensor(sample['bboxes'], dtype=torch.float32)\n            else:\n                target['boxes'] = torch.linspace(0,3, steps = 4, dtype = torch.float32)\n                target['boxes'] = target['boxes'].reshape(-1,4)\n            \n        return image, target, image_id","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_training_transforms():\n    return alb.Compose([\n    alb.VerticalFlip(p = 0.5),\n    alb.HorizontalFlip(p = 0.5),\n    ToTensorV2(p = 1.0)\n], p=1.0, bbox_params=alb.BboxParams(format='pascal_voc', label_fields=['labels']))\n\ndef get_validation_transforms():\n    return alb.Compose([ToTensorV2(p = 1.0)], p = 1.0, bbox_params = alb.BboxParams(format='pascal_voc', label_fields=['labels']))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"densenet_net = torchvision.models.densenet169(pretrained=True)\n\nmodules = list(densenet_net.children())[:-1]\nbackbone = nn.Sequential(*modules)\nbackbone.out_channels = 1664\n\nanchor_generator = AnchorGenerator(sizes=((32, 64, 128, 256, 512),),\n                                   aspect_ratios=((0.5, 1.0, 2.0),))\n\nroi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[\"0\"],\n                                                output_size=7,\n                                                sampling_ratio=2)\nmodel = FasterRCNN(backbone,\n                   num_classes=2,\n                   rpn_anchor_generator=anchor_generator,\n                   box_roi_pool=roi_pooler)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"training_dataset = WheatDataset(train_df, train_img_path, get_training_transforms())\nvalidation_dataset = WheatDataset(valid_df, train_img_path, get_validation_transforms())\n\ntrain_dataloader = DataLoader(\n        training_dataset, batch_size=2, shuffle= True, num_workers=4,\n        collate_fn= collate_fn)\n\nvalid_dataloader = DataLoader(\n        validation_dataset, batch_size=2, shuffle=False, num_workers=4,\n        collate_fn=collate_fn)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\ndevice","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"images, targets, image_ids = next(iter(train_dataloader))\nimages = list(image.to(device) for image in images)\ntargets = [{k: v.to(device) for k, v in t.items()} for t in targets]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.to(device)\nparams = [p for p in model.parameters() if p.requires_grad]\n\noptimizer = torch.optim.SGD(params, lr= 0.01, momentum=0.93)\n\nlr_scheduler =  torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.8, patience=2, eps=1e-08)\nnum_epochs=15","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"total_train_loss = []\ntotal_test_loss = []\n\nfor epoch in range(num_epochs):\n    model.train()\n\n    print('Epoch: ', epoch + 1)\n    train_loss = []\n    \n    for images, targets, image_ids in tqdm(train_dataloader):\n        images = list(image.to(device) for image in images)\n        targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n        \n        loss_dict = model(images, targets)  \n        losses = sum(loss for loss in loss_dict.values())\n        loss_value = losses.item()\n        train_loss.append(loss_value)\n        \n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n        \n    epoch_loss = np.mean(train_loss)\n    print('Epoch Loss is: ' , epoch_loss)\n    total_train_loss.append(epoch_loss)\n    \n    with torch.no_grad():\n        test_losses = []\n        for images, targets, image_ids in tqdm(valid_dataloader):\n            images = list(image.to(device) for image in images)\n            targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n            \n            loss_dict = model(images, targets)\n\n            losses = sum(loss for loss in loss_dict.values())\n            test_loss = losses.item()\n            test_losses.append(test_loss)\n            \n    test_losses_epoch = np.mean(test_losses)\n    print('Test Loss: ' ,test_losses_epoch)\n    total_test_loss.append(test_losses_epoch)\n    \n    if lr_scheduler is not None:\n        lr_scheduler.step(test_losses_epoch)\n        \ntorch.save(model.state_dict(), 'fasterrcnn.pth')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"model.eval()","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}