{"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":"<center style = \"font-family: 'Lucida Console', 'Courier New', monospace;\">\n    <img src = \"https://blogger.googleusercontent.com/img/a/AVvXsEj6-rQw5r22Bt47BUTtW5bn_dcWT7zMeADwtvsAHS3kBt6w8eWTmCM649ZcJcvosIMup6flKFIaI8p4M9ZzH1yXpEaMRjvwwfVZ_hMqgXCxtwNzEK25vTa-J2ly20by3M1zx7rTymo-tBI6Fq-mj1SJfCOXsOz0Ou1Esi4h2omvQSW98AjsONsVS-EA\" width=400 height = 200>\n    <h1 style = \"background: rgb(44,169,201);\nbackground: linear-gradient(180deg, rgba(44,169,201,1) 0%, rgba(1,94,125,1) 100%);border-radius: 20px; font-size:30px\">Tensorflow - Help Protect the Great Barrier Reef 🌟🐠</h1>\n</center>\n\n<div style = \"background: rgb(224,224,224);border-radius: 42px;\">\n    <h1 style = \"font-family: Consolas; text-align:center; color:#FF69B4\">Introduction</h1>\n    <h2 style = \"font-family: Consolas; text-align:center\">Why this Competition ❓</h2>\n    <p style = \"font-family : Lucida Sans Typewriter\">\n    Australia's stunningly beautiful Great Barrier Reef is the world’s largest coral reef and home to 1,500 species of fish, 400 species of corals, 130 species of sharks, rays, and a massive variety of other sea life.Unfortunately, the reef is under threat, in part because of the overpopulation of one particular starfish – the coral-eating crown-of-thorns starfish (or COTS for short).\n    </p>\n    <h2 style = \"font-family: Consolas; text-align:center\">Goal of Competition 🥅</h2>\n    <p style = \"font-family : Lucida Sans Typewriter\">\n    The goal of this competition is to accurately identify starfish in real-time by building an object detection model trained on underwater videos of coral reefs.\n    </p>\n</div>\n\n<div style = \"background: rgb(224,224,224);border-radius: 42px;\">\n    <h1 style = \"font-family: Consolas; text-align:center; color:#FF69B4\">Sponsors 💰</h1>\n    <h2 style = \"font-family: Consolas; text-align:center\">TensorFlow</h2>\n    <p style = \"font-family : Lucida Sans Typewriter\">\n    TensorFlow is a free and open-source software library for machine learning and artificial intelligence. It can be used across a range of tasks but has a particular focus on training and inference of deep neural networks.\n    </p>\n    <h2 style = \"font-family: Consolas; text-align:center\">CSIRO</h2>\n    <p style = \"font-family : Lucida Sans Typewriter\">\n    The Commonwealth Scientific and Industrial Research Organisation is an Australian Government agency responsible for scientific research. CSIRO works with leading organisations around the world.\n    </p>\n    <h2 style = \"font-family: Consolas; text-align:center\">GBRF</h2>\n    <p style = \"font-family : Lucida Sans Typewriter\">\n    The Great Barrier Reef Foundation is an Australian non-profit organisation established in 1999 to help protect and preserve the Great Barrier Reef. \n    </p>\n</div>\n\n<h2 style = \"font-family: Consolas\">More Details</h2>\n<p style = \"font-family : Lucida Sans Typewriter\">Check <a href = \"https://www.kaggle.com/c/petfinder-pawpularity-score/data\">competition page</a> for details</p>\n<h2 style = \"font-family : Comic Sans MS\">Let's dive in ⬇️</h2>\n\n<center><img src = \"https://img.shields.io/badge/Upvote-If%20you%20found%20this%20notebook%20useful-blue\" width=400 height = 400></center>","metadata":{}},{"cell_type":"markdown","source":"<h1 style = \"font-family: 'Lucida Console', 'Courier New', monospace; background: rgb(44,169,201);\nbackground: linear-gradient(180deg, rgba(44,169,201,1) 0%, rgba(1,94,125,1) 100%); border-radius: 20px; font-size:30px; text-align:center; \">Install Libraries ⏬</h1>","metadata":{}},{"cell_type":"code","source":"import torch\ncuda_version_major = int(torch.version.cuda.split('.')[0])\n\n!wget https://raw.githubusercontent.com/airctic/icevision/master/icevision_install.sh\n!bash icevision_install.sh cuda11\n!pip install torchtext==0.11.0 --upgrade\n\nimport IPython\nIPython.Application.instance().kernel.do_shutdown(True)","metadata":{"_kg_hide-output":true,"scrolled":true,"execution":{"iopub.status.busy":"2021-12-16T12:40:55.390749Z","iopub.execute_input":"2021-12-16T12:40:55.391075Z","iopub.status.idle":"2021-12-16T12:45:31.336809Z","shell.execute_reply.started":"2021-12-16T12:40:55.390992Z","shell.execute_reply":"2021-12-16T12:45:31.335989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h1 style = \"font-family: 'Lucida Console', 'Courier New', monospace; background: rgb(44,169,201);\nbackground: linear-gradient(180deg, rgba(44,169,201,1) 0%, rgba(1,94,125,1) 100%); border-radius: 20px; font-size:30px; text-align:center; \">Import Libraries 📚</h1>","metadata":{}},{"cell_type":"code","source":"import os\nimport shutil\n\nfrom kaggle_secrets import UserSecretsClient\nimport copy \nimport time\n\nimport pandas as pd\nfrom pandas_profiling import ProfileReport\n\nimport numpy as np\nimport ast\n\nimport cv2\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport seaborn as sns\nsns.set()\n\nimport torch\nfrom icevision.all import *\n\nimport wandb\n\nfrom colorama import Fore, Back, Style\n\nfrom IPython.display import IFrame\nfrom tqdm import tqdm\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:46:33.655535Z","iopub.execute_input":"2021-12-16T12:46:33.655796Z","iopub.status.idle":"2021-12-16T12:46:33.669179Z","shell.execute_reply.started":"2021-12-16T12:46:33.655758Z","shell.execute_reply":"2021-12-16T12:46:33.668485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h1 style = \"font-family: 'Lucida Console', 'Courier New', monospace; background: rgb(44,169,201);\nbackground: linear-gradient(180deg, rgba(44,169,201,1) 0%, rgba(1,94,125,1) 100%); border-radius: 20px; font-size:30px; text-align:center; \">Initialize Constants 🔰</h1>","metadata":{}},{"cell_type":"code","source":"TRAIN_PATH = \"../input/tensorflow-great-barrier-reef/train_images\"\nHEIGHT, WIDTH = 720, 1280\nimage_size = 640","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:46:43.910762Z","iopub.execute_input":"2021-12-16T12:46:43.911101Z","iopub.status.idle":"2021-12-16T12:46:43.915505Z","shell.execute_reply.started":"2021-12-16T12:46:43.911061Z","shell.execute_reply":"2021-12-16T12:46:43.91466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_files(path):\n    vid_ls = [os.path.join(path,f) for f in os.listdir(path)]\n    return sorted(vid_ls, key=lambda x: int(\"\".join([i for i in x if i.isdigit()])))","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:46:44.04325Z","iopub.execute_input":"2021-12-16T12:46:44.043506Z","iopub.status.idle":"2021-12-16T12:46:44.048513Z","shell.execute_reply.started":"2021-12-16T12:46:44.043477Z","shell.execute_reply":"2021-12-16T12:46:44.047692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vid_paths = [\n    f'{TRAIN_PATH}/video_0',\n    f'{TRAIN_PATH}/video_1',\n    f'{TRAIN_PATH}/video_2',\n]\n\nfiles_ls = [get_files(vid_path) for vid_path in vid_paths]\nlen(files_ls)\n\ntrain_df = pd.read_csv(\"../input/tensorflow-great-barrier-reef/train.csv\")","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:46:44.192042Z","iopub.execute_input":"2021-12-16T12:46:44.192336Z","iopub.status.idle":"2021-12-16T12:46:44.775114Z","shell.execute_reply.started":"2021-12-16T12:46:44.192306Z","shell.execute_reply":"2021-12-16T12:46:44.774279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:46:44.778761Z","iopub.execute_input":"2021-12-16T12:46:44.779002Z","iopub.status.idle":"2021-12-16T12:46:44.80357Z","shell.execute_reply.started":"2021-12-16T12:46:44.778971Z","shell.execute_reply":"2021-12-16T12:46:44.802897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h1 style = \"font-family: 'Lucida Console', 'Courier New', monospace; background: rgb(44,169,201);\nbackground: linear-gradient(180deg, rgba(44,169,201,1) 0%, rgba(1,94,125,1) 100%); border-radius: 20px; font-size:30px; text-align:center; \"> Data Preprocessing ⚒️🔬</h1>","metadata":{}},{"cell_type":"code","source":"def get_oldpath(x):\n    return os.path.join(vid_paths[x.video_id], f'{str(x.video_frame)}.jpg')\n\ndef get_newpath(x):\n    filename = f\"{x.video_id}_{x.video_frame}.jpg\"\n    return os.path.join(\"./dataset\", filename)\n\ndef get_filename(x):\n    return f\"{x.video_id}_{x.video_frame}.jpg\"","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:46:44.868967Z","iopub.execute_input":"2021-12-16T12:46:44.869183Z","iopub.status.idle":"2021-12-16T12:46:44.874293Z","shell.execute_reply.started":"2021-12-16T12:46:44.869157Z","shell.execute_reply":"2021-12-16T12:46:44.873399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# annotation 즉 레이블이 있는 것들만으로 추린다 (학습용 이니까)\ntrain_df = train_df[train_df.annotations != \"[]\"]\n\n# annotation 정보는 문자열이다 (예시.\"[{'x': 559, 'y': 213, 'width': 50, 'height': 32}]\")\n# 이를 파이썬 객체로 변환하는 방법 중 하나로 ast.literal_eval 을 사용할 수 있다.\ntrain_df[\"annotations\"] = train_df[\"annotations\"].map(lambda x : ast.literal_eval(x))\n\n# DataFrame의 apply 는 레코드별로 지정된 함수를 적용한 뒤, 전체가 적용된 새로운 DataFrame을 반환한다.\n# filepath는 실제 파일이 저장된 위치 (원본)\n# newpath는 원본 파일을 복사해 옮겨놓을 위치 (복사본)\n# filename은 단순히 파일이름\ntrain_df[\"filepath\"] = train_df.apply(lambda x : get_oldpath(x), axis=1)\ntrain_df[\"newpath\"] = train_df.apply(lambda x : get_newpath(x), axis=1)\ntrain_df[\"filename\"] = train_df.apply(lambda x : get_filename(x), axis=1)\n\nos.makedirs(\"./dataset\",exist_ok=True)\n\nfor i in tqdm(range(len(train_df))):\n    src = train_df.iloc[i][\"filepath\"]\n    dst = train_df.iloc[i][\"newpath\"]\n    shutil.copy(src,dst)\n    \ntrain_df.head(2)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:46:45.067234Z","iopub.execute_input":"2021-12-16T12:46:45.0675Z","iopub.status.idle":"2021-12-16T12:47:48.306649Z","shell.execute_reply.started":"2021-12-16T12:46:45.067468Z","shell.execute_reply":"2021-12-16T12:47:48.305848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.iloc[0:2].explode('annotations').apply(lambda x : x.annotations[\"x\"], axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:47:48.308279Z","iopub.execute_input":"2021-12-16T12:47:48.308574Z","iopub.status.idle":"2021-12-16T12:47:48.327139Z","shell.execute_reply.started":"2021-12-16T12:47:48.308533Z","shell.execute_reply":"2021-12-16T12:47:48.326247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = train_df\n\n# DataFrame의 explode 메서드는 리스트를 풀어헤친다\n# [{'x': 559, 'y': 213, 'width': 50, 'height': 32}] => {'x': 559, 'y': 213, 'width': 50, 'height': 32}\ndf = df.explode(\"annotations\")\n\n# 모든 이미지의 크기(높이 너비), 레이블이 모두 동일하다\n# 엑셀에서 드래그로 주루룩 같은 갚을 채워넣는것 같은 일\ndf[\"width\"] = [WIDTH]*len(df)\ndf[\"height\"] = [HEIGHT]*len(df)\ndf[\"label\"] = [\"starfish\"]*len(df)\n\n# annotation에 담긴 x, y, width, height 대신, \n# 객체탐지에서 일반적으로 사용되는 xmin, ymin, xmax, ymax 용어와 알맞은 값으로 대체한다\ndf[\"xmin\"] = df.apply(lambda x : x.annotations[\"x\"], axis=1)\ndf[\"ymin\"] = df.apply(lambda x : x.annotations[\"y\"], axis=1)\ndf[\"xmax\"] = df.apply(lambda x : x.annotations[\"x\"]+x.annotations[\"width\"], axis=1)\ndf[\"ymax\"] = df.apply(lambda x : x.annotations[\"y\"]+x.annotations[\"height\"], axis=1)\n\n# 바운딩박스의 우측 하단 좌표가 \n# 이미지의 우측 하단 모서리를 벗어나는 경우\ndf.loc[df[\"xmax\"] > 1280, \"xmax\"] = 1280\ndf.loc[df[\"ymax\"] > 720, \"ymax\"] = 720\n\n# 객체 탐지에 불필요한 열은 제거한다\ndf = df.drop([\"video_id\",\"sequence\",\"video_frame\",\"sequence_frame\",\"image_id\",\"annotations\",\"filepath\",\"newpath\"], axis=1)\ndf = df.reset_index(drop=True)\ndf.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:47:48.32937Z","iopub.execute_input":"2021-12-16T12:47:48.330044Z","iopub.status.idle":"2021-12-16T12:47:49.327624Z","shell.execute_reply.started":"2021-12-16T12:47:48.329996Z","shell.execute_reply":"2021-12-16T12:47:49.326826Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h1 style = \"font-family: 'Lucida Console', 'Courier New', monospace; background: rgb(44,169,201);\nbackground: linear-gradient(180deg, rgba(44,169,201,1) 0%, rgba(1,94,125,1) 100%); border-radius: 20px; font-size:30px; text-align:center; \">Data Visualization 📊💹</h1>","metadata":{}},{"cell_type":"markdown","source":"<div style = \"font-family : Lucida Sans Typewriter;background: rgb(224,224,224);border-radius: 25px;\">\n    <h2 style = \"font-family: 'Lucida Console', 'Courier New', monospace; border-radius: 20px; font-size:30px; text-align:center; ; color:#FF69B4\">Weights and Biases</h2>\n    <center><img src = \"https://i.imgur.com/KISYcqD.png\" width=200 height = 200></center>\n    <a href = \"https://wandb.ai/shanmukh/Protect%20Great%20Barrier%20Reef/runs/2eywhb67\"; style = \"font-family: 'Lucida Console', 'Courier New', monospace; border-radius: 20px; text-align:center; font-size:25px\">Checkout Dashboard created for this notebook</a>\n    <p style = \"font-family : Lucida Sans Typewriter\">\n    Weights and Biases is a set of Machine Learning tools used for experiment tracking, dataset versioning, and collaborating on ML projects. Weights and Biases is useful in many applications such as\n    </p>  \n    <ul>\n          <li>Experiment Tracking</li>\n          <li>Hyperparameter Tuning</li>\n          <li>Data Visualization</li>\n          <li>Data and model Versioning</li>\n          <li>Collaborative Reports</li>\n    </ul>\n    <a href = \"https://wandb.ai/site\">Go to offocial website for more tutorials and Documentation</a>\n</div>","metadata":{}},{"cell_type":"code","source":"# Check https://www.kaggle.com/debarshichanda/pytorch-w-b-pawpularity-training for more details\n\n# 이 섹션은 학습용 데이터셋을 W&B 대시보드에서 시각화하는 방법을 보여준다.\n# \n# 1. W&B의 API 키를 발급 받는다\n# 2. Add-ons => Secrets 메뉴를 통해, wandb_api 라는 키에 W&B API값을 할당한다\n# 3. 아래 코드를 실행한다.\n\ntry:\n    user_secrets = UserSecretsClient()\n    api_key = user_secrets.get_secret(\"wandb_api\")\n    wandb.login(key=api_key)\n    anony = None\nexcept:\n    anony = \"must\"\n    print('''If you want to use your W&B account, Follow these steps :\n            -> go to Add-ons {Below name of notebook} -> Secrets -> Add a new Secret\n            -> Label = wandb_api\n            -> Value = W&B access token from https://wandb.ai/authorize \n         ''')","metadata":{"execution":{"iopub.status.busy":"2021-12-16T01:50:52.636565Z","iopub.execute_input":"2021-12-16T01:50:52.636931Z","iopub.status.idle":"2021-12-16T01:50:54.540847Z","shell.execute_reply.started":"2021-12-16T01:50:52.636887Z","shell.execute_reply":"2021-12-16T01:50:54.539759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"WANDB_CONFIG = {\n   \"project_name\"    : \"Protect Great Barrier Reef\",\n   \"group_name\"      : \"IceVision Training\",\n   \"job_type_data\"   : \"Data Visualization\",\n   \"job_type_train\"  : \"Training\",\n   \"anonymity\"       : \"must\",\n   \"artifact\"        : \"training_data\"\n}\n\nrun = wandb.init(\n    project = WANDB_CONFIG[\"project_name\"],\n    group = WANDB_CONFIG[\"group_name\"],\n    job_type = WANDB_CONFIG[\"job_type_data\"],\n    anonymous= WANDB_CONFIG[\"anonymity\"]\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T01:50:56.440616Z","iopub.execute_input":"2021-12-16T01:50:56.440951Z","iopub.status.idle":"2021-12-16T01:51:04.157901Z","shell.execute_reply.started":"2021-12-16T01:50:56.440917Z","shell.execute_reply":"2021-12-16T01:51:04.156558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 디스플레이될 테이블의 열을 정의한다\nwb_table = wandb.Table(columns = [\n    \"filename\", \"Image\", \"xmin\", \"ymin\", \"xmax\", \"ymax\"\n])\n\n# 학습용 데이터 중 처음 100개에 대해서 tqdm 한다\nfor i in tqdm(range(len(df))[:100]):\n    row = df.loc[i]\n    impath = os.path.join(\"./dataset\",row[\"filename\"])\n    im = PIL.Image.open(impath)\n    bbox = [{\n            \"position\": {\n                \"minX\": int(row['xmin']),\n                \"maxX\": int(row[\"xmax\"]),\n                \"minY\": int(row[\"ymin\"]),\n                \"maxY\": int(row[\"ymax\"])\n            },\n            \"class_id\": 1,\n            \"box_caption\": \"starfish\",\n            \"domain\": \"pixel\"\n        }]\n    \n    # 이미지는 wandb.Image 객체 형태가 되어야한다.\n    # 보다시피 PIL의 Image 형식을 그대로 사용할 수 있으며,\n    # boxes 및 classes 라는 추가 파라미터를 설정하면 이미지내 객체 위치 및 범주를 결정해 보여줄 수 있다.\n    image = wandb.Image(im,\n                        boxes = {\n                            \"ground_truth\": {\n                                \"box_data\": bbox,\n                                \"class_labels\" : {1: 'starfish'}\n                            }\n                        },\n                        classes = [{\"id\": 0, \"name\": \"background\"}, {\"id\": 1, \"name\": \"starfish\"}]\n                    )\n    \n    # 입력된 데이터가 준비되었으면,\n    # 테이블의 행 데이터로 추가한다\n    wb_table.add_data(row['filename'],\n                      image,\n                      row[\"xmin\"],\n                      row[\"ymin\"],\n                      row[\"xmax\"],\n                      row[\"ymax\"]\n                     )\n    \nwandb.log({'Data Visualization': wb_table})\nrun.finish()","metadata":{"execution":{"iopub.status.busy":"2021-12-16T01:51:40.584526Z","iopub.execute_input":"2021-12-16T01:51:40.584843Z","iopub.status.idle":"2021-12-16T01:52:20.754018Z","shell.execute_reply.started":"2021-12-16T01:51:40.58481Z","shell.execute_reply":"2021-12-16T01:52:20.752946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 직접 W&B 대시보드에서 확인해도 되지만,\n# 아래 명령을 수행하면 IFrame으로 W&B 대시보드 인터페이스를 주피터 노트북내 출력한다\nframe = IFrame(run.url, width=1280, height=720)\nframe","metadata":{"execution":{"iopub.status.busy":"2021-12-16T01:52:22.062192Z","iopub.execute_input":"2021-12-16T01:52:22.062499Z","iopub.status.idle":"2021-12-16T01:52:22.074294Z","shell.execute_reply.started":"2021-12-16T01:52:22.062448Z","shell.execute_reply":"2021-12-16T01:52:22.073068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style = \"font-family : Lucida Sans Typewriter;background: rgb(224,224,224);border-radius: 25px;\">\n    <h2 style = \"font-family: 'Lucida Console', 'Courier New', monospace; border-radius: 20px; font-size:30px; text-align:center; ; color:#FF69B4\">Pandas Profiling</h2>\n    <center><img src = \"https://pandas-profiling.github.io/pandas-profiling/docs/assets/logo_header.png\" width=200 height = 200></center>\n    <p style = \"font-family : Lucida Sans Typewriter\">\n    Pandas profiling is an open source Python module with which we can quickly do an exploratory data analysis with just a few lines of code. Besides, if this is not enough to convince us to use this tool, it also generates interactive reports in web format that can be presented to any person, even if they don’t know programming.\n    </p>  \n    <a href = \"https://pandas-profiling.github.io/pandas-profiling/\">Go to offocial website for documentation</a>\n</div>","metadata":{}},{"cell_type":"code","source":"train_report = ProfileReport(df,title=\"Metadata of Training images\")\ntrain_report.to_file(\"./train_metadata.html\")\ntrain_report","metadata":{"execution":{"iopub.status.busy":"2021-12-16T01:52:57.440091Z","iopub.execute_input":"2021-12-16T01:52:57.440423Z","iopub.status.idle":"2021-12-16T01:53:16.366162Z","shell.execute_reply.started":"2021-12-16T01:52:57.440387Z","shell.execute_reply":"2021-12-16T01:53:16.363652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style = \"font-family : Lucida Sans Typewriter;background: rgb(224,224,224);border-radius: 25px;\">\n    <h2 style = \"font-family: 'Lucida Console', 'Courier New', monospace; border-radius: 20px; font-size:30px; text-align:center; ; color:#FF69B4\">IceVision</h2>\n    <center><img src = \"https://airctic.com/0.11.0/images/icevision-logo-slogan.png\" width=200 height = 200></center>\n    <p style = \"font-family : Lucida Sans Typewriter\">\n    IceVision is the first agnostic computer vision framework to offer a curated collection with hundreds of high-quality pre-trained models from torchvision, MMLabs, and soon Pytorch Image Models. It orchestrates the end-to-end deep learning workflow allowing to train networks with easy-to-use robust high-performance libraries such as Pytorch-Lightning and Fastai</p> \n    IceVision Unique Features:\n    <ul>\n        <li>Data curation/cleaning with auto-fix</li>\n        <li>Access to an exploratory data analysis dashboard</li>\n        <li>Pluggable transforms for better model generalization</li>\n        <li>Access to hundreds of neural net models</li>\n        <li>Acccss to multiple training loop libraries</li>\n        <li>Multi-task training to efficiently combine object detection, segmentation, and classification models</li>\n    </ul>\n    <a href = \"https://airctic.com/0.11.0/\">Go to offocial website for documentation</a>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<h1 style = \"font-family: 'Lucida Console', 'Courier New', monospace; background: rgb(44,169,201);\nbackground: linear-gradient(180deg, rgba(44,169,201,1) 0%, rgba(1,94,125,1) 100%); border-radius: 20px; font-size:30px; text-align:center; \">Modelling 🏫</h1>","metadata":{}},{"cell_type":"markdown","source":"<h2 style = \"font-family: 'Lucida Console', 'Courier New', monospace; border-radius: 20px; font-size:30px; text-align:center; ; color:#FF69B4\">Data Parser</h2>","metadata":{}},{"cell_type":"markdown","source":"How to create custom Parser for IceVision [[LINK](https://airctic.com/0.11.0/custom_parser/)]\n\n데이터셋을 모델의 입력으로 만들기위한 클래스를 만든다. Pandas DataFrame의 내용을 파싱해야 하기 때문에, Parser 라고 불리는 객체를 활용하며, 객체 탐지에 사용되는 기본 객체는 ObjectDetectionRecord 이다.","metadata":{}},{"cell_type":"code","source":"# 객체 탐지를 위한 레코드는 ObjectDetectionRecord 객체로 표현된다.\n# Parser.generate_template 메서드는 레코드 객체를 만들기 위해 필요한 기본 템플릿을 출력한다.\ntemplate_record = ObjectDetectionRecord()\nParser.generate_template(template_record)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:50:53.476792Z","iopub.execute_input":"2021-12-16T12:50:53.477114Z","iopub.status.idle":"2021-12-16T12:50:53.483971Z","shell.execute_reply.started":"2021-12-16T12:50:53.47708Z","shell.execute_reply":"2021-12-16T12:50:53.483058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# 보다시피 위에 출력된 MyParser 템플릿코드를 그대로 가져온 다음, 각 메서드를 구현하였다\nclass PGBRParser(Parser):\n    def __init__(self, template_record, data_dir, df):\n        super().__init__(template_record=template_record)\n\n        self.data_dir = data_dir\n        self.df = df\n        self.class_map = ClassMap(list(self.df['label'].unique()))\n\n    # 각 데이터 레코드(행)을 이터레이션하고, \n    # 각 이터레이션 마다 반환할 객체를 정의한다\n    def __iter__(self) -> Any:\n        for o in self.df.itertuples():\n            yield o\n\n    def __len__(self) -> int:\n        return len(self.df)\n\n    # 유니크 ID 할당에 사용될 수 있는 정보를 반환한다.\n    # 여기서 o는 __iter__가 이터레이션마다 반환하는 객체를 의미한다\n    def record_id(self, o) -> Hashable:\n        return o.filename\n\n    # 여기서 o는 __iter__가 이터레이션마다 반환하는 객체를 의미한다\n    #\n    # 보다시피 is_new 라는 인자가 존재한다. 사진 한 장에 여러 물체가 기록되어 있을 수 있다.\n    # DataFrame 행을 하나씩 탐색하다가 동일한 이미지 이름을 가진 레코드(행)이 또 다시 발견된다면 이를 같은 레코드로 간주한다 (record_id에서 수행)\n    # 그리고 record.detection.add_bboxes, record.detection.add_labels에 추가 bbox 및 레이블을 기록해 넣는다.\n    # is_new는 지금까지 본 적 없는 record_id가 발견되었을 때만 수행한다.\n    #\n    # 이 내용으로 미루어 보면, 학습 데이터의 입력인 이미지는 set_filepath로 지정된다 (이미지 객체 자체가 아니다)\n    def parse_fields(self, o, record, is_new):\n        if is_new:\n            record.set_filepath(os.path.join(self.data_dir,o.filename))\n            record.set_img_size(ImgSize(width=o.width, height=o.height))\n            record.detection.set_class_map(self.class_map)\n\n        record.detection.add_bboxes([BBox.from_xyxy(o.xmin, o.ymin, o.xmax, o.ymax)])\n        record.detection.add_labels([o.label])","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:50:54.367468Z","iopub.execute_input":"2021-12-16T12:50:54.367738Z","iopub.status.idle":"2021-12-16T12:50:54.376448Z","shell.execute_reply.started":"2021-12-16T12:50:54.367708Z","shell.execute_reply":"2021-12-16T12:50:54.37545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style = \"font-family: 'Lucida Console', 'Courier New', monospace; border-radius: 20px; font-size:30px; text-align:center; ; color:#FF69B4\">Data Loader</h2>","metadata":{}},{"cell_type":"code","source":"# 데이터프레임에서 데이터를 파싱 (레이블과 BBOX)\ntemplate_record = ObjectDetectionRecord()\nparser = PGBRParser(template_record, \"./dataset\", df)\n\ntrain_records, valid_records = parser.parse()\nprint(parser.class_map)\n# 여기까지하면 파싱이 완료된다.\n\ntrain_tfms = tfms.A.Adapter([*tfms.A.aug_tfms(size=image_size, presize=512), tfms.A.Normalize()])\nvalid_tfms = tfms.A.Adapter([*tfms.A.resize_and_pad(image_size), tfms.A.Normalize()])\n# 여기까지하면 파싱된 데이터 적용할 변형들의 정의가 완료된다.\n\ntrain_ds = Dataset(train_records, train_tfms)\nvalid_ds = Dataset(valid_records, valid_tfms)\n# 여기까지 하면 실제 모델에 입력될 Dataset 객체 생성이 완료된다.\n# 보다시피 일부 데이터 증강까지 수행되었다. (presizing - https://notesbylex.com/presizing.html)\n\nsamples = [train_ds[0] for _ in range(3)]\nshow_samples(samples, ncols=3)\n# 일부 데이터를 출력한다","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:51:04.913537Z","iopub.execute_input":"2021-12-16T12:51:04.914179Z","iopub.status.idle":"2021-12-16T12:51:10.195602Z","shell.execute_reply.started":"2021-12-16T12:51:04.914128Z","shell.execute_reply":"2021-12-16T12:51:10.194845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model_type은 객체탐지용 전체 모델 구조를 선택한다\n# - https://velog.io/@zeen263/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-3-Detection-2.-VFNet-%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0\nmodel_type = models.mmdet.vfnet\n\n# 모델 구조 중 백본으로 사용할 모델을 선택한다\nbackbone = model_type.backbones.resnet50_fpn_mstrain_2x(pretrained=True)\n\n# 그리고 이 둘을 결함해 전체 모델의 인스턴스를 생성한다\nmodel = model_type.model(backbone=backbone, num_classes=len(parser.class_map))\n\n# 모델에 입력될 데이터를 정의하는 DataLoader 객체를 생성한다\ntrain_dl = model_type.train_dl(train_ds, batch_size=16, num_workers=4, shuffle=True)\nvalid_dl = model_type.valid_dl(valid_ds, batch_size=16, num_workers=4, shuffle=False)","metadata":{"_kg_hide-output":true,"scrolled":true,"execution":{"iopub.status.busy":"2021-12-16T01:54:13.096071Z","iopub.execute_input":"2021-12-16T01:54:13.0967Z","iopub.status.idle":"2021-12-16T01:54:50.48565Z","shell.execute_reply.started":"2021-12-16T01:54:13.09665Z","shell.execute_reply":"2021-12-16T01:54:50.484514Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style = \"font-family: 'Lucida Console', 'Courier New', monospace; border-radius: 20px; font-size:30px; text-align:center; ; color:#FF69B4\">Metrics</h2>","metadata":{}},{"cell_type":"code","source":"# VFNet이 타게팅한 데이터셋은 COCO 이다\nmetrics = [COCOMetric(metric_type=COCOMetricType.bbox)]","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:56:04.523599Z","iopub.execute_input":"2021-12-16T12:56:04.52389Z","iopub.status.idle":"2021-12-16T12:56:04.528597Z","shell.execute_reply.started":"2021-12-16T12:56:04.523855Z","shell.execute_reply":"2021-12-16T12:56:04.52783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style = \"font-family: 'Lucida Console', 'Courier New', monospace; border-radius: 20px; font-size:30px; text-align:center; ; color:#FF69B4\">Training</h2>","metadata":{}},{"cell_type":"code","source":"learn = model_type.fastai.learner(dls=[train_dl, valid_dl], model=model, metrics=metrics)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T01:55:44.478828Z","iopub.execute_input":"2021-12-16T01:55:44.479184Z","iopub.status.idle":"2021-12-16T01:55:44.841406Z","shell.execute_reply.started":"2021-12-16T01:55:44.479149Z","shell.execute_reply":"2021-12-16T01:55:44.840263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# learn.lr_find()","metadata":{"execution":{"iopub.status.busy":"2021-12-15T14:02:51.872173Z","iopub.execute_input":"2021-12-15T14:02:51.872525Z","iopub.status.idle":"2021-12-15T14:04:54.539914Z","shell.execute_reply.started":"2021-12-15T14:02:51.872486Z","shell.execute_reply":"2021-12-15T14:04:54.539137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fine_tune(30, 0.0003, freeze_epochs=5)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T01:55:51.16381Z","iopub.execute_input":"2021-12-16T01:55:51.16415Z","iopub.status.idle":"2021-12-16T06:36:23.723767Z","shell.execute_reply.started":"2021-12-16T01:55:51.164107Z","shell.execute_reply":"2021-12-16T06:36:23.722544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(model.state_dict(), './gbr_vfnet_resnet50_fpn_mstrain_2x_30epochs.pt')","metadata":{"execution":{"iopub.status.busy":"2021-12-16T06:41:10.96571Z","iopub.execute_input":"2021-12-16T06:41:10.966058Z","iopub.status.idle":"2021-12-16T06:41:11.254012Z","shell.execute_reply.started":"2021-12-16T06:41:10.966026Z","shell.execute_reply":"2021-12-16T06:41:11.252829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls ../input/gbr-vfnet-resnet50-fpn-mstrain-2x-30epochspt/gbr_vfnet_resnet50_fpn_mstrain_2x_30epochs.pt","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:51:25.127727Z","iopub.execute_input":"2021-12-16T12:51:25.128025Z","iopub.status.idle":"2021-12-16T12:51:25.833698Z","shell.execute_reply.started":"2021-12-16T12:51:25.127991Z","shell.execute_reply":"2021-12-16T12:51:25.832754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"state_dict = torch.load('../input/gbr-vfnet-resnet50-fpn-mstrain-2x-30epochspt/gbr_vfnet_resnet50_fpn_mstrain_2x_30epochs.pt')","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:53:05.105276Z","iopub.execute_input":"2021-12-16T12:53:05.105599Z","iopub.status.idle":"2021-12-16T12:53:16.452642Z","shell.execute_reply.started":"2021-12-16T12:53:05.105564Z","shell.execute_reply":"2021-12-16T12:53:16.4518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_type = models.mmdet.vfnet\nbackbone = model_type.backbones.resnet50_fpn_mstrain_2x(pretrained=True)\nmodel = model_type.model(backbone=backbone, num_classes=len(parser.class_map))\n\ntrain_dl = model_type.train_dl(train_ds, batch_size=16, num_workers=4, shuffle=True)\nvalid_dl = model_type.valid_dl(valid_ds, batch_size=16, num_workers=4, shuffle=False)\n\nmodel.load_state_dict(state_dict)","metadata":{"_kg_hide-output":false,"execution":{"iopub.status.busy":"2021-12-16T12:53:21.773699Z","iopub.execute_input":"2021-12-16T12:53:21.774114Z","iopub.status.idle":"2021-12-16T12:53:43.131766Z","shell.execute_reply.started":"2021-12-16T12:53:21.774062Z","shell.execute_reply":"2021-12-16T12:53:43.130872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn = model_type.fastai.learner(dls=[train_dl, valid_dl], model=model, metrics=metrics)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T12:56:18.631493Z","iopub.execute_input":"2021-12-16T12:56:18.631766Z","iopub.status.idle":"2021-12-16T12:56:18.657451Z","shell.execute_reply.started":"2021-12-16T12:56:18.631734Z","shell.execute_reply":"2021-12-16T12:56:18.656645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fine_tune(1, 10e-5, freeze_epochs=0)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T13:02:42.512468Z","iopub.execute_input":"2021-12-16T13:02:42.512774Z","iopub.status.idle":"2021-12-16T13:10:01.032692Z","shell.execute_reply.started":"2021-12-16T13:02:42.512738Z","shell.execute_reply":"2021-12-16T13:10:01.031865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h1 style = \"font-family: 'Lucida Console', 'Courier New', monospace; background: rgb(44,169,201);\nbackground: linear-gradient(180deg, rgba(44,169,201,1) 0%, rgba(1,94,125,1) 100%); border-radius: 20px; font-size:30px; text-align:center; \">Inference 🔮</h1>","metadata":{}},{"cell_type":"code","source":"infer_dl = model_type.infer_dl([valid_ds[0],valid_ds[4],valid_ds[7],valid_ds[9]], batch_size=4, shuffle=False)\npreds = model_type.predict_from_dl(model, infer_dl, keep_images=True)\nshow_preds(preds=preds)","metadata":{"execution":{"iopub.status.busy":"2021-12-16T13:24:07.718007Z","iopub.execute_input":"2021-12-16T13:24:07.718317Z","iopub.status.idle":"2021-12-16T13:24:10.099679Z","shell.execute_reply.started":"2021-12-16T13:24:07.718282Z","shell.execute_reply":"2021-12-16T13:24:10.098895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# shutil.make_archive('./checkpoints',\n#                     'zip',\n#                     './',\n#                     'checkpoints')\n\n# shutil.rmtree(\"./checkpoints\")\n# shutil.rmtree(\"./dataset\")\n# shutil.rmtree(\"./wandb\")","metadata":{"execution":{"iopub.status.busy":"2021-12-13T21:22:40.848691Z","iopub.execute_input":"2021-12-13T21:22:40.849147Z","iopub.status.idle":"2021-12-13T21:22:57.503833Z","shell.execute_reply.started":"2021-12-13T21:22:40.84911Z","shell.execute_reply":"2021-12-13T21:22:57.502789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a href=\"./checkpoints.zip\"> Download File </a>","metadata":{}},{"cell_type":"markdown","source":"<br>\n<h3 style = \"font-family: Consolas; text-align:center; color:#FF0000\">If you come this far, you could've got some insights from this notebook. An upvote would be very helpful :). Kindly comment if there are any doubts or mistakes</h3>\n\n<center><img src = \"https://img.shields.io/badge/Completed-The%20End-brightgreen\" width=300 height = 300></center>","metadata":{}}]}