{"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":"markdown","source":"## Introductin\n* Reference kernel => https://www.kaggle.com/sovitrath/pytorch-starter-faster-rcnn-train?scriptVersionId=38399463","metadata":{}},{"cell_type":"code","source":"# !pip install --upgrade torch torchvision torchaudio","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:02.699911Z","iopub.execute_input":"2021-08-19T03:59:02.700361Z","iopub.status.idle":"2021-08-19T03:59:02.706388Z","shell.execute_reply.started":"2021-08-19T03:59:02.700269Z","shell.execute_reply":"2021-08-19T03:59:02.705279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install efficientnet_pytorch","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:02.765281Z","iopub.execute_input":"2021-08-19T03:59:02.765616Z","iopub.status.idle":"2021-08-19T03:59:13.539083Z","shell.execute_reply.started":"2021-08-19T03:59:02.765587Z","shell.execute_reply":"2021-08-19T03:59:13.538008Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\n\ntorch.__version__","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:13.542849Z","iopub.execute_input":"2021-08-19T03:59:13.543159Z","iopub.status.idle":"2021-08-19T03:59:14.920018Z","shell.execute_reply.started":"2021-08-19T03:59:13.543126Z","shell.execute_reply":"2021-08-19T03:59:14.919142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## All Imports","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport cv2\nimport os\nimport re\nimport albumentations as A\nimport torch\nimport torchvision\nimport time\n\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, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\nfrom PIL import Image\nfrom albumentations.pytorch.transforms import ToTensorV2\nfrom matplotlib import pyplot as plt\nfrom tqdm import tqdm\n\nimport matplotlib \nmatplotlib.style.use('ggplot')","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:14.921799Z","iopub.execute_input":"2021-08-19T03:59:14.922092Z","iopub.status.idle":"2021-08-19T03:59:16.923117Z","shell.execute_reply.started":"2021-08-19T03:59:14.922044Z","shell.execute_reply":"2021-08-19T03:59:16.922160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Constant Paths","metadata":{}},{"cell_type":"code","source":"DIR_INPUT = '../input/global-wheat-detection'\nDIR_TRAIN = f\"{DIR_INPUT}/train\"\nDIR_TEST = f\"{DIR_INPUT}/test\"","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:16.924912Z","iopub.execute_input":"2021-08-19T03:59:16.925329Z","iopub.status.idle":"2021-08-19T03:59:16.929700Z","shell.execute_reply.started":"2021-08-19T03:59:16.925287Z","shell.execute_reply":"2021-08-19T03:59:16.928782Z"},"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":{"execution":{"iopub.status.busy":"2021-08-19T03:59:16.931205Z","iopub.execute_input":"2021-08-19T03:59:16.931826Z","iopub.status.idle":"2021-08-19T03:59:16.988129Z","shell.execute_reply.started":"2021-08-19T03:59:16.931782Z","shell.execute_reply":"2021-08-19T03:59:16.987164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create Model","metadata":{}},{"cell_type":"code","source":"# # load the model\n# model = torchvision.models.resnet18(pretrained=True).eval()\n# # hook the feature extractor\n# # https://github.com/zhoubolei/CAM/blob/master/pytorch_CAM.py\n# features_blobs = []\n# def hook_feature(module, input, output):\n#     features_blobs.append(output.data.cpu().numpy())\n    \n# new_model = model._modules.get('layer4').register_forward_hook(hook_feature)\n# print(new_model)","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:16.991847Z","iopub.execute_input":"2021-08-19T03:59:16.992179Z","iopub.status.idle":"2021-08-19T03:59:16.999986Z","shell.execute_reply.started":"2021-08-19T03:59:16.992148Z","shell.execute_reply":"2021-08-19T03:59:16.998936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"\nmodel.py\n\nWe will create a FasterRCNN object detector with EfficientNet backbone for custom training.\nReference: https://github.com/lukemelas/EfficientNet-PyTorch\n\"\"\"\ndef create_model():\n    from efficientnet_pytorch import EfficientNet\n#     backbone = EfficientNet.from_pretrained('efficientnet-b0')\n#     print(backbone)\n    conv_stem = torch.nn.Sequential(EfficientNet.from_pretrained('efficientnet-b0')._conv_stem)\n    bn = torch.nn.Sequential(EfficientNet.from_pretrained('efficientnet-b0')._bn0)\n    blocks = torch.nn.Sequential(*EfficientNet.from_pretrained('efficientnet-b0')._blocks)\n    conv_head = torch.nn.Sequential(EfficientNet.from_pretrained('efficientnet-b0')._conv_head)\n#     conv_head.out_channels = 1280\n    backbone = torch.nn.Sequential(conv_stem, bn, blocks, conv_head)\n    backbone.out_channels = 1280\n    print(backbone)\n    # FasterRCNN needs to know the number of\n    # output channels in a backbone. For EfficientNetB0, it's 1280\n    # so we need to add it here\n#     backbone.out_channels = 1280\n    print('-'*70)\n#     print(backbone)\n    # let's make the RPN generate 5 x 3 anchors per spatial\n    # location, with 5 different sizes and 3 different aspect\n    # ratios. We have a Tuple[Tuple[int]] because each feature\n    # map could potentially have different sizes and\n    # aspect ratios\n    anchor_generator = AnchorGenerator(sizes=((32, 64, 128, 256, 512),),\n                                       aspect_ratios=((0.5, 1.0, 2.0),))\n    \n    # let's define what are the feature maps that we will\n    # use to perform the region of interest cropping, as well as\n    # the size of the crop after rescaling.\n    # if your backbone returns a Tensor, featmap_names is expected to\n    # be [0]. More generally, the backbone should return an\n    # OrderedDict[Tensor], and in featmap_names you can choose which\n    # feature maps to use.\n    roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'],\n                                                    output_size=7, \n                                                    sampling_ratio=2)\n    # put everything together\n    model = FasterRCNN(backbone, \n                       num_classes=2, \n                       rpn_anchor_generator=anchor_generator,\n                       box_roi_pool=roi_pooler) \n    return model\n\nmodel = create_model()\nprint('-'*50)\n# print(model)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-08-19T03:59:17.001612Z","iopub.execute_input":"2021-08-19T03:59:17.002035Z","iopub.status.idle":"2021-08-19T03:59:19.108183Z","shell.execute_reply.started":"2021-08-19T03:59:17.001992Z","shell.execute_reply":"2021-08-19T03:59:19.107186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare Proper DataFrame","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv(f\"{DIR_INPUT}/train.csv\")\nprint(train_df.shape)\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:19.111343Z","iopub.execute_input":"2021-08-19T03:59:19.111746Z","iopub.status.idle":"2021-08-19T03:59:19.380109Z","shell.execute_reply.started":"2021-08-19T03:59:19.111701Z","shell.execute_reply":"2021-08-19T03:59:19.379212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['x'] = -1\ntrain_df['y'] = -1\ntrain_df['w'] = -1\ntrain_df['h'] = -1\n\ndef expand_bbox(x):\n    r = np.array(re.findall(\"([0-9]+[.]?[0-9]*)\", x))\n    if len(r) == 0:\n        r = [-1, -1, -1, -1]\n    return r\n\ntrain_df[['x', 'y', 'w', 'h']] = np.stack(train_df['bbox'].apply(lambda x: expand_bbox(x)))\ntrain_df.drop(columns=['bbox'], inplace=True)\ntrain_df['x'] = train_df['x'].astype(np.float)\ntrain_df['y'] = train_df['y'].astype(np.float)\ntrain_df['w'] = train_df['w'].astype(np.float)\ntrain_df['h'] = train_df['h'].astype(np.float)\n\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:19.382196Z","iopub.execute_input":"2021-08-19T03:59:19.382598Z","iopub.status.idle":"2021-08-19T03:59:21.299378Z","shell.execute_reply.started":"2021-08-19T03:59:19.382557Z","shell.execute_reply":"2021-08-19T03:59:21.298161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unique_image_ids = train_df['image_id'].unique()\nprint(f\"Uninque image IDs: {len(unique_image_ids)}\")\nvalid_ids = unique_image_ids[-665:]\ntrain_ids = unique_image_ids[:-665]\nprint(f\"Unqiue image IDs for training: {len(train_ids)}\")\nprint(f\"Unqiue image IDs for validation: {len(valid_ids)}\")","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.301185Z","iopub.execute_input":"2021-08-19T03:59:21.301627Z","iopub.status.idle":"2021-08-19T03:59:21.322464Z","shell.execute_reply.started":"2021-08-19T03:59:21.301581Z","shell.execute_reply":"2021-08-19T03:59:21.321081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df = train_df[train_df['image_id'].isin(valid_ids)]\ntrain_df = train_df[train_df['image_id'].isin(train_ids)]\n\nprint(f\"Total training annotation instances: {len(train_df)}\")\nprint(f\"Total validation annotation instances: {len(valid_df)}\")","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.324138Z","iopub.execute_input":"2021-08-19T03:59:21.324872Z","iopub.status.idle":"2021-08-19T03:59:21.371846Z","shell.execute_reply.started":"2021-08-19T03:59:21.324826Z","shell.execute_reply":"2021-08-19T03:59:21.370913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head(7)","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.373242Z","iopub.execute_input":"2021-08-19T03:59:21.373604Z","iopub.status.idle":"2021-08-19T03:59:21.394142Z","shell.execute_reply.started":"2021-08-19T03:59:21.373568Z","shell.execute_reply":"2021-08-19T03:59:21.392544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df.head(7)","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.396422Z","iopub.execute_input":"2021-08-19T03:59:21.397219Z","iopub.status.idle":"2021-08-19T03:59:21.421664Z","shell.execute_reply.started":"2021-08-19T03:59:21.397151Z","shell.execute_reply":"2021-08-19T03:59:21.420669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare Dataset","metadata":{}},{"cell_type":"code","source":"class WheatDataset(Dataset):\n    def __init__(self, dataframe, image_dir, transforms=None):\n        super().__init__()\n        \n        self.image_ids = dataframe['image_id'].unique()\n        self.df = dataframe\n        self.image_dir = image_dir\n        self.transforms = transforms\n        \n    def __getitem__(self, index: int):\n        image_id = self.image_ids[index]\n        records = self.df[self.df['image_id'] == image_id]\n        \n        image = cv2.imread(f\"{self.image_dir}/{image_id}.jpg\", cv2.IMREAD_COLOR).astype(np.float32)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        image /= 255.0\n        \n        boxes = records[['x', 'y', 'w', 'h']].values\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        # as there is only one class\n        labels = torch.ones((records.shape[0], ), dtype=torch.int64)\n        \n        # no crowd instances\n        iscrowd = torch.zeros((records.shape[0], ), dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = boxes\n        target['labels'] = labels\n        target['image_id'] = torch.tensor([index])\n        target['area'] = area\n        target['iscrowd'] = iscrowd\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.stack(tuple(map(torch.FloatTensor, zip(*sample['bboxes'])))).permute(1, 0)\n            \n            return image, target, image_id\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.422956Z","iopub.execute_input":"2021-08-19T03:59:21.423361Z","iopub.status.idle":"2021-08-19T03:59:21.440167Z","shell.execute_reply.started":"2021-08-19T03:59:21.423315Z","shell.execute_reply":"2021-08-19T03:59:21.438628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Transforms","metadata":{}},{"cell_type":"code","source":"# define the training tranforms\ndef get_train_transform():\n    return A.Compose([\n        A.Flip(0.5),\n        A.RandomRotate90(0.5),\n        A.MotionBlur(p=0.2),\n        A.MedianBlur(blur_limit=3, p=0.1),\n        A.Blur(blur_limit=3, p=0.1),\n        ToTensorV2(p=1.0),\n    ], bbox_params={\n        'format': 'pascal_voc',\n        'label_fields': ['labels']\n    })\n\n# define the validation transforms\ndef get_valid_transform():\n    return A.Compose([\n        ToTensorV2(p=1.0),\n    ], bbox_params={\n        'format': 'pascal_voc', \n        'label_fields': ['labels']\n    })","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.442464Z","iopub.execute_input":"2021-08-19T03:59:21.443042Z","iopub.status.idle":"2021-08-19T03:59:21.454558Z","shell.execute_reply.started":"2021-08-19T03:59:21.442993Z","shell.execute_reply":"2021-08-19T03:59:21.453440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Utilities and Helper Functions","metadata":{}},{"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":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.458259Z","iopub.execute_input":"2021-08-19T03:59:21.458574Z","iopub.status.idle":"2021-08-19T03:59:21.470424Z","shell.execute_reply.started":"2021-08-19T03:59:21.458543Z","shell.execute_reply":"2021-08-19T03:59:21.469281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 8\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ntrain_dataset = WheatDataset(train_df, DIR_TRAIN, get_train_transform())\nvalid_dataset = WheatDataset(valid_df, DIR_TRAIN, get_valid_transform())\n\ntrain_data_loader = DataLoader(\n    train_dataset,\n    batch_size=BATCH_SIZE,\n    shuffle=True,\n    num_workers=4,\n    collate_fn=collate_fn\n)\n\nvalid_data_loader = DataLoader(\n    valid_dataset,\n    batch_size=BATCH_SIZE,\n    shuffle=False,\n    num_workers=4,\n    collate_fn=collate_fn\n)","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.474415Z","iopub.execute_input":"2021-08-19T03:59:21.474766Z","iopub.status.idle":"2021-08-19T03:59:21.498209Z","shell.execute_reply.started":"2021-08-19T03:59:21.474734Z","shell.execute_reply":"2021-08-19T03:59:21.497276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Sample Visualization","metadata":{}},{"cell_type":"code","source":"images, targets, image_ids = next(iter(train_data_loader))\nimages = list(image.to(DEVICE) for image in images)\ntargets = [{k: v.to(DEVICE) for k, v in t.items()} for t in targets]","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:21.499692Z","iopub.execute_input":"2021-08-19T03:59:21.500088Z","iopub.status.idle":"2021-08-19T03:59:30.835734Z","shell.execute_reply.started":"2021-08-19T03:59:21.500024Z","shell.execute_reply":"2021-08-19T03:59:30.834625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(2):\n    boxes = targets[i]['boxes'].cpu().numpy().astype(np.int32)\n    sample = images[i].permute(1, 2, 0).cpu().numpy()\n    plt.figure(figsize=(12, 9))\n    sample = cv2.cvtColor(sample, cv2.COLOR_RGB2BGR)\n    for box in boxes:\n#         print(box)\n        cv2.rectangle(sample,  # the image is in RGB, convert to BGR for cv2 annotations\n                      (box[0], box[1]),\n                      (box[2], box[3]),\n                      (0, 0, 255), 3)\n    plt.imshow(sample[:, :, ::-1])\n    plt.axis('off')","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:30.839694Z","iopub.execute_input":"2021-08-19T03:59:30.840032Z","iopub.status.idle":"2021-08-19T03:59:31.899630Z","shell.execute_reply.started":"2021-08-19T03:59:30.839997Z","shell.execute_reply":"2021-08-19T03:59:31.898538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{}},{"cell_type":"code","source":"model = model.to(DEVICE)","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:31.901232Z","iopub.execute_input":"2021-08-19T03:59:31.901624Z","iopub.status.idle":"2021-08-19T03:59:32.023284Z","shell.execute_reply.started":"2021-08-19T03:59:31.901586Z","shell.execute_reply":"2021-08-19T03:59:32.022370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print(model)","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:32.024710Z","iopub.execute_input":"2021-08-19T03:59:32.025108Z","iopub.status.idle":"2021-08-19T03:59:32.029311Z","shell.execute_reply.started":"2021-08-19T03:59:32.025052Z","shell.execute_reply":"2021-08-19T03:59:32.028243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"params = [p for p in model.parameters() if p.requires_grad]\noptimizer = torch.optim.SGD(params, lr=0.001, momentum=0.9, weight_decay=0.0005)\nlr_scheduler = None","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:32.031087Z","iopub.execute_input":"2021-08-19T03:59:32.031529Z","iopub.status.idle":"2021-08-19T03:59:32.044958Z","shell.execute_reply.started":"2021-08-19T03:59:32.031486Z","shell.execute_reply":"2021-08-19T03:59:32.043652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUM_EPOCHS = 55","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:32.049517Z","iopub.execute_input":"2021-08-19T03:59:32.049838Z","iopub.status.idle":"2021-08-19T03:59:32.056367Z","shell.execute_reply.started":"2021-08-19T03:59:32.049810Z","shell.execute_reply":"2021-08-19T03:59:32.055409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loss_hist = Averager()\nval_loss_hist = Averager()\ntrain_itr = 1\nval_itr = 1\ntrain_loss_list = []\nval_loss_list = []","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:32.058299Z","iopub.execute_input":"2021-08-19T03:59:32.058792Z","iopub.status.idle":"2021-08-19T03:59:32.066303Z","shell.execute_reply.started":"2021-08-19T03:59:32.058725Z","shell.execute_reply":"2021-08-19T03:59:32.065429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(train_data_loader):\n    global train_itr\n    global train_loss_list\n    for i, data in enumerate(train_data_loader):\n        images, targets, image_ids = data\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        train_loss_list.append(loss_value)\n\n        train_loss_hist.send(loss_value)\n\n        optimizer.zero_grad()\n\n        losses.backward()\n        optimizer.step()\n\n        if train_itr % 50 == 0:\n            print(f\"Training iteration #{train_itr} loss: {loss_value}\")\n\n        train_itr += 1\n    \n    # update the learning rate\n    if lr_scheduler is not None:\n        lr_scheduler.step()\n    return train_loss_list","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:32.068122Z","iopub.execute_input":"2021-08-19T03:59:32.068607Z","iopub.status.idle":"2021-08-19T03:59:32.078625Z","shell.execute_reply.started":"2021-08-19T03:59:32.068566Z","shell.execute_reply":"2021-08-19T03:59:32.077637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def validate(valid_data_loader):\n    global val_itr\n    global val_loss_list\n    for i, data in enumerate(valid_data_loader):\n        images, targets, image_ids = data\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        with torch.no_grad():\n            loss_dict = model(images, targets)\n\n        losses = sum(loss for loss in loss_dict.values())\n        loss_value = losses.item()\n        val_loss_list.append(loss_value)\n\n        val_loss_hist.send(loss_value)\n\n#         if itr % 50 == 0:\n#             print(f\"Validation iteration #{itr} loss: {loss_value}\")\n\n        val_itr += 1\n    \n    # update the learning rate\n#     if lr_scheduler is not None:\n#         lr_scheduler.step()\n    return val_loss_list","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:32.080247Z","iopub.execute_input":"2021-08-19T03:59:32.080670Z","iopub.status.idle":"2021-08-19T03:59:32.088895Z","shell.execute_reply.started":"2021-08-19T03:59:32.080627Z","shell.execute_reply":"2021-08-19T03:59:32.087950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for epoch in range(NUM_EPOCHS):\n    start = time.time()\n    train_loss_hist.reset()\n    val_loss_hist.reset()\n    train_loss = train(train_data_loader)\n    val_loss = validate(valid_data_loader)\n    print(f\"Epoch #{epoch} train loss: {train_loss_hist.value}\")   \n    print(f\"Epoch #{epoch} validation loss: {val_loss_hist.value}\")   \n    end = time.time()\n    print(f\"Took {(end - start) / 60} minutes for epoch {epoch}\")\n    print('SAVING MODEL...')\n    if epoch % 5 == 0:\n        torch.save(model.state_dict(), f\"fasterrcnn_efficientnetb0_{epoch+1}.pth\")\n    print('SAVING COMPLETE...\\n')\n    \n    \n    plt.plot(val_loss, color='red')\n    plt.plot(train_loss, color='blue', alpha=0.5)\n    plt.xlabel('iterations')\n    plt.ylabel('loss')\n    plt.savefig(f\"loss_{epoch+1}.png\")\n    if epoch % 5 == 0:\n        plt.show()\n    plt.close","metadata":{"execution":{"iopub.status.busy":"2021-08-19T03:59:32.090470Z","iopub.execute_input":"2021-08-19T03:59:32.091116Z","iopub.status.idle":"2021-08-19T04:06:33.672907Z","shell.execute_reply.started":"2021-08-19T03:59:32.091054Z","shell.execute_reply":"2021-08-19T04:06:33.669726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}