{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -qU wandb\n!pip install -qU bbox-utility # check https://github.com/awsaf49/bbox","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:41:54.653549Z","iopub.execute_input":"2022-01-24T18:41:54.653940Z","iopub.status.idle":"2022-01-24T18:42:21.107985Z","shell.execute_reply.started":"2022-01-24T18:41:54.653849Z","shell.execute_reply":"2022-01-24T18:42:21.106781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom os import listdir\nfrom tqdm.notebook import tqdm\n\nfrom bbox.utils import coco2yolo, annot2str","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-24T18:42:21.111227Z","iopub.execute_input":"2022-01-24T18:42:21.111592Z","iopub.status.idle":"2022-01-24T18:42:22.335735Z","shell.execute_reply.started":"2022-01-24T18:42:21.111529Z","shell.execute_reply":"2022-01-24T18:42:22.334704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\n\nfrom kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\napi_key = user_secrets.get_secret(\"WANDB\")\nwandb.login(key=api_key)\nanonymous = None","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:42:22.337309Z","iopub.execute_input":"2022-01-24T18:42:22.337608Z","iopub.status.idle":"2022-01-24T18:42:24.769795Z","shell.execute_reply.started":"2022-01-24T18:42:22.337568Z","shell.execute_reply":"2022-01-24T18:42:24.768673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images_directory = '/kaggle/working/images'\nlabels_directory = '/kaggle/working/labels'","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:42:24.773183Z","iopub.execute_input":"2022-01-24T18:42:24.773516Z","iopub.status.idle":"2022-01-24T18:42:24.778895Z","shell.execute_reply.started":"2022-01-24T18:42:24.773468Z","shell.execute_reply":"2022-01-24T18:42:24.777932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -r '/kaggle/working/images'\n!rm -r '/kaggle/working/labels'","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:42:24.780596Z","iopub.execute_input":"2022-01-24T18:42:24.781404Z","iopub.status.idle":"2022-01-24T18:42:26.325825Z","shell.execute_reply.started":"2022-01-24T18:42:24.781356Z","shell.execute_reply":"2022-01-24T18:42:26.324579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p '/kaggle/working/images'\n!mkdir -p '/kaggle/working/labels'","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:42:26.328310Z","iopub.execute_input":"2022-01-24T18:42:26.328917Z","iopub.status.idle":"2022-01-24T18:42:27.909985Z","shell.execute_reply.started":"2022-01-24T18:42:26.328866Z","shell.execute_reply":"2022-01-24T18:42:27.908464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load data with paths to images and labels\ndf = pd.read_csv('/kaggle/input/tensorflow-great-barrier-reef/train.csv')\n\ndf['old_image_path'] = '/kaggle/input/tensorflow-great-barrier-reef/train_images/video_' \\\n                            + df.video_id.astype(str) + '/' \\\n                            + df.video_frame.astype(str)+'.jpg'\n\ndf['image_path']  = images_directory + '/' + df.image_id + '.jpg'\ndf['label_path']  = labels_directory + '/' + df.image_id + '.txt'\n\n\n# annotations to yolo-format bboxes\ndf['bboxes'] = df['annotations'].apply(lambda annotations: \\\n                                            coco2yolo(\n                                                 np.array([list(annot.values()) for annot in eval(annotations)], dtype=float)\n                                             ))\ndf.drop(columns=['annotations'], inplace=True)\n\n# find non-empty images\ndf['num_bbox'] = df['bboxes'].apply(lambda x: len(x))\ndf = df.query(\"num_bbox>0\")\n\n\nprint('df.shape:', df.shape)\ndf.head(2)","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:42:27.913540Z","iopub.execute_input":"2022-01-24T18:42:27.914275Z","iopub.status.idle":"2022-01-24T18:42:34.928209Z","shell.execute_reply.started":"2022-01-24T18:42:27.914228Z","shell.execute_reply":"2022-01-24T18:42:34.927216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# select only 200 images\n\n#df = df.sample(n=200, ignore_index=True, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:42:34.930004Z","iopub.execute_input":"2022-01-24T18:42:34.930711Z","iopub.status.idle":"2022-01-24T18:42:34.936186Z","shell.execute_reply.started":"2022-01-24T18:42:34.930663Z","shell.execute_reply":"2022-01-24T18:42:34.935027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# copy images to new folder\n\nimport shutil\nfrom joblib import Parallel, delayed\n\ndef make_copy(row):\n    shutil.copyfile(row.old_image_path, row.image_path)\n    return\n\nimage_paths = df.old_image_path.tolist()\n_ = Parallel(n_jobs=-1, backend='threading')(delayed(make_copy)(row) for _, row in tqdm(df.iterrows(), total=len(df)))\n\nprint(len(listdir(images_directory)), ' elements in images directory')","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:42:34.937792Z","iopub.execute_input":"2022-01-24T18:42:34.938737Z","iopub.status.idle":"2022-01-24T18:43:10.265789Z","shell.execute_reply.started":"2022-01-24T18:42:34.938690Z","shell.execute_reply":"2022-01-24T18:43:10.264662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create labels files\n\ncount = 0\nall_bboxes = []\nbboxes_info = []\n\nfor row_idx in tqdm(range(df.shape[0])):\n    row = df.iloc[row_idx]\n    bboxes_yolo  = row.bboxes \n    num_bbox     = row.num_bbox\n    names        = ['cots']*num_bbox\n    labels       = np.array([0]*num_bbox)[..., None].astype(str)\n    \n    with open(row.label_path, 'w') as f:\n        if num_bbox<1:\n            f.write('')\n            count+=1\n            continue\n        \n        all_bboxes.extend(bboxes_yolo.astype(float))\n        bboxes_info.extend([[row.image_id, row.video_id, row.sequence]]*len(bboxes_yolo))\n        annots = np.concatenate([labels, bboxes_yolo], axis=1)\n        string = annot2str(annots)\n        \n        f.write(string)        \n        \nprint('Missing:',count)\nprint(len(listdir(labels_directory)), ' elements in labels directory')","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:43:10.269586Z","iopub.execute_input":"2022-01-24T18:43:10.270150Z","iopub.status.idle":"2022-01-24T18:43:13.127223Z","shell.execute_reply.started":"2022-01-24T18:43:10.270102Z","shell.execute_reply":"2022-01-24T18:43:13.126025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Group fold by video_id\n\nfrom sklearn.model_selection import GroupKFold\n\nkf = GroupKFold(n_splits = 3)\ndf = df.reset_index(drop=True)\n\ntry:\n    df.drop(['fold'], inplace=True, axis = 1)\nexcept:\n    pass\n\ndf['fold'] = -1\n\nfor fold, (train_idx, val_idx) in enumerate(kf.split(df, groups=df.video_id.tolist())):\n    df.loc[val_idx, 'fold'] = fold\n\ndf.fold.value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:43:13.129149Z","iopub.execute_input":"2022-01-24T18:43:13.129750Z","iopub.status.idle":"2022-01-24T18:43:13.860776Z","shell.execute_reply.started":"2022-01-24T18:43:13.129704Z","shell.execute_reply":"2022-01-24T18:43:13.859752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define train and validation datasets\nFOLD = 1\ntrain_files = []\nval_files   = []\n\ntrain_df = df.query(\"fold!=@FOLD\")\nvalid_df = df.query(\"fold==@FOLD\")\ntrain_files += list(train_df.image_path.unique())\nval_files += list(valid_df.image_path.unique())\n\nprint('train_files length:', len(train_files)) \nprint('val_files length:', len(val_files))","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:43:13.862601Z","iopub.execute_input":"2022-01-24T18:43:13.863151Z","iopub.status.idle":"2022-01-24T18:43:13.884481Z","shell.execute_reply.started":"2022-01-24T18:43:13.863104Z","shell.execute_reply":"2022-01-24T18:43:13.883290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import yaml\n\ncwd = '/kaggle/working/'\n\nwith open('/kaggle/working/train.txt', 'w') as f:\n    for path in train_df.image_path.tolist():\n        f.write(path+'\\n')\n            \nwith open('/kaggle/working/val.txt', 'w') as f:\n    for path in valid_df.image_path.tolist():\n        f.write(path+'\\n')\n\ndata = dict(\n    path  = '/kaggle/working',\n    train =  '/kaggle/working/train.txt',\n    val   =  '/kaggle/working/val.txt',\n    nc    = 1,\n    names = ['cots'],\n    )\n\nwith open('/kaggle/working/gbr.yaml', 'w') as outfile:\n    yaml.dump(data, outfile, default_flow_style=False)\n\nf = open('/kaggle/working/gbr.yaml', 'r')\nprint('\\nyaml:')\nprint(f.read())","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:43:13.886511Z","iopub.execute_input":"2022-01-24T18:43:13.886864Z","iopub.status.idle":"2022-01-24T18:43:13.904376Z","shell.execute_reply.started":"2022-01-24T18:43:13.886816Z","shell.execute_reply":"2022-01-24T18:43:13.902239Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%writefile /kaggle/working/hyp.yaml\nlr0: 0.01  # initial learning rate (SGD=1E-2, Adam=1E-3)\nlrf: 0.1  # final OneCycleLR learning rate (lr0 * lrf)\nmomentum: 0.937  # SGD momentum/Adam beta1\nweight_decay: 0.0005  # optimizer weight decay 5e-4\nwarmup_epochs: 3.0  # warmup epochs (fractions ok)\nwarmup_momentum: 0.8  # warmup initial momentum\nwarmup_bias_lr: 0.1  # warmup initial bias lr\nbox: 0.05  # box loss gain\ncls: 0.5  # cls loss gain\ncls_pw: 1.0  # cls BCELoss positive_weight\nobj: 1.0  # obj loss gain (scale with pixels)\nobj_pw: 1.0  # obj BCELoss positive_weight\niou_t: 0.20  # IoU training threshold\nanchor_t: 4.0  # anchor-multiple threshold\n# anchors: 3  # anchors per output layer (0 to ignore)\nfl_gamma: 0.0  # focal loss gamma (efficientDet default gamma=1.5)\nhsv_h: 0.015  # image HSV-Hue augmentation (fraction)\nhsv_s: 0.7  # image HSV-Saturation augmentation (fraction)\nhsv_v: 0.4  # image HSV-Value augmentation (fraction)\ndegrees: 0.0  # image rotation (+/- deg)\ntranslate: 0.10  # image translation (+/- fraction)\nscale: 0.5  # image scale (+/- gain)\nshear: 0.0  # image shear (+/- deg)\nperspective: 0.0  # image perspective (+/- fraction), range 0-0.001\nflipud: 0.5  # image flip up-down (probability)\nfliplr: 0.5  # image flip left-right (probability)\nmosaic: 0.5  # image mosaic (probability)\nmixup: 0.5 # image mixup (probability)\ncopy_paste: 0.0  # segment copy-paste (probability)","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:43:13.906433Z","iopub.execute_input":"2022-01-24T18:43:13.906866Z","iopub.status.idle":"2022-01-24T18:43:13.917583Z","shell.execute_reply.started":"2022-01-24T18:43:13.906822Z","shell.execute_reply":"2022-01-24T18:43:13.916114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get yolov5\n%cd /kaggle/working\n!rm -r /kaggle/working/yolov5\n!git clone https://github.com/ultralytics/yolov5\n    \n#!cp -r /kaggle/input/yolov5-lib-ds /kaggle/working/yolov5\n%cd yolov5\n%pip install -qr requirements.txt\n\nfrom yolov5 import utils\ndisplay = utils.notebook_init()","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:43:13.919112Z","iopub.execute_input":"2022-01-24T18:43:13.920383Z","iopub.status.idle":"2022-01-24T18:43:33.848477Z","shell.execute_reply.started":"2022-01-24T18:43:13.920324Z","shell.execute_reply":"2022-01-24T18:43:33.847109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DIM       = 3000 \nMODEL     = 'yolov5n'\nBATCH     = 32\nEPOCHS    = 10\nOPTMIZER  = 'Adam'\n\nPROJECT   = 'great-barrier-reef-public' # w&b in yolov5\nNAME      = f'{MODEL}-dim{DIM}-fold{FOLD}' # w&b for yolov5\n\n#REMOVE_NOBBOX = True # remove images with no bbox\nROOT_DIR  = '/kaggle/input/tensorflow-great-barrier-reef/'\nIMAGE_DIR = '/kaggle/images' # directory to save images\nLABEL_DIR = '/kaggle/labels' # directory to save labels","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:43:33.850838Z","iopub.execute_input":"2022-01-24T18:43:33.851140Z","iopub.status.idle":"2022-01-24T18:43:33.859121Z","shell.execute_reply.started":"2022-01-24T18:43:33.851107Z","shell.execute_reply":"2022-01-24T18:43:33.858079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python train.py --img {DIM}\\\n--batch {BATCH}\\\n--epochs {EPOCHS}\\\n--optimizer {OPTMIZER}\\\n--data /kaggle/working/gbr.yaml\\\n--hyp /kaggle/working/hyp.yaml\\\n--weights {MODEL}.pt\\\n--project {PROJECT} --name {NAME}\\\n--exist-ok","metadata":{"execution":{"iopub.status.busy":"2022-01-24T18:43:33.861187Z","iopub.execute_input":"2022-01-24T18:43:33.861920Z","iopub.status.idle":"2022-01-24T18:44:14.348614Z","shell.execute_reply.started":"2022-01-24T18:43:33.861874Z","shell.execute_reply":"2022-01-24T18:44:14.347455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}