{"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 # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport re\nfrom tqdm import tqdm\nfrom torch.utils.data import Dataset, DataLoader\nfrom albumentations import *\nimport random\nimport cv2\nimport torch\nfrom matplotlib import pyplot as plt\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","scrolled":true,"execution":{"iopub.status.busy":"2021-11-23T08:26:53.804178Z","iopub.execute_input":"2021-11-23T08:26:53.804559Z","iopub.status.idle":"2021-11-23T08:26:57.122275Z","shell.execute_reply.started":"2021-11-23T08:26:53.804434Z","shell.execute_reply":"2021-11-23T08:26:57.121309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#show nhiều ảnh\ndef plot_imgs(imgs, cols=5, size=7, is_rgb=False):\n    rows = len(imgs)//cols + 1\n    fig = plt.figure(figsize=(cols*size, rows*size))\n    for i, img in enumerate(imgs):\n        fig.add_subplot(rows, cols, i+1)\n        if is_rgb:\n            plt.imshow(img)\n        else:\n            plt.imshow(img[:,:,::-1])\n    plt.show()\n\n# vẽ bounding box lên ảnh\ndef visualize_bbox(img, boxes, thickness=3, color=(255, 0, 0)):\n    img_copy = img.copy()\n    for box in boxes:\n        img_copy = cv2.rectangle(\n            img_copy,\n            (int(box[0]), int(box[1])),\n            (int(box[2]), int(box[3])),\n            color, thickness)\n    return img_copy\n\n# load ảnh\ndef load_img(img_id, folder):\n    img_fn = f\"{folder}/{img_id}.jpg\"\n    img = cv2.imread(img_fn).astype(np.float32)\n    img /= 255.0\n    return img\n\ndef plot_imgs_and_boxes(imgs, boxes, cols=5, size=7, is_rgb=False, thickness=3, color=(255, 0, 0)):\n    rows = len(imgs)//cols + 1\n    fig = plt.figure(figsize=(cols*size, rows*size))\n    \n    for i, img in enumerate(imgs):\n        \n        new_img = img.copy()\n        \n        for box in boxes[i]['boxes']:\n            new_img = cv2.rectangle(\n            new_img,\n            (int(box[0]), int(box[1])),\n            (int(box[2]), int(box[3])),\n            color, thickness)\n        \n        fig.add_subplot(rows, cols, i+1)\n        if is_rgb:\n            plt.imshow(new_img)\n        else:\n            plt.imshow(new_img[:,:,::-1])\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:27:05.802409Z","iopub.execute_input":"2021-11-23T08:27:05.803129Z","iopub.status.idle":"2021-11-23T08:27:05.815799Z","shell.execute_reply.started":"2021-11-23T08:27:05.803092Z","shell.execute_reply":"2021-11-23T08:27:05.814981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def 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\ndef read_data_in_csv(csv_path=\"./wheat-dataset/train.csv\"):\n    df = pd.read_csv(csv_path)\n    df['xmin'], df['ymin'],  df['xmax'], df['ymax'] = -1, -1, -1, -1\n    df[['xmin', 'ymin', 'xmax', 'ymax']] = np.stack(df['bbox'].apply(lambda x: expand_bbox(x)))\n    df.drop(columns=['bbox'], inplace=True)\n    df['xmin'] = df['xmin'].astype(np.float)\n    df['ymin'] = df['ymin'].astype(np.float)\n    df['xmax'] = df['xmax'].astype(np.float)\n    df['ymax'] = df['ymax'].astype(np.float)\n    df['xmax'] = df['xmax'] + df['xmin']\n    df['ymax'] = df['ymax'] + df['ymin']\n    objs = []\n    img_ids = set(df[\"image_id\"])\n    \n    for img_id in tqdm(img_ids):\n        records = df[df[\"image_id\"] == img_id]\n        boxes = records[['xmin', 'ymin', 'xmax', 'ymax']].values\n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n\n        obj = {\n            \"img_id\": img_id,\n            \"boxes\": boxes,\n            \"area\":area\n        }\n        objs.append(obj)\n    return objs\n\n","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:27:07.864085Z","iopub.execute_input":"2021-11-23T08:27:07.864936Z","iopub.status.idle":"2021-11-23T08:27:07.8763Z","shell.execute_reply.started":"2021-11-23T08:27:07.864882Z","shell.execute_reply":"2021-11-23T08:27:07.875425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_aug(aug):\n    return Compose(aug, bbox_params=BboxParams(format='pascal_voc', min_area=0, min_visibility=0, label_fields=['labels']))\n\n\nclass WheatDataset(Dataset):\n    def __init__(self, df, img_dir, img_size, mode='train', bbox_removal_threshold=0.25):\n        self.df = df\n        self.img_size = img_size\n        self.img_dir = img_dir\n        assert mode in  ['train', 'valid']\n        self.mode = mode\n        self.bbox_removal_threshold = bbox_removal_threshold\n        \n        self.resize_transforms = get_aug([\n            Resize(height=self.img_size, width=self.img_size, interpolation=1, p=1)\n        ])\n        \n        if self.mode == 'train':\n            random.shuffle(self.df)\n            \n        self.transform = get_aug([\n            HorizontalFlip(p=0.5),\n            VerticalFlip(p=0.5),\n            ToGray(p=0.01),\n#             GaussNoise(p=0.2),\n            OneOf([\n                MotionBlur(p=0.2),\n                MedianBlur(blur_limit=3, p=0.1),\n                Blur(blur_limit=3, p=0.1),\n            ], p=0.2),\n            RandomBrightnessContrast(p=0.25),\n#             HueSaturationValue(p=0.25)\n        ])\n\n    def load_img(self, img_id, folder):\n        img_fn = f\"{folder}/{img_id}.jpg\"\n        img = cv2.imread(img_fn).astype(np.float32)\n        img /= 255.0\n        return img\n\n    def bb_overlap(self, boxA, boxB):\n        xA = max(boxA[0], boxB[0])\n        yA = max(boxA[1], boxB[1])\n        xB = min(boxA[2], boxB[2])\n        yB = min(boxA[3], boxB[3])\n        interArea = max(0, xB - xA) * max(0, yB - yA)\n        boxAArea = (boxA[2] - boxA[0]) * (boxA[3] - boxA[1])\n        iou = interArea / float(boxAArea)\n        return iou\n\n    def resize_image(self, image, boxes):\n        cats = np.ones(boxes.shape[0], dtype=int)\n        annotations = {'image': image, 'bboxes': boxes, 'labels': cats}\n        augmented = self.resize_transforms(**annotations)\n        image = augmented['image']\n        boxes = np.array(augmented['bboxes'])\n        return image, boxes        \n        \n    def crop_image(self, image, boxes, xmin, ymin, xmax, ymax):\n\n        image = image[ymin:ymax,xmin:xmax,:]\n        cutout_box = [xmin, ymin, xmax, ymax]\n        result_boxes = []\n        for box in boxes:\n            iou = self.bb_overlap(box, cutout_box)\n            if iou > self.bbox_removal_threshold:\n                result_boxes.append(box)\n        if len(result_boxes) > 0:\n            result_boxes = np.array(result_boxes, dtype=float)\n            result_boxes[:,[0,2]] -= xmin\n            result_boxes[:,[1,3]] -= ymin\n            result_boxes[:,[0,2]] = result_boxes[:,[0,2]].clip(0, xmax-xmin)\n            result_boxes[:,[1,3]] = result_boxes[:,[1,3]].clip(0, ymax-ymin)\n        else:\n            result_boxes = np.array([], dtype=float).reshape(0,4)\n        return image, result_boxes\n    \n    def random_crop_resize(self, image, boxes, img_size=1024, p=0.5):\n        if random.random() > p:\n            new_img_size = random.randint(int(0.75*img_size), img_size)\n            x = random.randint(0, img_size-new_img_size)\n            y = random.randint(0, img_size-new_img_size)\n            image, boxes = self.crop_image(image, boxes, x, y, x+new_img_size, y+new_img_size)\n            return self.resize_image(image, boxes)\n        else:\n            if self.img_size != 1024:\n                return self.resize_image(image, boxes)\n            else:\n                return image, boxes\n            \n    def load_cutmix_image_and_boxes(self, image_index, imsize=1024):   #custom mosaic data augmentation\n        image_indexs = [*range(len(self.df))]\n        image_indexs.remove(image_index)\n        cutmix_image_ids = [image_index] + random.sample(image_indexs, 3)\n        result_image = np.full((imsize, imsize, 3), 1, dtype='float32')\n        result_boxes = []\n        \n        xc, yc = [int(random.uniform(imsize * 0.25, imsize * 0.75)) for _ in range(2)]\n        \n        for i, img_id in enumerate(cutmix_image_ids):\n            image, boxes = self.load_img(self.df[img_id]['img_id'], self.img_dir), self.df[img_id]['boxes']\n            if i == 0:\n                image, boxes = self.crop_image(image, boxes, imsize-xc, imsize-yc, imsize, imsize)\n                result_image[0:yc, 0:xc,:] = image\n                result_boxes.extend(boxes)\n                \n            elif i == 1:\n                image, boxes = self.crop_image(image, boxes, 0, imsize-yc, imsize-xc, imsize)\n                result_image[0:yc, xc:imsize, :] = image\n                if boxes.shape[0] > 0:\n                    boxes[:,[0,2]] += xc\n                result_boxes.extend(boxes)\n                \n            elif i == 2:\n                image, boxes = self.crop_image(image, boxes, 0, 0, imsize-xc, imsize-yc)\n                result_image[yc:imsize, xc:imsize, :] = image\n                if boxes.shape[0] > 0:\n                    boxes[:,[0,2]] += xc\n                    boxes[:,[1,3]] += yc\n                result_boxes.extend(boxes)\n                \n            else:\n                image, boxes = self.crop_image(image, boxes, imsize-xc, 0, imsize, imsize-yc)\n                result_image[yc:imsize, 0:xc, :] = image\n                if boxes.shape[0] > 0:\n                    boxes[:,[1,3]] += yc\n                result_boxes.extend(boxes)\n                \n            del image\n            del boxes\n        del cutmix_image_ids\n        del image_indexs\n        \n        if len(result_boxes) == 0:\n            result_boxes = np.array([], dtype=float).reshape(0,4)\n        else:\n            result_boxes = np.vstack(result_boxes)\n            result_boxes[:,[0,2]] = result_boxes[:,[0,2]].clip(0, imsize)\n            result_boxes[:,[1,3]] = result_boxes[:,[1,3]].clip(0, imsize)\n            \n        return result_image, result_boxes\n    \n    def __getitem__(self, idx):\n\n        image, boxes = [], []\n        if self.mode == 'train':\n            while(True):\n                \n                if random.random() > 0.5:\n                    image, boxes = self.load_cutmix_image_and_boxes(idx)\n                else:\n                    image, boxes = self.load_img(self.df[idx]['img_id'], self.img_dir), self.df[idx]['boxes']\n                    image, boxes = self.random_crop_resize(image, boxes, p=0.5)\n                \n                if len(boxes) > 0:\n                    labels = np.ones(len(boxes), dtype=int)\n                    annotations = {'image': image, 'bboxes': boxes, 'labels': labels}\n                    augmented = self.transform(**annotations)\n                    image = augmented['image']\n                    boxes = np.array(augmented['bboxes'])\n                    break\n        else:\n            image, boxes = self.load_img(self.df[idx]['img_id'], self.img_dir), self.df[idx]['boxes']\n            \n\n        if len(boxes) == 0:\n                target = {\n                    \"boxes\": torch.zeros((0, 4), dtype=torch.float32),\n                    \"labels\": torch.zeros(0, dtype=torch.int64),\n                    \"area\": torch.zeros(0, dtype=torch.float32),\n                    \"iscrowd\": torch.zeros((0,), dtype=torch.int64)\n                }\n        else:\n            target = {}\n            area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n            target['boxes'] = torch.as_tensor(boxes, dtype=torch.float32)\n            target['labels'] = torch.ones((len(boxes),), dtype=torch.int64)\n            target['area'] = torch.as_tensor(area, dtype=torch.float32)\n            target['iscrowd'] = torch.zeros((len(boxes),), dtype=torch.int64)\n            \n#         image = torch.as_tensor(image, dtype=torch.float32)\n        image = torch.from_numpy(image).permute(2,0,1)\n\n        return image, target\n\n        \n    def __len__(self):\n        return len(self.df)\n    \n\ndef collate_fn(batch):\n    return tuple(zip(*batch))","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:27:10.058832Z","iopub.execute_input":"2021-11-23T08:27:10.059252Z","iopub.status.idle":"2021-11-23T08:27:10.105551Z","shell.execute_reply.started":"2021-11-23T08:27:10.059216Z","shell.execute_reply":"2021-11-23T08:27:10.104712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = read_data_in_csv('../input/global-wheat-detection/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:27:12.262962Z","iopub.execute_input":"2021-11-23T08:27:12.263452Z","iopub.status.idle":"2021-11-23T08:28:30.301239Z","shell.execute_reply.started":"2021-11-23T08:27:12.263415Z","shell.execute_reply":"2021-11-23T08:28:30.300312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_set = WheatDataset(df,'../input/global-wheat-detection/train',1024)\n\ntrain_loader = DataLoader(\n    data_set,\n    batch_size=16,\n    shuffle=True,\n    num_workers=2,\n    collate_fn=collate_fn)\n\n# temp = iter(train_loader)\n\n# outputs, labels = next(temp)\n\n# plot_imgs_and_boxes(outputs,labels, is_rgb=True)\n","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:28:30.303034Z","iopub.execute_input":"2021-11-23T08:28:30.30389Z","iopub.status.idle":"2021-11-23T08:28:30.313195Z","shell.execute_reply.started":"2021-11-23T08:28:30.303845Z","shell.execute_reply":"2021-11-23T08:28:30.31248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"£££££££££££££££££££££££££££££££ MODEL + MIXUP + SCHEDULE LEARING RATE £££££££££££££££££££££££££££","metadata":{}},{"cell_type":"code","source":"from torchvision.models.detection import FasterRCNN\n\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nimport torchvision","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:28:30.314466Z","iopub.execute_input":"2021-11-23T08:28:30.314857Z","iopub.status.idle":"2021-11-23T08:28:30.573371Z","shell.execute_reply.started":"2021-11-23T08:28:30.314814Z","shell.execute_reply":"2021-11-23T08:28:30.572643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.optim.lr_scheduler import _LRScheduler\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau\n\n\nclass GradualWarmupScheduler(_LRScheduler):\n    def __init__(self, optimizer, multiplier, total_epoch, after_scheduler=None):\n        self.multiplier = multiplier\n        if self.multiplier < 1.:\n            raise ValueError('multiplier should be greater thant or equal to 1.')\n        self.total_epoch = total_epoch\n        self.after_scheduler = after_scheduler\n        self.finished = False\n        super(GradualWarmupScheduler, self).__init__(optimizer)\n\n    def get_lr(self):\n        if self.last_epoch > self.total_epoch:\n            if self.after_scheduler:\n                if not self.finished:\n                    self.after_scheduler.base_lrs = [base_lr * self.multiplier for base_lr in self.base_lrs]\n                    self.finished = True\n                return self.after_scheduler.get_last_lr()\n            return [base_lr * self.multiplier for base_lr in self.base_lrs]\n\n        if self.multiplier == 1.0:\n            return [base_lr * (float(self.last_epoch) / self.total_epoch) for base_lr in self.base_lrs]\n        else:\n            return [base_lr * ((self.multiplier - 1.) * self.last_epoch / self.total_epoch + 1.) for base_lr in self.base_lrs]\n\n    def step_ReduceLROnPlateau(self, metrics, epoch=None):\n        if epoch is None:\n            epoch = self.last_epoch + 1\n        self.last_epoch = epoch if epoch != 0 else 1  # ReduceLROnPlateau is called at the end of epoch, whereas others are called at beginning\n        if self.last_epoch <= self.total_epoch:\n            warmup_lr = [base_lr * ((self.multiplier - 1.) * self.last_epoch / self.total_epoch + 1.) for base_lr in self.base_lrs]\n            for param_group, lr in zip(self.optimizer.param_groups, warmup_lr):\n                param_group['lr'] = lr\n        else:\n            if epoch is None:\n                self.after_scheduler.step(metrics, None)\n            else:\n                self.after_scheduler.step(metrics, epoch - self.total_epoch)\n\n    def step(self, epoch=None, metrics=None):\n        if type(self.after_scheduler) != ReduceLROnPlateau:\n            if self.finished and self.after_scheduler:\n                if epoch is None:\n                    self.after_scheduler.step(None)\n                else:\n                    self.after_scheduler.step(epoch - self.total_epoch)\n                self._last_lr = self.after_scheduler.get_last_lr()\n            else:\n                return super(GradualWarmupScheduler, self).step(epoch)\n        else:\n            self.step_ReduceLROnPlateau(metrics, epoch)","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:28:30.575153Z","iopub.execute_input":"2021-11-23T08:28:30.575429Z","iopub.status.idle":"2021-11-23T08:28:30.589938Z","shell.execute_reply.started":"2021-11-23T08:28:30.575382Z","shell.execute_reply":"2021-11-23T08:28:30.589275Z"},"_kg_hide-input":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n\n# Khởi tạo model\nnum_classes = 2\nnum_epochs = 2\n# iters = 1\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True, progress=False)\nin_features = model.roi_heads.box_predictor.cls_score.in_features\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\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\nscheduler_cosine = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, num_epochs-1)\nscheduler = GradualWarmupScheduler(optimizer, multiplier=10, total_epoch=1, after_scheduler=scheduler_cosine)\n\nmodel.to(device)\n","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:28:30.591089Z","iopub.execute_input":"2021-11-23T08:28:30.59157Z","iopub.status.idle":"2021-11-23T08:28:42.231815Z","shell.execute_reply.started":"2021-11-23T08:28:30.591531Z","shell.execute_reply":"2021-11-23T08:28:42.231113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# tiến hành train model\nfor epoch in range(num_epochs):\n    print('Epoch :', epoch)\n    scheduler.step(epoch)\n    model.train()\n    \n    for images, targets in train_loader:\n        \n        if random.random() > 0:\n            shuffle_indices = torch.randperm(len(images))\n            indices = torch.arange(len(images))\n            lam = np.clip(np.random.beta(1.0, 1.0), 0.35, 0.65)\n            images = list(images)\n\n            mix_targets = []\n            for i, si in zip(indices, shuffle_indices):\n                images[i] = lam * images[i] + (1 - lam) * images[si]\n                if i.item() == si.item():\n                    target = targets[i.item()]\n                else:\n                    target = {\n                        'boxes': torch.cat([targets[i.item()]['boxes'], targets[si.item()]['boxes']]),\n                        'labels': torch.cat([targets[i.item()]['labels'], targets[si.item()]['labels']]),\n                        'area': torch.cat([targets[i.item()]['area'], targets[si.item()]['area']]),\n                        'iscrowd': torch.cat([targets[i.item()]['iscrowd'], targets[si.item()]['iscrowd']])\n                    }\n\n                mix_targets.append(target)\n            images = tuple(images)\n            targets = mix_targets\n\n        images = list(image.cuda() for image in images)\n        targets = [{k: v.cuda() 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        \n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:28:42.233133Z","iopub.execute_input":"2021-11-23T08:28:42.233604Z","iopub.status.idle":"2021-11-23T08:43:28.041362Z","shell.execute_reply.started":"2021-11-23T08:28:42.233563Z","shell.execute_reply":"2021-11-23T08:43:28.040338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"############## TEST MIXUP ££££££££££££££££££££££","metadata":{}},{"cell_type":"code","source":"lam = np.clip(np.random.beta(1.0, 1.0), 0.35, 0.65)\nmixup_image = lam * outputs[4] + (1 - lam) * outputs[10]","metadata":{"execution":{"iopub.status.busy":"2021-11-22T13:58:25.396819Z","iopub.execute_input":"2021-11-22T13:58:25.398127Z","iopub.status.idle":"2021-11-22T13:58:25.453151Z","shell.execute_reply.started":"2021-11-22T13:58:25.398065Z","shell.execute_reply":"2021-11-22T13:58:25.4521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mixup_target = {\n    'boxes': torch.cat([labels[4]['boxes'], labels[10]['boxes']]),\n    'labels': torch.cat([labels[4]['labels'], labels[10]['labels']]),\n    'area': torch.cat([labels[4]['area'], labels[10]['area']]),\n    'iscrowd': torch.cat([labels[4]['iscrowd'], labels[10]['iscrowd']])\n}","metadata":{"execution":{"iopub.status.busy":"2021-11-22T13:58:25.454358Z","iopub.execute_input":"2021-11-22T13:58:25.454605Z","iopub.status.idle":"2021-11-22T13:58:25.467175Z","shell.execute_reply.started":"2021-11-22T13:58:25.454576Z","shell.execute_reply":"2021-11-22T13:58:25.466035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shuffle_indices = torch.randperm(len(outputs))\nindices = torch.arange(len(outputs))\nlam = np.clip(np.random.beta(1.0, 1.0), 0.35, 0.65)\nnew_images = torch.tenser(lam) * outputs + (1 - lam) * outputs[shuffle_indices, :]","metadata":{"execution":{"iopub.status.busy":"2021-11-22T14:12:40.435338Z","iopub.execute_input":"2021-11-22T14:12:40.43588Z","iopub.status.idle":"2021-11-22T14:12:40.453763Z","shell.execute_reply.started":"2021-11-22T14:12:40.43584Z","shell.execute_reply":"2021-11-22T14:12:40.452836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfor images, targets in train_loader:\n    ### mixup\n    if random.random() > 0:\n        shuffle_indices = torch.randperm(len(images))\n        indices = torch.arange(len(images))\n        lam = np.clip(np.random.beta(1.0, 1.0), 0.35, 0.65)\n        images = list(images)\n        \n        mix_targets = []\n        for i, si in zip(indices, shuffle_indices):\n            images[i] = lam * images[i] + (1 - lam) * images[si]\n            if i.item() == si.item():\n                target = targets[i.item()]\n            else:\n                target = {\n                    'boxes': torch.cat([targets[i.item()]['boxes'], targets[si.item()]['boxes']]),\n                    'labels': torch.cat([targets[i.item()]['labels'], targets[si.item()]['labels']]),\n                    'area': torch.cat([targets[i.item()]['area'], targets[si.item()]['area']]),\n                    'iscrowd': torch.cat([targets[i.item()]['iscrowd'], targets[si.item()]['iscrowd']])\n                }\n\n            mix_targets.append(target)\n        images = tuple(images)\n        targets = mix_targets\n    \n\n    mixup_image_box = visualize_mixup_image(images[0], targets[0]['boxes'])\n\n    plt.imshow(mixup_image_box)\n    break","metadata":{"execution":{"iopub.status.busy":"2021-11-22T15:04:46.85567Z","iopub.execute_input":"2021-11-22T15:04:46.855965Z","iopub.status.idle":"2021-11-22T15:04:50.65003Z","shell.execute_reply.started":"2021-11-22T15:04:46.855935Z","shell.execute_reply":"2021-11-22T15:04:50.64918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def visualize_mixup_image(img, boxes, thickness=3, color=(255, 0, 0)):\n  \n    img_copy = img.permute(1,2,0).numpy()\n    for box in boxes:\n        img_copy = cv2.rectangle(\n            img_copy,\n            (int(box[0]), int(box[1])),\n            (int(box[2]), int(box[3])),\n            color, thickness)\n    return img_copy\n\n# mixup_image_box = visualize_mixup_image(mixup_image, mixup_target['boxes'])\n\n# plt.imshow(mixup_image_box)","metadata":{"execution":{"iopub.status.busy":"2021-11-22T15:03:24.021151Z","iopub.execute_input":"2021-11-22T15:03:24.021528Z","iopub.status.idle":"2021-11-22T15:03:24.028795Z","shell.execute_reply.started":"2021-11-22T15:03:24.021486Z","shell.execute_reply":"2021-11-22T15:03:24.027798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n    ","metadata":{"execution":{"iopub.status.busy":"2021-11-22T12:16:19.866054Z","iopub.status.idle":"2021-11-22T12:16:19.866905Z","shell.execute_reply.started":"2021-11-22T12:16:19.866489Z","shell.execute_reply":"2021-11-22T12:16:19.866519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loop","metadata":{"execution":{"iopub.status.busy":"2021-11-22T12:16:19.8691Z","iopub.status.idle":"2021-11-22T12:16:19.869723Z","shell.execute_reply.started":"2021-11-22T12:16:19.869394Z","shell.execute_reply":"2021-11-22T12:16:19.869424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(outputs), len(labels)","metadata":{"execution":{"iopub.status.busy":"2021-11-22T12:16:19.871864Z","iopub.status.idle":"2021-11-22T12:16:19.872742Z","shell.execute_reply.started":"2021-11-22T12:16:19.872391Z","shell.execute_reply":"2021-11-22T12:16:19.872429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"######################## MODEL ##################################","metadata":{}},{"cell_type":"code","source":"from torchvision.models.detection import FasterRCNN\n\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nimport torchvision\n","metadata":{"execution":{"iopub.status.busy":"2021-11-22T10:56:06.721602Z","iopub.execute_input":"2021-11-22T10:56:06.721835Z","iopub.status.idle":"2021-11-22T10:56:07.011057Z","shell.execute_reply.started":"2021-11-22T10:56:06.721806Z","shell.execute_reply":"2021-11-22T10:56:07.010109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n\n# Khởi tạo model\nnum_classes = 2\nnum_epochs = 10\n# iters = 1\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True, progress=False)\nin_features = model.roi_heads.box_predictor.cls_score.in_features\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\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)\nmodel.to(device)\n\n","metadata":{"execution":{"iopub.status.busy":"2021-11-22T10:56:07.013037Z","iopub.execute_input":"2021-11-22T10:56:07.013391Z","iopub.status.idle":"2021-11-22T10:56:27.422803Z","shell.execute_reply.started":"2021-11-22T10:56:07.013348Z","shell.execute_reply":"2021-11-22T10:56:27.4219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def data_to_device(images, targets, device=torch.device(\"cuda\")):\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#     return images, targets","metadata":{"execution":{"iopub.status.busy":"2021-11-22T10:56:27.424254Z","iopub.execute_input":"2021-11-22T10:56:27.425273Z","iopub.status.idle":"2021-11-22T10:56:27.432834Z","shell.execute_reply.started":"2021-11-22T10:56:27.425227Z","shell.execute_reply":"2021-11-22T10:56:27.43125Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# tiến hành train model\nfor epoch in range(num_epochs):\n    print('Epoch :', epoch)\n    model.train()\n    for images, targets in train_loader:\n        \n        images = list(image.cuda() for image in images)\n        targets = [{k: v.cuda() 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        \n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n        \n","metadata":{"execution":{"iopub.status.busy":"2021-11-22T10:56:27.437613Z","iopub.execute_input":"2021-11-22T10:56:27.438584Z","iopub.status.idle":"2021-11-22T12:16:18.685897Z","shell.execute_reply.started":"2021-11-22T10:56:27.438536Z","shell.execute_reply":"2021-11-22T12:16:18.684727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(model.state_dict(), './model_mixup_lr_2epoch.h5')","metadata":{"execution":{"iopub.status.busy":"2021-11-23T08:44:11.255235Z","iopub.execute_input":"2021-11-23T08:44:11.256215Z","iopub.status.idle":"2021-11-23T08:44:11.672925Z","shell.execute_reply.started":"2021-11-23T08:44:11.256169Z","shell.execute_reply":"2021-11-23T08:44:11.672129Z"},"trusted":true},"execution_count":null,"outputs":[]}]}