{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Finetune Faster RCNN with Pytorch to Detect Wheat heads in Images\n\n"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport torch\nimport torchvision\nimport matplotlib.pyplot as plt\nimport matplotlib\nimport matplotlib.image as im\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, utils\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor, FasterRCNN\nfrom torchvision.models.detection.backbone_utils import resnet_fpn_backbone\nimport PIL\nfrom PIL import Image\nimport albumentations as A\n\n\"\"\"\nPeak at data - note only 3.3k unique images not alot which means will have to augment the images with albumentations library\n\"\"\"\ntrain_df = pd.read_csv(\"/kaggle/input/global-wheat-detection/train.csv\")\n\nprint(len(train_df[\"image_id\"].unique()))\n\ntrain_df.head()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Take a peak at the images and detection boxes\n\nAlso check out how the albumentations library affects the images."},{"metadata":{"trusted":true},"cell_type":"code","source":"# imgs_df=train_df[\"image_id\"].unique()\n\n# image_id = imgs_df[50]\n\n# im=Image.open(\"/kaggle/input/global-wheat-detection/train/\" + image_id +\".jpg\")\n# enhancer = PIL.ImageEnhance.Contrast(im)\n# im_output = enhancer.enhance(2)\n\n# out=np.array(im_output)\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"\"\"\"\nPeak at image\n\"\"\"\n\nimgs_df=train_df[\"image_id\"].unique()\n\nimage_id = imgs_df[45]\n\nimg = im.imread(\"/kaggle/input/global-wheat-detection/train/\" + image_id +\".jpg\")\n\nboxes = list(train_df[\"bbox\"][ train_df[\"image_id\"]==image_id ].values)\n\nbox=[]\nfor i,l in enumerate(boxes): \n    b=[float(num) for num in l[1:-1].split(\",\")] \n    #boxes[i]=[b[0],b[1],b[0]+b[2],b[1]+b[3]]\n    #box.append([b[0],b[1],b[0]+b[2],b[1]+b[3]])\n    box.append(b)\n\ndef print_im(image,bboxes):\n    \n    fig, ax = plt.subplots(figsize=(10, 10))\n    ax.imshow(image)\n    for c in bboxes:\n        rect = matplotlib.patches.Rectangle((c[0],c[1]),c[2],c[3],linewidth=1,edgecolor='r',facecolor='none')\n        ax.add_patch(rect)\n    plt.show()\n    \n###----------------------\n\n#format sets the format for the bounding boxes\ntransform = A.Compose([\n    #A.RandomCrop(width=450, height=450),\n    A.Resize(512, 512),\n    A.VerticalFlip(p=1),\n    #A.HorizontalFlip(p=1),\n    A.RandomBrightnessContrast(p=1),\n], bbox_params=A.BboxParams(format='coco', label_fields=['class_labels']))\n#bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))\n\ntransformed = transform( image=img, bboxes=box, class_labels=[\"wheat\"]*len(box) )\ntransformed_image = transformed['image']\ntransformed_bboxes = transformed['bboxes']\n\n#print_im(img,box)\nprint_im(transformed_image,transformed_bboxes)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Create the Dataset object"},{"metadata":{"trusted":true},"cell_type":"code","source":"class ImageDataset(Dataset):\n    def __init__(self, root=\"/kaggle/input/global-wheat-detection/\", tt=\"train\",transforms_tt=True):\n        \n        df=pd.read_csv(\"{}{}.csv\".format(root,tt))\n        \n        self.root = root\n        self.transforms = transforms\n        self.imgs = df[\"image_id\"].unique()\n        self.df=df\n        self.tt=tt\n        self.transform=None\n        if transforms_tt is True:\n            self.transform=A.Compose( [  A.Resize(512, 512),\n                                         A.VerticalFlip(p=0.25),\n                                         A.HorizontalFlip(p=0.25),\n                                         A.RandomBrightnessContrast(p=0.35)],\n                                         #ToTensorV2], \n                                      bbox_params=A.BboxParams(format='coco', label_fields=['class_labels']))\n\n    def __getitem__(self, idx):\n        # load images ad masks\n        image_id = self.imgs[idx]\n        pic_path=\"/kaggle/input/global-wheat-detection/{}/{}.jpg\".format(self.tt,image_id)\n        \n        im=Image.open( pic_path )\n        enhancer = PIL.ImageEnhance.Contrast(im)\n        im_output = enhancer.enhance(2)\n        \n        _image=np.array( im_output )\n        #_image = im.imread( pic_path)\n        #image = Image.open( \"/kaggle/input/global-wheat-detection/{}/{}.jpg\".format(self.tt,image_id) )\n        \n        records = self.df[\"bbox\"][self.df['image_id'] == image_id].values\n        boxes=[]\n        for i,l in enumerate(records): \n            b=[float(num) for num in l[1:-1].split(\",\")] \n            boxes.append ( b )\n        \n        #area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        target = {}\n        target[\"labels\"] = torch.ones((records.shape[0],), dtype=torch.int64)\n        #target[\"area\"] = area\n        target[\"iscrowd\"] = torch.zeros((records.shape[0],), dtype=torch.int64)\n        \n        if self.transforms is not None:\n            transformed = self.transform( image=_image, bboxes=boxes, class_labels=[\"wheat\"]*len(boxes) )\n            img = transformed['image']\n            img=torchvision.transforms.functional.to_tensor(img)\n            transformed_bboxes = transformed['bboxes']\n            bboxes=[]\n            for b in transformed_bboxes:\n                bboxes.append([b[0],b[1],b[0]+b[2],b[1]+b[3]])\n            target[\"boxes\"]=torch.as_tensor(bboxes, dtype=torch.float32)\n            \n        if self.transform is None:\n            bboxes=[]\n            for b in boxes:\n                bboxes.append([b[0],b[1],b[0]+b[2],b[1]+b[3]])\n            target[\"boxes\"]=bboxes\n            img=torchvision.transforms.functional.to_tensor(_image)\n        \n        del records\n        del _image\n        \n        return img, target\nFinetune Faster RCNN with Pytorch to Detect Wheat heads in Images\n\nimport os\n\nimport numpy as np # linear algebra\n\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport torch\n\nimport torchvision\n\nimport matplotlib.pyplot as plt\n\nimport matplotlib\n\nimport matplotlib.image as im\n\nfrom torch.utils.data import Dataset, DataLoader\n\nfrom torchvision import transforms, utils\n\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor, FasterRCNN\n\nfrom torchvision.models.detection.backbone_utils import resnet_fpn_backbone\n\nimport PIL\n\nfrom PIL import Image\n\nimport albumentations as A\n\n​\n\n\"\"\"\n\nPeak at data - note only 3.3k unique images not alot which means will have to augment the images with albumentations library\n\n\"\"\"\n\ntrain_df = pd.read_csv(\"/kaggle/input/global-wheat-detection/train.csv\")\n\n​\n\nprint(len(train_df[\"image_id\"].unique()))\n\n​\n\ntrain_df.head()\n\n​\n\n3373\n\n\timage_id \twidth \theight \tbbox \tsource\n0 \tb6ab77fd7 \t1024 \t1024 \t[834.0, 222.0, 56.0, 36.0] \tusask_1\n1 \tb6ab77fd7 \t1024 \t1024 \t[226.0, 548.0, 130.0, 58.0] \tusask_1\n2 \tb6ab77fd7 \t1024 \t1024 \t[377.0, 504.0, 74.0, 160.0] \tusask_1\n3 \tb6ab77fd7 \t1024 \t1024 \t[834.0, 95.0, 109.0, 107.0] \tusask_1\n4 \tb6ab77fd7 \t1024 \t1024 \t[26.0, 144.0, 124.0, 117.0] \tusask_1\nTake a peak at the images and detection boxes\n\nAlso check out how the albumentations library affects the images.\n\n# imgs_df=train_df[\"image_id\"].unique()\n\n​\n\n# image_id = imgs_df[50]\n\n​\n\n# im=Image.open(\"/kaggle/input/global-wheat-detection/train/\" + image_id +\".jpg\")\n\n# enhancer = PIL.ImageEnhance.Contrast(im)\n\n# im_output = enhancer.enhance(2)\n\n​\n\n# out=np.array(im_output)\n\n​\n\n\"\"\"\n\nPeak at image\n\n\"\"\"\n\n​\n\nimgs_df=train_df[\"image_id\"].unique()\n\n​\n\nimage_id = imgs_df[45]\n\n​\n\nimg = im.imread(\"/kaggle/input/global-wheat-detection/train/\" + image_id +\".jpg\")\n\n​\n\nboxes = list(train_df[\"bbox\"][ train_df[\"image_id\"]==image_id ].values)\n\n​\n\nbox=[]\n\nfor i,l in enumerate(boxes): \n\n    b=[float(num) for num in l[1:-1].split(\",\")] \n\n    #boxes[i]=[b[0],b[1],b[0]+b[2],b[1]+b[3]]\n\n    #box.append([b[0],b[1],b[0]+b[2],b[1]+b[3]])\n\n    box.append(b)\n\n​\n\ndef print_im(image,bboxes):\n\n    \n\n    fig, ax = plt.subplots(figsize=(10, 10))\n\n    ax.imshow(image)\n\n    for c in bboxes:\n\n        rect = matplotlib.patches.Rectangle((c[0],c[1]),c[2],c[3],linewidth=1,edgecolor='r',facecolor='none')\n\n        ax.add_patch(rect)\n\n    plt.show()\n\n    \n\n###----------------------\n\n​\n\n#format sets the format for the bounding boxes\n\ntransform = A.Compose([\n\n    #A.RandomCrop(width=450, height=450),\n\n    A.Resize(512, 512),\n\n    A.VerticalFlip(p=1),\n\n    #A.HorizontalFlip(p=1),\n\n    A.RandomBrightnessContrast(p=1),\n\n], bbox_params=A.BboxParams(format='coco', label_fields=['class_labels']))\n\n#bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))\n\n​\n\ntransformed = transform( image=img, bboxes=box, class_labels=[\"wheat\"]*len(box) )\n\ntransformed_image = transformed['image']\n\ntransformed_bboxes = transformed['bboxes']\n\n​\n\n#print_im(img,box)\n\nprint_im(transformed_image,transformed_bboxes)\n\nCreate the Dataset object\n\nclass ImageDataset(Dataset):\n\n    def __init__(self, root=\"/kaggle/input/global-wheat-detection/\", tt=\"train\",transforms_tt=True):\n\n        \n\n        df=pd.read_csv(\"{}{}.csv\".format(root,tt))\n\n        \n\n        self.root = root\n\n        self.transforms = transforms\n\n        self.imgs = df[\"image_id\"].unique()\n\n        self.df=df\n\n        self.tt=tt\n\n        self.transform=None\n\n        if transforms_tt is True:\n\n            self.transform=A.Compose( [  A.Resize(512, 512),\n\n                                         A.VerticalFlip(p=0.25),\n\n                                         A.HorizontalFlip(p=0.25),\n\n                                         A.RandomBrightnessContrast(p=0.35)],\n\n                                         #ToTensorV2], \n\n                                      bbox_params=A.BboxParams(format='coco', label_fields=['class_labels']))\n\n​\n\n    def __getitem__(self, idx):\n\n        # load images ad masks\n\n        image_id = self.imgs[idx]\n\n        pic_path=\"/kaggle/input/global-wheat-detection/{}/{}.jpg\".format(self.tt,image_id)\n\n        \n\n        im=Image.open( pic_path )\n\n        enhancer = PIL.ImageEnhance.Contrast(im)\n\n        im_output = enhancer.enhance(2)\n\n        \n\n        _image=np.array( im_output )\n\n        #_image = im.imread( pic_path)\n\n        #image = Image.open( \"/kaggle/input/global-wheat-detection/{}/{}.jpg\".format(self.tt,image_id) )\n\n        \n\n        records = self.df[\"bbox\"][self.df['image_id'] == image_id].values\n\n        boxes=[]\n\n        for i,l in enumerate(records): \n\n            b=[float(num) for num in l[1:-1].split(\",\")] \n\n            boxes.append ( b )\n\n        \n\n        #area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n\n        target = {}\n\n        target[\"labels\"] = torch.ones((records.shape[0],), dtype=torch.int64)\n\n        #target[\"area\"] = area\n\n        target[\"iscrowd\"] = torch.zeros((records.shape[0],), dtype=torch.int64)\n\n        \n\n        if self.transforms is not None:\n\n            transformed = self.transform( image=_image, bboxes=boxes, class_labels=[\"wheat\"]*len(boxes) )\n\n            img = transformed['image']\n\n            img=torchvision.transforms.functional.to_tensor(img)\n\n            transformed_bboxes = transformed['bboxes']\n\n            bboxes=[]\n\n            for b in transformed_bboxes:\n\n                bboxes.append([b[0],b[1],b[0]+b[2],b[1]+b[3]])\n\n            target[\"boxes\"]=torch.as_tensor(bboxes, dtype=torch.float32)\n\n            \n\n        if self.transform is None:\n\n            bboxes=[]\n\n            for b in boxes:\n\n                bboxes.append([b[0],b[1],b[0]+b[2],b[1]+b[3]])\n\n            target[\"boxes\"]=bboxes\n\n            img=torchvision.transforms.functional.to_tensor(_image)\n\n        \n\n        del records\n\n        del _image\n\n        \n\n        return img, target\n\n​\n\n    def __len__(self):\n\n        return len(self.imgs)\n\nCheck that the dataset object worked as expected\n\n\"\"\"\n\nCheck.\n\n\"\"\"\n\ndataset = ImageDataset()\n\ndata_loader = DataLoader(dataset,batch_size=50,collate_fn=lambda batch: list(zip(*batch)) )\n\n​\n\nimages, targets= next(iter(data_loader))\n\n​\n\nidx=45\n\n​\n\nimg= images[idx].permute(1,2,0).numpy()\n\n​\n\nprint(img.shape)\n\n​\n\nfig, ax = plt.subplots(figsize=(10, 10))\n\n​\n\nax.imshow(img)\n\n​\n\nboxes=targets[idx][\"boxes\"].numpy()\n\n​\n\nfor c in boxes:\n\n    rect = matplotlib.patches.Rectangle((c[0],c[1]),c[2]-c[0],c[3]-c[1],linewidth=1,edgecolor='r',facecolor='none')\n\n    ax.add_patch(rect)\n\n​\n\n​\n\nplt.show()\n\n(512, 512, 3)\n\nDownload the model\n\n\"\"\"\n\nDownload and set up model\n\n\"\"\"     \n\ntorchvision.__version__\n\n​\n\nmodel=torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True, progress=True, pretrained_backbone=True, trainable_backbone_layers=5)\n\n​\n\nnum_classes = 2  # 1 class (wheat) + background\n\nin_features = model.roi_heads.box_predictor.cls_score.in_features\n\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n\n​\n\ndevice = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n\nDownloading: \"https://download.pytorch.org/models/fasterrcnn_resnet50_fpn_coco-258fb6c6.pth\" to /root/.cache/torch/hub/checkpoints/fasterrcnn_resnet50_fpn_coco-258fb6c6.pth\n\n100%\n160M/160M [00:26<00:00, 6.39MB/s]\n\n\nSet up training loop\n\nfrom torch import optim\n\nimport time\n\nstart_time = time.time()\n\n​\n\ndataset = ImageDataset()\n\ndata_loader = DataLoader(dataset,batch_size=10,collate_fn=lambda batch: list(zip(*batch)) )\n\n​\n\nEPOCHS=8\n\n​\n\nmodel = model.to(device)\n\nmodel.train()\n\n​\n\n​\n\nparams = [p for p in model.parameters() if p.requires_grad]\n\noptimizer = torch.optim.SGD(params, lr=0.0008, momentum=0.9, weight_decay=0.0005)\n\n#scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=5,cooldown=20,factor=0.65,min_lr=0.00001,verbose=True)\n\n​\n\nprint(\"Begin training\")\n\nlossAvg,lossPer=[],[]\n\nfor epoch in range(EPOCHS):\n\n    total_loss,count=0,0\n\n    for batch in data_loader:\n\n        #check if targets is a list\n\n        images,targets=batch\n\n        \n\n        images = list(image.to(device) for image in images)\n\n        targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\n​\n\n        loss_dict = model(images, targets)\n\n        losses = sum(loss for loss in loss_dict.values())\n\n        \n\n        optimizer.zero_grad()\n\n        losses.backward()\n\n        optimizer.step()\n\n        \n\n        if count%10==0:\n\n            #scheduler.step(losses)\n\n            print(\"loss: {}\".format( losses.item() ))\n\n            lossPer.append(losses.item())\n\n        count+=1\n\n        total_loss+=losses.item()\n\n    g=total_loss/count \n\n    lossAvg.append( g )\n\n    print(\"END EPOCH #{} avg: {}\".format(epoch,total_loss/count))\n\n    \n\nprint(\" \")\n\nprint(\" \")\n\nprint(\"Training Time: {}\".format( time.time() - start_time ))\n\nBegin training\nloss: 5.3773603439331055\nloss: 1.7676422595977783\nloss: 1.6178905963897705\nloss: 1.4473177194595337\nloss: 1.2948307991027832\nloss: 1.1440315246582031\nloss: 1.2207309007644653\nloss: 1.2663609981536865\nloss: 1.1774954795837402\nloss: 1.144769549369812\nloss: 1.0742299556732178\nloss: 1.0932400226593018\nloss: 1.112673282623291\nloss: 0.8862013816833496\nloss: 0.7781498432159424\nloss: 1.2107676267623901\nloss: 1.076627492904663\nloss: 0.9980862140655518\nloss: 0.8189986348152161\nloss: 0.9870530962944031\nloss: 0.8758689165115356\nloss: 0.8170798420906067\nloss: 1.201951265335083\nloss: 0.8513198494911194\nloss: 0.8411060571670532\nloss: 0.6542643904685974\nloss: 1.0925242900848389\nloss: 0.8526032567024231\nloss: 0.8829998970031738\nloss: 0.6939114928245544\nloss: 0.840462863445282\nloss: 0.7291010022163391\nloss: 1.2138803005218506\nloss: 1.144069790840149\nEND EPOCH #0 avg: 1.0848297739522696\nloss: 1.1295771598815918\nloss: 0.9422412514686584\nloss: 1.2606966495513916\nloss: 1.0974177122116089\nloss: 0.9704293012619019\nloss: 0.8956283330917358\nloss: 1.0221991539001465\nloss: 1.1031385660171509\nloss: 1.0429081916809082\nloss: 1.081375241279602\nloss: 1.029093861579895\nloss: 1.0231525897979736\nloss: 1.0729111433029175\nloss: 0.7949182391166687\nloss: 0.6968480944633484\nloss: 1.044675350189209\nloss: 0.9089928865432739\nloss: 0.9083682298660278\nloss: 0.7775700092315674\nloss: 0.8898879289627075\nloss: 0.8356339931488037\nloss: 0.7464484572410583\nloss: 1.1672194004058838\nloss: 0.74812251329422\nloss: 0.7185171246528625\nloss: 0.6108216047286987\nloss: 1.0366991758346558\nloss: 0.795727550983429\nloss: 0.791501522064209\nloss: 0.6359931230545044\nloss: 0.8216689825057983\nloss: 0.715979814529419\nloss: 1.1524872779846191\nloss: 1.0816165208816528\nEND EPOCH #1 avg: 0.9159213260433378\nloss: 1.1054511070251465\nloss: 0.9043039679527283\nloss: 1.1845911741256714\nloss: 1.0641263723373413\nloss: 0.9565077424049377\nloss: 0.8626723885536194\nloss: 0.9958709478378296\nloss: 1.079559087753296\nloss: 1.0012873411178589\nloss: 1.0347480773925781\nloss: 1.0234328508377075\nloss: 0.9892176389694214\nloss: 1.024899959564209\nloss: 0.7989320158958435\nloss: 0.6749310493469238\nloss: 1.0227930545806885\nloss: 0.8956414461135864\nloss: 0.8723995089530945\nloss: 0.7228422164916992\nloss: 0.8645232915878296\nloss: 0.802834153175354\nloss: 0.7171276211738586\nloss: 1.1454535722732544\nloss: 0.7112791538238525\nloss: 0.751304566860199\nloss: 0.5773029327392578\nloss: 0.9820866584777832\nloss: 0.7787880897521973\nloss: 0.6983950734138489\nloss: 0.6155737042427063\nloss: 0.7751432061195374\nloss: 0.6831026673316956\nloss: 1.0839111804962158\nloss: 1.043839931488037\nEND EPOCH #2 avg: 0.8833970891300743\nloss: 1.083410620689392\nloss: 0.8858187198638916\nloss: 1.1823391914367676\nloss: 1.081310510635376\nloss: 0.9618273973464966\nloss: 0.8539998531341553\nloss: 0.9593894481658936\nloss: 1.0246202945709229\nloss: 1.008090615272522\nloss: 1.0244140625\nloss: 1.0037574768066406\nloss: 0.9788201451301575\nloss: 1.0234441757202148\nloss: 0.7437090873718262\nloss: 0.6481432318687439\nloss: 0.953135073184967\nloss: 0.8553492426872253\nloss: 0.8461558222770691\nloss: 0.7225533127784729\nloss: 0.8381380438804626\nloss: 0.76811683177948\nloss: 0.7189196944236755\nloss: 1.1184853315353394\nloss: 0.723427951335907\nloss: 0.7179039120674133\nloss: 0.5872145891189575\nloss: 0.9288179874420166\nloss: 0.7350367307662964\nloss: 0.7283239960670471\nloss: 0.6243577003479004\nloss: 0.7144389152526855\nloss: 0.7042189836502075\nloss: 1.0888075828552246\nloss: 1.0356618165969849\nEND EPOCH #3 avg: 0.8650050099784806\nloss: 1.071728229522705\nloss: 0.839587926864624\nloss: 1.15238356590271\nloss: 1.051287055015564\nloss: 0.9267892241477966\nloss: 0.8182893991470337\nloss: 0.9587641954421997\nloss: 1.03286612033844\nloss: 0.9621620178222656\nloss: 0.9935327768325806\nloss: 0.9907262921333313\nloss: 0.9586783647537231\nloss: 1.0137196779251099\nloss: 0.7292211651802063\nloss: 0.6346433162689209\nloss: 0.9699356555938721\nloss: 0.8741214871406555\nloss: 0.8274796009063721\nloss: 0.6668477654457092\nloss: 0.8392725586891174\nloss: 0.7519924640655518\nloss: 0.7219560146331787\nloss: 1.1282408237457275\nloss: 0.6899096965789795\nloss: 0.6869916319847107\nloss: 0.5826075077056885\nloss: 0.9374849200248718\nloss: 0.7292343378067017\nloss: 0.6891161799430847\nloss: 0.6209076046943665\nloss: 0.7288148403167725\nloss: 0.673041582107544\nloss: 1.0544297695159912\nloss: 1.0301791429519653\nEND EPOCH #4 avg: 0.8527683896073223\nloss: 1.0556403398513794\nloss: 0.8644134998321533\nloss: 1.134766697883606\nloss: 1.0547491312026978\nloss: 0.9298425912857056\nloss: 0.8254854679107666\nloss: 0.9497174620628357\nloss: 1.0174678564071655\nloss: 0.960101306438446\nloss: 0.9652133584022522\nloss: 0.9794471263885498\nloss: 0.9848933815956116\nloss: 0.9919844269752502\nloss: 0.7459942698478699\nloss: 0.6435001492500305\nloss: 0.984830915927887\nloss: 0.854371190071106\nloss: 0.8223806023597717\nloss: 0.6488444209098816\nloss: 0.7983894348144531\nloss: 0.7479805946350098\nloss: 0.6899083852767944\nloss: 1.0918748378753662\nloss: 0.6922121644020081\nloss: 0.7084393501281738\nloss: 0.5830597877502441\nloss: 0.900880753993988\nloss: 0.7332385778427124\nloss: 0.6541018486022949\nloss: 0.6129364371299744\nloss: 0.7105181813240051\nloss: 0.645356297492981\nloss: 1.115420937538147\nloss: 1.0224666595458984\nEND EPOCH #5 avg: 0.8461936740480231\nloss: 1.0488696098327637\nloss: 0.8805951476097107\nloss: 1.1222046613693237\nloss: 1.0275280475616455\nloss: 0.9013416171073914\nloss: 0.8165730237960815\nloss: 0.9252338409423828\nloss: 1.0125350952148438\nloss: 0.9250748157501221\nloss: 1.0036269426345825\nloss: 0.9902605414390564\nloss: 0.9469006061553955\nloss: 1.0053725242614746\nloss: 0.727440595626831\nloss: 0.6181288957595825\nloss: 0.9528722167015076\nloss: 0.8416427373886108\nloss: 0.8427289724349976\nloss: 0.6555745601654053\nloss: 0.7798478603363037\nloss: 0.7155237793922424\nloss: 0.6813979148864746\nloss: 1.061938762664795\nloss: 0.64375239610672\nloss: 0.6701700687408447\nloss: 0.5810566544532776\nloss: 0.9237428307533264\nloss: 0.7555829882621765\nloss: 0.6798772811889648\nloss: 0.6036335229873657\nloss: 0.7505882382392883\nloss: 0.6340476274490356\nloss: 1.0630533695220947\nloss: 1.031473994255066\nEND EPOCH #6 avg: 0.8362922913576725\nloss: 1.0409913063049316\nloss: 0.8402179479598999\nloss: 1.1149544715881348\nloss: 1.0278797149658203\nloss: 0.9337402582168579\nloss: 0.821302056312561\nloss: 0.9374873042106628\nloss: 0.995248019695282\nloss: 0.945940375328064\nloss: 1.0007140636444092\nloss: 0.9755243062973022\nloss: 0.9258332848548889\nloss: 1.0028263330459595\nloss: 0.7320798635482788\nloss: 0.629856288433075\nloss: 0.973311722278595\nloss: 0.80784672498703\nloss: 0.7938651442527771\nloss: 0.6481931209564209\nloss: 0.7761248350143433\nloss: 0.7249721884727478\nloss: 0.6993616819381714\nloss: 1.0777709484100342\nloss: 0.6563688516616821\nloss: 0.6769535541534424\nloss: 0.5799486637115479\nloss: 0.9209359288215637\nloss: 0.7030892372131348\nloss: 0.6731210350990295\nloss: 0.6070143580436707\nloss: 0.7212318778038025\nloss: 0.6338415741920471\nloss: 1.0464491844177246\nloss: 1.0131089687347412\nEND EPOCH #7 avg: 0.8302864148419284\n \n \nTraining Time: 5442.206134796143\n\nTest trained model on images\n\ntest_imgs=[]\n\nfor file in os.listdir(\"/kaggle/input/global-wheat-detection/test/\"):\n\n    test_imgs.append(file)\n\n​\n\nmodel = model.to(device)\n\nmodel.eval()\n\n​\n\nprint(\"Begin testing\")\n\n​\n\npredsA,scoresA=[],[]\n\nfor image_id in test_imgs:\n\n​\n\n    #img = im.imread(\"/kaggle/input/global-wheat-detection/test/{}\".format(image_id))\n\n    pic_path = \"/kaggle/input/global-wheat-detection/test/{}\".format(image_id)\n\n    img=Image.open( pic_path )\n\n    enhancer = PIL.ImageEnhance.Contrast(img)\n\n    im_output = enhancer.enhance(2)\n\n​\n\n    img=np.array( im_output )\n\n        \n\n    print( img.shape )\n\n    img=torchvision.transforms.functional.to_tensor(img).to(device)\n\n    preds = model([img])[0]\n\n    \n\n    #print(preds)\n\n    \n\n    predsA.append( preds[\"boxes\"].detach().cpu().numpy() )\n\n    scoresA.append( preds[\"scores\"].detach().cpu().numpy() )\n\n​\n\n​\n\n#torch.save(model.state_dict(), 'fasterRCNN_101.pth')\n\n​\n\nBegin testing\n(1024, 1024, 3)\n(1024, 1024, 3)\n(1024, 1024, 3)\n(1024, 1024, 3)\n(1024, 1024, 3)\n(1024, 1024, 3)\n(1024, 1024, 3)\n(1024, 1024, 3)\n(1024, 1024, 3)\n(1024, 1024, 3)\n\nprint(scoresA)\n\n[array([0.97807443, 0.9753739 , 0.97003776, 0.9584341 , 0.9491141 ,\n       0.9333785 , 0.9311873 , 0.86149406, 0.8526346 , 0.8466793 ,\n       0.8051504 , 0.8004479 , 0.7830257 , 0.7636314 , 0.74014527,\n       0.61116433, 0.5696377 , 0.49029648, 0.4890823 , 0.45735744,\n       0.36451694, 0.36082876, 0.3417122 , 0.30376065, 0.27701193,\n       0.26202998, 0.2519644 , 0.19107942, 0.18816645, 0.1390586 ,\n       0.13788958, 0.11886665, 0.10898799, 0.09486211, 0.08454068,\n       0.07993189, 0.07656579, 0.07069565, 0.06685372, 0.06659518,\n       0.06460207, 0.06321312, 0.06282053, 0.05628582, 0.05579887,\n       0.05426925, 0.05326167, 0.05139584], dtype=float32), array([0.9880822 , 0.98526037, 0.98469514, 0.9840082 , 0.98274857,\n       0.9821832 , 0.9815285 , 0.9799073 , 0.9760517 , 0.97459203,\n       0.9673014 , 0.9664239 , 0.9641636 , 0.9609325 , 0.95094067,\n       0.9371962 , 0.9316037 , 0.89728373, 0.8591849 , 0.85757965,\n       0.8561401 , 0.7270324 , 0.72366536, 0.52253556, 0.4932982 ,\n       0.27712357, 0.23671183, 0.20237227, 0.1486367 , 0.13519245,\n       0.13128284, 0.11732569, 0.09069648, 0.08852869, 0.08696767,\n       0.08276133, 0.07664495, 0.06272565, 0.06268521, 0.0579011 ,\n       0.0526136 , 0.05180103], dtype=float32), array([0.96926874, 0.9686326 , 0.96595055, 0.963764  , 0.963527  ,\n       0.9605326 , 0.95130205, 0.9506546 , 0.94426364, 0.93546236,\n       0.9339509 , 0.9182916 , 0.91349477, 0.9056246 , 0.8467633 ,\n       0.76552916, 0.75501007, 0.751316  , 0.42639443, 0.37764174,\n       0.31778452, 0.2775363 , 0.20944071, 0.20469317, 0.19141531,\n       0.17881714, 0.1765811 , 0.17129898, 0.1618251 , 0.14996876,\n       0.13941824, 0.1222906 , 0.11696491, 0.11379523, 0.10783732,\n       0.0995105 , 0.08536722, 0.07617257, 0.07592005, 0.0751294 ,\n       0.07172281, 0.06568614, 0.06424253, 0.06302674, 0.0559894 ,\n       0.05454595, 0.05410636, 0.05233131], dtype=float32), array([0.9906482 , 0.9889233 , 0.98746127, 0.9858483 , 0.98507684,\n       0.9846064 , 0.98418623, 0.9830482 , 0.982822  , 0.9820518 ,\n       0.9771261 , 0.97487295, 0.974647  , 0.9720864 , 0.9718478 ,\n       0.97070247, 0.9681864 , 0.9676042 , 0.9624396 , 0.96031547,\n       0.9231909 , 0.89654034, 0.89006037, 0.87983066, 0.7935773 ,\n       0.6586753 , 0.47726876, 0.34778586, 0.3177151 , 0.19899267,\n       0.17562541, 0.15428853, 0.14881663, 0.14308447, 0.12808037,\n       0.1142918 , 0.09796544, 0.09389071, 0.09190769, 0.09175417,\n       0.07347901, 0.07244246, 0.07065839, 0.06753799, 0.06291909,\n       0.05980609, 0.05719017, 0.0548024 ], dtype=float32), array([0.981058  , 0.9790075 , 0.9747347 , 0.9724988 , 0.97099733,\n       0.97004336, 0.96750456, 0.9641676 , 0.9613948 , 0.9599943 ,\n       0.9567954 , 0.95253134, 0.94180477, 0.93772703, 0.93274325,\n       0.9322776 , 0.9310487 , 0.9268871 , 0.9222758 , 0.85463804,\n       0.84856707, 0.62681216, 0.60830355, 0.47720996, 0.33076078,\n       0.20617661, 0.17868303, 0.17134936, 0.15014587, 0.13783568,\n       0.1285725 , 0.11202935, 0.08783555, 0.08355907, 0.07882313,\n       0.07356532, 0.0558968 ], dtype=float32), array([0.9859066 , 0.97469455, 0.9727947 , 0.9677788 , 0.9666885 ,\n       0.96276265, 0.9521699 , 0.9420549 , 0.937476  , 0.9308226 ,\n       0.91539234, 0.86911494, 0.8339428 , 0.7447064 , 0.68574244,\n       0.6792095 , 0.6782478 , 0.62064093, 0.44809556, 0.3744241 ,\n       0.36416447, 0.30141994, 0.2963251 , 0.2800056 , 0.2442305 ,\n       0.23109524, 0.20950526, 0.1923969 , 0.1911544 , 0.17397188,\n       0.17362803, 0.13694075, 0.12820157, 0.11839604, 0.11618487,\n       0.11051968, 0.10176627, 0.10091935, 0.09999033, 0.08622714,\n       0.08428813, 0.08384799, 0.06906297, 0.06730299, 0.05441818,\n       0.05317609, 0.05232513], dtype=float32), array([0.9904417 , 0.98794216, 0.98743385, 0.9870027 , 0.9853139 ,\n       0.98453563, 0.98327625, 0.9830178 , 0.9779382 , 0.97510934,\n       0.9731213 , 0.9716904 , 0.96447146, 0.96224684, 0.9616763 ,\n       0.96087414, 0.95982945, 0.95008993, 0.94770426, 0.9441898 ,\n       0.9209652 , 0.91897523, 0.9084852 , 0.9063913 , 0.8931875 ,\n       0.8844235 , 0.87914735, 0.7625479 , 0.7620654 , 0.70382804,\n       0.69746155, 0.6780654 , 0.67320704, 0.6643801 , 0.6268324 ,\n       0.3819922 , 0.38195658, 0.19163412, 0.18259083, 0.13692348,\n       0.10954501, 0.0788341 , 0.06336594, 0.05507063, 0.05135394],\n      dtype=float32), array([0.9888786 , 0.9887102 , 0.9887101 , 0.9887038 , 0.98769337,\n       0.9874636 , 0.98576593, 0.9846907 , 0.9835909 , 0.98356676,\n       0.98221177, 0.9780001 , 0.97488153, 0.97219163, 0.9706516 ,\n       0.96896714, 0.9667318 , 0.9560996 , 0.9305987 , 0.928595  ,\n       0.9283766 , 0.8719414 , 0.81975615, 0.7699161 , 0.3963539 ,\n       0.39000934, 0.16117196, 0.16087157, 0.15147269, 0.1266664 ,\n       0.11887079, 0.10065451, 0.08527206, 0.08496463, 0.07349262,\n       0.06381813, 0.05736136, 0.05336627, 0.05210874, 0.0513335 ,\n       0.05026396], dtype=float32), array([0.9820967 , 0.97006893, 0.9696916 , 0.96810406, 0.96587634,\n       0.96471936, 0.9629513 , 0.95973283, 0.9596717 , 0.9514466 ,\n       0.93655187, 0.9303815 , 0.92793506, 0.92087674, 0.915446  ,\n       0.89878964, 0.8660321 , 0.86346656, 0.8480074 , 0.8468629 ,\n       0.80761194, 0.6321597 , 0.3658223 , 0.18738379, 0.160436  ,\n       0.10506778, 0.08925476, 0.07362913, 0.07258227], dtype=float32), array([0.9901336 , 0.98769826, 0.98649085, 0.98544127, 0.9834849 ,\n       0.9820218 , 0.9799243 , 0.97848207, 0.97819513, 0.97787744,\n       0.9719902 , 0.96999425, 0.9694765 , 0.96923906, 0.9682566 ,\n       0.96564865, 0.9641009 , 0.95245874, 0.9515392 , 0.949231  ,\n       0.9373602 , 0.93562853, 0.9313646 , 0.9210315 , 0.8641027 ,\n       0.86239034, 0.8339733 , 0.81361616, 0.52072227, 0.4717853 ,\n       0.21615691, 0.15515174, 0.1385189 , 0.13105182, 0.12034093,\n       0.11816803, 0.11382288, 0.11207241, 0.10904637, 0.07651953,\n       0.07386469, 0.06472921, 0.06423542, 0.06102907, 0.05260476],\n      dtype=float32)]\n\nimport matplotlib\n\n​\n\n​\n\nfig, ax = plt.subplots(10,figsize=(60,60))\n\n​\n\nfor i,boxes in enumerate(predsA):\n\n    img = im.imread(\"/kaggle/input/global-wheat-detection/test/{}\".format(test_imgs[i]))\n\n    ax[i].imshow(img)\n\n    for c in boxes:\n\n        rect = matplotlib.patches.Rectangle((c[0],c[1]),c[2]-c[0],c[3]-c[1],linewidth=1,edgecolor='r',facecolor='none')\n\n        ax[i].add_patch(rect)\n\n​\n\nplt.show()\n\n---------------------------------------------------------------------------\nAttributeError                            Traceback (most recent call last)\n<ipython-input-28-82cf3d006f4b> in <module>\n      5 \n      6 for i,boxes in enumerate(predsA):\n----> 7     img = im.imread(\"/kaggle/input/global-wheat-detection/test/{}\".format(test_imgs[i]))\n      8     ax[i].imshow(img)\n      9     for c in boxes:\n\nAttributeError: 'JpegImageFile' object has no attribute 'imread'\n\n\n\n    def __len__(self):\n        return len(self.imgs)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Check that the dataset object worked as expected"},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\nCheck.\n\"\"\"\ndataset = ImageDataset()\ndata_loader = DataLoader(dataset,batch_size=50,collate_fn=lambda batch: list(zip(*batch)) )\n\nimages, targets= next(iter(data_loader))\n\nidx=45\n\nimg= images[idx].permute(1,2,0).numpy()\n\nprint(img.shape)\n\nfig, ax = plt.subplots(figsize=(10, 10))\n\nax.imshow(img)\n\nboxes=targets[idx][\"boxes\"].numpy()\n\nfor c in boxes:\n    rect = matplotlib.patches.Rectangle((c[0],c[1]),c[2]-c[0],c[3]-c[1],linewidth=1,edgecolor='r',facecolor='none')\n    ax.add_patch(rect)\n\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Download the model"},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\nDownload and set up model\n\"\"\"     \ntorchvision.__version__\n\nmodel=torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True, progress=True, pretrained_backbone=True, trainable_backbone_layers=5)\n\nnum_classes = 2  # 1 class (wheat) + background\nin_features = model.roi_heads.box_predictor.cls_score.in_features\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n\ndevice = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Set up training loop"},{"metadata":{"trusted":true},"cell_type":"code","source":"from torch import optim\nimport time\nstart_time = time.time()\n\ndataset = ImageDataset()\ndata_loader = DataLoader(dataset,batch_size=10,collate_fn=lambda batch: list(zip(*batch)) )\n\nEPOCHS=32\n\nmodel = model.to(device)\nmodel.train()\n\n\nparams = [p for p in model.parameters() if p.requires_grad]\noptimizer = torch.optim.SGD(params, lr=0.0005, momentum=0.9, weight_decay=0.0005)\n#scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=5,cooldown=20,factor=0.65,min_lr=0.00001,verbose=True)\n\nprint(\"Begin training\")\nlossAvg,lossPer=[],[]\nfor epoch in range(EPOCHS):\n    total_loss,count=0,0\n    for batch in data_loader:\n        #check if targets is a list\n        images,targets=batch\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        losses = sum(loss for loss in loss_dict.values())\n        \n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n        \n        if count%10==0:\n            #scheduler.step(losses)\n            print(\"loss: {}\".format( losses.item() ))\n            lossPer.append(losses.item())\n        count+=1\n        total_loss+=losses.item()\n    g=total_loss/count \n    lossAvg.append( g )\n    print(\"END EPOCH #{} avg: {}\".format(epoch,total_loss/count))\n    \nprint(\" \")\nprint(\" \")\nprint(\"Training Time: {}\".format( time.time() - start_time ))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Test trained model on images"},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib\nimport matplotlib.image as im_age\n\ndef make_contrast(pic_path):\n    img=Image.open( pic_path )\n    enhancer = PIL.ImageEnhance.Contrast(img)\n    im_output = enhancer.enhance(3)\n\n    return np.array( im_output )\n\n\ntest_imgs=[]\nfor file in os.listdir(\"/kaggle/input/global-wheat-detection/test/\"):\n    test_imgs.append(file)\n\nmodel = model.to(device)\nmodel.eval()\n\nprint(\"Begin testing\")\n\npredsA,scoresA=[],[]\nfor image_id in test_imgs:\n\n    pic_path = \"/kaggle/input/global-wheat-detection/test/{}\".format(image_id)\n    #img=make_contrast(pic_path)\n    img = im_age.imread(pic_path)\n        \n    print( img.shape )\n    img=torchvision.transforms.functional.to_tensor(img).to(device)\n    preds = model([img])[0]\n    \n    #print(preds)\n    \n    predsA.append( preds[\"boxes\"].detach().cpu().numpy() )\n    scoresA.append( preds[\"scores\"].detach().cpu().numpy() )\n\n\n#torch.save(model.state_dict(), 'fasterRCNN_101.pth')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print( len(scoresA[0]) )\nprint( predsA[0] )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib\nimport matplotlib.image as im_age\n\nfig, ax = plt.subplots(10,figsize=(60,60))\n\nfor i,pic in enumerate(predsA):\n    img = im_age.imread(\"/kaggle/input/global-wheat-detection/test/{}\".format(test_imgs[i]))\n    ax[i].imshow(img)\n    for j,box in enumerate(pic):\n        if scoresA[i][j]>0.2:\n            rect = matplotlib.patches.Rectangle((box[0],box[1]),box[2]-box[0],box[3]-box[1],linewidth=1,edgecolor='r',facecolor='none')\n            ax[i].add_patch(rect)\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# test_df=pd.read_csv(\"{}{}.csv\".format(\"/kaggle/input/global-wheat-detection/\",\"test\"))\n\n# test_df\n\n\n#print(os.listdir(\"/kaggle/input/global-wheat-detection/\",))\n\n#for i,boxes in enumerate(predsA):","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}