{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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 20GB 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","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import cv2\nimport os\nimport re\n\n# Imports for image transforms\n# Albumentations bounding box augmentation docs: https://albumentations.ai/docs/getting_started/bounding_boxes_augmentation/\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\n\n# Torch imports\nimport torch\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, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\n\nfrom matplotlib import pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Install Ax for Bayesian Optimization of hyperparameters\n!pip install ax-platform","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Ax imports\nfrom ax.plot.contour import plot_contour\nfrom ax.plot.trace import optimization_trace_single_method\nfrom ax.service.managed_loop import optimize\nfrom ax.utils.notebook_plotting import render, init_notebook_plotting\n# from ax.utils.tutorials.cnn_utils import train, evaluate\n\ninit_notebook_plotting()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"INPUT_DIR = '/kaggle/input/global-wheat-detection/'\nOUTPUT_DIR = '/kaggle/output/'\nTRAIN_DIR = f'{INPUT_DIR}/train'\nTEST_DIR = f'{INPUT_DIR}/test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(f'{INPUT_DIR}/train.csv')\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create individual columns for data from train_df['bbox']\nbbox_cols = ['x', 'y', 'w', 'h']\nfor c in bbox_cols:\n    train_df[c] = -1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['bbox'][1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\nReformats bbox entry for insertion into newly created x, y, w, h rows\nInput: box (String) in form \"[x, y, w, h]\"\nOutput: data (list) in form [x, y, w, h]\n\"\"\"\ndef extract_bbox_data(box):\n    # NOTE: not sure if this properly accounts for image with no bbox\n    data = [x.strip() for x in box.strip(\"[]\").split(\",\")]\n    if len(data) == 0:\n        data = [-1, -1, -1, -1]\n    return data\n\n# Get string data from bbox into numerical data in bbox_cols\ntrain_df[bbox_cols] = np.stack(train_df['bbox'].apply(lambda x: extract_bbox_data(x)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.drop(columns='bbox', inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for c in bbox_cols:\n    train_df[c] = train_df[c].astype(np.float)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_ids = train_df['image_id'].unique()\nimage_ids.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"3373 * .2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Split train_df into 80% train, 20% validation\ntrain_ids = image_ids[:-675]\nvalid_ids = image_ids[-675:]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"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# train_df = train_df[train_df['image_id'].isin(image_ids)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.shape, valid_df.shape\n# train_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\nAlbumentations transforms for creating datasets from raw data.\nThese functions call A.compose() which returns a transform function that preforms\nimage augmentation.\nCalled by creating a data dictionary and calling transform_fn(**data)\nWill be used later in our Dataset object definition\n\"\"\"\n\nbound_params = {\n    'format': 'pascal_voc',\n    'label_fields': ['labels']\n}\n\n\"\"\"\nTransforms for training data. Flip image with probability of .5,\nconvert to torch Tensor with probability of 1.\n\"\"\"\ndef train_transform():\n    # Parameter p is the probability of performing the transform\n    return A.Compose([A.Flip(p=0.5), A.Resize(512, 512), ToTensorV2(p=1.0)], bbox_params=bound_params)\n\n# This actually ended up making it worse\n# def train_transform_improved():\n#     return A.Compose([\n#     A.HorizontalFlip(p=0.5),\n#     A.VerticalFlip(p=0.5),\n#     A.OneOf([A.RandomContrast(),A.RandomGamma(),A.RandomBrightness()], p=1.0),\n#     ToTensorV2(p=1.0)], bbox_params=bound_params)\n\n\"\"\"\nTransforms for validation data. Only convert to torch Tensor (p=1)\n\"\"\"\ndef valid_transform():\n    return A.Compose([ToTensorV2(p=1.0)], bbox_params=bound_params)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Testing dataset workflow for single image before defining Dataset class\nt_image_id = 'b6ab77fd7'\nt_image = cv2.imread(f'{TRAIN_DIR}/{t_image_id}.jpg', cv2.IMREAD_COLOR)\nt_image = cv2.cvtColor(t_image, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"t_box_data = train_df[train_df['image_id']==t_image_id]\nt_boxes = t_box_data[bbox_cols].values\nt_boxes[:,2] = t_boxes[:,0] + t_boxes[:,2]\nt_boxes[:,3] = t_boxes[:,1] + t_boxes[:,3]\nt_boxes = t_boxes.astype(np.int32)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(1,1,figsize=(16,8))\nfor box in t_boxes:\n    cv2.rectangle(t_image, (box[0], box[1]), (box[2], box[3]), (200,0,0), 3)\nax.set_axis_off()\nax.imshow(t_image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"t_sample = {'image': t_image, 'bboxes': t_boxes, 'labels': torch.ones((t_box_data.shape[0],), dtype=torch.int64)}\nt_trans = train_transform_improved()\ntrans_sample = t_trans(**t_sample)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trans_sample['bboxes'][0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\ntorch Dataset object for our raw data. Dataset subclasses must overwrite the following:\n__getitem__(): fetches a data sample for a given key\n__len__(): returns he size of the dataset\n\"\"\"\nclass WheatDataset(Dataset):\n    \n    \"\"\"\n    Parameters:\n        df: dataframe containing image_id, width, height, source, x, y, w, h\n        directory: directory where image corresponding to image_id is stored\n        transforms: transform function\n    \"\"\"\n    def __init__(self, df, directory, transforms=None):\n        super().__init__()\n        \n        self.image_ids = df['image_id'].unique()\n        self.df = df\n        self.dir = directory\n        self.transforms = transforms\n        \n    def __len__(self):\n        return int(self.image_ids.shape[0])\n    \n    def __getitem__(self, index: int):\n        image_id = self.image_ids[index]\n        \n        image = cv2.imread(f'{self.dir}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        # cv2 reads images into BGR format, must convert to RGB for f-RCNN\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        # f-RCNN requires images in [C,W,H] form with values in [0,1]\n        image /= 255.0\n        \n        image_bbox_data = self.df[self.df['image_id'] == image_id]\n        bboxes = image_bbox_data[bbox_cols].values\n        # f-RCNN requires bboxes in pascal_voc format: [xmin, ymin, xmax, ymax]\n        bboxes[:,2] = bboxes[:,0] + bboxes[:,2]\n        bboxes[:,3] = bboxes[:,1] + bboxes[:,3]\n        \n        # we only have 1 class (wheat head) so label tensor is all ones\n        labels = torch.ones((image_bbox_data.shape[0],), dtype=torch.int64)\n        \n        target = {\n            'boxes': bboxes,\n            'labels': labels,\n            'image_id': torch.tensor([index])\n        }\n        \n        if self.transforms:\n            dataToTransform = {\n                'image': image,\n                'bboxes': bboxes,\n                'labels': labels\n            }\n            transData = self.transforms(**dataToTransform)\n            image = transData['image']\n            target['boxes'] = torch.tensor([list(tup) for tup in transData['bboxes']], dtype=torch.float32)\n        \n        return image, target, image_id\n            ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\nModel creation. Using frcnn with resnet50 backbone that has been pretrained on\nCOCO dataset\n\"\"\"\n\n# get pretrained data from internet once then save to file for quicker use\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)\n# torch.save(model, 'frcnn_pretrained.pth')\n# model = torch.load('frcnn_pretrained.pth')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"num_classes = 2 # wheat head + background (background required for fRCNN)\ninput_features = model.roi_heads.box_predictor.cls_score.in_features\n\n# Replace pretrained head with new, untrained fRCNN predictor\nmodel.roi_heads.box_predictor = FastRCNNPredictor(input_features, num_classes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model Training\n\nTraining process:\n* Create train and valid WheatDatasets\n* Create DataLoaders from Datasets\n* Get training parameters as params in model.parameters() that require gradient\n* Set up SGD optimizer w/ lr=5e-3, momentum=.9, decay=5e-4\n* Set num epochs\n* Do numEpochs iterations of standard PyTorch training loop\n* Infer bboxes on validation data and show sample as before \n* Save model to disk\n\nStandard PyTorch training loop. For image, targets, image_ids in training dataloader:\n1. Zero the parameter gradients\n2. Call the model to get loss\n3. Backprop loss\n4. Step opimizer forward"},{"metadata":{"trusted":true},"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))\n\nmodel.to(device)\n\ntrain_dataset = WheatDataset(train_df, TRAIN_DIR, train_transform())\nvalid_dataset = WheatDataset(valid_df, TRAIN_DIR, valid_transform())\n# train_dataset = WheatDataset(train_df, TRAIN_DIR, train_transform_improved())\n\ntrain_dl = DataLoader(dataset=train_dataset, batch_size=16, num_workers=4, collate_fn=collate_fn)\nvalid_dl = DataLoader(dataset=valid_dataset, batch_size=8, num_workers=4, collate_fn=collate_fn)\n\ntrain_params = [param for param in model.parameters() if param.requires_grad]\noptimizer = torch.optim.SGD(train_params, lr=5e-3, momentum=.9, weight_decay=5e-4)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Vanilla Pytorch Training Loop:"},{"metadata":{"trusted":true},"cell_type":"code","source":"# from IPython.display import display, clear_output # for outputting loss on same line\n# model.train()\n# epochs = 30\n# overall_epoch_losses = []\n# for epoch in range(epochs):\n#     epoch_losses = []\n#     for imgs, targets, img_ids in train_dl:\n#         imgs = list(image.to(device) for image in imgs)\n#         targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n# #         clear_output(wait=True)\n#         optimizer.zero_grad()\n#         loss_out = model(imgs, targets)\n#         loss_total = sum([loss for loss in loss_out.values()])\n#         loss_total.backward()\n#         epoch_losses.append(loss_total.item())\n# #         display(f'Batch Loss: {loss_total.item()}, epoch {epoch + 1} avg loss: {sum(epoch_losses)/len(epoch_losses)}')\n#         print(f'Batch Loss: {loss_total.item()}, Epoch {epoch + 1} avg loss: {sum(epoch_losses)/len(epoch_losses)}')\n#         optimizer.step()\n#     overall_epoch_losses.append(sum(epoch_losses)/len(epoch_losses))\n#     print(f'Epoch {epoch + 1} loss: {overall_epoch_losses[-1]}')\n# print(f'Total loss: {sum(overall_epoch_losses)/len(overall_epoch_losses)}')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Ax Training Loop With Hyperparameter Optimization:"},{"metadata":{"trusted":true},"cell_type":"code","source":"def train(\n    net: torch.nn.Module,\n    train_loader: DataLoader,\n    parameters: Dict[str, float],\n    dtype: torch.dtype,\n    device: torch.device,\n) -> nn.Module:\n    \"\"\"\n    Train CNN on provided data set.\n\n    Args:\n        net: initialized neural network\n        train_loader: DataLoader containing training set\n        parameters: dictionary containing parameters to be passed to the optimizer.\n            - lr: default (0.001)\n            - momentum: default (0.0)\n            - weight_decay: default (0.0)\n            - num_epochs: default (1)\n        dtype: torch dtype\n        device: torch device\n    Returns:\n        nn.Module: trained CNN.\n    \"\"\"\n    # Initialize network\n    net.to(dtype=dtype, device=device)  # pyre-ignore [28]\n    net.train()\n    # Define loss and optimizer\n#     criterion = nn.NLLLoss(reduction=\"sum\")\n    optimizer = torch.optim.SGD(\n        [p for p in net.parameters() if p.requires_grad],\n        lr=parameters.get(\"lr\", 0.001),\n        momentum=parameters.get(\"momentum\", 0.0),\n        weight_decay=parameters.get(\"weight_decay\", 0.0),\n    )\n    scheduler = optim.lr_scheduler.StepLR(\n        optimizer,\n        step_size=int(parameters.get(\"step_size\", 30)),\n        gamma=parameters.get(\"gamma\", 1.0),  # default is no learning rate decay\n    )\n    num_epochs = parameters.get(\"num_epochs\", 1)\n\n    # Train Network\n    # pyre-fixme[6]: Expected `int` for 1st param but got `float`.\n    for _ in range(num_epochs):\n        for imgs, targets, img_ids in train_loader:\n            # move data to proper dtype and device\n            imgs = list(image.to(device) for image in imgs)\n            targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\n            # zero the parameter gradients\n            optimizer.zero_grad()\n\n            # forward + backward + optimize\n            outputs = net(imgs, targets)\n            loss = sum(l for l in outputs.values())\n            loss.backward()\n            optimizer.step()\n            scheduler.step()\n    return net\n\n\ndef calc_iou(trueBox, predBox):\n    t_xmin, t_ymin, t_xmax, t_ymax = trueBox\n    p_xmin, p_ymin, p_xmax, p_ymax = predBox\n    \n    overlap_area = 0.0\n    union_area = 0.0\n    \n    xdiff = min(t_xmax, p_xmax) - min(t_xmin, p_xmin)\n    ydiff = min(t_ymax, p_ymax) - min(t_ymin, p_ymin)\n    \n    t_area = (t_xmax - t_xmin) * (t_ymax - t_ymin)\n    p_area = (p_xmax - p_xmin) * (p_ymax - p_ymin)\n    \n    if (ydiff > 0) and (xdiff > 0): overlap_area = xdiff * ydiff\n    \n    union_area = (t_area + p_area - overlap_area)\n    \n    return overlap_area / union_area\n    \n    \ndef find_best(trues, predicted_box, threshold=0.5):\n    best_iou = -np.inf\n    best_idx = -1\n    \n    for idx, true_box in enumerate(trues):\n        curr_iou = calc_iou(true_box, predicted_box)\n        \n        if (curr_iou > threshold) and (curr_iou > best_iou):\n            best_iou = curr_iou\n            best_idx = idx\n            \n    return best_idx\n    \ndef calc_boxes_precision(sorted_preds, true_targets, threshold=0.5):\n    tp = 0 # true positives\n    fp = 0 # false positives\n    fn = 0 # false negatives\n    \n    false_negatives = []\n    for idx, pred in enumerate(sorted_preds):\n        t_idx_best = find_best(true_targets, pred, threshold=threshold)\n        if t_idx_best >= 0:\n            tp += 1\n            true_targets = np.delete(true_targets, t_idx_best, axis=0)\n        else:\n            fn += 1\n            false_negatives.append(pred)\n    fp = len(true_targets)\n    prec = tp / (tp + fp + fn)\n    return precision, false_negatives, true_targets\n    \ndef calc_total_precision(sorted_preds, true_targets, thresholds=iou_thresholds = [x for x in np.arange(0.5, 0.76, 0.05)]):\n    threshCount = len(thresholds)\n    total_prec = 0.0\n    \n    for thresh in thresholds:\n        thresh_prec, _, _ = calc_boxes_precision(sorted_preds, true_targets, threshold=thresh)\n        total_prec += thresh_prec / threshCount\n        \n    return total_prec\n\ndef evaluate(\n    net: nn.Module, data_loader: DataLoader, dtype: torch.dtype, device: torch.device\n) -> float:\n    \"\"\"\n    Compute classification accuracy on provided dataset.\n\n    Args:\n        net: trained model\n        data_loader: DataLoader containing the evaluation set\n        dtype: torch dtype\n        device: torch device\n    Returns:\n        float: classification accuracy\n    \"\"\"\n    net.eval()\n    total_images = 0\n    total_score = 0\n    thresh = 0.5\n    with torch.no_grad():\n        for imgs, targets, img_ids in data_loader:\n            # move data to proper dtype and device\n            imgs = list(image.to(device) for image in imgs)\n            targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n            model_outputs = net(imgs)\n            batch_precisions = []\n            \n            for i,img in enumerate(imgs):\n                scores = model_outputs[i]['scores'].data.cpu().numpy()\n                boxes = model_outputs[i]['boxes'].data.cpu().numpy().astype(np.int32)\n#                 bboxes = bboxes[scores >= thresh].astype(np.int32)\n#                 scores = scores[scores >= thresh]\n                boxes_true = targets[i]['boxes'].cpu().numpy()\n                \n                sorted_pred_idx = np.argsort(scores)[::-1]\n                sorted_boxes = boxes[sorted_pred_idx]\n                \n#                 prec, _, _ = calc_boxes_precision(sorted_boxes, boxes_true, threshold=0.5)\n                img_prec = calc_total_precision(sorted_boxes, boxes_true)\n                batch_precisions.append(img_prec)\n                \n            total_imgs += 1\n            total_score += np.mean(batch_precisions)\n\n    return total_Score / total_imgs\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_evaluate(paramaterization):\n    net = copy.deepcopy(model)\n    net = train(\n        net=net,\n        train_loader=train_dl,\n        parameters=paramaterization,\n        dtype=dtype,\n        device=device\n    )\n    return evaluate(\n        net=net,\n        data_loader=valid_dl,\n        dtype=dtype,\n        device=device\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"optimize_parameters = [\n    {\"name\": \"lr\", \"type\": \"range\", \"bounds\": [1e-6, 0.4], \"value_type\": \"float\",\"log_scale\": True},\n    {\"name\": \"momentum\", \"type\": \"range\", \"bounds\": [0.0, 1.0], \"value_type\": \"float\"},\n    {\"name\": \"weight_decay\", \"type\": \"range\", \"bounds\": [0.0, 0.4], \"value_type\": \"float\"},\n    {\"name\": \"num_epochs\", \"type\": \"fixed\", \"value\": 30, , \"value_type\": \"int\"}\n]\n\nbest_parameters, values, experiment, opt_model = optimize(\n    parameters=optimize_parameters,\n    evaluation_function=train_evaluate,\n    objective_name='precision'\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"render(plot_contour(model=opt_model, param_x='lr', param_y='momentum', metric_name='accuracy'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"render(plot_contour(model=opt_model, param_x='lr', param_y='weight_decay', metric_name='accuracy'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"render(plot_contour(model=opt_model, param_x='momentum', param_y='weight_decay', metric_name='accuracy'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"best_objectives = np.array([[trial.objective_mean for trial in experiment.trials.values()]])\nbest_objective_plot = optimization_trace_single_method(\n    y=np.maximum.accumulate(best_objectives, axis=1),\n    title=\"Model performance vs. # of iterations\",\n    ylabel=\"Overall Model Precision\"\n)\nrender(best_objective_plot)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"expData = experiment.fetch_data()\nexpDf = expData.df\nbest_arm_name = expDf.arm_name[expDf['mean'] == expDf['mean'].max()].values[0]\nbest_arm = experiment.arms_by_name[best_arm_name]\nbest_arm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"combined_dataset = torch.utils.data.ConcatDataset([\n    train_dl.dataset.dataset,\n    valid_dl.dataset.dataset\n])\n\ncombined_dl = DataLoader(combined_dataset, batch_size=16, shuffle=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"bayesOpt_model = train(\n    net=copy.deepcopy(model),\n    train_loader=combined_dl,\n    parameters=best_arm.parameters,\n    dtype=dtype,\n    device=device\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"torch.save(model.state_dict(), 'fasterrcnn_resnet50_fpn_BAYESOPT.pth')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# images, targets, image_ids = next(iter(valid_data_loader))\n# images = list(img.to(device) for img in images)\n# targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n# boxes = targets[1]['boxes'].cpu().numpy().astype(np.int32)\n# sample = images[1].permute(1,2,0).cpu().numpy()\n\n# model.eval()\n# outputs = model(images)\n# outputs = [{k: v.to(cpu_device) for k, v in t.items()} for t in outputs]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# v_image_id = '33ea56e1c'\n# v_image = cv2.imread(f'{TRAIN_DIR}/{v_image_id}.jpg', cv2.IMREAD_COLOR)\n# v_image = cv2.cvtColor(v_image, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0\n# v_box_data = valid_df[valid_df['image_id']==v_image_id]\n# v_boxes = v_box_data[bbox_cols].values\n# v_boxes[:,2] = v_boxes[:,0] + v_boxes[:,2]\n# v_boxes[:,3] = v_boxes[:,1] + v_boxes[:,3]\n# v_boxes = v_boxes.astype(np.int32)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# fig, ax = plt.subplots(1,1,figsize=(16,8))\n# for box in v_boxes:\n#     cv2.rectangle(v_image, (box[0], box[1]), (box[2], box[3]), (200,0,0), 3)\n# ax.set_axis_off()\n# ax.imshow(v_image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}