{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":19989,"databundleVersionId":1160143,"sourceType":"competition"}],"dockerImageVersionId":29928,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"I entered this competition as an opportunity to implement an object detection model, something I know how to do in theory but have not yet put into practice. As yolo is the model I am most familiar with I will be implementing a model inspired by yolov3 (though not exactly the same) using Tensorflow.","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nimport tensorflow as tf\nimport os\nimport matplotlib.pyplot as plt\nfrom PIL import Image, ImageDraw, ImageEnhance\nimport albumentations as albu\nfrom tqdm.notebook import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-08-26T18:04:07.971261Z","iopub.execute_input":"2024-08-26T18:04:07.971587Z","iopub.status.idle":"2024-08-26T18:04:07.976785Z","shell.execute_reply.started":"2024-08-26T18:04:07.971559Z","shell.execute_reply":"2024-08-26T18:04:07.975942Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load data\n\nI'll begin by loading the labels data and extracting the bounding boxes (which I refer to as \"bboxes\" in the code) from the table.","metadata":{}},{"cell_type":"code","source":"labels = pd.read_csv('../input/global-wheat-detection/train.csv')\nlabels.head()","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","execution":{"iopub.status.busy":"2024-08-26T18:04:07.978638Z","iopub.execute_input":"2024-08-26T18:04:07.978974Z","iopub.status.idle":"2024-08-26T18:04:08.189924Z","shell.execute_reply.started":"2024-08-26T18:04:07.978945Z","shell.execute_reply":"2024-08-26T18:04:08.188975Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In the raw data each bounding box is in an array of length 4 but formatted as a string. The below block of code groups the bounding boxes by image id and places the bounding boxes as numpy arrays next to each image id. The image id can then be used to quickly retrieve all of the bounding boxes.","metadata":{}},{"cell_type":"code","source":"def group_boxes(group):\n    boundaries = group['bbox'].str.split(',', expand=True)\n    boundaries[0] = boundaries[0].str.slice(start=1)\n    boundaries[3] = boundaries[3].str.slice(stop=-1)\n    \n    return boundaries.values.astype(float)\n\nlabels = labels.groupby('image_id').apply(group_boxes)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:04:08.191202Z","iopub.execute_input":"2024-08-26T18:04:08.191464Z","iopub.status.idle":"2024-08-26T18:04:14.183406Z","shell.execute_reply.started":"2024-08-26T18:04:08.191438Z","shell.execute_reply":"2024-08-26T18:04:14.182676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Here's a sample of five bounding boxes for one of the images.","metadata":{}},{"cell_type":"code","source":"labels['b6ab77fd7'][0:5]","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:04:14.186337Z","iopub.execute_input":"2024-08-26T18:04:14.186749Z","iopub.status.idle":"2024-08-26T18:04:14.193519Z","shell.execute_reply.started":"2024-08-26T18:04:14.186710Z","shell.execute_reply":"2024-08-26T18:04:14.192566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"With the labels extracted from the data I now need the images loaded as numpy arrays. At this point it is worth splitting the data into a training and validation dataset. As the dataset is small I will keep the vast majority of the images in the training dataset and only put the last ten images aside as a validation dataset. This may not be the best size to perform accurate validation but I think it is the right compromise considering the number of images available and the complexity of the task.","metadata":{}},{"cell_type":"code","source":"train_image_ids = np.unique(labels.index.values)[0:3363]\nval_image_ids = np.unique(labels.index.values)[3363:3373]","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:04:14.196311Z","iopub.execute_input":"2024-08-26T18:04:14.196683Z","iopub.status.idle":"2024-08-26T18:04:14.211394Z","shell.execute_reply.started":"2024-08-26T18:04:14.196646Z","shell.execute_reply":"2024-08-26T18:04:14.210683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"With the ids split it's now time to load the images. To keep the training of the model relatively fast I will resize each image from (1024,1024) to (256,256). I experimented with larger images and with the model I am using I didn't see a good enough lift in training accuracy to make up for the extra time it took to train a model with larger images.","metadata":{}},{"cell_type":"code","source":"def load_image(image_id):\n    image = Image.open('../input/global-wheat-detection/train/' + image_id + \".jpg\")\n    image = image.resize((256, 256))\n    \n    return np.asarray(image)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:04:14.212618Z","iopub.execute_input":"2024-08-26T18:04:14.213121Z","iopub.status.idle":"2024-08-26T18:04:14.221169Z","shell.execute_reply.started":"2024-08-26T18:04:14.213053Z","shell.execute_reply":"2024-08-26T18:04:14.220454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_pixels = {}\ntrain_labels = {}\n\nfor image_id in tqdm(train_image_ids):\n    train_pixels[image_id] = load_image(image_id)\n    train_labels[image_id] = labels[image_id].copy() / 4","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:04:14.222484Z","iopub.execute_input":"2024-08-26T18:04:14.222851Z","iopub.status.idle":"2024-08-26T18:06:25.400892Z","shell.execute_reply.started":"2024-08-26T18:04:14.222815Z","shell.execute_reply":"2024-08-26T18:06:25.399912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_pixels = {}\nval_labels = {}\n\nfor image_id in tqdm(val_image_ids):\n    val_pixels[image_id] = load_image(image_id)    \n    val_labels[image_id] = labels[image_id].copy() / 4","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:25.402558Z","iopub.execute_input":"2024-08-26T18:06:25.402927Z","iopub.status.idle":"2024-08-26T18:06:25.835902Z","shell.execute_reply.started":"2024-08-26T18:06:25.402887Z","shell.execute_reply":"2024-08-26T18:06:25.835158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualise images\n\nBefore going on it is worth having a look at some of the images and bounding boxes in the dataset. For that a few helper functions will be required. The below functions take an image id and the corresponding bounding boxes and return the bounding boxes drawn onto the image.","metadata":{}},{"cell_type":"code","source":"def draw_bboxes(image_id, bboxes, source='train'):  \n    image = Image.open('../input/global-wheat-detection/' + source +'/' + image_id + \".jpg\")\n    image = image.resize((256,256))\n    \n    draw = ImageDraw.Draw(image)\n            \n    for bbox in bboxes:\n        draw_bbox(draw, bbox)\n    \n    return np.asarray(image)\n\n\ndef draw_bbox(draw, bbox):\n    x, y, width, height = bbox\n    draw.rectangle([x, y, x + width, y + height], width=2, outline='red')","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:25.837351Z","iopub.execute_input":"2024-08-26T18:06:25.837631Z","iopub.status.idle":"2024-08-26T18:06:25.845520Z","shell.execute_reply.started":"2024-08-26T18:06:25.837603Z","shell.execute_reply":"2024-08-26T18:06:25.844544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I'll also add a wrapper function to call this function multiple times for multiple images.","metadata":{}},{"cell_type":"code","source":"def show_images(image_ids, bboxes, source='train'):\n    pixels = []\n    \n    for image_id in image_ids:\n        pixels.append(\n            draw_bboxes(image_id, bboxes[image_id], source)\n        )\n    \n    num_of_images = len(image_ids)\n    fig, axes = plt.subplots(\n        1, \n        num_of_images, \n        figsize=(5 * num_of_images, 5 * num_of_images)\n    )\n    \n    for i, image_pixels in enumerate(pixels):\n        axes[i].imshow(image_pixels)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:25.847136Z","iopub.execute_input":"2024-08-26T18:06:25.847637Z","iopub.status.idle":"2024-08-26T18:06:25.856192Z","shell.execute_reply.started":"2024-08-26T18:06:25.847597Z","shell.execute_reply":"2024-08-26T18:06:25.855328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images(train_image_ids[0:4], train_labels)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:25.857450Z","iopub.execute_input":"2024-08-26T18:06:25.857725Z","iopub.status.idle":"2024-08-26T18:06:26.660201Z","shell.execute_reply.started":"2024-08-26T18:06:25.857697Z","shell.execute_reply":"2024-08-26T18:06:26.659192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Clean bounding boxes\n\nThere are a small number of bounding boxes in this dataset that do not bound a head of wheat. While the number is small enough that the model can still learn how to detect the heads of wheat they still cause a little bit of inaccuracy. Below I'll search for tiny bounding boxes that cannot possibly fit a head of wheat inside them and huge bounding boxes that miss the head of wheat they are aimed at.","metadata":{}},{"cell_type":"code","source":"tiny_bboxes = []\n\nfor i, image_id in enumerate(train_image_ids):\n    for label in train_labels[image_id]:\n        if label[2] * label[3] <= 10 and label[2] * label[3] != 0:\n            tiny_bboxes.append(i)\n\n            \nprint(str(len(tiny_bboxes)) + ' tiny bounding boxes found')","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:26.661475Z","iopub.execute_input":"2024-08-26T18:06:26.661765Z","iopub.status.idle":"2024-08-26T18:06:26.891888Z","shell.execute_reply.started":"2024-08-26T18:06:26.661736Z","shell.execute_reply":"2024-08-26T18:06:26.890852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"huge_bboxes = []\n\nfor i, image_id in enumerate(train_image_ids):\n    for label in train_labels[image_id]:\n        if label[2] * label[3] > 8000:\n            huge_bboxes.append(i)\n\n            \nprint(str(len(huge_bboxes)) + ' huge bounding boxes found')","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:26.892923Z","iopub.execute_input":"2024-08-26T18:06:26.893214Z","iopub.status.idle":"2024-08-26T18:06:27.122998Z","shell.execute_reply.started":"2024-08-26T18:06:26.893187Z","shell.execute_reply":"2024-08-26T18:06:27.122160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The tiny bounding boxes are actually too small to show when visualised on an image. However we can take a peak at one of the huge bounding boxes.","metadata":{}},{"cell_type":"code","source":"show_images(train_image_ids[562:564], train_labels)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:27.123996Z","iopub.execute_input":"2024-08-26T18:06:27.124273Z","iopub.status.idle":"2024-08-26T18:06:27.536899Z","shell.execute_reply.started":"2024-08-26T18:06:27.124246Z","shell.execute_reply":"2024-08-26T18:06:27.536150Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I did some more manual inspection of the bad labels picked out of this code that I have not included in this notebook. I found that some huge bounding boxes were actually okay as they bound a very zoomed in image. To this end I have listed a few to be kept (1079, 1371, 2020). Otherwise the below code throws out any bounding boxes whose area is larger than 8000 or smaller than 5.","metadata":{}},{"cell_type":"code","source":"def clean_labels(train_image_ids, train_labels):\n    good_labels = {}\n    \n    for i, image_id in enumerate(train_image_ids):\n        good_labels[image_id] = []\n        \n        for j, label in enumerate(train_labels[image_id]):\n\n            # remove huge bbox\n            if label[2] * label[3] > 8000 and i not in [1079, 1371, 2020]:\n                continue\n\n            # remove tiny bbox\n            elif label[2] < 5 or label[3] < 5:\n                continue\n                \n            else:\n                good_labels[image_id].append(\n                    train_labels[image_id][j]\n                )\n                \n    return good_labels\n\ntrain_labels = clean_labels(train_image_ids, train_labels)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:27.538107Z","iopub.execute_input":"2024-08-26T18:06:27.538380Z","iopub.status.idle":"2024-08-26T18:06:28.055916Z","shell.execute_reply.started":"2024-08-26T18:06:27.538353Z","shell.execute_reply":"2024-08-26T18:06:28.055168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data pipeline\n\nUsually I would use Tensorflows data api or keras data generators to build a pipeline to get data into the model. However the pre-processing that needs to be done for this model is not trivial and it turned out to be easier to create a custom data generator. This takes the form of a class that is passed to keras' fit generator function. It contains the following functionality:\n\n- define the size of the dataset. Keras needs this to work out how long an epoch is.\n- shuffle the dataset.\n- get an image and augment it to add variety to the dataset. This includes amending bounding boxes when a head of wheat has changed in the image.\n- reshape the bounding boxes to a label grid.\n\nI'll start by initialising the class.","metadata":{}},{"cell_type":"code","source":"class DataGenerator(tf.keras.utils.Sequence):\n\n    def __init__(self, image_ids, image_pixels, labels=None, batch_size=1, shuffle=False, augment=False):\n        self.image_ids = image_ids\n        self.image_pixels = image_pixels\n        self.labels = labels\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.augment = augment\n        self.on_epoch_end()\n        \n        self.image_grid = self.form_image_grid()\n        \n        \n    def form_image_grid(self):    \n        image_grid = np.zeros((32, 32, 4))\n\n        # x, y, width, height\n        cell = [0, 0, 256 / 32, 256 / 32] \n\n        for i in range(0, 32):\n            for j in range(0, 32):\n                image_grid[i,j] = cell\n\n                cell[0] = cell[0] + cell[2]\n\n            cell[0] = 0\n            cell[1] = cell[1] + cell[3]\n\n        return image_grid","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:28.057815Z","iopub.execute_input":"2024-08-26T18:06:28.058177Z","iopub.status.idle":"2024-08-26T18:06:28.069216Z","shell.execute_reply.started":"2024-08-26T18:06:28.058144Z","shell.execute_reply":"2024-08-26T18:06:28.068175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Next I will add some methods to the class that keras needs to operate the data generation. length is used to determine how many images there are in the dataset. on_epoch_end is called at the end of each epoch (as well once before training starts) to get the index of all images in the dataset. It is also has the opportunity to shuffle the dataset per epoch if the generator was configured to do so.","metadata":{}},{"cell_type":"code","source":"def __len__(self):\n    return int(np.floor(len(self.image_ids) / self.batch_size))\n\n\ndef on_epoch_end(self):\n    self.indexes = np.arange(len(self.image_ids))\n\n    if self.shuffle == True:\n        np.random.shuffle(self.indexes)\n\n\nDataGenerator.__len__ = __len__\nDataGenerator.on_epoch_end = on_epoch_end","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:28.070662Z","iopub.execute_input":"2024-08-26T18:06:28.070947Z","iopub.status.idle":"2024-08-26T18:06:28.078777Z","shell.execute_reply.started":"2024-08-26T18:06:28.070919Z","shell.execute_reply":"2024-08-26T18:06:28.077822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Regarding the augmentations a number of transformations will be applied to each training image before they are fed into the model. This helps to add some diversity to a small dataset effectively growing it to a much larger one:\n\n- **random sized crop:** The model needs to be able to detect a wheat head regardless of how close or far away the head is to the camera. To produce more zoom levels in the dataset the crop method will take a portion of the image and zoom in to create a new image with larger wheat heads.\n- **flip amd rotate**: The wheat heads can point in any direction. To create more examples of wheat heads pointing in different directions the image will randomly be flipped both horizontally and vertically or rotated.\n- **hue saturation and brightness:** these are various methods that will alter the lighting of the image which will help to create different lighting scenarios. This helps as the test pictures are from various countries each with their own lighting levels.\n- **noise:** Some wheat heads aren't quite in focus. Adding some noise to the images helps to catch these wheat heads while also forcing the model to learn more abstract wheat head shapes. This helps a lot with over-fitting.\n- **cutout**: randomly remove small squares of pixels in the image. This prevents the model simply memorizing certain wheat heads and instead forces it to learn the patterns that represent a wheat head.\n- **clahe:** this is a must have. In many images the wheat heads are a similar colour to the grass in the background making it tricky for the model to differentiate between them. CLAHE helps to exemplify the colour difference between the two.\n- **grey scale:** I found that there were a few images with a yellow/gold tint. My model was learning to detect wheat heads without a tint (as most images do not contain a tint) and was really struggling to detect anything on the yellow images. By converting all images to grey scale the model is forced to ignore these tints making it much more effective at identifying wheat heads regardless of tint.\n\nI also greyscale and apply CLAHE to each validation image as the model has learnt on grey images where the wheat heads are given a lighter shade of grey.","metadata":{}},{"cell_type":"code","source":"DataGenerator.train_augmentations = albu.Compose([\n        albu.RandomSizedCrop(\n            min_max_height=(200, 200), \n            height=256, \n            width=256, \n            p=0.8\n        ),\n        albu.OneOf([\n            albu.Flip(),\n            albu.RandomRotate90(),\n        ], p=1),\n        albu.OneOf([\n            albu.HueSaturationValue(),\n            albu.RandomBrightnessContrast()\n        ], p=1),\n        albu.OneOf([\n            albu.GaussNoise(),\n            albu.GlassBlur(),\n            albu.ISONoise(),\n            albu.MultiplicativeNoise(),\n        ], p=0.5),\n        albu.Cutout(\n            num_holes=8, \n            max_h_size=16, \n            max_w_size=16, \n            fill_value=0, \n            p=0.5\n        ),\n        albu.CLAHE(p=1),\n        albu.ToGray(p=1),\n    ], \n    bbox_params={'format': 'coco', 'label_fields': ['labels']})\n\nDataGenerator.val_augmentations = albu.Compose([\n    albu.CLAHE(p=1),\n    albu.ToGray(p=1),\n])","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:28.079991Z","iopub.execute_input":"2024-08-26T18:06:28.080365Z","iopub.status.idle":"2024-08-26T18:06:28.092187Z","shell.execute_reply.started":"2024-08-26T18:06:28.080321Z","shell.execute_reply":"2024-08-26T18:06:28.091391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The next functions load an image and the corresponding bounding boxes depending on randomly picked image ids. As well as loading the images the above augmentations are added to an image as it is loaded. As the albumentaitons library was used to apply these augmentations I get the bounding boxes re-sized for free.","metadata":{}},{"cell_type":"code","source":"def __getitem__(self, index):\n    indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]\n\n    batch_ids = [self.image_ids[i] for i in indexes]\n\n    X, y = self.__data_generation(batch_ids)\n\n    return X, y\n\n\ndef __data_generation(self, batch_ids):\n    X, y = [], []\n\n    # Generate data\n    for i, image_id in enumerate(batch_ids):\n        pixels = self.image_pixels[image_id]\n        bboxes = self.labels[image_id]\n\n        if self.augment:     \n            pixels, bboxes = self.augment_image(pixels, bboxes)\n        else:\n            pixels = self.contrast_image(pixels)\n            bboxes = self.form_label_grid(bboxes)\n\n        X.append(pixels)\n        y.append(bboxes)\n\n    return np.array(X), np.array(y)\n\n\ndef augment_image(self, pixels, bboxes):\n    bbox_labels = np.ones(len(bboxes))\n\n    aug_result = self.train_augmentations(image=pixels, bboxes=bboxes, labels=bbox_labels)\n\n    bboxes = self.form_label_grid(aug_result['bboxes'])\n\n    return np.array(aug_result['image']) / 255, bboxes\n\n\ndef contrast_image(self, pixels):        \n    aug_result = self.val_augmentations(image=pixels)\n    return np.array(aug_result['image']) / 255\n\n\nDataGenerator.__getitem__ = __getitem__\nDataGenerator.__data_generation = __data_generation\nDataGenerator.augment_image = augment_image\nDataGenerator.contrast_image = contrast_image","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:28.097371Z","iopub.execute_input":"2024-08-26T18:06:28.097672Z","iopub.status.idle":"2024-08-26T18:06:28.112920Z","shell.execute_reply.started":"2024-08-26T18:06:28.097643Z","shell.execute_reply":"2024-08-26T18:06:28.112166Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The final part of the data generator class re-shapes the bounding box labels. It's worth mentioning here that there are a number of ways to represent a bounding box with four numbers. Some common ways are coco (the shape the boxes are in the raw data), voc-pascal and yolo.\n\n![Screenshot%202020-07-13%20at%2010.29.09.png](attachment:Screenshot%202020-07-13%20at%2010.29.09.png)\n*Figure 1, some common ways to represent bounding boxes*\n\nI'll be using the yolo shape for this model. In addition to the above shape, yolo detects objects by placing a grid over the image and asking if an object (such as a wheat head) is present in any of the cells of the grid. I've decided to use a 32x32 grid for this challenge which I'll refer to as a label grid. The bounding boxes are reshaped to be offset within the relevant cells of the image. Then all four variables (x, y, width and height) are scaled down to a 0-1 scale using the width and height of the image.\n\n![Screenshot%202020-06-12%20at%2016.29.19.png](attachment:Screenshot%202020-06-12%20at%2016.29.19.png)\n*Figure 2, a bounding box is put in the cell most at the centre of an object. It's x and y are offset to the cell while width and height remain the same*\n\nAny cells in the grid that have no objects within them contain a bounding box with the dimensions [0, 0, 0, 0].\n\nEach bounding box gets a confidence score where a value of 1 tells us that an object (wheat head) is present in the cell and a value of 0 tells us that no object is present. So a cell with an object present could contain a value like this: [1, 0.5, 0.5, 0.2, 0.2] telling us that there is an object present (due to the confidence score of 1, the centre of the bounding box is exactly in the middle of the cell and the box is 20% of the images total width and height.\n\nAs a cell could contain two overlapping heads of wheat I have configured the grid to contain up to two bounding boxes. These are known as anchor boxes.\n\nThe below code takes the list of bounding boxes for an image and puts them into the yolo label grid shape.","metadata":{},"attachments":{"Screenshot%202020-07-13%20at%2010.29.09.png":{"image/png":"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AjUsQFBYwyefQ0cAAQQQQAABBBBAAAEECAr5G0AAAQQQQAABBBBAAAEEaliAoLCGTz6HjgACCCCAAAIIIIAAAggQFPI3gAACCCCAAAIIIIAAAgjUsABBYQ2ffA4dAQQQQAABBBBAAAEEECAo5G8AAQQQQAABBBBAAAEEEKhhAYLCGj75HDoCCCCAAAIIIIAAAgggQFDI3wACCCCAAAIIIIAAAgggUMMCBIU1fPI5dAQQQAABBBBAAAEEEECAoJC/AQQQQAABBBBAAAEEEECghgUICmv45HPoCCCAAAIIIIAAAggggABBIX8DCCCAAAIIIIAAAggggEANCxAU1vDJ59ARQAABBBBAAAEEEEAAAYJC/gYQQAABBBBAAAEEEEAAgRoWICis4ZPPoSOAAAIIIIAAAggggAACBIX8DSCAAAIIIIAAAggggAACNSxAUFjDJ59DRwABBBBAAAEEEEAAAQQICvkbQAABBBBAAAEEEEAAAQRqWICgsIZPPoeOAAIIIIAAAggggAACCBAU8jeAAAIIIIAAAggggAACCNSwAEFhDZ98Dh0BBBBAAAEEEEAAAQQQICjkbwABBBBAAAEEEEAAAQQQqGEBgsIaPvkcOgIIIIAAAggggAACCCBAUMjfAAIIIIAAAggggAACCCBQwwIEhTV88jl0BBBAAIHqEgiCQP766y/RTxICCCDQmgL//POP/P33361ZBPZdhABBYRFYrIoAAggggEAlC9x8880y99xzy+OPP17JxaRsCCBQAwILLbSQbLrppjVwpNVxiASF1XEeOQoEEEAAAQSkrq4OBQQQQKAiBH755ZeKKAeFKEyAoLAwJ9ZCAAEEEEAAAQQQQAABBKpSYI6qPCoOqlUFxo8fL88995y899570qlTJ9l5551lscUWi8qkbcyHDh0q48aNE72L1LFjR9l///1lmWWWidbRiT///NPn8+yzz8oPP/wgu+66q2y77bYy33zzResVmle0ARMIIFBxAr///rv0799fFl10UTn88MMzyvfxxx/LiBEjZIsttvA/uvDDDz+UYcOGyUcffSRLLLGEbLbZZrLXXnuJMSZj208//VSefvppefnll309o3XI6quvnrFO9pfvvvtObrvtNunSpYt8+eWX8sQTT/hVdtppJ1//tGnTJmOTF154QV588UVfpnnmmUdWWWUVOfjgg/2xhCt+/fXXcvfdd8s777wjc845p6y55pq+ztOyp6dC6s6HHnpI3n77bX/s8847r2+addhhh8lcc82VnhXTCCCAQNEC99xzj3z++edy5JFHysILLxxtb62Va665RhZccMGojtbrssGDB/t6Teuf9dZbz9d9Wi81lJq6XUN5sqxMAu5EkxAom8D1119v3Z+m/1l66aWjaXfh5Pfx448/2rXXXjua7y4C/fT8889vH3300agcLtizXbt2jdbT5Zqvfn7//fdF5RVlygQCCFSswPrrr+//jc+YMSOjjCeddJKf/+STT/r5t99+e1QvpNcx7uaT/eOPP6Jtx44dm3O9Sy+9NFon18QHH3zgtwvz1s+wntp9992ta54ZbXbcccdF+wjXCeupL774wq/37bff2hVXXNGvp/VXel3mgsQor8bqThc429BI95G+PxcwW9exjM/LBdd+X+n1abQTJhBAAIEGBC6++GJffwwYMCBjrbA+7d27t5//+uuvR3WZ1kVhvaZ1nbtZF22rdZXWW2EqdLtwfT5bVkBadnfsrZoFRo8e7SuTjTbayIYXdq+88oqfp5WCXky5pwD+u1Ysroc8z+Hu5Pt5Wqm4u/R+3nnnnefnHX300dY9MbQaJIYXO6eeeqpfp9C8qtmcY0OgWgT0IkQvIPTfeZi0jtB6QS86XA929v333/fr6Pc33njDr/brr79GN5D0gkaTe8Lnt9NtX331VT9P66RVV13Vb+/uhPt5uX6FQaGW5eqrr/ar6L7//e9/+22vuOIKP08vfHQdDRrD+u6rr76KyqJBnqZbb73Vr3fZZZf5ekzrMnfH3c879thj/TqF1J3ujrzfplu3blaPWZOWNQw4Q4+wniQo9ET8QgCBIgQmT57s6xm9jktP4Q0w15rBzpw5M6p3XAsIv5relOrbt6/fdrvttotuUqUHhcVsl75vpltOgKCw5ayrfk8nn3yyrxD0jlJ60ouUM88803722Wd+uV5EaaCXni644AK/TJ8CaNKniXpB55qXRqvpxdSJJ55oL7/8cr99eEHWWF5RBkwggEDFCugTtfQLCC3oqFGj/Lxzzz3Xl1sDK13nlltuyTgObT2g8zVY1PTII4/471pXpKennnrK1yF6tzpfCoNCvZEVPn3TdbWVg+7D9aTnN500aZLVANE1lc/I6uGHH/br6Y0tTWGwe9RRR9lvvvnGz9Mg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CCCAAAIIIIAAAnEUsC5wC049R0QDw7ZtJeh5ksjkqU06FNN1L7+d9kRqH3vST5sD9m1SXmzUPAIEhc3jSq4IIIAAAggggAACCMRT4M+/xB4x6z3CW66VxA39/HEEPXrP1otoQQe49JJiumzrA0J7210iK68oZoN1C9qUlVpGgKCwZZzZCwIIIIAAAggggAACsRAI+lwpduL7Yg7tJma7TmL23s3/2FffEHtVqgMaqauTunZL+59CDsocvH9qtW++lYT2SEqqKAGCwoo6HRQGAQQQQAABBBBAAIHWE4gCP9dsNHHJuVFBEldclGpGevEVYt95zw9uHy0sYMLstL3fXlc1/5dqTlrAZqzSQgJztNB+2A0CCCCAAAIIIIAAAghUuIDZaH1J/vzZ7KVcdBFJfvFBxvzE4w+4dw1PzJiX98vMmb4XU9/j6JKL512NBa0jQFDYOu7sFQEEEEAAAQQQQACB+Ar8MVPsf88Xs4MbgL6h5NYTayXoe61fyxyR6om0oU1Y1vICBIUtb84eEUAAAQQQQAABBBCIt4AbTsL8p6eYPXdp8DiCcy4Re/Mgv47ptIULIrdrcH0Wto4AQWHruLNXBBBAAAEEEEAAAQRiLWD23aPR8psu24hMnSayTkdJHHe0SDLZ6Das0PICBIUtb84eEUAAAQQQQAABBBCoCQF9h9C/R1gTRxvfg6T30fieO0qOAAIIIIAAAggggAACCJQsQFBYMiEZIIAAAggggAACCCCAAALxFSAojO+5o+QIIIAAAggggAACCCCAQMkCBIUlE5IBAggggAACCCCAAAIIIBBfAYLC+J47So4AAggggAACCCCAAAIIlCxAUFgyIRkggAACCCCAAAIIIIAAAvEVICiM77mj5AgggAACCCCAAAIIIIBAyQIEhSUTkgECCCCAAAIIIIAAAgggEF8BgsL4njtKjgACCCCAAAIIIIAAAgiULEBQWDIhGSCAAAIIIIAAAggggAAC8RUgKIzvuaPkCCCAAAIIIIAAAggggEDJAgSFJROSAQIIIIAAAggggAACCCAQXwGCwvieO0qOAAIIIIAAAggggAACCJQsQFBYMiEZIIAAAggggAACCCCAAALxFSAojO+5o+QIIIAAAggggAACCCCAQMkCBIUlE5IBAggggAACCCCAAAIIIBBfAYLC+J47So4AAggggAACCCCAAAII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"},"Screenshot%202020-06-12%20at%2016.29.19.png":{"image/png":"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"}}},{"cell_type":"code","source":"def form_label_grid(self, bboxes):\n    label_grid = np.zeros((32, 32, 10))\n\n    for i in range(0, 32):\n        for j in range(0, 32):\n            cell = self.image_grid[i,j]\n            label_grid[i,j] = self.rect_intersect(cell, bboxes)\n\n    return label_grid\n\n\ndef rect_intersect(self, cell, bboxes): \n    cell_x, cell_y, cell_width, cell_height = cell\n    cell_x_max = cell_x + cell_width \n    cell_y_max = cell_y + cell_height\n    \n    anchor_one = np.array([0, 0, 0, 0, 0])\n    anchor_two = np.array([0, 0, 0, 0, 0])\n\n    # check all boxes\n    for bbox in bboxes:\n        box_x, box_y, box_width, box_height = bbox\n        box_x_centre = box_x + (box_width / 2)\n        box_y_centre = box_y + (box_height / 2)\n\n        if(box_x_centre >= cell_x and box_x_centre < cell_x_max and box_y_centre >= cell_y and box_y_centre < cell_y_max):\n            \n            if anchor_one[0] == 0:\n                anchor_one = self.yolo_shape(\n                    [box_x, box_y, box_width, box_height], \n                    [cell_x, cell_y, cell_width, cell_height]\n                )\n            \n            elif anchor_two[0] == 0:\n                anchor_two = self.yolo_shape(\n                    [box_x, box_y, box_width, box_height], \n                    [cell_x, cell_y, cell_width, cell_height]\n                )\n                \n            else:\n                break\n\n    return np.concatenate((anchor_one, anchor_two), axis=None)\n\n\ndef yolo_shape(self, box, cell):\n    box_x, box_y, box_width, box_height = box\n    cell_x, cell_y, cell_width, cell_height = cell\n\n    # top left x,y to centre x,y\n    box_x = box_x + (box_width / 2)\n    box_y = box_y + (box_height / 2)\n\n    # offset bbox x,y to cell x,y\n    box_x = (box_x - cell_x) / cell_width\n    box_y = (box_y - cell_y) / cell_height\n\n    # bbox width,height relative to cell width,height\n    box_width = box_width / 256\n    box_height = box_height / 256\n\n    return [1, box_x, box_y, box_width, box_height]\n\n\nDataGenerator.form_label_grid = form_label_grid\nDataGenerator.rect_intersect = rect_intersect\nDataGenerator.yolo_shape = yolo_shape","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:28.114619Z","iopub.execute_input":"2024-08-26T18:06:28.114949Z","iopub.status.idle":"2024-08-26T18:06:28.134210Z","shell.execute_reply.started":"2024-08-26T18:06:28.114920Z","shell.execute_reply":"2024-08-26T18:06:28.133312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_generator = DataGenerator(\n    train_image_ids,\n    train_pixels,\n    train_labels, \n    batch_size=6, \n    shuffle=True,\n    augment=True\n)\n\nval_generator = DataGenerator(\n    val_image_ids, \n    val_pixels,\n    val_labels, \n    batch_size=10,\n    shuffle=False,\n    augment=False\n)\n\nimage_grid = train_generator.image_grid","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:28.135532Z","iopub.execute_input":"2024-08-26T18:06:28.135899Z","iopub.status.idle":"2024-08-26T18:06:28.185033Z","shell.execute_reply.started":"2024-08-26T18:06:28.135861Z","shell.execute_reply":"2024-08-26T18:06:28.184243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model\n\nWith the data ready to go I'll define and train the model. As mentioned before this model is inspired by yolo, specifically yolo v3. This is a large and at times complex model. Below is an outline of the model. Basically the model begins with a convolutional layer with 32 filters which doubles in size in the next layer. The filters are then halved in size before doubling every layer up to 128 layers. The filters are then halved again while a larger stride reduces the size of the input image. This pattern of doubling and halving filter sizes continues with a few repeated blocks until we reach a size of 1024. A few resnet skip layers are added in as well to stabilise the large number of layers and reduce the chance of vanishing gradients.\n\n![Screenshot%202020-07-13%20at%2010.42.35.png](attachment:Screenshot%202020-07-13%20at%2010.42.35.png)\n*figure 3, An outline of the model taken from the yolov3 [paper](https://pjreddie.com/media/files/papers/YOLOv3.pdf).*\n\nBelow is my keras implementation of the model. The model is mostly in line with the yolov3 architecture though I have removed a few layers and altered some others. ","metadata":{},"attachments":{"Screenshot%202020-07-13%20at%2010.42.35.png":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAQAAAAE8CAYAAAAvym+wAAAK1mlDQ1BJQ0MgUHJvZmlsZQAASImVlwdUk8kWx+f70kNCC4QiJfSOdAJICT0UQTqISkhCEkoMCUFFbMjiCq4FFREsK7oiouDqCshaEFEsLIK9bxARUJ6LBRsq7ws8wu6+8947754zmd+5mbllMnPOPwCQQ1kiUTasCkCOME8cE+JPS0pOoeGeASwgAhgYA3MWWyJiREdHAMSm57/a+zsAks837eSx/v37/2rqHK6EDQCUinA6R8LOQbgNGS/YInEeAKgjiN9kSZ5Izj0Ia4iRAhF+JmfeFH+Uc/oko0mTa+JiAhCmAYAnsVhiHgAkW8RPy2fzkDgkeQ8OQo5AiHAhwj5sPouD8GmEbXNyFst5CGFLZL0IADJyOoCe/qeYvL/ET1fEZ7F4Cp7qa9LwgQKJKJu17P88mv9tOdnS6RzmyCDxxaEx8nzI+d3LWhyuYGH63KhpFnCmapIzXxoaP81sSUDKNHNYgeGKvdlzI6Y5QxDMVMTJY8ZNM1cSFDvN4sUxilwZ4gDGNLPEk3mJCMukWfEKP5/LVMQv4MclTnO+IGHuNEuyYsNn1gQo/GJpjKJ+rjDEfyZvsKL3HMmf+hUwFXvz+HGhit5ZM/VzhYyZmJIkRW0cbmDQzJp4xXpRnr8ilyg7WrGemx2i8EvyYxV785DLObM3WnGGmayw6GkGAhAJWIBNU5kmAPK4S/PkjQQsFi0TC3j8PBoDeW1cGlPItrelOTk4OQAgf7tT1+EtdfJNQtSrM77cNgA8ShEnb8bHMgHg1HMAKO9nfCZvkKu0GYAzPWypOH/Kh5Z/YJBfTwVoAB1gAEyAJbADTsANeAE/EATCQBSIA8lgIVIrH+QAMVgCCsEaUALKwGawHVSBvWA/OASOguOgGZwG58ElcA30gNvgIZCBAfASjIL3YByCIBxEhiiQDmQImUE2kBNEh3ygICgCioGSoTSIBwkhKVQIrYXKoHKoCtoH1UE/Q6eg89AVqBe6D/VBw9Ab6DOMgkmwBqwPm8OzYTrMgMPhOHgBzINz4QK4GN4IV8I18BG4CT4PX4NvwzL4JTyGAiglFBVlhLJD0VEBqChUCioDJUatRJWiKlA1qAZUK6oTdRMlQ42gPqGxaAqahrZDe6FD0fFoNjoXvRK9AV2FPoRuQnegb6L70KPobxgyRg9jg/HEMDFJGB5mCaYEU4E5iDmJuYi5jRnAvMdisVSsBdYdG4pNxmZil2M3YHdjG7Ft2F5sP3YMh8Pp4Gxw3rgoHAuXhyvB7cQdwZ3D3cAN4D7ilfCGeCd8MD4FL8QX4Svwh/Fn8Tfwg/hxgirBjOBJiCJwCMsImwgHCK2E64QBwjhRjWhB9CbGETOJa4iVxAbiReIj4lslJSVjJQ+leUoCpdVKlUrHlC4r9Sl9IqmTrEkBpFSSlLSRVEtqI90nvSWTyeZkP3IKOY+8kVxHvkB+Qv6oTFG2V2Yqc5RXKVcrNynfUH6lQlAxU2GoLFQpUKlQOaFyXWVElaBqrhqgylJdqVqtekr1ruqYGkXNUS1KLUdtg9phtStqQ+o4dXP1IHWOerH6fvUL6v0UFMWEEkBhU9ZSDlAuUgY0sBoWGkyNTI0yjaMa3RqjmuqaLpoJmks1qzXPaMqoKKo5lUnNpm6iHqfeoX7W0tdiaHG11ms1aN3Q+qA9S9tPm6tdqt2ofVv7sw5NJ0gnS2eLTrPOY120rrXuPN0lunt0L+qOzNKY5TWLPat01vFZD/RgPWu9GL3levv1uvTG9A30Q/RF+jv1L+iPGFAN/AwyDbYZnDUYNqQY+hgKDLcZnjN8QdOkMWjZtEpaB23USM8o1EhqtM+o22jc2MI43rjIuNH4sQnRhG6SYbLNpN1k1NTQNNK00LTe9IEZwYxuxjfbYdZp9sHcwjzRfJ15s/mQhbYF06LAot7ikSXZ0tcy17LG8pYV1opulWW126rHGrZ2teZbV1tft4Ft3GwENrttem0xth62Qtsa27t2JDuGXb5dvV2fPdU+wr7Ivtn+1WzT2Smzt8zunP3NwdUh2+GAw0NHdccwxyLHVsc3TtZObKdqp1vOZOdg51XOLc6vXWxcuC57XO65UlwjXde5trt+dXN3E7s1uA27m7qnue9yv0vXoEfTN9Ave2A8/D1WeZz2+OTp5pnnedzzDy87ryyvw15DcyzmcOccmNPvbezN8t7nLfOh+aT5/Ogj8zXyZfnW+D71M/Hj+B30G2RYMTIZRxiv/B38xf4n/T8EeAasCGgLRAWGBJYGdgepB8UHVQU9CTYO5gXXB4+GuIYsD2kLxYSGh24JvcvUZ7KZdczRMPewFWEd4aTw2PCq8KcR1hHiiNZIODIscmvko7lmc4Vzm6NAFDNqa9TjaIvo3Ohf52HnRc+rnvc8xjGmMKYzlhK7KPZw7Ps4/7hNcQ/jLeOl8e0JKgmpCXUJHxIDE8sTZUmzk1YkXUvWTRYkt6TgUhJSDqaMzQ+av33+QKpraknqnQUWC5YuuLJQd2H2wjOLVBaxFp1Iw6Qlph1O+8KKYtWwxtKZ6bvSR9kB7B3slxw/zjbOMNebW84dzPDOKM8Y4nnztvKG+b78Cv6IIEBQJXidGZq5N/NDVlRWbdZEdmJ2Yw4+Jy3nlFBdmCXsWGyweOniXpGNqEQky/XM3Z47Kg4XH5RAkgWSljwNRCR1SS2l30n78n3yq/M/LklYcmKp2lLh0q5l1svWLxssCC74aTl6OXt5e6FR4ZrCvhWMFftWQivTV7avMllVvGpgdcjqQ2uIa7LW/FbkUFRe9G5t4trWYv3i1cX934V8V1+iXCIuubvOa93e79HfC77vXu+8fuf6b6Wc0qtlDmUVZV82sDdc/cHxh8ofJjZmbOze5LZpz2bsZuHmO1t8txwqVysvKO/fGrm1aRttW+m2d9sXbb9S4VKxdwdxh3SHrDKismWn6c7NO79U8atuV/tXN+7S27V+14fdnN039vjtadirv7ds7+cfBT/e2xeyr6nGvKZiP3Z//v7nBxIOdP5E/6nuoO7BsoNfa4W1skMxhzrq3OvqDusd3lQP10vrh4+kHuk5Gni0pcGuYV8jtbHsGDgmPfbi57Sf7xwPP95+gn6i4RezX3adpJwsbYKaljWNNvObZS3JLb2nwk61t3q1nvzV/tfa00anq89ontl0lni2+OzEuYJzY22itpHzvPP97YvaH15IunCrY15H98Xwi5cvBV+60MnoPHfZ+/LpK55XTl2lX22+5natqcu16+Rvrr+d7Hbrbrrufr2lx6OntXdO79kbvjfO3wy8eekW89a123Nv996Jv3Pvbupd2T3OvaH72fdfP8h/MP5w9SPMo9LHqo8rnug9qfnd6vdGmZvsTF9gX9fT2KcP+9n9L59Jnn0ZKH5Ofl4xaDhYN+Q0dHo4eLjnxfwXAy9FL8dHSv6h9o9dryxf/fKH3x9do0mjA6/FryfebHir87b2ncu79rHosSfvc96Pfyj9qPPx0Cf6p87PiZ8Hx5d8wX2p/Gr1tfVb+LdHEzkTEyKWmDUpBVDIgDMyAHhTi2jjZEQ7ILqcOH9KW08aNPV/YJLAf+Ip/T1pbgDU+gEQvxqACESj7EGGGcIkZJZLojg/ADs7K8a/TJLh7DQVi4QoS8zHiYm3+gDgWgH4Kp6YGN89MfH1AFLsfQDacqc0vdywiJY/hpFTl8FK8Heb0vt/6vHvM5BX4AL+Pv8TZuQX02Ir5hoAAABWZVhJZk1NACoAAAAIAAGHaQAEAAAAAQAAABoAAAAAAAOShgAHAAAAEgAAAESgAgAEAAAAAQAAAQCgAwAEAAAAAQAAATwAAAAAQVNDSUkAAABTY3JlZW5zaG90bqZLNQAAAdZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MjU2PC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6VXNlckNvbW1lbnQ+U2NyZWVuc2hvdDwvZXhpZjpVc2VyQ29tbWVudD4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMxNjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgrcoml1AABAAElEQVR4Ae2dC9w1VVX/x383KrMig1K5JRUpgQgJcgnEAA0hQUDuL8RVrvH2QnInuchNbkIYAgGGoJgJJaUgUhiagDfoSoqSFlhJV7u3/7/vkjXsM2dmzsw5+8z7vO/Z6/N5nnPOzJ49e9bsvfbaa6/fWs8LoiJT5kDmwEJy4P8t5FPnh84cyBwwDmQBkDtC5sACcyALgAV++fnRMweyAMh9IHNggTmQBcACv/z86JkD3z4EC5588sni7W9/e+2tNthgg+KUU06pPbfoB//93/+9WL58+Rgbnv/85xeXXHJJcfzxxxcnn3xy8a//+q/Fe97zHuMxmzr/+7//W3z7t8/31f7jP/5j8aEPfaj44Ac/WHzf931f8frXv7544xvfWNC2L3zhC8X73ve+4vzzzx9r+6p84Etf+lLxa7/2a8UjjzxSfNd3fVfxile8ojjppJOKtddee+Jj8U6e97znFf/v/003587rvU7XmomPO17ge77newr+YOJv/MZv2Hd+w8hM9Rz4r//6r+Jd73pX8Xd/93fFt33bt5V/XvorX/lKgZD467/+axMAHH/nO99Z7LTTTl5kbp/Lli2ze2277bYmABBGe+21l93P2zS3m6+Eihn0W221VfGJT3zCBB08/t3f/d1i8803L/7sz/5sYou23357e5cTCzYUmNt7xQ9gSNJMFX7gB36gvOXnP//58OCDD5a///mf/zn8zu/8TtCsFj760Y+Gp59+Otx22232p45VluP4b/7mb4b3v//94Rvf+EZ5fHX6olkWH43wyU9+svaxPvaxjwXK/P7v/3548YtfHCQowhFHHBFe9rKXhT/+4z+2a5r49Hu/93vh7//+741/XPc///M/4b777gvXXHNN+NznPld7Pz/4xBNPBM1m4dFHH/VD9q449k//9E/Wjj/8wz+0cx//+MftffJO/e+///u/7Rz3+fVf//VAGc2QZV1L8cuWW24ZXvva1xqfvH3f/OY3w4te9KKw22672aGHH344SBj4aXtvEtKBPv5TP/VT4cgjjwxf/vKXG/v13/zN3wTeqRNl/+iP/qj2vXqZWT+LWSvoe31VAEgbMIHwn//5n1bVu9/97vAjP/IjNqjp/C95yUvCG97whrD++uuH7bbbzsrA0B/+4R8OP/3TPx1+9Ed/1Mo8/vjjfZuy5MtPEgDf+Z3faQPdBQADCp688IUvDGeffbZ1vCY+SW0P6623npX98z//86CZPGiGC1Llw3d/93eHu+++u5E/Tz31lAmAAw44wITA//3f/1lZf4daGoR1113Xjh100EFWN/Wvueaa4Tu+4ztMaF1xxRX2neMc23333YPX03jjlXRCS1gTxPHg9KYce+yxYY011rC277333uGtb32rnwo77rhjuPLKK4OWDdbHN9100/Dbv/3bVlddv77jjjvCj/3Yj5XXX3vttWGbbbYxgRy/17JAgi8rXQAw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"}}},{"cell_type":"code","source":"x_input = tf.keras.Input(shape=(256,256,3))\n\nx = tf.keras.layers.Conv2D(32, (3, 3), strides=(1, 1), padding='same')(x_input)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n########## block 1 ##########\nx = tf.keras.layers.Conv2D(64, (3, 3), strides=(1, 1), padding='same')(x)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\nx_shortcut = x\n\nfor i in range(2):\n    x = tf.keras.layers.Conv2D(32, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Conv2D(64, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Add()([x_shortcut, x])\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x_shortcut = x\n\n\n########## block 2 ##########\nx = tf.keras.layers.Conv2D(128, (3, 3), strides=(1, 1), padding='same')(x)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\nx_shortcut = x\n\nfor i in range(2):\n    x = tf.keras.layers.Conv2D(64, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Conv2D(128, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Add()([x_shortcut, x])\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x_shortcut = x\n\n########## block 3 ##########\nx = tf.keras.layers.Conv2D(256, (3, 3), strides=(2, 2), padding='same')(x)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\nx_shortcut = x\n\nfor i in range(8):\n    x = tf.keras.layers.Conv2D(128, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Conv2D(256, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Add()([x_shortcut, x])\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x_shortcut = x\n\n    \n########## block 4 ##########\nx = tf.keras.layers.Conv2D(512, (3, 3), strides=(2, 2), padding='same')(x)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\nx_shortcut = x\n\nfor i in range(8):\n    x = tf.keras.layers.Conv2D(256, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Conv2D(512, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Add()([x_shortcut, x])\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x_shortcut = x\n\n########## block 5 ##########\nx = tf.keras.layers.Conv2D(1024, (3, 3), strides=(2, 2), padding='same')(x)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\nx_shortcut = x\n\nfor i in range(4):\n    x = tf.keras.layers.Conv2D(512, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Conv2D(1024, (3, 3), strides=(1, 1), padding='same')(x)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x = tf.keras.layers.Add()([x_shortcut, x])\n    x = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\n    x_shortcut = x\n\n########## output layers ##########\nx = tf.keras.layers.Conv2D(512, (3, 3), strides=(1, 1), padding='same')(x)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\nx = tf.keras.layers.Conv2D(256, (3, 3), strides=(1, 1), padding='same')(x)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\nx = tf.keras.layers.Conv2D(128, (3, 3), strides=(1, 1), padding='same')(x)\nx = tf.keras.layers.BatchNormalization()(x)\nx = tf.keras.layers.LeakyReLU(alpha=0.1)(x)\n\npredictions = tf.keras.layers.Conv2D(10, (1, 1), strides=(1, 1), activation='sigmoid')(x)\n\nmodel = tf.keras.Model(inputs=x_input, outputs=predictions)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:28.186286Z","iopub.execute_input":"2024-08-26T18:06:28.186603Z","iopub.status.idle":"2024-08-26T18:06:30.741139Z","shell.execute_reply.started":"2024-08-26T18:06:28.186573Z","shell.execute_reply":"2024-08-26T18:06:30.740169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"One issue with yolo is that it is likely to contain more cells in its label grid that contain no objects than cells that do contain objects. It is easy then for the model to focus too much on learning to reduce no object cells to zero and not focus enough on getting the bounding boxes to the right shape. To overcome this the yolo [paper](https://pjreddie.com/media/files/papers/YOLOv3.pdf) suggests weighting the cells containing bounding boxes five times higher and the cells with no bounding boxes by half. \n\nI have defined a custom loss function to do just this. I have also split the loss function into three parts. The first takes care of the confidence score that is trying to work out if a label grid cell contains a head of wheat or not. Binary cross entropy is used here as that is a binary classification task. The second part looks at the x,y position of the bounding boxes while the third looks at the width,height of the bounding boxes. MSE (mean squared loss) is used for the second and third parts as they are regression tasks. ","metadata":{}},{"cell_type":"code","source":"# def custom_loss(y_true, y_pred):\n#     binary_crossentropy = prob_loss = tf.keras.losses.BinaryCrossentropy(\n#         reduction=tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE\n#     )\n    \n#     prob_loss = binary_crossentropy(\n#         tf.concat([y_true[:,:,:,0], y_true[:,:,:,5]], axis=0), \n#         tf.concat([y_pred[:,:,:,0], y_pred[:,:,:,5]], axis=0)\n#     )\n    \n#     xy_loss = tf.keras.losses.MSE(\n#         tf.concat([y_true[:,:,:,1:3], y_true[:,:,:,6:8]], axis=0), \n#         tf.concat([y_pred[:,:,:,1:3], y_pred[:,:,:,6:8]], axis=0)\n#     )\n    \n#     wh_loss = tf.keras.losses.MSE(\n#         tf.concat([y_true[:,:,:,3:5], y_true[:,:,:,8:10]], axis=0), \n#         tf.concat([y_pred[:,:,:,3:5], y_pred[:,:,:,8:10]], axis=0)\n#     )\n    \n#     bboxes_mask = get_mask(y_true)\n    \n#     xy_loss = xy_loss * bboxes_mask\n#     wh_loss = wh_loss * bboxes_mask\n    \n#     return prob_loss + xy_loss + wh_loss\n\n\n# def get_mask(y_true):\n#     anchor_one_mask = tf.where(\n#         y_true[:,:,:,0] == 0, \n#         0.5, \n#         5.0\n#     )\n    \n#     anchor_two_mask = tf.where(\n#         y_true[:,:,:,5] == 0, \n#         0.5, \n#         5.0\n#     )\n    \n#     bboxes_mask = tf.concat(\n#         [anchor_one_mask,anchor_two_mask],\n#         axis=0\n#     )\n    \n#     return bboxes_mask","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:30.742452Z","iopub.execute_input":"2024-08-26T18:06:30.742745Z","iopub.status.idle":"2024-08-26T18:06:30.747196Z","shell.execute_reply.started":"2024-08-26T18:06:30.742716Z","shell.execute_reply":"2024-08-26T18:06:30.746388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I experimented with a few optimisers including FTRL and SGD but in the end Adam was the fastest and most reliable function. I have kept the learning rate reasonably high as it can take a number of steps to get the model moving quickly towards convergence. A higher rate helps to reduce the number of steps needed to get the model going.","metadata":{}},{"cell_type":"code","source":"optimiser = tf.keras.optimizers.Adam(learning_rate=0.0001)\n\nmodel.compile(\n    optimizer=optimiser, \n    loss=tf.keras.losses.BinaryCrossentropy(\n        reduction=tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE)\n)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:30.748541Z","iopub.execute_input":"2024-08-26T18:06:30.748814Z","iopub.status.idle":"2024-08-26T18:06:30.805935Z","shell.execute_reply.started":"2024-08-26T18:06:30.748787Z","shell.execute_reply":"2024-08-26T18:06:30.805256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"While a high learning rate at the beginning of a training run is great at the start, it can cause issues as the model approaches convergence when smaller, more careful steps are needed. I considered using learning rate decay to handle this but decided on a callback to reduce the learning rate when it plateaus (or increases) over the space of two epochs. This allows the model to make the most of a higher rate until it that rate is too high at which point the model wuicky reduces it.\n\nIn addition to this I have added an early stopping callback to stop the model training if is no longer able to reduce the loss. This reduces any waste processing and provides faster feedback if the model just isn't training very well.","metadata":{}},{"cell_type":"code","source":"callbacks = [\n    tf.keras.callbacks.ReduceLROnPlateau(monitor='loss', patience=2, verbose=1),\n    tf.keras.callbacks.EarlyStopping(monitor='loss', patience=5, verbose=1, restore_best_weights=True),\n]","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:30.807159Z","iopub.execute_input":"2024-08-26T18:06:30.807419Z","iopub.status.idle":"2024-08-26T18:06:30.812339Z","shell.execute_reply.started":"2024-08-26T18:06:30.807394Z","shell.execute_reply":"2024-08-26T18:06:30.811403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Finally the model is ready to be trained. The data generators are passed into the fit generator method of the model alongside the callbacks and the maximum number of epochs to take. Be warned that with 100 or less images this model can train at an okay speed on CPU. Any more images than that will need the GPU (which could still run for a few hours).","metadata":{}},{"cell_type":"code","source":"history = model.fit_generator(\n    train_generator,\n    validation_data=val_generator,\n    epochs=4,\n    callbacks=callbacks\n)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:06:30.813458Z","iopub.execute_input":"2024-08-26T18:06:30.813763Z","iopub.status.idle":"2024-08-26T18:40:43.565765Z","shell.execute_reply.started":"2024-08-26T18:06:30.813733Z","shell.execute_reply":"2024-08-26T18:40:43.564894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prediction post processing\n\nThe model outputs the predicted bounding boxes as a label grid. However to visualise the bounding boxes on an image or submit them to the competition the shape for one images bounding boxes need changing from (16,16,10) to (m, 4) where m represents the number of bounding boxes that have a high confidence.\n\nThis first function transforms the boxes from the yolo format to the coco format. It does this through the following:\n\n- return the scale of the boxes from 0-1 to 0-256\n- change the x,y from the centre of the box to the top left corner\n- change width and height to x_max, y_max i.e. change to voc shape","metadata":{}},{"cell_type":"code","source":"def prediction_to_bbox(bboxes, image_grid):    \n    bboxes = bboxes.copy()\n    \n    im_width = (image_grid[:,:,2] * 32)\n    im_height = (image_grid[:,:,3] * 32)\n    \n    # descale x,y\n    bboxes[:,:,1] = (bboxes[:,:,1] * image_grid[:,:,2]) + image_grid[:,:,0]\n    bboxes[:,:,2] = (bboxes[:,:,2] * image_grid[:,:,3]) + image_grid[:,:,1]\n    bboxes[:,:,6] = (bboxes[:,:,6] * image_grid[:,:,2]) + image_grid[:,:,0]\n    bboxes[:,:,7] = (bboxes[:,:,7] * image_grid[:,:,3]) + image_grid[:,:,1]\n    \n    # descale width,height\n    bboxes[:,:,3] = bboxes[:,:,3] * im_width \n    bboxes[:,:,4] = bboxes[:,:,4] * im_height\n    bboxes[:,:,8] = bboxes[:,:,8] * im_width \n    bboxes[:,:,9] = bboxes[:,:,9] * im_height\n    \n    # centre x,y to top left x,y\n    bboxes[:,:,1] = bboxes[:,:,1] - (bboxes[:,:,3] / 2)\n    bboxes[:,:,2] = bboxes[:,:,2] - (bboxes[:,:,4] / 2)\n    bboxes[:,:,6] = bboxes[:,:,6] - (bboxes[:,:,8] / 2)\n    bboxes[:,:,7] = bboxes[:,:,7] - (bboxes[:,:,9] / 2)\n    \n    # width,heigth to x_max,y_max\n    bboxes[:,:,3] = bboxes[:,:,1] + bboxes[:,:,3]\n    bboxes[:,:,4] = bboxes[:,:,2] + bboxes[:,:,4]\n    bboxes[:,:,8] = bboxes[:,:,6] + bboxes[:,:,8]\n    bboxes[:,:,9] = bboxes[:,:,7] + bboxes[:,:,9]\n    \n    return bboxes","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:43.567769Z","iopub.execute_input":"2024-08-26T18:40:43.568105Z","iopub.status.idle":"2024-08-26T18:40:43.588314Z","shell.execute_reply.started":"2024-08-26T18:40:43.568040Z","shell.execute_reply":"2024-08-26T18:40:43.587369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Next the bounding boxes with low confidence need removing. I also need to remove any boxes that overlap another box. Luckily Tensorflow has a non-max suppression function that filters out both low confidence boxes and removes one box if any two overlap. There's just a little bit of reshaping to prepare the bounding boxes for this function one of which includes switching the position of the x and y dimensions.","metadata":{}},{"cell_type":"code","source":"def non_max_suppression(predictions, top_n):\n    probabilities = np.concatenate((predictions[:,:,0].flatten(), predictions[:,:,5].flatten()), axis=None)\n    \n    first_anchors = predictions[:,:,1:5].reshape((32*32, 4))\n    second_anchors = predictions[:,:,6:10].reshape((32*32, 4))\n    \n    bboxes = np.concatenate(\n        (first_anchors,second_anchors),\n        axis=0\n    )\n    \n    bboxes = switch_x_y(bboxes)\n    bboxes, probabilities = select_top(probabilities, bboxes, top_n=top_n)\n    bboxes = switch_x_y(bboxes)\n    \n    return bboxes\n\n\ndef switch_x_y(bboxes):\n    x1 = bboxes[:,0].copy()\n    y1 = bboxes[:,1].copy()\n    x2 = bboxes[:,2].copy()\n    y2 = bboxes[:,3].copy()\n    \n    bboxes[:,0] = y1\n    bboxes[:,1] = x1\n    bboxes[:,2] = y2\n    bboxes[:,3] = x2\n    \n    return bboxes\n\n\ndef select_top(probabilities, boxes, top_n=10):\n    top_indices = tf.image.non_max_suppression(\n        boxes = boxes, \n        scores = probabilities, \n        max_output_size = top_n, \n        iou_threshold = 0.3,\n        score_threshold = 0.3\n    )\n    \n    top_indices = top_indices.numpy()\n    \n    return boxes[top_indices], probabilities[top_indices]","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:43.589591Z","iopub.execute_input":"2024-08-26T18:40:43.589880Z","iopub.status.idle":"2024-08-26T18:40:43.604571Z","shell.execute_reply.started":"2024-08-26T18:40:43.589847Z","shell.execute_reply":"2024-08-26T18:40:43.603586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Wrap these post-processing functions into one and output the predicted bounding boxes as a dictionary where the image id is the key.","metadata":{}},{"cell_type":"code","source":"def process_predictions(predictions, image_ids, image_grid):\n    bboxes = {}\n    \n    for i, image_id in enumerate(image_ids):\n        predictions[i] = prediction_to_bbox(predictions[i], image_grid)\n        bboxes[image_id] = non_max_suppression(predictions[i], top_n=100)\n        \n        # back to coco shape\n        bboxes[image_id][:,2:4] = bboxes[image_id][:,2:4] - bboxes[image_id][:,0:2]\n    \n    return bboxes","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:43.605927Z","iopub.execute_input":"2024-08-26T18:40:43.606241Z","iopub.status.idle":"2024-08-26T18:40:43.620044Z","shell.execute_reply.started":"2024-08-26T18:40:43.606212Z","shell.execute_reply":"2024-08-26T18:40:43.618982Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's see how the model did by producing predictions for some images in the validation dataset.","metadata":{}},{"cell_type":"code","source":"val_predictions = model.predict(val_generator)\nval_predictions = process_predictions(val_predictions, val_image_ids, image_grid)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:43.621497Z","iopub.execute_input":"2024-08-26T18:40:43.621906Z","iopub.status.idle":"2024-08-26T18:40:48.558980Z","shell.execute_reply.started":"2024-08-26T18:40:43.621848Z","shell.execute_reply":"2024-08-26T18:40:48.558250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images(val_image_ids[0:4], val_predictions)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:48.560268Z","iopub.execute_input":"2024-08-26T18:40:48.560544Z","iopub.status.idle":"2024-08-26T18:40:49.337235Z","shell.execute_reply.started":"2024-08-26T18:40:48.560517Z","shell.execute_reply":"2024-08-26T18:40:49.336381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images(val_image_ids[4:8], val_predictions)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:49.338414Z","iopub.execute_input":"2024-08-26T18:40:49.338680Z","iopub.status.idle":"2024-08-26T18:40:50.102694Z","shell.execute_reply.started":"2024-08-26T18:40:49.338653Z","shell.execute_reply":"2024-08-26T18:40:50.101863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Evaluate Model\n\nWith the model trained it's time to look at the quality of the model. Begin by plotting the loss curve.","metadata":{}},{"cell_type":"code","source":"print('Epochs: ' + str(len(history.history['loss'])))\nprint('Final training loss: ' + str(history.history['loss'][-1]))\nprint('Final validation loss: ' + str(history.history['val_loss'][-1]))","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:50.104185Z","iopub.execute_input":"2024-08-26T18:40:50.104532Z","iopub.status.idle":"2024-08-26T18:40:50.111447Z","shell.execute_reply.started":"2024-08-26T18:40:50.104492Z","shell.execute_reply":"2024-08-26T18:40:50.110670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1, 2, figsize=(15, 5))\n\nax[0].set_title('Training Loss')\nax[0].plot(history.history['loss'])\n\nax[1].set_title('Validation Loss')\nax[1].plot(history.history['val_loss'])","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:50.112858Z","iopub.execute_input":"2024-08-26T18:40:50.113210Z","iopub.status.idle":"2024-08-26T18:40:50.400622Z","shell.execute_reply.started":"2024-08-26T18:40:50.113174Z","shell.execute_reply":"2024-08-26T18:40:50.399724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Then visualise the first few layers of the model to see how each layer influences the bounding boxes. Start by copying the model and configuring the new one to return each layers output when a prediction is made.","metadata":{}},{"cell_type":"code","source":"layer_outputs = [layer.output for layer in model.layers]\nevaluation_model = tf.keras.Model(inputs=model.input, outputs=layer_outputs)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:50.401886Z","iopub.execute_input":"2024-08-26T18:40:50.402193Z","iopub.status.idle":"2024-08-26T18:40:50.439393Z","shell.execute_reply.started":"2024-08-26T18:40:50.402162Z","shell.execute_reply":"2024-08-26T18:40:50.438584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Then pick an image and cycle through the layers making a prediction and visualising the features outputted by the layer. The warm colours represent where the features lie in this image.\n\nNote that I have not visualised all the layers here due to the large number of them.","metadata":{}},{"cell_type":"code","source":"image = Image.open('../input/global-wheat-detection/train/' + train_image_ids[1] + \".jpg\")\nimage = image.resize((256, 256))\n\npixels = np.asarray(image) / 255\npixels = np.expand_dims(pixels, axis=0)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:50.440495Z","iopub.execute_input":"2024-08-26T18:40:50.440880Z","iopub.status.idle":"2024-08-26T18:40:50.487816Z","shell.execute_reply.started":"2024-08-26T18:40:50.440837Z","shell.execute_reply":"2024-08-26T18:40:50.487132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_of_layers = len(layer_outputs)\n\nfig, axes = plt.subplots(2, 6, figsize=(20, 10))\n\nlayer = 0\nfor i in range(0, 2):\n    for j in range(0, 6):\n        layer_output = evaluation_model.predict(pixels)[layer]\n        axes[i, j].imshow(layer_output[0, :, :, 1], cmap='inferno')\n        \n        layer = layer + 1","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:40:50.488963Z","iopub.execute_input":"2024-08-26T18:40:50.489272Z","iopub.status.idle":"2024-08-26T18:41:22.363933Z","shell.execute_reply.started":"2024-08-26T18:40:50.489243Z","shell.execute_reply":"2024-08-26T18:41:22.363207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Test Images\n\nFinally predict bounding boxes for the test set. I wanted to see how easy/difficult it would be to use the model without a data generator class so I have inputted the images into the model as numpy arrays.\n\nFirst, load the test image ids.","metadata":{}},{"cell_type":"code","source":"test_image_ids = os.listdir('/kaggle/input/global-wheat-detection/test/')\ntest_image_ids = [image_id[:-4] for image_id in test_image_ids]","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:41:22.365040Z","iopub.execute_input":"2024-08-26T18:41:22.365324Z","iopub.status.idle":"2024-08-26T18:41:22.375661Z","shell.execute_reply.started":"2024-08-26T18:41:22.365296Z","shell.execute_reply":"2024-08-26T18:41:22.374879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now loop through the images, loading each one as a numpy array, applying augmentations to it and feeding it into the model. Save the bounding box predictions as a numpy array.","metadata":{}},{"cell_type":"code","source":"test_predictions = []\n\nfor i, image_id in enumerate(test_image_ids):\n    image = Image.open('/kaggle/input/global-wheat-detection/test/' + image_id + \".jpg\")\n    image = image.resize((256, 256))            \n\n    pixels = np.asarray(image)\n\n    val_augmentations = albu.Compose([\n        albu.CLAHE(p=1),\n        albu.ToGray(p=1)\n    ])\n\n    aug_result = val_augmentations(image=pixels)\n    pixels = np.array(aug_result['image']) / 255\n    \n    pixels = np.expand_dims(pixels, axis=0)\n    \n    bboxes = model.predict(pixels)\n\n    test_predictions.append(bboxes)\n    \ntest_predictions = np.concatenate(test_predictions)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:41:22.377210Z","iopub.execute_input":"2024-08-26T18:41:22.377545Z","iopub.status.idle":"2024-08-26T18:41:24.873135Z","shell.execute_reply.started":"2024-08-26T18:41:22.377512Z","shell.execute_reply":"2024-08-26T18:41:24.872289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Then apply the typical post processing functions to the predictions.","metadata":{}},{"cell_type":"code","source":"test_predictions = process_predictions(test_predictions, test_image_ids, image_grid)","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:41:24.874411Z","iopub.execute_input":"2024-08-26T18:41:24.874686Z","iopub.status.idle":"2024-08-26T18:41:24.883634Z","shell.execute_reply.started":"2024-08-26T18:41:24.874659Z","shell.execute_reply":"2024-08-26T18:41:24.882225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Although only a submission to the competition will provide a final score on how good the model is, I'll visualise each test image with their predicted boxes to get an idea of the models quality. This involves a slightly different visualisation function just to accomodate the larger images.","metadata":{}},{"cell_type":"code","source":"show_images(test_image_ids[0:4], test_predictions, source='test')","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:41:24.885415Z","iopub.execute_input":"2024-08-26T18:41:24.885962Z","iopub.status.idle":"2024-08-26T18:41:25.657097Z","shell.execute_reply.started":"2024-08-26T18:41:24.885913Z","shell.execute_reply":"2024-08-26T18:41:25.656148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images(test_image_ids[4:8], test_predictions, source='test')","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:41:25.658326Z","iopub.execute_input":"2024-08-26T18:41:25.658622Z","iopub.status.idle":"2024-08-26T18:41:26.417389Z","shell.execute_reply.started":"2024-08-26T18:41:25.658592Z","shell.execute_reply":"2024-08-26T18:41:26.416559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images(test_image_ids[8:10], test_predictions, source='test')","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:41:26.418734Z","iopub.execute_input":"2024-08-26T18:41:26.419091Z","iopub.status.idle":"2024-08-26T18:41:26.821058Z","shell.execute_reply.started":"2024-08-26T18:41:26.419038Z","shell.execute_reply":"2024-08-26T18:41:26.820297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Finally save the weights so that the model can be used in an inference notebook.","metadata":{}},{"cell_type":"code","source":"model.save_weights('wheat_detection_model')","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:41:26.822492Z","iopub.execute_input":"2024-08-26T18:41:26.822868Z","iopub.status.idle":"2024-08-26T18:41:28.809371Z","shell.execute_reply.started":"2024-08-26T18:41:26.822828Z","shell.execute_reply":"2024-08-26T18:41:28.808649Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('obj_det.keras')","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:41:28.810653Z","iopub.execute_input":"2024-08-26T18:41:28.810925Z","iopub.status.idle":"2024-08-26T18:41:31.287900Z","shell.execute_reply.started":"2024-08-26T18:41:28.810899Z","shell.execute_reply":"2024-08-26T18:41:31.286692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install tf2onnx\n\nimport tf2onnx\nimport tensorflow as tf\n\n# Load your Keras model\nmodel = tf.keras.models.load_model('/kaggle/working/obj_det.keras')\n\n# Convert the model to ONNX format\nspec = (tf.TensorSpec((None, ) * len(model.inputs[0].shape), tf.float32, name=\"input\"),)\noutput_path = 'obj_det.onnx'\n\n# Convert the model\nmodel_proto, _ = tf2onnx.convert.from_keras(model, input_signature=spec)\n\n# Save the ONNX model\nwith open(output_path, \"wb\") as f:\n    f.write(model_proto.SerializeToString())","metadata":{"execution":{"iopub.status.busy":"2024-08-26T18:44:19.382740Z","iopub.execute_input":"2024-08-26T18:44:19.383122Z","iopub.status.idle":"2024-08-26T18:45:37.910999Z","shell.execute_reply.started":"2024-08-26T18:44:19.383077Z","shell.execute_reply":"2024-08-26T18:45:37.909523Z"},"trusted":true},"execution_count":null,"outputs":[]}]}