{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"papermill":{"default_parameters":{},"duration":2985.779264,"end_time":"2023-07-14T19:21:02.083876","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2023-07-14T18:31:16.304612","version":"2.4.0"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"055adb0f15914c698e6ab5d066cd1d86":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"DescriptionStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"19bd980b918a40b3ab3a95aecdd66397":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"26fda71bfd624730a6d989f5bb20e8c7":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"2a24ac75b665441ba29d6039db7ae174":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"success","description":"","description_tooltip":null,"layout":"IPY_MODEL_cca0ed608be7498b866593fba936185e","max":25001,"min":0,"orientation":"horizontal","style":"IPY_MODEL_cd8ac034914646a090f519d7b038c62b","value":25001}},"2cdbf1ceb79a46d7ac8090ab45d97094":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_fac75e37e41343f0a18497897535a767","IPY_MODEL_2a24ac75b665441ba29d6039db7ae174","IPY_MODEL_c6885cd6fbe14451a4dc756f42fa898c"],"layout":"IPY_MODEL_72b6e6d69a58444fb8505b8d2f0549a6"}},"3a5854f0edbf451a8a280b8d258e9879":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"DescriptionStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"3cb7ab808c6f4cb3a0e780e8cdf5696c":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"4643d666add34d8baec18b65baa9fc80":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"4cad3846f46b4161946f8c29845b5e91":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_4643d666add34d8baec18b65baa9fc80","placeholder":"​","style":"IPY_MODEL_055adb0f15914c698e6ab5d066cd1d86","value":"Extracting: 100%"}},"4cbcfd1bdc7d4dd69f6a1a4cd9f408af":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"DescriptionStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"53104c4413ea4e64b3f7edc1aed30916":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"66567724bcb44d5a8a9eb8425c73bd54":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"722f39eb74344185aa65cb8a29caea53":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_4cad3846f46b4161946f8c29845b5e91","IPY_MODEL_a24de6f1211f4ea0991521bfa6b6c483","IPY_MODEL_c020ad555829489cb2e075ead0d3d109"],"layout":"IPY_MODEL_19bd980b918a40b3ab3a95aecdd66397"}},"72b6e6d69a58444fb8505b8d2f0549a6":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"9607268fc9e74a14928ddb1a3731ee98":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"a24de6f1211f4ea0991521bfa6b6c483":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"success","description":"","description_tooltip":null,"layout":"IPY_MODEL_9607268fc9e74a14928ddb1a3731ee98","max":12501,"min":0,"orientation":"horizontal","style":"IPY_MODEL_26fda71bfd624730a6d989f5bb20e8c7","value":12501}},"be593e3171474fe19d291bab59f619dc":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"DescriptionStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"c020ad555829489cb2e075ead0d3d109":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_3cb7ab808c6f4cb3a0e780e8cdf5696c","placeholder":"​","style":"IPY_MODEL_3a5854f0edbf451a8a280b8d258e9879","value":" 12501/12501 [00:05&lt;00:00, 2398.93it/s]"}},"c6885cd6fbe14451a4dc756f42fa898c":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_66567724bcb44d5a8a9eb8425c73bd54","placeholder":"​","style":"IPY_MODEL_4cbcfd1bdc7d4dd69f6a1a4cd9f408af","value":" 25001/25001 [00:10&lt;00:00, 2388.96it/s]"}},"cca0ed608be7498b866593fba936185e":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"cd8ac034914646a090f519d7b038c62b":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"fac75e37e41343f0a18497897535a767":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_53104c4413ea4e64b3f7edc1aed30916","placeholder":"​","style":"IPY_MODEL_be593e3171474fe19d291bab59f619dc","value":"Extracting: 100%"}}},"version_major":2,"version_minor":0}},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":30665,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Chapter 5. Image Classification via Transfer Learning","metadata":{"papermill":{"duration":0.020002,"end_time":"2023-07-14T18:31:26.153823","exception":false,"start_time":"2023-07-14T18:31:26.133821","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# 5.1. Import Libraries","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":0.018745,"end_time":"2023-07-14T18:31:26.191708","exception":false,"start_time":"2023-07-14T18:31:26.172963","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# For metadata/feature processing\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom tqdm.notebook import tqdm\nimport os\nimport shutil\n\n# For neural network\nimport tensorflow as tf\n\n# For Accuracy metric\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.metrics import classification_report\n\n# For image\nimport cv2\nimport matplotlib.pyplot as plt","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":7.943051,"end_time":"2023-07-14T18:31:34.154718","exception":false,"start_time":"2023-07-14T18:31:26.211667","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T12:54:09.102444Z","iopub.execute_input":"2024-02-28T12:54:09.102824Z","iopub.status.idle":"2024-02-28T12:54:22.542510Z","shell.execute_reply.started":"2024-02-28T12:54:09.102793Z","shell.execute_reply":"2024-02-28T12:54:22.541687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.2. Uncompress Data","metadata":{"papermill":{"duration":0.01899,"end_time":"2023-07-14T18:31:34.193628","exception":false,"start_time":"2023-07-14T18:31:34.174638","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import zipfile\n\ndef unzip(src, dst):\n    with zipfile.ZipFile(src, 'r') as zf:\n        files = zf.namelist()\n        with tqdm(total=len(files), desc='Extracting') as pbar:\n            for file in files:\n                zf.extract(file, dst)\n                pbar.update(1)\n\n                \n# Remove old directory\n# shutil.rmtree('/kaggle/dogs-vs-cats')\n\n\n# New directory\nos.makedirs('/kaggle/dogs-vs-cats', exist_ok=True)\n\n# Train\nunzip('/kaggle/input/dogs-vs-cats/train.zip', '/kaggle/dogs-vs-cats/')\n\n# Test\nunzip('/kaggle/input/dogs-vs-cats/test1.zip', '/kaggle/dogs-vs-cats/')","metadata":{"papermill":{"duration":16.670072,"end_time":"2023-07-14T18:31:50.883219","exception":false,"start_time":"2023-07-14T18:31:34.213147","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:00:38.151636Z","iopub.execute_input":"2024-02-28T13:00:38.152533Z","iopub.status.idle":"2024-02-28T13:00:55.233734Z","shell.execute_reply.started":"2024-02-28T13:00:38.152489Z","shell.execute_reply":"2024-02-28T13:00:55.232802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!tree /kaggle/dogs-vs-cats -L 1","metadata":{"papermill":{"duration":0.985498,"end_time":"2023-07-14T18:31:51.888886","exception":false,"start_time":"2023-07-14T18:31:50.903388","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:00:58.233996Z","iopub.execute_input":"2024-02-28T13:00:58.234894Z","iopub.status.idle":"2024-02-28T13:00:59.230176Z","shell.execute_reply.started":"2024-02-28T13:00:58.234863Z","shell.execute_reply":"2024-02-28T13:00:59.228985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.3. Meta Data\nNot all dataset comes with prepared **metadata** (csv file containing file/image/feature/label info). Thus we need to learn how to prepare one for a custom dataset.","metadata":{"papermill":{"duration":0.019417,"end_time":"2023-07-14T18:31:51.928277","exception":false,"start_time":"2023-07-14T18:31:51.908860","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"## Get Image Paths\nFirst we'll use `glob` to access the file paths of each image to link them to their labels and data split.\n\n","metadata":{"papermill":{"duration":0.019877,"end_time":"2023-07-14T18:31:51.967828","exception":false,"start_time":"2023-07-14T18:31:51.947951","status":"completed"},"tags":[]}},{"cell_type":"code","source":"paths = glob('/kaggle/dogs-vs-cats/train/*jpg')\nprint(f\"Num Train: {len(paths)}\")\n\ntest_paths = glob('/kaggle/dogs-vs-cats/test1/*jpg')\nprint(f\"Num Test: {len(test_paths)}\")","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.161319,"end_time":"2023-07-14T18:31:52.148905","exception":false,"start_time":"2023-07-14T18:31:51.987586","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:01:04.504869Z","iopub.execute_input":"2024-02-28T13:01:04.505608Z","iopub.status.idle":"2024-02-28T13:01:04.643582Z","shell.execute_reply.started":"2024-02-28T13:01:04.505578Z","shell.execute_reply":"2024-02-28T13:01:04.642674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Build DataFrame (CSV File)","metadata":{"papermill":{"duration":0.019465,"end_time":"2023-07-14T18:31:52.187842","exception":false,"start_time":"2023-07-14T18:31:52.168377","status":"completed"},"tags":[]}},{"cell_type":"code","source":"print('Train:')\ndf = pd.DataFrame(paths, columns=['image_path'])\ndisplay(df.head(2))\n\nprint('Test:')\ntest_df = pd.DataFrame(test_paths, columns=['image_path'])\ndisplay(test_df.head(2))","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.054147,"end_time":"2023-07-14T18:31:52.262601","exception":false,"start_time":"2023-07-14T18:31:52.208454","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:01:09.150101Z","iopub.execute_input":"2024-02-28T13:01:09.150451Z","iopub.status.idle":"2024-02-28T13:01:09.177264Z","shell.execute_reply.started":"2024-02-28T13:01:09.150424Z","shell.execute_reply":"2024-02-28T13:01:09.176257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.4. Sample from Data\nTo reduce time we've down sampled the data. If you are welcome to run on the full dataset. To do so, simply comment out the cell.","metadata":{"papermill":{"duration":0.019944,"end_time":"2023-07-14T18:31:52.303811","exception":false,"start_time":"2023-07-14T18:31:52.283867","status":"completed"},"tags":[]}},{"cell_type":"code","source":"df = df.sample(6000, random_state=42)\ntest_df = test_df.sample(1000, random_state=42)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.03469,"end_time":"2023-07-14T18:31:52.358784","exception":false,"start_time":"2023-07-14T18:31:52.324094","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:01:31.327406Z","iopub.execute_input":"2024-02-28T13:01:31.327767Z","iopub.status.idle":"2024-02-28T13:01:31.341494Z","shell.execute_reply.started":"2024-02-28T13:01:31.327737Z","shell.execute_reply":"2024-02-28T13:01:31.340570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.5. Retreive Metadata\nIn the following cell we'll retreive `train-test` split and `class` infomation from **image path**. \n","metadata":{"papermill":{"duration":0.019894,"end_time":"2023-07-14T18:31:52.399039","exception":false,"start_time":"2023-07-14T18:31:52.379145","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# First we map the class name from the image paths, similar to how it is done in the above code\n# Train\ndf['class_name'] = df.image_path.map(lambda x: x.split('/')[-1].split('.')[0]) # extract class\n\ndisplay(df.head(2))","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.052061,"end_time":"2023-07-14T18:31:52.471654","exception":false,"start_time":"2023-07-14T18:31:52.419593","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:01:38.792677Z","iopub.execute_input":"2024-02-28T13:01:38.793380Z","iopub.status.idle":"2024-02-28T13:01:38.812166Z","shell.execute_reply.started":"2024-02-28T13:01:38.793351Z","shell.execute_reply":"2024-02-28T13:01:38.811049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"name2label = {k: v for v, k in enumerate(sorted(df['class_name'].unique()))}\nname2label","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.033679,"end_time":"2023-07-14T18:31:52.526237","exception":false,"start_time":"2023-07-14T18:31:52.492558","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:01:43.069759Z","iopub.execute_input":"2024-02-28T13:01:43.070557Z","iopub.status.idle":"2024-02-28T13:01:43.080191Z","shell.execute_reply.started":"2024-02-28T13:01:43.070527Z","shell.execute_reply":"2024-02-28T13:01:43.079302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label2name = {v: k for k, v in name2label.items()}\nlabel2name","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.030539,"end_time":"2023-07-14T18:31:52.577545","exception":false,"start_time":"2023-07-14T18:31:52.547006","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:01:45.467575Z","iopub.execute_input":"2024-02-28T13:01:45.467935Z","iopub.status.idle":"2024-02-28T13:01:45.474398Z","shell.execute_reply.started":"2024-02-28T13:01:45.467908Z","shell.execute_reply":"2024-02-28T13:01:45.473385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we map the class_labels to the number","metadata":{"papermill":{"duration":0.020235,"end_time":"2023-07-14T18:31:52.618261","exception":false,"start_time":"2023-07-14T18:31:52.598026","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# transforming the labels\ndf['class_label'] = df['class_name'].map(name2label)\ndisplay(df.head(2))","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.036942,"end_time":"2023-07-14T18:31:52.675621","exception":false,"start_time":"2023-07-14T18:31:52.638679","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:01:49.419128Z","iopub.execute_input":"2024-02-28T13:01:49.419817Z","iopub.status.idle":"2024-02-28T13:01:49.433347Z","shell.execute_reply.started":"2024-02-28T13:01:49.419787Z","shell.execute_reply":"2024-02-28T13:01:49.432278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Retreiver `id` column","metadata":{"papermill":{"duration":0.020765,"end_time":"2023-07-14T18:31:52.718765","exception":false,"start_time":"2023-07-14T18:31:52.698000","status":"completed"},"tags":[]}},{"cell_type":"code","source":"df['id'] = df.image_path.map(lambda x: x.split('/')[-1].split('.')[1]) # extract id\ndisplay(df.head(2))\n\n\ntest_df['id'] = test_df.image_path.map(lambda x: x.split('/')[-1].split('.')[0]) # extract id\ndisplay(test_df.head(2))","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.063422,"end_time":"2023-07-14T18:31:52.803348","exception":false,"start_time":"2023-07-14T18:31:52.739926","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:01:54.656439Z","iopub.execute_input":"2024-02-28T13:01:54.656814Z","iopub.status.idle":"2024-02-28T13:01:54.680474Z","shell.execute_reply.started":"2024-02-28T13:01:54.656785Z","shell.execute_reply":"2024-02-28T13:01:54.679303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.6. Data Split","metadata":{"papermill":{"duration":0.020831,"end_time":"2023-07-14T18:31:52.845748","exception":false,"start_time":"2023-07-14T18:31:52.824917","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"We create the train and validation split by using the `train_test_split` library from `skleaarn.model_selection`\n\nIn this case, we kept the validation data size 30% of the total data","metadata":{"papermill":{"duration":0.020863,"end_time":"2023-07-14T18:31:52.888103","exception":false,"start_time":"2023-07-14T18:31:52.867240","status":"completed"},"tags":[]}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain_df, valid_df = train_test_split(df, test_size=0.3, random_state=42)\nprint(f\"Train: {len(train_df)}\")\nprint(f\"Valid: {len(valid_df)}\")","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.049273,"end_time":"2023-07-14T18:31:52.958494","exception":false,"start_time":"2023-07-14T18:31:52.909221","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:02:22.621160Z","iopub.execute_input":"2024-02-28T13:02:22.621944Z","iopub.status.idle":"2024-02-28T13:02:22.644184Z","shell.execute_reply.started":"2024-02-28T13:02:22.621915Z","shell.execute_reply":"2024-02-28T13:02:22.643018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.7. Data Validation\n\nBefore diving deeper into the analysis, it's crucial to ensure that our metadata – including path and label – aligns accurately with the actual data. Any discrepancies may lead to inaccurate results, undermining the integrity of our findings.\n","metadata":{"papermill":{"duration":0.020955,"end_time":"2023-07-14T18:31:53.001055","exception":false,"start_time":"2023-07-14T18:31:52.980100","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"## Utility","metadata":{"papermill":{"duration":0.020971,"end_time":"2023-07-14T18:31:53.043456","exception":false,"start_time":"2023-07-14T18:31:53.022485","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# opencv (cv2) is used for loading image\ndef load_image(path):\n    img = cv2.imread(path, -1) # `-1` means load image as it is, thus no gray to rgb conversion\n    img = img[...,::-1] # bgr to rgb\n    return img","metadata":{"_kg_hide-input":true,"papermill":{"duration":0.029443,"end_time":"2023-07-14T18:31:53.094416","exception":false,"start_time":"2023-07-14T18:31:53.064973","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:02:50.854644Z","iopub.execute_input":"2024-02-28T13:02:50.855332Z","iopub.status.idle":"2024-02-28T13:02:50.859784Z","shell.execute_reply.started":"2024-02-28T13:02:50.855295Z","shell.execute_reply":"2024-02-28T13:02:50.858910Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## One Sample","metadata":{"papermill":{"duration":0.020959,"end_time":"2023-07-14T18:31:53.137803","exception":false,"start_time":"2023-07-14T18:31:53.116844","status":"completed"},"tags":[]}},{"cell_type":"code","source":"row = train_df.iloc[20]\nimg = load_image(row.image_path)\nprint(f\"## Image Shape: {img.shape}\")\nprint(f\"## Label: {row.class_label}\")\nprint(f'## Name: {row.class_name}')\n\nplt.figure(figsize=(5,5))\nplt.imshow(img);","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.445246,"end_time":"2023-07-14T18:31:53.604166","exception":false,"start_time":"2023-07-14T18:31:53.158920","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:03:07.622661Z","iopub.execute_input":"2024-02-28T13:03:07.623009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Multiple Samples","metadata":{"papermill":{"duration":0.027154,"end_time":"2023-07-14T18:31:53.659380","exception":false,"start_time":"2023-07-14T18:31:53.632226","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Define the size of the grid\ngrid_size = 4\n\n# Create a figure and axes for the grid of images\nfig, axes = plt.subplots(grid_size, grid_size, figsize=(grid_size*2, grid_size*2))\n\n# Iterate over the images and labels\nfor i in range(grid_size**2):\n    # Generate random index\n    img_idx = np.random.randint(0, len(train_df))\n    row = train_df.iloc[img_idx]\n    \n    # Load the image using your preferred method (not implemented here)\n    img = load_image(row.image_path)\n\n    # Determine the row and column indices in the grid\n    x = i // grid_size\n    y = i % grid_size\n\n    # Display the image in the corresponding grid cell\n    axes[x, y].imshow(img)\n    axes[x, y].set_title(str(row.class_name))\n    axes[x, y].axis('off')\n\n# Adjust the spacing and layout of the subplots\nplt.tight_layout()\n\n# Show the grid of images\nplt.show()","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":2.672525,"end_time":"2023-07-14T18:31:56.360542","exception":false,"start_time":"2023-07-14T18:31:53.688017","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:03:44.985285Z","iopub.execute_input":"2024-02-28T13:03:44.985662Z","iopub.status.idle":"2024-02-28T13:03:46.566913Z","shell.execute_reply.started":"2024-02-28T13:03:44.985632Z","shell.execute_reply":"2024-02-28T13:03:46.565969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.8. Data Loader\nProcessing large datasets that consume a significant amount of memory can be challenging. Thus loading full data on memory is not feasible. Thus our previously used code format like this is not useful,\n\n```python\nX, y = np.load('some_training_set_with_labels.npy')\n\n# Build model\nmodel = LinearRegression()\n\n# Train model on dataset, where all the data is loaded on memory at once\nmodel.fit(x=X, y=y)\n```\nMoreover, traditional methods may not have enough memory to handle the data effectively. In such cases, batching, which involves dividing the dataset into smaller subsets or batches, can be employed to process the data efficiently. By generating and batching datasets using multiple cores in real-time, it becomes possible to seamlessly integrate them with deep learning models.","metadata":{"papermill":{"duration":0.038913,"end_time":"2023-07-14T18:31:56.438626","exception":false,"start_time":"2023-07-14T18:31:56.399713","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"This dataloader can also handle the cases when label is not available (the test dataset where the images are available but there is no label). This makes it suitable for both training and testing.\n\nThe two cases (`label is not None` and `label is None`) are handled within the Dataloader code using `if` condition.\n\nTo be more specific, handling the `label is not None` case and keeping the `label is None` as the default case is adequate here","metadata":{"papermill":{"duration":0.039104,"end_time":"2023-07-14T18:31:56.513942","exception":false,"start_time":"2023-07-14T18:31:56.474838","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import albumentations as A\n\nclass DataLoader(tf.keras.utils.Sequence):\n    \"\"\"\n    Custom data loader for Keras model training.\n    Ref: https://stanford.edu/~shervine/blog/keras-how-to-generate-data-on-the-fly\n\n    Args:\n        paths (list): List of file paths for the images.\n        labels (list): List of corresponding labels for the images. \n                       Set labels= None if you are infering on test dataset (where you dont have labels)\n        batch_size (int): Number of samples per batch.\n        num_classes (int): Number of classes in the dataset.\n        dim (tuple): Dimensions of the input images.\n        shuffle (bool): Whether to shuffle the data after each epoch.\n\n    Methods:\n        __len__(): Returns the number of batches per epoch.\n        __getitem__(index): Generates one batch of data.\n        on_epoch_end(): Updates indexes after each epoch.\n        __data_generation(batch_indexes): Generates data for a batch.\n    \"\"\"\n\n    def __init__(self, paths, labels=None, batch_size=32, num_classes=1,\n                 dim=(128, 128), shuffle=True, augment=False, augment_fn=None):\n        \"\"\"Initialization method for the DataLoader class.\"\"\"\n        self.paths = paths\n        self.labels = labels\n        self.batch_size = batch_size\n        self.num_classes = num_classes\n        self.dim = dim\n        self.shuffle = shuffle\n        \n        # For augmentation\n        self.augment = augment\n        self.augment_fn = augment_fn\n        if self.augment and self.augment_fn is None:\n            self.augment_fn = A.Compose([A.HorizontalFlip(p=0.5),\n                                         A.RandomBrightnessContrast(p=0.5),\n                                         A.Rotate(limit=30, p=0.5)])\n                                        \n        self.on_epoch_end()\n\n    def __len__(self):\n        \"\"\"Returns the number of batches per epoch.\"\"\"\n        return int(np.ceil(len(self.paths) / self.batch_size))\n\n    def __getitem__(self, index):\n        \"\"\"Generates one batch of data.\"\"\"\n        # Generate indexes of the batch\n        batch_indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]\n\n        # Generate data\n        batch = self.__data_generation(batch_indexes)\n\n        return batch\n\n    def on_epoch_end(self):\n        \"\"\"Updates indexes after each epoch.\"\"\"\n        self.indexes = np.arange(len(self.paths))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n\n    def __data_generation(self, batch_indexes):\n        \"\"\"Generates data containing batch_size samples.\"\"\"\n        # Initialization\n        X = np.empty((self.batch_size, *self.dim, 3), dtype=np.float32)\n        if self.labels is not None:\n            y = np.empty((self.batch_size), dtype=np.float32)\n\n        # Generate data\n        for i, idx in enumerate(batch_indexes):\n            # Load image\n            img = load_image(self.paths[idx])\n            \n            # Resize image as not all images are with same shape\n            img = cv2.resize(img, dsize=self.dim)             \n            \n            # Apply augmentation\n            if self.augment:\n                img = self.augment_fn(image=img)[\"image\"]\n                \n            # Store sample\n            X[i,] = img\n\n            # Store class\n            if self.labels is not None:\n                y[i] = self.labels[idx]\n\n        # Flatten the image pixels for Dense layer\n#         X = X.reshape(self.batch_size, -1)  # shape: (32, 28, 28) => (32, 28*28) => (32, 784)\n\n        # Do scaling, range: [0, 255] => [0, 1]\n        X = X / 255.0\n\n        # Apply one-hot encoding to labels [0, 1, 2] => [[1, 0, 0], [0, 1, 0], [0, 0, 1]]\n        if self.labels is not None:\n#             y = tf.keras.utils.to_categorical(y, num_classes=self.num_classes)\n            y = y.reshape(-1, 1)\n            return X, y\n        \n        # if there is labels = None, then only return X\n        return X","metadata":{"_kg_hide-input":true,"papermill":{"duration":0.867912,"end_time":"2023-07-14T18:31:57.422755","exception":false,"start_time":"2023-07-14T18:31:56.554843","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:04:09.429100Z","iopub.execute_input":"2024-02-28T13:04:09.430286Z","iopub.status.idle":"2024-02-28T13:04:09.445875Z","shell.execute_reply.started":"2024-02-28T13:04:09.430253Z","shell.execute_reply":"2024-02-28T13:04:09.444892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Loader check","metadata":{"papermill":{"duration":0.037573,"end_time":"2023-07-14T18:31:57.498063","exception":false,"start_time":"2023-07-14T18:31:57.460490","status":"completed"},"tags":[]}},{"cell_type":"code","source":"paths = train_df.image_path.tolist()\nlabels = train_df.class_label.tolist()\n\ntrain_loader = DataLoader(paths, labels, batch_size=16, augment=True)\n\nimgs, tars = train_loader.__getitem__(0)\nprint(\"Images:\\n\", imgs.shape)\n\nprint(\"\\nLabels:\\n\", tars.shape)","metadata":{"_kg_hide-input":true,"papermill":{"duration":0.124526,"end_time":"2023-07-14T18:31:57.658311","exception":false,"start_time":"2023-07-14T18:31:57.533785","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:04:13.670764Z","iopub.execute_input":"2024-02-28T13:04:13.671122Z","iopub.status.idle":"2024-02-28T13:04:13.745158Z","shell.execute_reply.started":"2024-02-28T13:04:13.671094Z","shell.execute_reply":"2024-02-28T13:04:13.744264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualize Loader","metadata":{"papermill":{"duration":0.035349,"end_time":"2023-07-14T18:31:57.730948","exception":false,"start_time":"2023-07-14T18:31:57.695599","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Define the size of the grid\ngrid_size = 4\n\n# Create a figure and axes for the grid of images\nfig, axes = plt.subplots(grid_size, grid_size, figsize=(grid_size*2, grid_size*2))\n\n# Iterate over the images and labels\nfor i in range(16):\n    \n    # Load the image\n    img = imgs[i] # images are feed as flatten to models\n    \n    # Get Label\n    tar = int(tars[i]>0.5) # label is one hot encoded\n    name = label2name[tar]\n\n    # Determine the row and column indices in the grid\n    x = i // grid_size\n    y = i % grid_size\n\n    # Display the image in the corresponding grid cell\n    axes[x, y].imshow(img)\n    axes[x, y].set_title(name)\n    axes[x, y].axis('off')\n\n# Adjust the spacing and layout of the subplots\nplt.tight_layout()\n\n# Show the grid of images\nplt.show()","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":1.797504,"end_time":"2023-07-14T18:31:59.564009","exception":false,"start_time":"2023-07-14T18:31:57.766505","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:04:31.780929Z","iopub.execute_input":"2024-02-28T13:04:31.781310Z","iopub.status.idle":"2024-02-28T13:04:33.122719Z","shell.execute_reply.started":"2024-02-28T13:04:31.781275Z","shell.execute_reply":"2024-02-28T13:04:33.121769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.9. Normalization Layers\n\nNormalization in deep learning is a technique used to standardize the inputs of a model. It's used to adjust the scales of features to a standard and consistent range, which usually helps speed up the learning process and often improves the final performance of the model.\n\nWhen we apply normalization to a model, we're trying to mitigate the problems that occur due to the scales of input features differing widely. This could cause the model to give undue importance to some features while neglecting others.\n\n## Why Use Normalization Inside the Model?\n\nThere are two primary reasons to use normalization layers inside a model, even when we can normalize the images from the outside:\n\n1. **Covariate Shift**: Covariate shift refers to the change in input distribution during training. Normalizing the inputs can make the model invariant to the scale of the features, and hence more robust to the variations in input distribution. Normalizing the features within the model helps handle covariate shift as the model trains over time.\n\n2. **Internal Covariate Shift**: This is a more specific problem in deep learning where the distribution of layer inputs changes during training, as the parameters of the previous layers change. This can slow down training and make it harder for the network to converge. Normalization layers inside the model address this issue.\n\n> \"Covariate Shift\" refers to the situation where the distribution of input data to a model changes between the training phase and the testing (or deployment) phase. It's a problem because machine learning models assume that the training data and the test data are drawn from the same distribution.\n\n## Different Types of Normalization Layers\n\nDifferent types of normalization layers include:\n\n1. **Batch Normalization**: This method normalizes the output of a previous activation layer by subtracting the batch mean and dividing by the batch standard deviation. This can help speed up learning in deep neural networks by reducing internal covariate shift.\n\n$$y_i = γ \\left( \\frac{x_i - μ_B}{\\sqrt{σ_B² + ε}} \\right) + β$$\n\nHere:\n\n- $x_i$ is an input,\n- $y_i$ is the corresponding output,\n- $μ_B$ is the mean of the mini-batch B aka `moving_mean`,\n- $σ_B²$ is the variance of the mini-batch B aka `moving_variance`,\n- $γ$ and $β$ are learnable parameters (scale and shift),\n- $ε$ is a constant for numerical stability (typically a very small number).\n\n\n2. **Layer Normalization**: Unlike batch normalization which normalizes along the batch dimension, layer normalization normalizes along the feature dimension. It computes the mean and variance used for normalization from all of the summed inputs to the neurons in a layer on a single training case.\n\n3. **Instance Normalization**: This is also called contrast normalization and is used primarily in style transfer (generative adversarial networks). It normalizes the features in each individual example in the same way batch normalization normalizes features in each batch.\n\n4. **Group Normalization**: Group normalization divides the channels into smaller groups and normalizes the features within each group. It's designed to perform well in a wide range of contexts, including both small and large batch sizes.\n\n<img src=\"https://theaisummer.com/static/ac89fbcf1c115f07ae68af695c28c4a0/b97f6/normalization.png\">\n\n> Normalization layers should be used when the scale of input features differs widely, or when training deep neural networks to help reduce internal covariate shift and speed up learning. ","metadata":{"papermill":{"duration":0.049298,"end_time":"2023-07-14T18:31:59.667806","exception":false,"start_time":"2023-07-14T18:31:59.618508","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Instantiate a batch normalization layer\nbn = tf.keras.layers.BatchNormalization()\n\n# Inputs\ninp = tf.random.uniform(shape=(1, 32, 32, 3))\n\n# The forward pass\nout = bn(inp)\n\n# shapes\ninp.shape, out.shape","metadata":{"papermill":{"duration":4.936469,"end_time":"2023-07-14T18:32:04.653526","exception":false,"start_time":"2023-07-14T18:31:59.717057","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:04:59.624417Z","iopub.execute_input":"2024-02-28T13:04:59.625432Z","iopub.status.idle":"2024-02-28T13:05:00.753802Z","shell.execute_reply.started":"2024-02-28T13:04:59.625384Z","shell.execute_reply":"2024-02-28T13:05:00.752757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bn.weights","metadata":{"papermill":{"duration":0.061309,"end_time":"2023-07-14T18:32:04.764774","exception":false,"start_time":"2023-07-14T18:32:04.703465","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:05:02.870966Z","iopub.execute_input":"2024-02-28T13:05:02.871577Z","iopub.status.idle":"2024-02-28T13:05:02.877407Z","shell.execute_reply.started":"2024-02-28T13:05:02.871548Z","shell.execute_reply":"2024-02-28T13:05:02.876430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bn.get_weights()","metadata":{"papermill":{"duration":0.059452,"end_time":"2023-07-14T18:32:04.870103","exception":false,"start_time":"2023-07-14T18:32:04.810651","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:05:05.744556Z","iopub.execute_input":"2024-02-28T13:05:05.745487Z","iopub.status.idle":"2024-02-28T13:05:05.756061Z","shell.execute_reply.started":"2024-02-28T13:05:05.745441Z","shell.execute_reply":"2024-02-28T13:05:05.754980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.10. AlexNet\n\n**Performance compared to ML models**\n\n<img src=\"https://www.researchgate.net/publication/346091812/figure/fig2/AS:979480482938881@1610537753860/Algorithms-that-won-the-ImageNet-Large-Scale-Visual-Recognition-Challenge-ILSVRC-in.png\" width=\"700\">\n\n\n**Architecture**\n\n<img src=\"https://miro.medium.com/v2/resize:fit:1100/format:webp/0*pJ3o_2zTTNnixhKH.png\" width=\"800\">\n\n**Major Contributions of AlexNet:**\n\n1. **Introduction of Deep Learning:** AlexNet introduced a deeper and wider model compared to previous networks, setting the stage for future deep learning models.\n2. **Convolutional Layers:** AlexNet popularized the use of convolutional layers to process input images in chunks, which improved performance and efficiency.\n3. **ReLU Activation Function:** AlexNet was the first to use ReLU (Rectified Linear Unit) as its activation function, accelerating the training speed significantly compared to traditional activation functions.\n4. **GPU Usage:** AlexNet made efficient use of GPUs for its computations, making it feasible to train deep networks.\n\n---\n\n**Pros and Cons of AlexNet:**\n\n| Pros | Cons |\n|---|---|\n| Pioneered deep learning, starting the trend of deeper networks | Requires substantial computational resources, primarily a GPU, for training |\n| ReLU activation function increased training speed | Has many hyperparameters that need to be tuned |\n| Utilized GPU for computations, thus speeding up the training process | Larger than necessary for many simpler tasks |\n| Showed impressive results on ImageNet, thus proving the potential of deep networks | Overfitting risk due to its complexity |\n","metadata":{"papermill":{"duration":0.045907,"end_time":"2023-07-14T18:32:04.961518","exception":false,"start_time":"2023-07-14T18:32:04.915611","status":"completed"},"tags":[],"jupyter":{"source_hidden":true}}},{"cell_type":"code","source":"from tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Flatten, Dense, Conv2D, MaxPooling2D, Activation, Dropout\n\ndef CNN_Model(input_shape=(128, 128, 3), num_classes=1, lr=1e-3):\n    # Input layer\n    inp = Input(shape=input_shape)\n\n    # 1st Convolutional Layer\n    x = Conv2D(filters=96, kernel_size=(11,11), strides=(4,4), padding='same')(inp)\n    x = Activation('relu')(x)\n    x = MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid')(x)\n\n    # 2nd Convolutional Layer\n    x = Conv2D(filters=256, kernel_size=(5,5), strides=(1,1), padding='same')(x)\n    x = Activation('relu')(x)\n    x = MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid')(x)\n\n    # 3rd Convolutional Layer\n    x = Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='same')(x)\n    x = Activation('relu')(x)\n\n    # 4th Convolutional Layer\n    x = Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='same')(x)\n    x = Activation('relu')(x)\n\n    # 5th Convolutional Layer\n    x = Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), padding='same')(x)\n    x = Activation('relu')(x)\n    x = MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid')(x)\n\n    # Fully Connected layer\n    x = Flatten()(x)\n    x = Dense(128)(x)  # 4096 for AlexNet\n    x = Activation('relu')(x)\n#     x = Dropout(0.4)(x)  # uncomment for AlexNet\n\n#     # 2nd Fully Connected Layer\n#     x = Dense(4096)(x)\n#     x = Activation('relu')(x)\n#     x = Dropout(0.4)(x)\n\n    # Output Layer\n    out = Dense(num_classes, activation='sigmoid')(x)\n\n    # Instantiate and return the model\n    model = Model(inputs=inp, outputs=out)\n\n    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lr),\n                  loss='binary_crossentropy',\n                  metrics=[tf.keras.metrics.BinaryAccuracy(name='accuracy')])\n    return model\n","metadata":{"_kg_hide-input":true,"papermill":{"duration":0.065095,"end_time":"2023-07-14T18:32:05.072507","exception":false,"start_time":"2023-07-14T18:32:05.007412","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:09:48.002086Z","iopub.execute_input":"2024-02-28T13:09:48.002920Z","iopub.status.idle":"2024-02-28T13:09:48.014978Z","shell.execute_reply.started":"2024-02-28T13:09:48.002887Z","shell.execute_reply":"2024-02-28T13:09:48.014035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use function to create a model\nmodel = CNN_Model(input_shape=(128, 128, 3), num_classes=1)\nmodel.summary()\n\ntf.keras.utils.plot_model(model, show_shapes=True)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":0.521387,"end_time":"2023-07-14T18:32:05.640277","exception":false,"start_time":"2023-07-14T18:32:05.118890","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:09:55.546957Z","iopub.execute_input":"2024-02-28T13:09:55.547323Z","iopub.status.idle":"2024-02-28T13:09:56.237189Z","shell.execute_reply.started":"2024-02-28T13:09:55.547294Z","shell.execute_reply":"2024-02-28T13:09:56.236285Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Check Feed Forward","metadata":{"papermill":{"duration":0.052333,"end_time":"2023-07-14T18:32:05.748800","exception":false,"start_time":"2023-07-14T18:32:05.696467","status":"completed"},"tags":[]}},{"cell_type":"code","source":"out = model(imgs)\nout.shape","metadata":{"papermill":{"duration":2.542655,"end_time":"2023-07-14T18:32:08.345268","exception":false,"start_time":"2023-07-14T18:32:05.802613","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:10:11.098422Z","iopub.execute_input":"2024-02-28T13:10:11.098794Z","iopub.status.idle":"2024-02-28T13:10:12.272467Z","shell.execute_reply.started":"2024-02-28T13:10:11.098769Z","shell.execute_reply":"2024-02-28T13:10:12.271531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{"papermill":{"duration":0.054132,"end_time":"2023-07-14T18:32:08.453214","exception":false,"start_time":"2023-07-14T18:32:08.399082","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Step 1: Get train-test image paths and labels\ntrain_paths = train_df['image_path'].tolist()\ntrain_labels = train_df['class_label'].tolist()\n\nvalid_paths = valid_df['image_path'].tolist()\nvalid_labels = valid_df['class_label'].tolist()\n\n# Step 2: Data loader\ntrain_loader = DataLoader(train_paths, train_labels, batch_size=128, augment=False)\n\nvalid_loader = DataLoader(valid_paths, valid_labels, batch_size=128, shuffle=False)\n\n\n# Step 3: Build the model\nmodel = AlexNet(input_shape=(128, 128, 3), num_classes=1, lr=0.5e-3)\n\n# Step 4: Model training\nckpt_cb = tf.keras.callbacks.ModelCheckpoint(filepath = '/kaggle/working/best_ckpt.keras',\n                                             monitor = 'val_accuracy',\n                                             verbose = 0,\n                                             save_best_only = True,\n                                             save_weights_only = False,\n                                             mode = 'max') # to save best scoring model\n\nprint('## Training')\nhistory = model.fit(train_loader,\n                    validation_data=valid_loader,\n                    epochs=15,\n                    verbose=1,\n                    callbacks=[ckpt_cb])\n\n# Step 5: Predict on test data\n\n## Load best model\nmodel = tf.keras.models.load_model('/kaggle/working/best_ckpt.h5') # you can save model using model.save()\n\nprint(\"\\n## Inference\")\nvalid_loader = DataLoader(valid_paths, valid_labels, batch_size=100, shuffle=False)\npredictions = model.predict(valid_loader)[:len(valid_df)]\n\n# Step 6: Measure performance\nacc = accuracy_score(valid_labels, (predictions > 0.5).astype(int))\nprint(f\"\\n## Accuracy: {acc}\")","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":945.618846,"end_time":"2023-07-14T18:47:54.125219","exception":false,"start_time":"2023-07-14T18:32:08.506373","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-02-28T13:12:26.649224Z","iopub.execute_input":"2024-02-28T13:12:26.649619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Plot History","metadata":{"papermill":{"duration":0.200106,"end_time":"2023-07-14T18:47:54.489737","exception":false,"start_time":"2023-07-14T18:47:54.289631","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ndef plot_history(history):\n    # summarize history for accuracy\n    plt.figure(figsize=(10, 8))\n    plt.subplot(2, 1, 1)\n    plt.plot(history.history['accuracy'], '-o')\n    plt.plot(history.history['val_accuracy'], '-o')\n    plt.title('Accuracy vs Epoch')\n    plt.ylabel('Accuracy')\n    plt.xlabel('Epoch')\n    plt.legend(['train', 'validation'], loc='upper left')\n    plt.grid(True)\n\n    # Get the epoch at which the validation accuracy is max\n    best_val_acc = max(history.history['val_accuracy'])\n    best_val_acc_epoch = history.history['val_accuracy'].index(best_val_acc)\n    plt.annotate(f'best: {best_val_acc:.2f} @ {best_val_acc_epoch+1}',\n                 xy=(best_val_acc_epoch, best_val_acc),\n                 xytext=(-20, 20),\n                 textcoords='offset points',\n                 arrowprops=dict(facecolor='orange', shrink=0.05),\n                 fontsize=10,\n                 color='black')\n\n    # summarize history for loss\n    plt.subplot(2, 1, 2)\n    plt.plot(history.history['loss'], '-o')\n    plt.plot(history.history['val_loss'], '-o')\n    plt.title('Loss vs Epoch')\n    plt.ylabel('Loss')\n    plt.xlabel('Epoch')\n    plt.legend(['train', 'validation'], loc='upper left')\n    plt.grid(True)\n\n    # Get the epoch at which the validation loss is min\n    best_val_loss_epoch = best_val_acc_epoch\n    best_val_loss = history.history['val_loss'][best_val_loss_epoch]\n    plt.annotate(f'best: {best_val_loss:.2f} @ {best_val_loss_epoch+1}',\n                 xy=(best_val_loss_epoch, best_val_loss),\n                 xytext=(-20, 20),\n                 textcoords='offset points',\n                 arrowprops=dict(facecolor='orange', shrink=0.05),\n                 fontsize=10,\n                 color='black')\n\n    plt.tight_layout()\n    plt.show()\n    \n# Plot history of training\nplot_history(history)","metadata":{"_kg_hide-input":true,"papermill":{"duration":0.912669,"end_time":"2023-07-14T18:47:55.553460","exception":false,"start_time":"2023-07-14T18:47:54.640791","status":"completed"},"tags":[],"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Result Analysis","metadata":{"papermill":{"duration":0.151514,"end_time":"2023-07-14T18:47:55.862781","exception":false,"start_time":"2023-07-14T18:47:55.711267","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\n\nnum_images = 36\nsqrt_num_images = int(np.sqrt(num_images))\n# indices = np.random.choice(len(valid_paths), num_images, replace=False)\nfig, axes = plt.subplots(nrows=sqrt_num_images, ncols=sqrt_num_images, figsize=(10, 10))\n\nfor i, idx in enumerate(range(num_images)):\n    row = i // sqrt_num_images\n    col = i % sqrt_num_images\n\n    image_path = valid_paths[idx]\n    image = load_image(image_path)  # Load and preprocess single image\n    \n    # Get prediction and ground truth\n    pred = (predictions[idx]>0.5).astype(int)[0]\n    pred = label2name[pred] # 0 -> cat\n    true = valid_labels[idx]\n    true = label2name[true] # 0 -> cat\n\n    axes[row, col].imshow(image)\n    axes[row, col].axis('off')\n\n    if pred == true:\n        axes[row, col].set_title(f'Pred: {pred}\\nTruth: {true}')\n    else:\n        axes[row, col].set_title(f'Pred: {pred}\\nTruth: {true}', color='red')\n\nplt.tight_layout()\nplt.show()\n","metadata":{"_kg_hide-input":true,"papermill":{"duration":3.320342,"end_time":"2023-07-14T18:47:59.337012","exception":false,"start_time":"2023-07-14T18:47:56.016670","status":"completed"},"tags":[],"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.11. VGG\n\n\n**Major Contributions of VGG Network:**\n\n1. **Uniform Architecture:** VGG demonstrated that using small (3x3) convolution filters in a deep network can achieve excellent performance.\n2. **Depth Importance:** VGG showed the importance of depth in a network. It included 16-19 layers and outperformed shallower architectures.\n3. **Transfer Learning:** VGG models, due to their excellent generalization capabilities, have been widely used for transfer learning.\n\n\n**Achitecture**\n\n<img src=\"https://iq.opengenus.org/content/images/2019/01/vgg_layers.png\" width=\"700\">\n\n---\n\n**Pros and Cons of VGG Network:**\n\n| Pros | Cons |\n|---|---|\n| Demonstrated the power of depth in neural networks | Very resource-intensive due to its depth |\n| Simple and uniform architecture is easy to understand | Longer training times due to the large number of layers |\n| Excellent for transfer learning due to good feature generalization | Requires more memory due to the number of parameters |\n| Good performance on object recognition tasks | Overfitting risk due to its complexity and depth |\n\n\n**AlexNet Vs VGG**\n\n| Features | AlexNet | VGG |\n|---|---|---|\n| **Depth** | Has 8 layers (5 convolutional and 3 fully connected layers) | Deeper networks with 16-19 layers |\n| **Architecture** | Varies the size of convolution filters (11x11, 5x5, 3x3) | Uniform architecture using small (3x3) convolution filters |\n| **Usage of ReLU** | First to use ReLU activation function | Also uses ReLU, but not the first |\n| **Size** | Smaller, with around 60 million parameters | Larger, with around 138 million parameters in VGG16 and 144 million in VGG19 |\n| **Training Speed** | Faster due to less depth | Slower because of deeper architecture |\n| **Transfer Learning** | Less commonly used for transfer learning | Excellent for transfer learning due to better generalization of features |","metadata":{"papermill":{"duration":0.172717,"end_time":"2023-07-14T18:47:59.689724","exception":false,"start_time":"2023-07-14T18:47:59.517007","status":"completed"},"tags":[]}},{"cell_type":"code","source":"from tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Flatten, Dense, Conv2D, MaxPooling2D, Activation, Dropout\n\ndef VGG16_S(input_shape=(224, 224, 3), num_classes=1, lr=0.5e-3):\n    # Input layer\n    inp = Input(shape=input_shape)\n\n    # Block 1\n    x = Conv2D(64, (3, 3), padding='same')(inp)\n    x = Activation('relu')(x)\n    x = Conv2D(64, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = MaxPooling2D((2, 2))(x)\n\n    # Block 2\n    x = Conv2D(128, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = Conv2D(128, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = MaxPooling2D((2, 2))(x)\n\n    # Block 3\n    x = Conv2D(256, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = Conv2D(256, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = Conv2D(256, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = MaxPooling2D((2, 2))(x)\n\n    # Block 4\n    x = Conv2D(512, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = Conv2D(512, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = Conv2D(512, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = MaxPooling2D((2, 2))(x)\n\n    # Block 5\n    x = Conv2D(512, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = Conv2D(512, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = Conv2D(512, (3, 3), padding='same')(x)\n    x = Activation('relu')(x)\n    x = MaxPooling2D((2, 2))(x)\n\n    # FC layers\n    x = Flatten()(x)\n    x = Dense(4096)(x)\n    x = Activation('relu')(x)\n    x = Dropout(0.5)(x)\n    x = Dense(4096)(x)\n    x = Activation('relu')(x)\n    x = Dropout(0.5)(x)\n\n    # Output Layer\n    out = Dense(num_classes, activation='sigmoid')(x)\n\n    # Instantiate and return the model\n    model = Model(inputs=inp, outputs=out)\n\n    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lr),\n                  loss='binary_crossentropy',\n                  metrics=[tf.keras.metrics.BinaryAccuracy(name='accuracy')])\n    return model\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.execute_input":"2023-07-14T18:48:00.031953Z","iopub.status.busy":"2023-07-14T18:48:00.031587Z","iopub.status.idle":"2023-07-14T18:48:00.049657Z","shell.execute_reply":"2023-07-14T18:48:00.048644Z"},"papermill":{"duration":0.191992,"end_time":"2023-07-14T18:48:00.051737","exception":false,"start_time":"2023-07-14T18:47:59.859745","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use function to create a model\nmodel = VGG16_S(input_shape=(128, 128, 3), num_classes=1)\nmodel.summary()\n\ntf.keras.utils.plot_model(model, show_shapes=True)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T18:48:00.396993Z","iopub.status.busy":"2023-07-14T18:48:00.396643Z","iopub.status.idle":"2023-07-14T18:48:01.342321Z","shell.execute_reply":"2023-07-14T18:48:01.341328Z"},"papermill":{"duration":1.121524,"end_time":"2023-07-14T18:48:01.344629","exception":false,"start_time":"2023-07-14T18:48:00.223105","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training???\n\nTraining a VGG16 model or any other deep learning model from scratch on a small dataset can present several issues:\n\n1. **Overfitting:** Deep learning models have millions of parameters. If the dataset is small, the model may end up memorizing the training data instead of learning generalized features, leading to poor performance on unseen data.\n\n2. **Computational Expense:** VGG16 is a large model with approximately 138 million parameters. Training such a large model from scratch requires significant computational resources, which might not be feasible for everyone.\n\n4. **Training Time:** Even with modern hardware, training a model like VGG16 from scratch can take a lot of time, especially if multiple epochs are needed.\n\n### So, **What is the Solution??**\n","metadata":{"papermill":{"duration":0.18792,"end_time":"2023-07-14T18:48:01.723655","exception":false,"start_time":"2023-07-14T18:48:01.535735","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# 5.12. Transfer Learning\n\nTransfer learning is a machine learning technique where knowledge gained from solving one problem is applied to a different but related problem. It's like using past experience to help with a new task.\n\nThink of it this way: you know how to ride a bicycle and you have been doing it for years. Now, if you want to learn how to ride a motorcycle, you don't start from scratch. You apply some of the skills you learned from bicycle riding to this new task. This is similar to how transfer learning works.\n\n**How it Works:**\n\nTransfer learning involves using a pre-trained neural network trained on a large dataset called ImageNet with 1,000 different classes. There are two main strategies:\n\n* **Feature Extraction**: The pre-trained network's learned features are used as a starting point. Only the final layers (classifier) are replaced and trained from scratch for the new task. This allows the model to extract relevant features while utilizing the general knowledge from the pre-training on ImageNet.\n\n* **Fine-Tuning**: In addition to replacing the final layers, a few top layers of the pre-trained network are unfrozen. These layers, along with the new classifier layers, are jointly trained using the new dataset. Fine-tuning the higher-order feature representations helps the network adapt to the specific task.\n\n* **Full Fine-Tuning**: All layers of the pre-trained network, including the base layers used for feature extraction, are unfrozen and trained. This approach provides comprehensive adaptation but requires a larger dataset to avoid overfitting.\n\nTransfer learning leverages the pre-trained network's understanding of diverse visual patterns to accelerate learning on new tasks, achieving better performance even with limited data.","metadata":{"papermill":{"duration":0.187461,"end_time":"2023-07-14T18:48:02.096591","exception":false,"start_time":"2023-07-14T18:48:01.909130","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# 5.13. VGG with Transfer Learning","metadata":{"papermill":{"duration":0.18675,"end_time":"2023-07-14T18:48:02.471949","exception":false,"start_time":"2023-07-14T18:48:02.285199","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def VGG16(input_shape=(224, 224, 3),\n          num_classes=1,\n          lr=0.5e-3,\n          num_unfreeze=2):\n    # Define input layer\n    inp = Input(shape=input_shape)\n\n    # Load pre-trained VGG16 model with imagenet weights\n    base_model = tf.keras.applications.VGG16(weights='imagenet',\n                                             include_top=False, # drop classifer head\n                                             input_shape=input_shape)\n\n    # Freeze or unfreeze the model\n    if num_unfreeze is None:\n        base_model.trainable = True  # Full fine-tuning\n    else:\n        base_model.trainable = False  # Freeze all layers by default\n        if num_unfreeze > 0:\n            # Unfreeze the specified number of layers from the end\n            for layer in base_model.layers[-num_unfreeze:]:\n                layer.trainable = True\n\n    # Add custom classification layers on top\n    x = base_model(inp)\n    x = Flatten()(x)\n    x = Dense(128, activation='relu')(x)\n    out = Dense(num_classes, activation='sigmoid')(x)\n\n    # Create the final model\n    model = Model(inputs=inp, outputs=out)\n    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lr),\n                  loss='binary_crossentropy',\n                  metrics=[tf.keras.metrics.BinaryAccuracy(name='accuracy')])\n    return model","metadata":{"execution":{"iopub.execute_input":"2023-07-14T18:48:02.859426Z","iopub.status.busy":"2023-07-14T18:48:02.858895Z","iopub.status.idle":"2023-07-14T18:48:02.869211Z","shell.execute_reply":"2023-07-14T18:48:02.868313Z"},"papermill":{"duration":0.200788,"end_time":"2023-07-14T18:48:02.871493","exception":false,"start_time":"2023-07-14T18:48:02.670705","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use function to create a model\nmodel = VGG16(input_shape=(128, 128, 3), num_classes=1, num_unfreeze=5)\nmodel.summary()\n\ntf.keras.utils.plot_model(model, show_shapes=True)","metadata":{"execution":{"iopub.execute_input":"2023-07-14T18:48:03.247761Z","iopub.status.busy":"2023-07-14T18:48:03.247171Z","iopub.status.idle":"2023-07-14T18:48:05.978771Z","shell.execute_reply":"2023-07-14T18:48:05.977814Z"},"papermill":{"duration":2.924252,"end_time":"2023-07-14T18:48:05.981089","exception":false,"start_time":"2023-07-14T18:48:03.056837","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{"papermill":{"duration":0.188188,"end_time":"2023-07-14T18:48:06.364676","exception":false,"start_time":"2023-07-14T18:48:06.176488","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Step 1: Get train-test image paths and labels\ntrain_paths = train_df['image_path'].tolist()\ntrain_labels = train_df['class_label'].tolist()\n\nvalid_paths = valid_df['image_path'].tolist()\nvalid_labels = valid_df['class_label'].tolist()\n\n# Step 2: Data loader\ntrain_loader = DataLoader(train_paths, train_labels, batch_size=128, augment=False)\n\nvalid_loader = DataLoader(valid_paths, valid_labels, batch_size=128, shuffle=False)\n\n\n# Step 3: Build the model\nmodel = VGG16(input_shape=(128, 128, 3), num_classes=1, lr=0.5e-3, num_unfreeze=5)\n\n# Step 4: Model training\nckpt_cb = tf.keras.callbacks.ModelCheckpoint(filepath = '/kaggle/working/best_vgg.h5',\n                                             monitor = 'val_accuracy',\n                                             verbose = 0,\n                                             save_best_only = True,\n                                             save_weights_only = False,\n                                             mode = 'max') # to save best scoring model\n\nprint('## Training')\nhistory = model.fit(train_loader,\n                    validation_data=valid_loader,\n                    epochs=15,\n                    verbose=1,\n                    callbacks=[ckpt_cb])\n\n# Step 5: Predict on test data\n\n## Load best model\nmodel = tf.keras.models.load_model('/kaggle/working/best_vgg.h5') # you can save model using model.save()\n\nprint(\"\\n## Inference\")\nvalid_loader = DataLoader(valid_paths, valid_labels, batch_size=100, shuffle=False)\npredictions = model.predict(valid_loader)[:len(valid_df)]\n\n# Step 6: Measure performance\nacc = accuracy_score(valid_labels, (predictions > 0.5).astype(int))\nprint(f\"\\n## Accuracy: {acc}\")","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T18:48:06.741840Z","iopub.status.busy":"2023-07-14T18:48:06.741269Z","iopub.status.idle":"2023-07-14T19:03:58.008892Z","shell.execute_reply":"2023-07-14T19:03:58.007497Z"},"papermill":{"duration":951.459285,"end_time":"2023-07-14T19:03:58.010929","exception":false,"start_time":"2023-07-14T18:48:06.551644","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Plot History","metadata":{"papermill":{"duration":0.28749,"end_time":"2023-07-14T19:03:58.595279","exception":false,"start_time":"2023-07-14T19:03:58.307789","status":"completed"},"tags":[]}},{"cell_type":"code","source":"plot_history(history)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T19:03:59.218939Z","iopub.status.busy":"2023-07-14T19:03:59.218572Z","iopub.status.idle":"2023-07-14T19:03:59.955567Z","shell.execute_reply":"2023-07-14T19:03:59.954628Z"},"papermill":{"duration":1.028958,"end_time":"2023-07-14T19:03:59.958477","exception":false,"start_time":"2023-07-14T19:03:58.929519","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Result","metadata":{"papermill":{"duration":0.2907,"end_time":"2023-07-14T19:04:00.548489","exception":false,"start_time":"2023-07-14T19:04:00.257789","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\n\nnum_images = 36\nsqrt_num_images = int(np.sqrt(num_images))\n# indices = np.random.choice(len(valid_paths), num_images, replace=False)\nfig, axes = plt.subplots(nrows=sqrt_num_images, ncols=sqrt_num_images, figsize=(10, 10))\n\nfor i, idx in enumerate(range(num_images)):\n    row = i // sqrt_num_images\n    col = i % sqrt_num_images\n\n    image_path = valid_paths[idx]\n    image = load_image(image_path)  # Load and preprocess single image\n    \n    # Get prediction and ground truth\n    pred = (predictions[idx]>0.5).astype(int)[0]\n    pred = label2name[pred] # 0 -> cat\n    true = valid_labels[idx]\n    true = label2name[true] # 0 -> cat\n\n    axes[row, col].imshow(image)\n    axes[row, col].axis('off')\n\n    if pred == true:\n        axes[row, col].set_title(f'Pred: {pred}\\nTruth: {true}')\n    else:\n        axes[row, col].set_title(f'Pred: {pred}\\nTruth: {true}', color='red')\n\nplt.tight_layout()\nplt.show()\n","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T19:04:01.131486Z","iopub.status.busy":"2023-07-14T19:04:01.130934Z","iopub.status.idle":"2023-07-14T19:04:04.801155Z","shell.execute_reply":"2023-07-14T19:04:04.800277Z"},"papermill":{"duration":3.974379,"end_time":"2023-07-14T19:04:04.814719","exception":false,"start_time":"2023-07-14T19:04:00.840340","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.14. ResNet with Transfer Learning\n\n**Major Contributions of ResNet (Residual Network):**\n\n1. **Residual Blocks:** ResNet introduced the concept of residual blocks with shortcut connections, allowing for networks to be deeper without suffering from the vanishing gradient problem.\n2. **Extreme Depth:** ResNet has shown the importance of extreme depth in networks, with architectures spanning 34, 50, 101, and 152 layers.\n3. **Achieving State-of-the-art Results:** ResNet has achieved top performance in many benchmarks and competitions, like ILSVRC 2015, thanks to its deep architecture.\n\n**Achitecture**\n\n<img src=\"https://cdn-images-1.medium.com/max/1600/1*YFlBISIjc3zbyzq0g7CPnA.png\" width=\"300\">\n\n---\n\n**Pros and Cons of ResNet Network:**\n\n| Pros | Cons |\n|---|---|\n| Overcomes the vanishing gradient problem with residual blocks | Can be more complex to understand due to residual connections |\n| Scales well with increasing depth, unlike other networks | Might be overkill for simpler, smaller datasets |\n| Delivers state-of-the-art performance in various tasks | Requires considerable resources for very deep networks |\n| Effective for transfer learning due to high generalization capabilities | Training deep networks can take longer time |\n\n**VGG Vs ResNet**\n\n| Features | VGG | ResNet |\n|---|---|---|\n| **Depth** | Deeper networks with 16-19 layers | Even deeper networks, up to 152 layers in some versions |\n| **Architecture** | Uniform architecture using small (3x3) convolution filters | Uses 3x3 convolutions within its residual blocks, with shortcut connections |\n| **Usage of ReLU** | Uses ReLU, but not the first | Continues the usage of ReLU as an activation function |\n| **Size** | Larger, with around 138 million parameters in VGG16 and 144 million in VGG19 | Varies, but typically fewer parameters than VGG due to parameter sharing in residual blocks |\n| **Training Speed** | Slower because of deeper architecture | Depending on the depth, can be slower or faster due to residual connections allowing for better backpropagation |\n| **Transfer Learning** | Excellent for transfer learning due to better generalization of features | Also very effective for transfer learning, thanks to the learned residual functions |\n| **Vanishing Gradient Problem** | Can suffer from this problem due to depth | Mitigates this issue through the use of residual blocks and shortcut connections |\"\n\n","metadata":{"papermill":{"duration":0.315299,"end_time":"2023-07-14T19:04:05.447543","exception":false,"start_time":"2023-07-14T19:04:05.132244","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"### ResBlock","metadata":{"papermill":{"duration":0.308671,"end_time":"2023-07-14T19:04:06.067662","exception":false,"start_time":"2023-07-14T19:04:05.758991","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\n\ndef ResBlock(x, filters, kernel_size):\n    shortcut = x\n    x = layers.Conv2D(filters, kernel_size, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Activation('relu')(x)\n\n    x = layers.Conv2D(filters, kernel_size, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n\n    x = layers.Add()([shortcut, x])\n    x = layers.Activation('relu')(x)\n\n    return x\n\ninput_layer = layers.Input(shape=(32, 32, 64))\noutput_layer = ResBlock(input_layer, 64, 3)\n\nmodel = models.Model(inputs=input_layer, outputs=output_layer)\n\ntf.keras.utils.plot_model(model, show_shapes=True)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T19:04:06.693841Z","iopub.status.busy":"2023-07-14T19:04:06.693302Z","iopub.status.idle":"2023-07-14T19:04:06.835202Z","shell.execute_reply":"2023-07-14T19:04:06.834212Z"},"papermill":{"duration":0.458446,"end_time":"2023-07-14T19:04:06.837313","exception":false,"start_time":"2023-07-14T19:04:06.378867","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Pre-trained Model","metadata":{"papermill":{"duration":0.313175,"end_time":"2023-07-14T19:04:07.475340","exception":false,"start_time":"2023-07-14T19:04:07.162165","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.layers import Input, Flatten, Dense\nfrom tensorflow.keras.models import Model\n\ndef ResNet50(input_shape=(224, 224, 3),\n             num_classes=1,\n             lr=0.5e-3,\n             num_unfreeze=2):\n    # Define input layer\n    inp = Input(shape=input_shape)\n\n    # Load pre-trained ResNet50 model with imagenet weights\n    base_model = tf.keras.applications.ResNet50(weights='imagenet',\n                                                include_top=False,\n                                                input_shape=input_shape)\n    \n\n    # Freeze or unfreeze the model\n    if num_unfreeze is None:\n        base_model.trainable = True  # Full fine-tuning\n    else:\n        base_model.trainable = False  # Freeze all layers by default\n        if num_unfreeze > 0:\n            # Unfreeze the specified number of layers from the end\n            for layer in base_model.layers[-num_unfreeze:]:\n                layer.trainable = True\n\n    # Add custom classification layers on top\n    x = base_model(inp)\n    x = Flatten()(x)\n    x = Dense(128, activation='relu')(x)\n    out = Dense(num_classes, activation='sigmoid')(x)\n\n    # Create the final model\n    model = Model(inputs=inp, outputs=out)\n    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lr),\n                  loss='binary_crossentropy',\n                  metrics=[tf.keras.metrics.BinaryAccuracy(name='accuracy')])\n    return model\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.execute_input":"2023-07-14T19:04:08.149059Z","iopub.status.busy":"2023-07-14T19:04:08.148458Z","iopub.status.idle":"2023-07-14T19:04:08.161277Z","shell.execute_reply":"2023-07-14T19:04:08.160341Z"},"papermill":{"duration":0.375987,"end_time":"2023-07-14T19:04:08.163308","exception":false,"start_time":"2023-07-14T19:04:07.787321","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use function to create a model\nmodel = ResNet50(input_shape=(128, 128, 3), num_classes=1, num_unfreeze=30)\nmodel.summary()\n\ntf.keras.utils.plot_model(model, show_shapes=True)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T19:04:08.789417Z","iopub.status.busy":"2023-07-14T19:04:08.788824Z","iopub.status.idle":"2023-07-14T19:04:14.926101Z","shell.execute_reply":"2023-07-14T19:04:14.925182Z"},"papermill":{"duration":6.453283,"end_time":"2023-07-14T19:04:14.928102","exception":false,"start_time":"2023-07-14T19:04:08.474819","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{"papermill":{"duration":0.316541,"end_time":"2023-07-14T19:04:15.579116","exception":false,"start_time":"2023-07-14T19:04:15.262575","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Step 1: Get train-test image paths and labels\ntrain_paths = train_df['image_path'].tolist()\ntrain_labels = train_df['class_label'].tolist()\n\nvalid_paths = valid_df['image_path'].tolist()\nvalid_labels = valid_df['class_label'].tolist()\n\n# Step 2: Data loader\ntrain_loader = DataLoader(train_paths, train_labels, batch_size=128, augment=False)\n\nvalid_loader = DataLoader(valid_paths, valid_labels, batch_size=128, shuffle=False)\n\n\n# Step 3: Build the model\nmodel = ResNet50(input_shape=(128, 128, 3), num_classes=1, lr=0.5e-3, num_unfreeze=3)\n\n# Step 4: Model training\nckpt_cb = tf.keras.callbacks.ModelCheckpoint(filepath = '/kaggle/working/best_res.h5',\n                                             monitor = 'val_accuracy',\n                                             verbose = 0,\n                                             save_best_only = True,\n                                             save_weights_only = False,\n                                             mode = 'max') # to save best scoring model\n\nprint('## Training')\nhistory = model.fit(train_loader,\n                    validation_data=valid_loader,\n                    epochs=15,\n                    verbose=1,\n                    callbacks=[ckpt_cb])\n\n# Step 5: Predict on test data\n\n## Load best model\nmodel = tf.keras.models.load_model('/kaggle/working/best_res.h5') # you can save model using model.save()\n\nprint(\"\\n## Inference\")\nvalid_loader = DataLoader(valid_paths, valid_labels, batch_size=100, shuffle=False)\npredictions = model.predict(valid_loader)[:len(valid_df)]\n\n# Step 6: Measure performance\nacc = accuracy_score(valid_labels, (predictions > 0.5).astype(int))\nprint(f\"\\n## Accuracy: {acc}\")","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T19:04:16.217762Z","iopub.status.busy":"2023-07-14T19:04:16.217393Z","iopub.status.idle":"2023-07-14T19:20:44.220262Z","shell.execute_reply":"2023-07-14T19:20:44.219298Z"},"papermill":{"duration":988.323034,"end_time":"2023-07-14T19:20:44.222415","exception":false,"start_time":"2023-07-14T19:04:15.899381","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Plot History","metadata":{"papermill":{"duration":0.417685,"end_time":"2023-07-14T19:20:45.123887","exception":false,"start_time":"2023-07-14T19:20:44.706202","status":"completed"},"tags":[]}},{"cell_type":"code","source":"plot_history(history)","metadata":{"_kg_hide-input":true,"execution":{"iopub.execute_input":"2023-07-14T19:20:45.968974Z","iopub.status.busy":"2023-07-14T19:20:45.968411Z","iopub.status.idle":"2023-07-14T19:20:46.720980Z","shell.execute_reply":"2023-07-14T19:20:46.719988Z"},"papermill":{"duration":1.175194,"end_time":"2023-07-14T19:20:46.723608","exception":false,"start_time":"2023-07-14T19:20:45.548414","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Result","metadata":{"papermill":{"duration":0.424416,"end_time":"2023-07-14T19:20:47.573717","exception":false,"start_time":"2023-07-14T19:20:47.149301","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\n\nnum_images = 36\nsqrt_num_images = int(np.sqrt(num_images))\n# indices = np.random.choice(len(valid_paths), num_images, replace=False)\nfig, axes = plt.subplots(nrows=sqrt_num_images, ncols=sqrt_num_images, figsize=(10, 10))\n\nfor i, idx in enumerate(range(num_images)):\n    row = i // sqrt_num_images\n    col = i % sqrt_num_images\n\n    image_path = valid_paths[idx]\n    image = load_image(image_path)  # Load and preprocess single image\n    \n    # Get prediction and ground truth\n    pred = (predictions[idx]>0.5).astype(int)[0]\n    pred = label2name[pred] # 0 -> cat\n    true = valid_labels[idx]\n    true = label2name[true] # 0 -> cat\n\n    axes[row, col].imshow(image)\n    axes[row, col].axis('off')\n\n    if pred == true:\n        axes[row, col].set_title(f'Pred: {pred}\\nTruth: {true}')\n    else:\n        axes[row, col].set_title(f'Pred: {pred}\\nTruth: {true}', color='red')\n\nplt.tight_layout()\nplt.show()\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.execute_input":"2023-07-14T19:20:48.476051Z","iopub.status.busy":"2023-07-14T19:20:48.475526Z","iopub.status.idle":"2023-07-14T19:20:52.040710Z","shell.execute_reply":"2023-07-14T19:20:52.039830Z"},"papermill":{"duration":4.008332,"end_time":"2023-07-14T19:20:52.054328","exception":false,"start_time":"2023-07-14T19:20:48.045996","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.15. InceptionNet\n\n**Major Contributions of InceptionNet:**\n\n1. **Efficient Inception Modules:** InceptionNet introduced the inception module, which enabled it to learn multi-level features in the same layer. This improved performance while also reducing computational cost.\n2. **Depth and Width Importance:** InceptionNet showed that increasing the depth and width of the network, within the limits of the available computational budget, improves performance.\n3. **Auxiliary Classifiers:** InceptionNet used auxiliary classifiers to combat the vanishing gradients problem, which allowed it to successfully train deeper networks.\n\n**Architecture**\n\n<img src=\"https://miro.medium.com/max/1400/1*DKjGRDd_lJeUfVlY50ojOA.png\" width=\"700\">\n\n---\n\n**Pros and Cons of InceptionNet:**\n\n| Pros | Cons |\n|---|---|\n| Introduced the efficient Inception modules | More complex architecture compared to other networks |\n| Managed to increase depth and width of network without significant computational cost | Requires careful tuning and is more prone to overfitting |\n| Auxiliary classifiers help in training deeper networks | While it performs well on larger datasets, it may not generalize well to smaller ones |\n| Achieved state-of-the-art performance on image classification tasks | The complexity makes the network harder to modify and adapt |\n","metadata":{"papermill":{"duration":0.441012,"end_time":"2023-07-14T19:20:52.940488","exception":false,"start_time":"2023-07-14T19:20:52.499476","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"### InceptionBlock","metadata":{"papermill":{"duration":0.441469,"end_time":"2023-07-14T19:20:53.819175","exception":false,"start_time":"2023-07-14T19:20:53.377706","status":"completed"},"tags":[]}},{"cell_type":"code","source":"from tensorflow.keras import layers\n\ndef InceptionBlock(x, filters):\n    path1 = layers.Conv2D(filters=filters, kernel_size=(1, 1), padding='same', activation='relu')(x)\n\n    path2 = layers.Conv2D(filters=filters, kernel_size=(1, 1), padding='same', activation='relu')(x)\n    path2 = layers.Conv2D(filters=filters, kernel_size=(3, 3), padding='same', activation='relu')(path2)\n\n    path3 = layers.Conv2D(filters=filters, kernel_size=(1, 1), padding='same', activation='relu')(x)\n    path3 = layers.Conv2D(filters=filters, kernel_size=(5, 5), padding='same', activation='relu')(path3)\n    \n    path4 = layers.MaxPool2D((3, 3), strides=(1, 1), padding='same')(x)\n\n    output = layers.concatenate([path1, path2, path3, path4], axis=-1)\n    return output\n\ninput_layer = layers.Input(shape=(32, 32, 3))\noutput_layer = InceptionBlock(input_layer, 64)\n\nmodel = models.Model(inputs=input_layer, outputs=output_layer)\ntf.keras.utils.plot_model(model, show_shapes=True)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T19:20:54.797165Z","iopub.status.busy":"2023-07-14T19:20:54.796645Z","iopub.status.idle":"2023-07-14T19:20:54.968931Z","shell.execute_reply":"2023-07-14T19:20:54.967990Z"},"papermill":{"duration":0.710058,"end_time":"2023-07-14T19:20:54.970943","exception":false,"start_time":"2023-07-14T19:20:54.260885","status":"completed"},"tags":[],"collapsed":true,"jupyter":{"outputs_hidden":true}},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.16. DenseNet\n\n**Major Contributions of DenseNet:**\n\n1. **Dense Connectivity:** DenseNet introduced a novel architecture where each layer is connected to every other layer in a feed-forward fashion. This allows for efficient feature reuse, thus improving performance and reducing the number of parameters.\n2. **Feature Reuse:** DenseNet significantly reduces the number of parameters and computational cost, making it more efficient than traditional architectures.\n3. **Alleviation of Vanishing-Gradient Problem:** The dense connectivity facilitates the propagation of gradients throughout the network, which helps alleviate the vanishing-gradient problem and aids in deep network training.\n\n**Architecture**\n\n<img src=\"https://pytorch.org/assets/images/densenet1.png\" width=\"500\">\n\n---\n\n**Pros and Cons of DenseNet:**\n\n| Pros | Cons |\n|---|---|\n| Dense connectivity leads to efficient feature reuse | The architecture can lead to a high computational cost in terms of memory usage |\n| Requires fewer parameters, making it computationally efficient | Dense connections might not always improve performance and could make the model complex |\n| Alleviates the vanishing-gradient problem | Although the model is more parameter-efficient, it still requires a lot of computational resources for large scale datasets |\n| Achieved state-of-the-art performance on image classification tasks | The model's complexity can make it harder to implement and modify |","metadata":{"papermill":{"duration":0.435614,"end_time":"2023-07-14T19:20:55.852466","exception":false,"start_time":"2023-07-14T19:20:55.416852","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"### DenseBlock","metadata":{"papermill":{"duration":0.436147,"end_time":"2023-07-14T19:20:56.727255","exception":false,"start_time":"2023-07-14T19:20:56.291108","status":"completed"},"tags":[]}},{"cell_type":"code","source":"from tensorflow.keras import layers, models\n\ndef conv_layer(x, filters, kernel=1, strides=1):\n    x = layers.BatchNormalization()(x)\n    x = layers.ReLU()(x)\n    x = Conv2D(filters, kernel, strides=strides, padding=\"same\")(x)\n    return x\n\ndef DenseBlock(x, repetition,filters):\n    for _ in range(repetition):\n        y = conv_layer(x, 4 * filters)\n        y = conv_layer(y, filters, 3)\n        x = layers.concatenate([y, x])\n    return x\n\ninput_layer = layers.Input(shape=(32, 32, 3))\noutput_layer = DenseBlock(input_layer, 3, 32)\n\nmodel = models.Model(inputs=input_layer, outputs=output_layer)\n\ntf.keras.utils.plot_model(model, show_shapes=True)\n","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-07-14T19:20:57.770091Z","iopub.status.busy":"2023-07-14T19:20:57.769280Z","iopub.status.idle":"2023-07-14T19:20:58.288817Z","shell.execute_reply":"2023-07-14T19:20:58.287673Z"},"papermill":{"duration":1.125252,"end_time":"2023-07-14T19:20:58.291818","exception":false,"start_time":"2023-07-14T19:20:57.166566","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]}]}