{"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":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport torch\nimport cv2\nfrom torchvision import datasets,transforms\nfrom glob import glob\nimport os\nfrom PIL import Image\nfrom matplotlib import patches\nfrom torch.utils.data import Dataset\nimport torchvision\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.rpn import AnchorGenerator\nfrom torch.utils.data import DataLoader","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dir ='/kaggle/input/global-wheat-detection/train/'\ntest_dir = '../input/global-wheat-detection/test/'\ntrain = pd.read_csv('../input/global-wheat-detection/train.csv') ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images = glob(train_dir +'*')\ntest_images = glob(test_dir +'*')\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images[:10]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['bbox'] = train['bbox'].fillna('[0,0,0,0]')\nbbox_items = train['bbox'].str.split(',',expand = True)\ntrain['x'] = bbox_items[0].str.strip('[').astype(float)\ntrain['y'] = bbox_items[1].str.strip(' ').astype(float)\ntrain['w'] = bbox_items[2].str.strip(' ').astype(float)\ntrain['h'] = bbox_items[3].str.strip(']').astype(float)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_id = train['image_id'].unique()\nvalid_ids = img_id[-665:]\ntrain_ids = img_id[:-665]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df = train[train['image_id'].isin(valid_ids)]\ntrain_df = train[train['image_id'].isin(train_ids)]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df.shape,train_df.shape\ntrain['area'] = train['w']*train['h']","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Wheatdatasets(Dataset):\n    \n    def __init__(self,dataframe,image_dir,transforms = None):\n        \n        super().__init__()\n    \n        self.image_id = dataframe['image_id'].unique()\n        self.df = dataframe\n        self.img_dir = image_dir\n        self.transforms = transforms\n        \n    def __getitem__(self,index:int):\n        \n        image_id = self.image_id[index]\n        record = self.df[self.df['image_id']==image_id]\n        image = cv2.imread(self.img_dir+image_id+'.jpg',cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB).astype(np.float32)\n        image = image/255.0\n        \n        boxes = record[['x','y','w','h']].values\n        boxes[:,2] = boxes[:,2]+boxes[:,0]\n        boxes[:,3] = boxes[:,3]+boxes[:,1]\n        \n        area = (boxes[:,2]- boxes[:,0])*(boxes[:,1]-boxes[:,3])\n        area = torch.as_tensor(area,dtype=torch.float32)\n        \n        #There is any class\n        labels = torch.ones((record.shape[0],),dtype =torch.int64)\n        \n        #suppose all instances are not crowd\n        iscrowd = torch.zeros((record.shape[0],),dtype =torch.int64)\n        \n        target ={}\n        target['boxes']=boxes\n        target['area'] =area\n        target['labels']=labels\n        target['iscrowd'] = iscrowd\n        target['image_id'] = torch.tensor([index])\n        \n        if self.transforms:\n            sample ={\n                'image':image,\n                'bboxes':target['boxes'],\n                'labels':labels\n            }\n            sample =self.transforms(**sample)\n            image = sample['image']\n                \n            target['boxes'] = torch.tensor(sample['bboxes']).float()\n            return image,target,image_id\n        \n    def __len__(self) -> int:\n        return self.image_id.shape[0]\n        \n        ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Albumentation\nimport albumentations as al\nfrom albumentations.pytorch.transforms import ToTensorV2\n\ndef train_trans():\n    return al.Compose([\n    al.Flip(0.5),\n    al.HorizontalFlip(p=0.5),\n    al.VerticalFlip(p=0.5),\n    al.OneOf([al.RandomContrast(),\n             al.RandomGamma(),\n             al.RandomBrightness()],p=1.0),\n    \n    ToTensorV2(p=1.0)], bbox_params ={'format':'pascal_voc','label_fields':['labels']})\n\n\n\ndef valid_trans():\n    return al.Compose([\n    \n    ToTensorV2(p=1.0)], bbox_params ={'format': 'pascal_voc','label_fields':['labels']})\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Create the Model\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained = True)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_class = 2 #wheats and background\n\nin_feature = model.roi_heads.box_predictor.cls_score.in_features\n\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_feature,num_class) #changin the pretrained head with a new one","metadata":{"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\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\n    def reset(self):\n        self.current_total = 0.0\n        self.iterations = 0.0","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))\n\ntrain_dataset = Wheatdatasets(train_df, train_dir,train_trans())\nvalid_dataset = Wheatdatasets(valid_df,train_dir,valid_trans())\n\nindices = torch.randperm(len(train_dataset)).tolist()\n\ntrain_dataloader = DataLoader(\ntrain_dataset,\nbatch_size=8,\nshuffle =False,\nnum_workers =4,\ncollate_fn = collate_fn)\n\nvalid_dataloader  = DataLoader(\nvalid_dataset,\n    batch_size=8,\n    shuffle=False,\n    num_workers=4,\n    collate_fn=collate_fn)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\nprint(device)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Sample","metadata":{}},{"cell_type":"code","source":"images,target,image_id = 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 target]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"boxes = targets[2]['boxes'].cpu().numpy().astype(np.int32)\nsample = images[2].permute(1,2,0).cpu().numpy()","metadata":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"model.to(device)\nparams = [p for p in model.parameters() if p.requires_grad]\noptimizer = torch.optim.SGD(params, lr=0.005, momentum=0.9, weight_decay=0.0005)\n# lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.1)\nlr_scheduler = None\n\nnum_epochs = 2\ntorch.cuda.empty_cache()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.empty_cache()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_hist = Averager()\nitr = 2\n\nfor epoch in range(num_epochs):\n    loss_hist.reset()\n    \n    for images, targets, image_ids 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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now for Validation","metadata":{}},{"cell_type":"code","source":"\nimages, targets, image_ids = next(iter(valid_dataloader))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"             \nimages = list(img.to(device) for img in images)\ntargets = [{k: v.to(device) for k, v in t.items()} for t in targets]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\nboxes = targets[1]['boxes'].cpu().numpy().astype(np.int32)\nsample = images[1].permute(1,2,0).cpu().numpy()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\ncpu_device = torch.device(\"cpu\")\n\noutputs = model(images)\noutputs = [{k: v.to(cpu_device) for k, v in t.items()} for t in outputs]","metadata":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(model.state_dict(), 'fasterrcnn_resnet50_fpn.pth')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}