{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<a id=\"Libraries\"></a> <br> \n# **1. TensorFlow Object Detection API installation and Libraries** ","metadata":{}},{"cell_type":"markdown","source":"## Install TensorFlow Object Detection API","metadata":{"papermill":{"duration":0.021045,"end_time":"2021-11-19T08:38:07.403389","exception":false,"start_time":"2021-11-19T08:38:07.382344","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"### Clone github project","metadata":{}},{"cell_type":"code","source":"!git clone https://github.com/tensorflow/models\n    \n# Check out a certain commit to ensure that future changes in the TF ODT API codebase won't affect this notebook.\n!cd models && git checkout ac8d06519","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":25.822618,"end_time":"2021-11-19T08:38:33.247836","exception":false,"start_time":"2021-11-19T08:38:07.425218","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:37:20.020401Z","iopub.execute_input":"2022-04-22T07:37:20.02107Z","iopub.status.idle":"2022-04-22T07:37:41.429586Z","shell.execute_reply.started":"2022-04-22T07:37:20.021029Z","shell.execute_reply":"2022-04-22T07:37:41.428725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Install tensorflow object detection API","metadata":{}},{"cell_type":"code","source":"%%bash\ncd models/research\n\n# Compile protos.\nprotoc object_detection/protos/*.proto --python_out=.\n\nwget https://storage.googleapis.com/odml-dataset/others/setup.py\npip install -q --user .\n\n# Test if the Object Dectection API is working correctly\npython object_detection/builders/model_builder_tf2_test.py","metadata":{"papermill":{"duration":79.154739,"end_time":"2021-11-19T08:39:52.448588","exception":false,"start_time":"2021-11-19T08:38:33.293849","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:37:52.871771Z","iopub.execute_input":"2022-04-22T07:37:52.872075Z","iopub.status.idle":"2022-04-22T07:38:33.861249Z","shell.execute_reply.started":"2022-04-22T07:37:52.872038Z","shell.execute_reply":"2022-04-22T07:38:33.859919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import dependencies","metadata":{}},{"cell_type":"code","source":"# Libraries\nimport os\nimport io\nimport json\nimport sys\nimport cv2\nfrom PIL import Image, ImageDraw\nimport pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport matplotlib as mply\nimport matplotlib.patches as patches\nimport matplotlib.pyplot as plt\nimport contextlib2\nimport IPython\nimport time\nimport pathlib\nimport tensorflow as tf\nimport random\nfrom PIL import Image, ImageDraw","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.075545Z","iopub.status.idle":"2022-04-22T07:35:06.075847Z","shell.execute_reply.started":"2022-04-22T07:35:06.075692Z","shell.execute_reply":"2022-04-22T07:35:06.075713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"INPUT_DIR = '/kaggle/input/tensorflow-great-barrier-reef/'\nsys.path.insert(0, INPUT_DIR)","metadata":{"papermill":{"duration":1.526137,"end_time":"2021-11-19T08:39:54.022253","exception":false,"start_time":"2021-11-19T08:39:52.496116","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.077174Z","iopub.status.idle":"2022-04-22T07:35:06.077601Z","shell.execute_reply.started":"2022-04-22T07:35:06.077363Z","shell.execute_reply":"2022-04-22T07:35:06.077386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# The notebook is supposed to run with TF 2.6.0\nprint(tf.__version__)\nprint(tf.test.is_gpu_available())\nprint(tf.config.list_physical_devices('GPU'))","metadata":{"papermill":{"duration":0.729459,"end_time":"2021-11-19T08:39:54.798333","exception":false,"start_time":"2021-11-19T08:39:54.068874","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.07931Z","iopub.status.idle":"2022-04-22T07:35:06.080189Z","shell.execute_reply.started":"2022-04-22T07:35:06.079929Z","shell.execute_reply":"2022-04-22T07:35:06.079955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"Data_Analysis\"></a> <br> \n# **2. Data Analysis** ","metadata":{}},{"cell_type":"code","source":"# Read metadata\ntrain_df = pd.read_csv(os.path.join(INPUT_DIR,\"train.csv\"))\ntest_df =  pd.read_csv(os.path.join(INPUT_DIR,\"test.csv\"))","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.081357Z","iopub.status.idle":"2022-04-22T07:35:06.081787Z","shell.execute_reply.started":"2022-04-22T07:35:06.081544Z","shell.execute_reply":"2022-04-22T07:35:06.081582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.shape","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.082816Z","iopub.status.idle":"2022-04-22T07:35:06.084886Z","shell.execute_reply.started":"2022-04-22T07:35:06.084633Z","shell.execute_reply":"2022-04-22T07:35:06.084659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.086148Z","iopub.status.idle":"2022-04-22T07:35:06.086581Z","shell.execute_reply.started":"2022-04-22T07:35:06.08633Z","shell.execute_reply":"2022-04-22T07:35:06.086353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.shape","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.088017Z","iopub.status.idle":"2022-04-22T07:35:06.088426Z","shell.execute_reply.started":"2022-04-22T07:35:06.088198Z","shell.execute_reply":"2022-04-22T07:35:06.088221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.089898Z","iopub.status.idle":"2022-04-22T07:35:06.090311Z","shell.execute_reply.started":"2022-04-22T07:35:06.090083Z","shell.execute_reply":"2022-04-22T07:35:06.090104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We have looked at the content of [train/test].csv - \nThese files contains the metadata for the images. Most of the test metadata data is only available to your notebook upon submission. Just the first few rows available for download.\n\nWe have 6 columns (train data has also the annotations for each frame):\n* **video_id** - ID number of the video the image was part of. The video ids are not meaningfully ordered.\n* **video_frame** - The frame number of the image within the video. Expect to see occasional gaps in the frame number from when the diver surfaced.\n* **sequence - ID** of a gap-free subset of a given video. The sequence ids are not meaningfully ordered.\n* **sequence_frame** - The frame number within a given sequence.\n* **image_id** - ID code for the image, in the format '{video_id}-{video_frame}'\n* **annotations** - The bounding boxes of any starfish detections in a string format that can be evaluated directly with Python. Does not use the same format as the predictions you will submit. Not available in test.csv. A bounding box is described by the pixel coordinate (x_min, y_min) of its upper left corner within the image together with its width and height in pixels.","metadata":{}},{"cell_type":"code","source":"# Look at the data types\ntrain_df.dtypes","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.091394Z","iopub.status.idle":"2022-04-22T07:35:06.092168Z","shell.execute_reply.started":"2022-04-22T07:35:06.091915Z","shell.execute_reply":"2022-04-22T07:35:06.091941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"type(train_df['annotations'][0])","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.093281Z","iopub.status.idle":"2022-04-22T07:35:06.094083Z","shell.execute_reply.started":"2022-04-22T07:35:06.093821Z","shell.execute_reply":"2022-04-22T07:35:06.093847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# See if the training dataset contains null values\ntrain_df.isnull().sum()","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.095183Z","iopub.status.idle":"2022-04-22T07:35:06.096011Z","shell.execute_reply.started":"2022-04-22T07:35:06.095751Z","shell.execute_reply":"2022-04-22T07:35:06.095779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"Helper_functions\"></a> <br> \n# **2.0 Helper functions** ","metadata":{}},{"cell_type":"code","source":"def show_values_on_bars(axs, h_v=\"v\", space=0.4):\n    '''Plots the value at the end of the a seaborn barplot.\n    axs: the ax of the plot\n    h_v: weather or not the barplot is vertical/ horizontal'''\n    \n    def _show_on_single_plot(ax):\n        if h_v == \"v\":\n            for p in ax.patches:\n                _x = p.get_x() + p.get_width() / 2\n                _y = p.get_y() + p.get_height()\n                value = int(p.get_height())\n                ax.text(_x, _y, format(value, ','), ha=\"center\") \n        elif h_v == \"h\":\n            for p in ax.patches:\n                _x = p.get_x() + p.get_width() + float(space)\n                _y = p.get_y() + p.get_height()\n                value = int(p.get_width())\n                ax.text(_x, _y, format(value, ','), ha=\"left\")\n\n    if isinstance(axs, np.ndarray):\n        for idx, ax in np.ndenumerate(axs):\n            _show_on_single_plot(ax)\n    else:\n        _show_on_single_plot(axs)\n\n        \n#----------------------------------------------\ndef show_image(path, annot, axs=None):\n    '''Shows an image and marks any COTS annotated within the frame.\n    path: full path to the .jpg image\n    annot: string of the annotation for the coordinates of COTS'''\n    \n    # This is in case we plot only 1 image\n    if axs==None:\n        fig, axs = plt.subplots(figsize=(23, 8))\n    \n    img = plt.imread(path)\n    axs.imshow(img)\n\n    if annot:\n        for a in eval(annot):\n            rect = patches.Rectangle((a[\"x\"], a[\"y\"]), a[\"width\"], a[\"height\"], \n                                     linewidth=3, edgecolor=\"#FF6103\", facecolor='none')\n            axs.add_patch(rect)\n\n    axs.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.097202Z","iopub.status.idle":"2022-04-22T07:35:06.098174Z","shell.execute_reply.started":"2022-04-22T07:35:06.097926Z","shell.execute_reply":"2022-04-22T07:35:06.097951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"Video_Id\"></a> <br> \n# **2.1 Video Id** ","metadata":{}},{"cell_type":"code","source":"# count the number of occurences in a video\nfig_dims = (10, 8)\nfig, ax = plt.subplots(figsize=fig_dims)\ndf1 = train_df[\"video_id\"].value_counts().reset_index()\nsns.barplot(data=df1, x=\"index\", y=\"video_id\", ax=ax,\n            palette=[\"r\",\"g\",\"b\"])\nshow_values_on_bars(ax, h_v=\"v\", space=0.1)\nax.set_xlabel(\"Video ID\")\nax.set_ylabel(\"\")\nax.title.set_text(\"Frequency of Frames per Video\")\nax.set_yticks([])","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.099506Z","iopub.status.idle":"2022-04-22T07:35:06.099934Z","shell.execute_reply.started":"2022-04-22T07:35:06.099712Z","shell.execute_reply":"2022-04-22T07:35:06.099735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We have only 3 videos. The third video (index 2) has a large number of frames.","metadata":{}},{"cell_type":"markdown","source":"<a id=\"Sequences\"></a> <br> \n# **2.2 Sequences** ","metadata":{}},{"cell_type":"code","source":"groups = train_df.groupby([\"video_id\",\"sequence\"]).size()","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.101398Z","iopub.status.idle":"2022-04-22T07:35:06.101842Z","shell.execute_reply.started":"2022-04-22T07:35:06.101612Z","shell.execute_reply":"2022-04-22T07:35:06.101635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"groups","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.104315Z","iopub.status.idle":"2022-04-22T07:35:06.105107Z","shell.execute_reply.started":"2022-04-22T07:35:06.104847Z","shell.execute_reply":"2022-04-22T07:35:06.104872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('sequences first video: {} \\nsequences second video: {} \\nsequences third video: {}'.format(len(groups[0]),len(groups[1]),len(groups[2])))","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.106172Z","iopub.status.idle":"2022-04-22T07:35:06.106894Z","shell.execute_reply.started":"2022-04-22T07:35:06.106646Z","shell.execute_reply":"2022-04-22T07:35:06.106672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We have 3 videos, the first and the second video contains 8 sequences each, the third video contains only 4 sequences but has more frames (see previous section).","metadata":{}},{"cell_type":"markdown","source":"<a id=\"Annotations\"></a> <br> \n# **2.3 Annotations** ","metadata":{}},{"cell_type":"code","source":"# Calculate the number of total number of annotations within each frame. \ntrain_df[\"no_annotations\"] = train_df[\"annotations\"].apply(lambda x: len(eval(x)))","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.108103Z","iopub.status.idle":"2022-04-22T07:35:06.108778Z","shell.execute_reply.started":"2022-04-22T07:35:06.108529Z","shell.execute_reply":"2022-04-22T07:35:06.108566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig_dims = (10, 8)\nfig, ax = plt.subplots(figsize=fig_dims)\ntrain_df[\"no_annotations\"].hist()\nn_of_images = len(train_df)\nno_annotations = round(train_df[train_df.no_annotations==0].shape[0])\nwith_annotations = round(train_df[train_df.no_annotations!=0].shape[0])","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.109895Z","iopub.status.idle":"2022-04-22T07:35:06.110692Z","shell.execute_reply.started":"2022-04-22T07:35:06.110427Z","shell.execute_reply":"2022-04-22T07:35:06.110453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Total number of frames: {} \\nframes with annotations: {} \\nframes without annotations: {}'.format(n_of_images,with_annotations,no_annotations))","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.111863Z","iopub.status.idle":"2022-04-22T07:35:06.112666Z","shell.execute_reply.started":"2022-04-22T07:35:06.112405Z","shell.execute_reply":"2022-04-22T07:35:06.112432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see that most of the frame have only 1 annotion. We have 23501 total frames, 18582 with annotations and 4919 without annotations.","metadata":{}},{"cell_type":"markdown","source":"<a id=\"Image_visualization\"></a> <br> \n# **2.5 Image visualization** ","metadata":{}},{"cell_type":"code","source":"# Create a \"path\" column containing full path to the frames\nbase_folder = os.path.join(INPUT_DIR,\"train_images\")\n\ntrain_df[\"path\"] = base_folder + \"/video_\" + \\\n                         train_df['video_id'].astype(str) + \"/\" +\\\n                         train_df['video_frame'].astype(str) +\".jpg\"\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.113822Z","iopub.status.idle":"2022-04-22T07:35:06.114609Z","shell.execute_reply.started":"2022-04-22T07:35:06.114347Z","shell.execute_reply":"2022-04-22T07:35:06.114373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# look for an image with some annotations\nimage_path = list(train_df[train_df[\"no_annotations\"] == 4][\"path\"])[0]\nannotation = list(train_df[train_df[\"no_annotations\"] == 4][\"annotations\"])[0]\nshow_image(image_path, annotation, axs=None)","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.115789Z","iopub.status.idle":"2022-04-22T07:35:06.116587Z","shell.execute_reply.started":"2022-04-22T07:35:06.116325Z","shell.execute_reply":"2022-04-22T07:35:06.116352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"Data_Preparation\"></a> <br> \n# **3. Data Preparation** ","metadata":{}},{"cell_type":"code","source":"train_df=train_df.loc[train_df[\"annotations\"].astype(str) != \"[]\"] # remove images without annotations\ntrain_df['annotations'] = train_df['annotations'].apply(eval)\n","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.117742Z","iopub.status.idle":"2022-04-22T07:35:06.118514Z","shell.execute_reply.started":"2022-04-22T07:35:06.118269Z","shell.execute_reply":"2022-04-22T07:35:06.118296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAINING_RATIO = 0.8\n\n# Split the dataset so that no sequence is leaked from the training dataset into the validation dataset.\nsplit_index = int(TRAINING_RATIO * len(train_df))\nwhile train_df.iloc[split_index - 1].sequence == train_df.iloc[split_index].sequence:\n    split_index += 1\n    \n# Shuffle both the training and validation datasets.\ntrain_data_df = train_df.iloc[:split_index].sample(frac=1).reset_index(drop=True)\nval_data_df = train_df.iloc[split_index:].sample(frac=1).reset_index(drop=True)\n\nprint('Training ratio:', \n      float(len(train_data_df)) / (len(train_data_df) + len(val_data_df)))\n","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.119692Z","iopub.status.idle":"2022-04-22T07:35:06.120464Z","shell.execute_reply.started":"2022-04-22T07:35:06.120218Z","shell.execute_reply":"2022-04-22T07:35:06.120245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del train_df","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.121564Z","iopub.status.idle":"2022-04-22T07:35:06.122366Z","shell.execute_reply.started":"2022-04-22T07:35:06.122109Z","shell.execute_reply":"2022-04-22T07:35:06.122136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Convert the training and validation dataset into TFRecord format as required by the TensorFlow Object Detection API.","metadata":{"papermill":{"duration":0.115403,"end_time":"2021-11-19T08:40:50.494003","exception":false,"start_time":"2021-11-19T08:40:50.3786","status":"completed"},"tags":[]}},{"cell_type":"code","source":"from object_detection.utils import dataset_util\nfrom object_detection.dataset_tools import tf_record_creation_util\nfrom object_detection.utils import visualization_utils as viz_utils\nfrom object_detection.utils import label_map_util\n\ndef create_tf_example(video_id, video_frame, data_df, image_path):\n    \"\"\"Create a tf.Example entry for a given training image.\"\"\"\n    full_path = os.path.join(image_path, os.path.join(f'video_{video_id}', f'{video_frame}.jpg'))\n    with tf.io.gfile.GFile(full_path, 'rb') as fid:\n        encoded_jpg = fid.read()\n    encoded_jpg_io = io.BytesIO(encoded_jpg)\n    image = Image.open(encoded_jpg_io)\n    if image.format != 'JPEG':\n        raise ValueError('Image format not JPEG')\n\n    height = image.size[1] # Image height\n    width = image.size[0] # Image width\n    filename = f'{video_id}:{video_frame}'.encode('utf8') # Unique id of the image.\n    encoded_image_data = None # Encoded image bytes\n    image_format = 'jpeg'.encode('utf8') # b'jpeg' or b'png'\n\n    xmins = [] # List of normalized left x coordinates in bounding box (1 per box)\n    xmaxs = [] # List of normalized right x coordinates in bounding box\n             # (1 per box)\n    ymins = [] # List of normalized top y coordinates in bounding box (1 per box)\n    ymaxs = [] # List of normalized bottom y coordinates in bounding box\n             # (1 per box)\n    classes_text = [] # List of string class name of bounding box (1 per box)\n    classes = [] # List of integer class id of bounding box (1 per box)\n    \n    rows = data_df[(data_df.video_id == video_id) & (data_df.video_frame == video_frame)]\n    for _, row in rows.iterrows():\n        for annotation in row.annotations:\n            xmins.append(annotation['x'] / width) \n            xmaxs.append((annotation['x'] + annotation['width']) / width) \n            ymins.append(annotation['y'] / height) \n            ymaxs.append((annotation['y'] + annotation['height']) / height) \n\n            classes_text.append('COTS'.encode('utf8'))\n            classes.append(1)\n\n    tf_example = tf.train.Example(features=tf.train.Features(feature={\n      'image/height': dataset_util.int64_feature(height),\n      'image/width': dataset_util.int64_feature(width),\n      'image/filename': dataset_util.bytes_feature(filename),\n      'image/source_id': dataset_util.bytes_feature(filename),\n      'image/encoded': dataset_util.bytes_feature(encoded_jpg),\n      'image/format': dataset_util.bytes_feature(image_format),\n      'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),\n      'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),\n      'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),\n      'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),\n      'image/object/class/text': dataset_util.bytes_list_feature(classes_text),\n      'image/object/class/label': dataset_util.int64_list_feature(classes),\n    }))\n    \n    return tf_example\n\n\ndef convert_to_tfrecord(data_df, tfrecord_filebase, image_path, num_shards = 10):\n    \"\"\"Convert the object detection dataset to TFRecord as required by the TF ODT API.\"\"\"\n    with contextlib2.ExitStack() as tf_record_close_stack:\n        output_tfrecords = tf_record_creation_util.open_sharded_output_tfrecords(\n            tf_record_close_stack, tfrecord_filebase, num_shards)\n        \n        for index, row in data_df.iterrows():\n            if index % 500 == 0:\n                print('Processed {0} images.'.format(index))\n            tf_example = create_tf_example(row.video_id, row.video_frame, data_df, image_path)\n            output_shard_index = index % num_shards\n            output_tfrecords[output_shard_index].write(tf_example.SerializeToString())\n        \n        print('Completed processing {0} images.'.format(len(data_df)))","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.12358Z","iopub.status.idle":"2022-04-22T07:35:06.124242Z","shell.execute_reply.started":"2022-04-22T07:35:06.123998Z","shell.execute_reply":"2022-04-22T07:35:06.124029Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir dataset\nimage_path = os.path.join(INPUT_DIR, 'train_images')\n\n# Convert train images to TFRecord\nprint('Converting TRAIN images...')\nconvert_to_tfrecord(\n  train_data_df,\n  'dataset/cots_train',\n  image_path,\n  num_shards = 4\n)\n\n# Convert validation images to TFRecord\nprint('Converting VALIDATION images...')\nconvert_to_tfrecord(\n  val_data_df,\n  'dataset/cots_val',\n  image_path,\n  num_shards = 4\n)","metadata":{"papermill":{"duration":38.916848,"end_time":"2021-11-19T08:41:29.641271","exception":false,"start_time":"2021-11-19T08:40:50.724423","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.125339Z","iopub.status.idle":"2022-04-22T07:35:06.126191Z","shell.execute_reply.started":"2022-04-22T07:35:06.125939Z","shell.execute_reply":"2022-04-22T07:35:06.125966Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a label map to map between label index and human-readable label name.\n\nlabel_map_str = \"\"\"item {\n  id: 1\n  name: 'COTS'\n}\"\"\"\n\nwith open('dataset/label_map.pbtxt', 'w') as f:\n  f.write(label_map_str)\n\n!more dataset/label_map.pbtxt","metadata":{"papermill":{"duration":16.05844,"end_time":"2021-11-19T08:41:45.838392","exception":false,"start_time":"2021-11-19T08:41:29.779952","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.127699Z","iopub.status.idle":"2022-04-22T07:35:06.128109Z","shell.execute_reply.started":"2022-04-22T07:35:06.127885Z","shell.execute_reply":"2022-04-22T07:35:06.127907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"Model\"></a> <br> \n# **4. Model** ","metadata":{}},{"cell_type":"markdown","source":"## Train an object detection model\n\nI'll use [TensorFlow Object Detection API](https://github.com/tensorflow/models/tree/master/research/object_detection) and an [EfficientDet-D0](https://arxiv.org/pdf/1911.09070v7.pdf) base model and apply transfer learning to train a COTS detection model. ","metadata":{"papermill":{"duration":3.355764,"end_time":"2021-11-19T08:41:50.909779","exception":false,"start_time":"2021-11-19T08:41:47.554015","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"### Download the pretrained EfficientDet-D0 checkpoint","metadata":{}},{"cell_type":"code","source":"!wget http://download.tensorflow.org/models/object_detection/tf2/20200711/efficientdet_d0_coco17_tpu-32.tar.gz\n!tar -xvzf efficientdet_d0_coco17_tpu-32.tar.gz","metadata":{"papermill":{"duration":3.256545,"end_time":"2021-11-19T08:41:54.358822","exception":false,"start_time":"2021-11-19T08:41:51.102277","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.129422Z","iopub.status.idle":"2022-04-22T07:35:06.129863Z","shell.execute_reply.started":"2022-04-22T07:35:06.129638Z","shell.execute_reply":"2022-04-22T07:35:06.12966Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare templete for model configuration\n\nFor this task we need to copy the content of the pipeline.config file (this file can be found in the dataset repository) and modify some fields:\n\n- *num_classes* should be changed to 1\n- *fine_tune_checkpoint* should be set to the checkpoint path\n- *label_map_path* inside train_input_reader should be set to the labels file\n- *label_map_path* inside eval_input_reader should be set to the labels file\n- *input_path* inside train_input_reader should be set to the train/validation dataset\n- *input_path* inside eval_input_reader should be set to the train/validation dataset\n\nOther parameters can be changed to optimize the model","metadata":{}},{"cell_type":"code","source":"from string import Template\n\nconfig_file_template = \"\"\"\n# SSD with EfficientNet-b0 + BiFPN feature extractor,\n# shared box predictor and focal loss (a.k.a EfficientDet-d0).\n# See EfficientDet, Tan et al, https://arxiv.org/abs/1911.09070\n# See Lin et al, https://arxiv.org/abs/1708.02002\n# Initialized from an EfficientDet-D0 checkpoint.\n#\n# Train on GPU\n\nmodel {\n  ssd {\n    inplace_batchnorm_update: true\n    freeze_batchnorm: false\n    num_classes: 1\n    add_background_class: false\n    box_coder {\n      faster_rcnn_box_coder {\n        y_scale: 10.0\n        x_scale: 10.0\n        height_scale: 5.0\n        width_scale: 5.0\n      }\n    }\n    matcher {\n      argmax_matcher {\n        matched_threshold: 0.5\n        unmatched_threshold: 0.5\n        ignore_thresholds: false\n        negatives_lower_than_unmatched: true\n        force_match_for_each_row: true\n        use_matmul_gather: true\n      }\n    }\n    similarity_calculator {\n      iou_similarity {\n      }\n    }\n    encode_background_as_zeros: true\n    anchor_generator {\n      multiscale_anchor_generator {\n        min_level: 3\n        max_level: 7\n        anchor_scale: 4.0\n        aspect_ratios: [1.0, 2.0, 0.5]\n        scales_per_octave: 3\n      }\n    }\n    image_resizer {\n      keep_aspect_ratio_resizer {\n        min_dimension: 1280\n        max_dimension: 1280\n        pad_to_max_dimension: true\n        }\n    }\n    box_predictor {\n      weight_shared_convolutional_box_predictor {\n        depth: 64\n        class_prediction_bias_init: -4.6\n        conv_hyperparams {\n          force_use_bias: true\n          activation: SWISH\n          regularizer {\n            l2_regularizer {\n              weight: 0.00004\n            }\n          }\n          initializer {\n            random_normal_initializer {\n              stddev: 0.01\n              mean: 0.0\n            }\n          }\n          batch_norm {\n            scale: true\n            decay: 0.99\n            epsilon: 0.001\n          }\n        }\n        num_layers_before_predictor: 3\n        kernel_size: 3\n        use_depthwise: true\n      }\n    }\n    feature_extractor {\n      type: 'ssd_efficientnet-b0_bifpn_keras'\n      bifpn {\n        min_level: 3\n        max_level: 7\n        num_iterations: 3\n        num_filters: 64\n      }\n      conv_hyperparams {\n        force_use_bias: true\n        activation: SWISH\n        regularizer {\n          l2_regularizer {\n            weight: 0.00004\n          }\n        }\n        initializer {\n          truncated_normal_initializer {\n            stddev: 0.03\n            mean: 0.0\n          }\n        }\n        batch_norm {\n          scale: true,\n          decay: 0.99,\n          epsilon: 0.001,\n        }\n      }\n    }\n    loss {\n      classification_loss {\n        weighted_sigmoid_focal {\n          alpha: 0.25\n          gamma: 1.5\n        }\n      }\n      localization_loss {\n        weighted_smooth_l1 {\n        }\n      }\n      classification_weight: 1.0\n      localization_weight: 1.0\n    }\n    normalize_loss_by_num_matches: true\n    normalize_loc_loss_by_codesize: true\n    post_processing {\n      batch_non_max_suppression {\n        score_threshold: 1e-8\n        iou_threshold: 0.5\n        max_detections_per_class: 100\n        max_total_detections: 100\n      }\n      score_converter: SIGMOID\n    }\n  }\n}\n\ntrain_config: {\n  fine_tune_checkpoint: \"efficientdet_d0_coco17_tpu-32/checkpoint/ckpt-0\"\n  fine_tune_checkpoint_version: V2\n  fine_tune_checkpoint_type: \"detection\"\n  batch_size: 2\n  sync_replicas: false\n  startup_delay_steps: 0\n  replicas_to_aggregate: 1\n  use_bfloat16: false\n  num_steps: $training_steps\n  data_augmentation_options {\n    random_horizontal_flip {\n    }\n  }\n  data_augmentation_options {\n    random_scale_crop_and_pad_to_square {\n      output_size: 1280\n      scale_min: 0.5\n      scale_max: 2.0\n    }\n  }\n  optimizer {\n    momentum_optimizer: {\n      learning_rate: {\n        cosine_decay_learning_rate {\n          learning_rate_base: 5e-3\n          total_steps: $training_steps\n          warmup_learning_rate: 5e-4\n          warmup_steps: $warmup_steps\n        }\n      }\n      momentum_optimizer_value: 0.9\n    }\n    use_moving_average: false\n  }\n  max_number_of_boxes: 100\n  unpad_groundtruth_tensors: false\n}\n\ntrain_input_reader: {\n  label_map_path: \"dataset/label_map.pbtxt\"\n  tf_record_input_reader {\n    input_path: \"dataset/cots_train-?????-of-00004\"\n  }\n}\n\neval_config: {\n  metrics_set: \"coco_detection_metrics\"\n  use_moving_averages: false\n  batch_size: 2;\n}\n\neval_input_reader: {\n  label_map_path: \"dataset/label_map.pbtxt\"\n  shuffle: false\n  num_epochs: 1\n  tf_record_input_reader {\n    input_path: \"dataset/cots_val-?????-of-00004\"\n  }\n}\n\"\"\"","metadata":{"papermill":{"duration":0.133468,"end_time":"2021-11-19T08:41:54.609774","exception":false,"start_time":"2021-11-19T08:41:54.476306","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.131306Z","iopub.status.idle":"2022-04-22T07:35:06.131739Z","shell.execute_reply.started":"2022-04-22T07:35:06.131495Z","shell.execute_reply":"2022-04-22T07:35:06.131524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Define the training pipeline","metadata":{}},{"cell_type":"code","source":"# Here I redefine the training and warmup steps\n# Note. by setting TRAINING_STEPS = 20000 and WARMUP_STEPS = 2000 --> I can obtaina  score of 0.335\nTRAINING_STEPS = 28000 # change to improve results\nWARMUP_STEPS = 2000 # change to improve results\nPIPELINE_CONFIG_PATH='dataset/pipeline.config'\n\npipeline = Template(config_file_template).substitute(\n    training_steps=TRAINING_STEPS, warmup_steps=WARMUP_STEPS)\n\nwith open(PIPELINE_CONFIG_PATH, 'w') as f:\n    f.write(pipeline)","metadata":{"papermill":{"duration":0.121946,"end_time":"2021-11-19T08:41:54.846958","exception":false,"start_time":"2021-11-19T08:41:54.725012","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.133057Z","iopub.status.idle":"2022-04-22T07:35:06.133574Z","shell.execute_reply.started":"2022-04-22T07:35:06.133244Z","shell.execute_reply":"2022-04-22T07:35:06.133267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train the object detection model","metadata":{}},{"cell_type":"code","source":"MODEL_DIR='cots_efficientdet_d0'\n!mkdir {MODEL_DIR}\n!python models/research/object_detection/model_main_tf2.py \\\n    --pipeline_config_path={PIPELINE_CONFIG_PATH} \\\n    --model_dir={MODEL_DIR} \\\n    --alsologtostderr","metadata":{"papermill":{"duration":18463.625406,"end_time":"2021-11-19T13:49:38.586506","exception":false,"start_time":"2021-11-19T08:41:54.9611","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.13493Z","iopub.status.idle":"2022-04-22T07:35:06.135345Z","shell.execute_reply.started":"2022-04-22T07:35:06.135119Z","shell.execute_reply":"2022-04-22T07:35:06.135142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Evaluate the object detection model","metadata":{"papermill":{"duration":0.226793,"end_time":"2021-11-19T13:49:39.043281","exception":false,"start_time":"2021-11-19T13:49:38.816488","status":"completed"},"tags":[]}},{"cell_type":"code","source":"!python models/research/object_detection/model_main_tf2.py \\\n    --pipeline_config_path={PIPELINE_CONFIG_PATH} \\\n    --model_dir={MODEL_DIR} \\\n    --checkpoint_dir={MODEL_DIR} \\\n    --eval_timeout=0 \\\n    --alsologtostderr","metadata":{"papermill":{"duration":323.73381,"end_time":"2021-11-19T13:55:03.004285","exception":false,"start_time":"2021-11-19T13:49:39.270475","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.136687Z","iopub.status.idle":"2022-04-22T07:35:06.137098Z","shell.execute_reply.started":"2022-04-22T07:35:06.136873Z","shell.execute_reply":"2022-04-22T07:35:06.136895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Export as SavedModel for inference","metadata":{"papermill":{"duration":0.239823,"end_time":"2021-11-19T13:55:03.483464","exception":false,"start_time":"2021-11-19T13:55:03.243641","status":"completed"},"tags":[]}},{"cell_type":"code","source":"!python models/research/object_detection/exporter_main_v2.py \\\n    --input_type image_tensor \\\n    --pipeline_config_path={PIPELINE_CONFIG_PATH} \\\n    --trained_checkpoint_dir={MODEL_DIR} \\\n    --output_directory={MODEL_DIR}/output","metadata":{"papermill":{"duration":122.093553,"end_time":"2021-11-19T13:57:05.815158","exception":false,"start_time":"2021-11-19T13:55:03.721605","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.138405Z","iopub.status.idle":"2022-04-22T07:35:06.138844Z","shell.execute_reply.started":"2022-04-22T07:35:06.138618Z","shell.execute_reply":"2022-04-22T07:35:06.138642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls {MODEL_DIR}/output","metadata":{"papermill":{"duration":0.931074,"end_time":"2021-11-19T13:57:06.998967","exception":false,"start_time":"2021-11-19T13:57:06.067893","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-22T07:35:06.140126Z","iopub.status.idle":"2022-04-22T07:35:06.140548Z","shell.execute_reply.started":"2022-04-22T07:35:06.140313Z","shell.execute_reply":"2022-04-22T07:35:06.140335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MODEL_DIR","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.141991Z","iopub.status.idle":"2022-04-22T07:35:06.1424Z","shell.execute_reply.started":"2022-04-22T07:35:06.142175Z","shell.execute_reply":"2022-04-22T07:35:06.142197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"Results\"></a> <br> \n# **5. Results** ","metadata":{}},{"cell_type":"code","source":"# Define some utils method for prediction and display images\ndef load_image_into_numpy_array(path):\n    \"\"\"Load an image from file into a numpy array.\n\n    Puts image into numpy array to feed into tensorflow graph.\n    Note that by convention we put it into a numpy array with shape\n    (height, width, channels), where channels=3 for RGB.\n\n    Args:\n    path: a file path (this can be local or on colossus)\n\n    Returns:\n    uint8 numpy array with shape (img_height, img_width, 3)\n    \"\"\"\n    img_data = tf.io.gfile.GFile(path, 'rb').read()\n    image = Image.open(io.BytesIO(img_data))\n    (im_width, im_height) = image.size\n    \n    return np.array(image.getdata()).reshape(\n      (im_height, im_width, 3)).astype(np.uint8)\n\ndef detect(image_np, model):\n    \"\"\"Detect COTS from a given numpy image.\"\"\"\n\n    input_tensor = np.expand_dims(image_np, 0)\n    start_time = time.time()\n    detections = model(input_tensor)\n    return detections\n\n# redefine function to show images\ndef show_image(path, annot, axs=None):\n    '''Shows an image and marks any COTS annotated within the frame.\n    path: full path to the .jpg image\n    annot: string of the annotation for the coordinates of COTS'''\n        \n    # This is in case we plot only 1 image\n    if axs==None:\n        fig, axs = plt.subplots(figsize=(23, 8))\n        \n    img = plt.imread(path)\n    axs.imshow(img)\n\n    if annot:\n        for a in annot:\n            rect = patches.Rectangle((a[\"x\"], a[\"y\"]), a[\"width\"], a[\"height\"], \n                                     linewidth=3, edgecolor=\"#FF6103\", facecolor='none')\n            axs.add_patch(rect)\n\n    axs.axis(\"off\") \n  \n# disp predicted detection box on images\ndef disp_prediction(path, detections, detection_threshold, axs=None):\n    '''Shows an image and marks any COTS annotated within the frame.\n    path: full path to the .jpg image\n    annot: string of the annotation for the coordinates of COTS'''\n    \n    image_np = load_image_into_numpy_array(image_path)\n    height, width, _ = image_np.shape\n    \n    num = len(detections['detection_boxes'].numpy()[0])\n    detection_array = detections['detection_boxes'].numpy()[0]\n    \n    \n    # This is in case we plot only 1 image\n    if axs==None:\n        fig, axs = plt.subplots(figsize=(23, 8))\n    \n    img = plt.imread(path)\n    axs.imshow(img)\n\n    if detection_array is not None:\n        for i in range(0, num):\n            score = detections['detection_scores'][0][i].numpy()\n            \n            if score < detection_threshold:\n                continue\n        \n            bbox = detection_array[i]\n            y_min = int(bbox[0] * height)\n            x_min = int(bbox[1] * width)\n            y_max = int(bbox[2] * height)\n            x_max = int(bbox[3] * width)\n                                   \n            bbox_width = x_max - x_min\n            bbox_height = y_max - y_min\n                                   \n            rect = patches.Rectangle((x_min, y_min), bbox_width, bbox_height, \n                                     linewidth=3, edgecolor=\"#FF6103\", facecolor='none')\n            axs.add_patch(rect)\n\n    axs.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.143792Z","iopub.status.idle":"2022-04-22T07:35:06.144204Z","shell.execute_reply.started":"2022-04-22T07:35:06.143979Z","shell.execute_reply":"2022-04-22T07:35:06.144001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load the TensorFlow COTS detection model into memory.\nstart_time = time.time()\ntf.keras.backend.clear_session()\ndetect_fn_tf_odt = tf.saved_model.load(os.path.join(os.path.join(MODEL_DIR, 'output'), 'saved_model'))\nend_time = time.time()\nelapsed_time = end_time - start_time\nprint('Elapsed time: ' + str(elapsed_time) + 's')","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.145683Z","iopub.status.idle":"2022-04-22T07:35:06.146091Z","shell.execute_reply.started":"2022-04-22T07:35:06.145868Z","shell.execute_reply":"2022-04-22T07:35:06.14589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# look for an image with some annotations\nimage_path = list(train_data_df[train_data_df[\"no_annotations\"] == 4][\"path\"])[0]\nannotation = list(train_data_df[train_data_df[\"no_annotations\"] == 4][\"annotations\"])[0]\nshow_image(image_path, annotation, axs=None)","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.147396Z","iopub.status.idle":"2022-04-22T07:35:06.147843Z","shell.execute_reply.started":"2022-04-22T07:35:06.147614Z","shell.execute_reply":"2022-04-22T07:35:06.147638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_np = load_image_into_numpy_array(image_path)\ndetections = detect(image_np, detect_fn_tf_odt)","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.149115Z","iopub.status.idle":"2022-04-22T07:35:06.149533Z","shell.execute_reply.started":"2022-04-22T07:35:06.1493Z","shell.execute_reply":"2022-04-22T07:35:06.149322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"detection_threshold = 0.3\ndisp_prediction(image_path, detections, detection_threshold)","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.150841Z","iopub.status.idle":"2022-04-22T07:35:06.151251Z","shell.execute_reply.started":"2022-04-22T07:35:06.151027Z","shell.execute_reply":"2022-04-22T07:35:06.15105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"threshold = 0.25\n# Visulize more images at the same time\ndef compare_predictions_real_detection(number_images, detection_threshold):\n    # randomnly select some images from the validation set\n    # disp on the left original images with annotations\n    # on the right prediction\n    indices = []\n    for i in range(0, number_images):\n        indices.append(random.randint(0, len(val_data_df)-1))\n    fig, axs = plt.subplots(number_images, 2,figsize=(20,20))\n    for i in range(0, number_images):\n        index = indices[i]\n        image_path = val_data_df[\"path\"][index]\n        image_np = load_image_into_numpy_array(image_path)\n        detections = detect(image_np, detect_fn_tf_odt)\n        annotations = val_data_df[\"annotations\"][index]\n        if number_images>1:\n            show_image(image_path, annotations, axs=axs[i, 0])\n            axs[i, 0].set_title('Image with annotations')\n            disp_prediction(image_path, detections, detection_threshold, axs=axs[i, 1])\n            axs[i, 1].set_title('Image with predicted bounding boxes')\n        else:\n            show_image(image_path, annotations, axs=axs[0])\n            axs[0].set_title('Image with annotations')\n            detection_threshold = 0.001\n            disp_prediction(image_path, detections, detection_threshold, axs=axs[1])\n            axs[1].set_title('Image with predicted bounding boxes')","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.152768Z","iopub.status.idle":"2022-04-22T07:35:06.15318Z","shell.execute_reply.started":"2022-04-22T07:35:06.152957Z","shell.execute_reply":"2022-04-22T07:35:06.15298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Display some detections and original images with annotations","metadata":{}},{"cell_type":"code","source":"number_images = 5\ncompare_predictions_real_detection(number_images, threshold)","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.154498Z","iopub.status.idle":"2022-04-22T07:35:06.15494Z","shell.execute_reply.started":"2022-04-22T07:35:06.154713Z","shell.execute_reply":"2022-04-22T07:35:06.154736Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Results can be improved by fine tuning the model","metadata":{}},{"cell_type":"markdown","source":"<a id=\"Download\"></a> <br> \n# **6. Zip and download trained model** \nHere I zip and download the trained model. I will do the inference in a second notebook since the competition rules don't allow internet connection","metadata":{}},{"cell_type":"code","source":"!ls","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.158147Z","iopub.status.idle":"2022-04-22T07:35:06.158584Z","shell.execute_reply.started":"2022-04-22T07:35:06.158334Z","shell.execute_reply":"2022-04-22T07:35:06.158357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!zip -r trained_model.zip /kaggle/working/cots_efficientdet_d0","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.159921Z","iopub.status.idle":"2022-04-22T07:35:06.160336Z","shell.execute_reply.started":"2022-04-22T07:35:06.16011Z","shell.execute_reply":"2022-04-22T07:35:06.160132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import FileLink\nFileLink(r'trained_model.zip')","metadata":{"execution":{"iopub.status.busy":"2022-04-22T07:35:06.161432Z","iopub.status.idle":"2022-04-22T07:35:06.16222Z","shell.execute_reply.started":"2022-04-22T07:35:06.161968Z","shell.execute_reply":"2022-04-22T07:35:06.161994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The model can then be downloaded and opened in a new notebook to make a submission","metadata":{}}]}