{"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\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2 \nimport torchvision\nfrom torchvision import datasets,transforms\nfrom tqdm import tqdm\nimport cv2\nfrom torch.utils.data import Dataset,DataLoader\nimport torch.optim as optim\nfrom PIL import Image\nimport os\nimport torch.nn.functional as F\nimport ast","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-10-15T18:13:12.476723Z","iopub.execute_input":"2021-10-15T18:13:12.476988Z","iopub.status.idle":"2021-10-15T18:13:18.386462Z","shell.execute_reply.started":"2021-10-15T18:13:12.476961Z","shell.execute_reply":"2021-10-15T18:13:18.385728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# config\nLR = 1e-4\nSPLIT = 0.2\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nBATCH_SIZE = 4\nEPOCHS = 2\nDATAPATH = '../input/global-wheat-detection'","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:18.389599Z","iopub.execute_input":"2021-10-15T18:13:18.389803Z","iopub.status.idle":"2021-10-15T18:13:18.433655Z","shell.execute_reply.started":"2021-10-15T18:13:18.38978Z","shell.execute_reply":"2021-10-15T18:13:18.432207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls '../input/global-wheat-detection'","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:18.435026Z","iopub.execute_input":"2021-10-15T18:13:18.43528Z","iopub.status.idle":"2021-10-15T18:13:19.120855Z","shell.execute_reply.started":"2021-10-15T18:13:18.435249Z","shell.execute_reply":"2021-10-15T18:13:19.120099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(DATAPATH + '/train.csv')\ndf.bbox = df.bbox.apply(ast.literal_eval)","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:19.123246Z","iopub.execute_input":"2021-10-15T18:13:19.123512Z","iopub.status.idle":"2021-10-15T18:13:21.574451Z","shell.execute_reply.started":"2021-10-15T18:13:19.123477Z","shell.execute_reply":"2021-10-15T18:13:21.573701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = df.groupby(\"image_id\")[\"bbox\"].apply(list).reset_index(name=\"bboxes\")","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:21.575547Z","iopub.execute_input":"2021-10-15T18:13:21.575793Z","iopub.status.idle":"2021-10-15T18:13:21.809926Z","shell.execute_reply.started":"2021-10-15T18:13:21.575761Z","shell.execute_reply":"2021-10-15T18:13:21.809209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_test_split(dataFrame,split):\n    len_tot = len(dataFrame)\n    val_len = int(split*len_tot)\n    train_len = len_tot-val_len\n    train_data,val_data = dataFrame.iloc[:train_len][:],dataFrame.iloc[train_len:][:]\n    return train_data,val_data","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:21.811407Z","iopub.execute_input":"2021-10-15T18:13:21.811652Z","iopub.status.idle":"2021-10-15T18:13:21.818672Z","shell.execute_reply.started":"2021-10-15T18:13:21.811609Z","shell.execute_reply":"2021-10-15T18:13:21.817934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data_df,val_data_df = train_test_split(df,SPLIT)","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:21.821055Z","iopub.execute_input":"2021-10-15T18:13:21.821351Z","iopub.status.idle":"2021-10-15T18:13:21.82622Z","shell.execute_reply.started":"2021-10-15T18:13:21.821319Z","shell.execute_reply":"2021-10-15T18:13:21.825342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data_df","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:21.827847Z","iopub.execute_input":"2021-10-15T18:13:21.828167Z","iopub.status.idle":"2021-10-15T18:13:21.962724Z","shell.execute_reply.started":"2021-10-15T18:13:21.828099Z","shell.execute_reply":"2021-10-15T18:13:21.961938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class WheatDataset(Dataset):\n    def __init__(self,data,root_dir,transform=None,train=True):\n        self.data = data\n        self.root_dir = root_dir\n        self.image_names = self.data.image_id.values\n        self.bboxes = self.data.bboxes.values\n        self.transform = transform\n        self.isTrain = train\n    def __len__(self):\n        return len(self.data)\n    def __getitem__(self,index):\n#         print(self.image_names)\n#         print(self.bboxes)\n        img_path = os.path.join(self.root_dir,self.image_names[index]+\".jpg\")\n        image = cv2.imread(img_path, cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n        bboxes = torch.tensor(self.bboxes[index],dtype=torch.float64)\n#         print(bboxes)\n        \"\"\"\n            As per the docs of torchvision\n            we need bboxes in format (xmin,ymin,xmax,ymax)\n            Currently we have them in format (xmin,ymin,width,height)\n        \"\"\"\n        bboxes[:,2] = bboxes[:,0]+bboxes[:,2]\n        bboxes[:,3] = bboxes[:,1]+bboxes[:,3]\n#         print(image.size,type(image))\n        \"\"\"\n            we need to return image and a target dictionary\n            target:\n                boxes,labels,image_id,area,iscrowd\n        \"\"\"\n        area = (bboxes[:,3]-bboxes[:,1])*(bboxes[:,2]-bboxes[:,0])\n        area = torch.as_tensor(area,dtype=torch.float32)\n        \n        # there is only one class\n        labels = torch.ones((len(bboxes),),dtype=torch.int64)\n        \n        # suppose all instances are not crowded\n        iscrowd = torch.zeros((len(bboxes),),dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = bboxes\n        target['labels']= labels\n        target['image_id'] = torch.tensor([index])\n        target[\"area\"] = area\n        target['iscrowd'] = iscrowd\n        \n        if self.transform is not None:\n            sample = {\n                'image': image,\n                'bboxes': target['boxes'],\n                'labels': labels\n            }\n            sample = self.transform(**sample)\n            image = sample['image']\n            \n            target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n            \n        return image,target\n        ","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:21.964095Z","iopub.execute_input":"2021-10-15T18:13:21.964361Z","iopub.status.idle":"2021-10-15T18:13:21.978352Z","shell.execute_reply.started":"2021-10-15T18:13:21.96433Z","shell.execute_reply":"2021-10-15T18:13:21.977561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transform = A.Compose([\n    A.Flip(0.5),\n    ToTensorV2(p=1.0)\n],bbox_params = {'format':\"pascal_voc\",'label_fields': ['labels']})\nval_transform = A.Compose([\n      ToTensorV2(p=1.0)\n],bbox_params = {'format':\"pascal_voc\",\"label_fields\":['labels']})\n","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:21.979901Z","iopub.execute_input":"2021-10-15T18:13:21.980364Z","iopub.status.idle":"2021-10-15T18:13:21.990365Z","shell.execute_reply.started":"2021-10-15T18:13:21.980327Z","shell.execute_reply":"2021-10-15T18:13:21.989632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:22.508566Z","iopub.execute_input":"2021-10-15T18:13:22.509146Z","iopub.status.idle":"2021-10-15T18:13:22.514907Z","shell.execute_reply.started":"2021-10-15T18:13:22.509108Z","shell.execute_reply":"2021-10-15T18:13:22.514198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = WheatDataset(train_data_df,DATAPATH+\"/train\",transform=train_transform)\nvalid_data = WheatDataset(val_data_df,DATAPATH+\"/train\",transform=val_transform)","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:23.24291Z","iopub.execute_input":"2021-10-15T18:13:23.243476Z","iopub.status.idle":"2021-10-15T18:13:23.248763Z","shell.execute_reply.started":"2021-10-15T18:13:23.243439Z","shell.execute_reply":"2021-10-15T18:13:23.247879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image,target = train_data.__getitem__(0)\n# plt.imshow(image)\nprint(image.shape)","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:25.954589Z","iopub.execute_input":"2021-10-15T18:13:25.954846Z","iopub.status.idle":"2021-10-15T18:13:26.118245Z","shell.execute_reply.started":"2021-10-15T18:13:25.954818Z","shell.execute_reply":"2021-10-15T18:13:26.116798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision.models.detection.faster_rcnn import FastRCNNPredictor\n\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)\nnum_classes = 2\nin_features = model.roi_heads.box_predictor.cls_score.in_features\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features,num_classes)","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:26.979055Z","iopub.execute_input":"2021-10-15T18:13:26.979649Z","iopub.status.idle":"2021-10-15T18:13:36.626762Z","shell.execute_reply.started":"2021-10-15T18:13:26.979615Z","shell.execute_reply":"2021-10-15T18:13:36.626002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Averager:\n    def __init__(self):\n        self.current_total=0.0\n        self.iterations = 0.0\n    def send(self,value):\n        self.current_total+=value\n        self.iterations+=1\n    \n    @property\n    def value(self):\n        if self.iterations == 0:\n            return 0\n        else:\n            return 1.0*self.current_total/self.iterations\n    def reset(self):\n        self.current_total = 0.0\n        self.iterations = 0.0","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:36.629249Z","iopub.execute_input":"2021-10-15T18:13:36.629954Z","iopub.status.idle":"2021-10-15T18:13:36.636058Z","shell.execute_reply.started":"2021-10-15T18:13:36.629915Z","shell.execute_reply":"2021-10-15T18:13:36.635359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataloader = DataLoader(train_data,batch_size=BATCH_SIZE,shuffle=True,collate_fn=collate_fn)\nval_dataloader = DataLoader(valid_data,batch_size=BATCH_SIZE,shuffle=False,collate_fn=collate_fn)","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:36.637038Z","iopub.execute_input":"2021-10-15T18:13:36.637276Z","iopub.status.idle":"2021-10-15T18:13:36.650589Z","shell.execute_reply.started":"2021-10-15T18:13:36.637251Z","shell.execute_reply":"2021-10-15T18:13:36.64992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loss = []\n# val_loss = []\nmodel = model.to(DEVICE)\nparams =[p for p in model.parameters() if p.requires_grad]\noptimizer = optim.Adam(params,lr=LR)\nloss_hist = Averager()\nitr = 1\nlr_scheduler=None","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:13:36.652247Z","iopub.execute_input":"2021-10-15T18:13:36.652567Z","iopub.status.idle":"2021-10-15T18:13:41.663217Z","shell.execute_reply.started":"2021-10-15T18:13:36.652532Z","shell.execute_reply":"2021-10-15T18:13:41.662402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_hist = Averager()\nitr = 1\n\nfor epoch in range(EPOCHS):\n    loss_hist.reset()\n    \n    for images, targets in train_dataloader:\n        \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        loss_value = losses.item()\n\n        loss_hist.send(loss_value)\n\n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n\n        if itr % 50 == 0:\n            print(f\"Iteration #{itr} loss: {loss_value}\")\n\n        itr += 1\n    \n    # update the learning rate\n    if lr_scheduler is not None:\n        lr_scheduler.step()\n\n    print(f\"Epoch #{epoch} loss: {loss_hist.value}\")  ","metadata":{"execution":{"iopub.status.busy":"2021-10-15T16:31:34.202792Z","iopub.execute_input":"2021-10-15T16:31:34.203067Z","iopub.status.idle":"2021-10-15T16:44:04.336283Z","shell.execute_reply.started":"2021-10-15T16:31:34.203037Z","shell.execute_reply":"2021-10-15T16:44:04.335559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(model.state_dict(), 'fasterrcnn_resnet50_fpn.pth')","metadata":{"execution":{"iopub.status.busy":"2021-10-15T16:44:33.376784Z","iopub.execute_input":"2021-10-15T16:44:33.377066Z","iopub.status.idle":"2021-10-15T16:44:33.801728Z","shell.execute_reply.started":"2021-10-15T16:44:33.377031Z","shell.execute_reply":"2021-10-15T16:44:33.800946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images, targets = next(iter(val_dataloader))\nimages = list(img.to(DEVICE) for img in images)\n# print(images[0].shape)\ntargets = [{k: v.to(DEVICE) for k, v in t.items()} for t in targets]\nboxes = targets[1]['boxes'].cpu().numpy().astype(np.int32)\nsample = images[1].permute(1,2,0).cpu().numpy()","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:19:14.025883Z","iopub.execute_input":"2021-10-15T18:19:14.02663Z","iopub.status.idle":"2021-10-15T18:19:14.186468Z","shell.execute_reply.started":"2021-10-15T18:19:14.026585Z","shell.execute_reply":"2021-10-15T18:19:14.185677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\ncpu_device = torch.device(\"cpu\")\n# print(images[0].shape)\noutputs = model(images)\noutputs = [{k: v.to(cpu_device) for k, v in t.items()} for t in outputs]\n# print(outputs)","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:19:27.099002Z","iopub.execute_input":"2021-10-15T18:19:27.099873Z","iopub.status.idle":"2021-10-15T18:19:27.321176Z","shell.execute_reply.started":"2021-10-15T18:19:27.099826Z","shell.execute_reply":"2021-10-15T18:19:27.32044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1, 1, figsize=(16, 8))\n\nfor box in boxes:\n    cv2.rectangle(sample,\n                  (box[0], box[1]),\n                  (box[2], box[3]),\n                  (220, 0, 0), 3)\n    \nax.set_axis_off()\nax.imshow(sample)","metadata":{"execution":{"iopub.status.busy":"2021-10-15T18:18:13.928688Z","iopub.execute_input":"2021-10-15T18:18:13.929338Z","iopub.status.idle":"2021-10-15T18:18:14.407611Z","shell.execute_reply.started":"2021-10-15T18:18:13.929274Z","shell.execute_reply":"2021-10-15T18:18:14.406755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_imgs_paths = pd.read_csv(os.path.join(DATAPATH,'sample_submission.csv'))\ntest_img_paths = test_imgs_paths.image_id.values\ntest_dir = DATAPATH+\"/test\"","metadata":{"execution":{"iopub.status.busy":"2021-10-15T19:44:49.240882Z","iopub.execute_input":"2021-10-15T19:44:49.241164Z","iopub.status.idle":"2021-10-15T19:44:49.255700Z","shell.execute_reply.started":"2021-10-15T19:44:49.241134Z","shell.execute_reply":"2021-10-15T19:44:49.254871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions=[]\nimage_ids=[]\nwith torch.no_grad():\n    for path in test_img_paths:\n        img_path = os.path.join(test_dir,path+\".jpg\")\n        image = cv2.imread(img_path, cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n        image = np.transpose(image,(2,0,1))\n    #     print(image.shape)\n        image = torch.tensor(image,dtype=torch.float)\n        image = image.unsqueeze(0)\n    #     print(image.shape)\n        image = image.to(DEVICE)\n        outputs = model(image)\n\n        predict=[]\n        outputs = outputs[0]\n        for i in range(len(outputs['boxes'])):\n            temp = np.array([str(outputs['scores'][i].item()),str(outputs['boxes'][i][0].item()),str(outputs['boxes'][i][1].item()),str(outputs['boxes'][i][2].item()-outputs['boxes'][i][0].item()),str(outputs['boxes'][i][3].item()-outputs['boxes'][i][1].item())])\n            predict.append(temp)\n        predict = np.array(predict).flatten()\n        predict = ' '.join(predict.flatten())\n        image_ids.append(path)\n        predictions.append(predict)\n    print(\"------------Generating Submission File---------\")\n    df = pd.DataFrame({\"image_id\":image_ids,\"PredictionString\":predictions})\n    df.to_csv('./submission.csv.gz',index=False,compression='gzip')","metadata":{"execution":{"iopub.status.busy":"2021-10-15T19:44:53.539371Z","iopub.execute_input":"2021-10-15T19:44:53.539748Z","iopub.status.idle":"2021-10-15T19:44:54.512770Z","shell.execute_reply.started":"2021-10-15T19:44:53.539711Z","shell.execute_reply":"2021-10-15T19:44:54.512027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}