{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"030a9a2a07bd43998d3d6021f460f3a8":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"0eda6590b3d747d7a3e707d9f13cb9a1":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":"hidden","width":null}},"10d2d910d34c4378bb981877c9740ab7":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_de4689dca1a441059ae0e4e40bc548c7","placeholder":"​","style":"IPY_MODEL_33ad3fc83e714f2aa4bc59aa1fdf08c9","tabbable":null,"tooltip":null,"value":"100%"}},"15e294c770c04bc8b517958485c16f47":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"220821cf20b0491f8a76f1b27d71e876":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"33ad3fc83e714f2aa4bc59aa1fdf08c9":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"51f092b056674e2fbc8254737ab155aa":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"5691aa42e0d6432c8edc457f8a7882c9":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"5cd5a111553541f9af37848136402d38":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"","description":"","description_allow_html":false,"layout":"IPY_MODEL_70ffdc066d3f4114b68e63fe230943ce","max":75,"min":0,"orientation":"horizontal","style":"IPY_MODEL_ef636c11b5e14e6e99f4811c599f7ddc","tabbable":null,"tooltip":null,"value":75}},"5d2d330f6c0a471cb9f71c6bfe7c33aa":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"6dc5ac665f2142ad99f6697b7644bc7a":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"70ffdc066d3f4114b68e63fe230943ce":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"80ef821c241346a4b73c87771d5894ec":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":"hidden","width":null}},"8302dc8194b74f959ea507a593c2102b":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_d36dfde2c3784843b0a8a6a1b4d59352","IPY_MODEL_5cd5a111553541f9af37848136402d38","IPY_MODEL_b90382a4ce4d4a29811683c0d3219f9d"],"layout":"IPY_MODEL_0eda6590b3d747d7a3e707d9f13cb9a1","tabbable":null,"tooltip":null}},"88a9e68a5dcb4c579685ac18a8deeb85":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"95b3783b1972419b8abbd9769d827887":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_6dc5ac665f2142ad99f6697b7644bc7a","placeholder":"​","style":"IPY_MODEL_5691aa42e0d6432c8edc457f8a7882c9","tabbable":null,"tooltip":null,"value":"100%"}},"a06de83489c5470f8b0d4916f67f3e17":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"b90382a4ce4d4a29811683c0d3219f9d":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_e8f45dbfe31c45688058b8c62cfcd399","placeholder":"​","style":"IPY_MODEL_a06de83489c5470f8b0d4916f67f3e17","tabbable":null,"tooltip":null,"value":" 75/75 [00:13&lt;00:00,  5.55it/s]"}},"bbf06f61005f4a748a20a5079dcc5658":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"c3a7c19abccc44cfb01a3f01f83e1f51":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"c51d95b54d1846ec9240a5b591c2aa6a":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"c5314718124e4ad283f8699104ccb54b":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_ee3463c963ae41c695428abd5f574277","placeholder":"​","style":"IPY_MODEL_030a9a2a07bd43998d3d6021f460f3a8","tabbable":null,"tooltip":null,"value":" 313/313 [00:56&lt;00:00,  5.35it/s]"}},"d20ffb647fe64b2f980c5701097bdf73":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_95b3783b1972419b8abbd9769d827887","IPY_MODEL_f74243431269445c9318b99bc554e765","IPY_MODEL_f7d0d367b22f426cbb06a23923f0a1f2"],"layout":"IPY_MODEL_80ef821c241346a4b73c87771d5894ec","tabbable":null,"tooltip":null}},"d36dfde2c3784843b0a8a6a1b4d59352":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_5d2d330f6c0a471cb9f71c6bfe7c33aa","placeholder":"​","style":"IPY_MODEL_220821cf20b0491f8a76f1b27d71e876","tabbable":null,"tooltip":null,"value":"100%"}},"d6ed59fbb4104243955f1c4d00c1be79":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"success","description":"","description_allow_html":false,"layout":"IPY_MODEL_dcb00992c873426bad28fdc26b115e4e","max":313,"min":0,"orientation":"horizontal","style":"IPY_MODEL_c51d95b54d1846ec9240a5b591c2aa6a","tabbable":null,"tooltip":null,"value":313}},"db3ff8b4959a4a559d423920ee04409a":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_10d2d910d34c4378bb981877c9740ab7","IPY_MODEL_d6ed59fbb4104243955f1c4d00c1be79","IPY_MODEL_c5314718124e4ad283f8699104ccb54b"],"layout":"IPY_MODEL_88a9e68a5dcb4c579685ac18a8deeb85","tabbable":null,"tooltip":null}},"dcb00992c873426bad28fdc26b115e4e":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"de4689dca1a441059ae0e4e40bc548c7":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"e8f45dbfe31c45688058b8c62cfcd399":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"ee3463c963ae41c695428abd5f574277":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"ef636c11b5e14e6e99f4811c599f7ddc":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"f74243431269445c9318b99bc554e765":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"","description":"","description_allow_html":false,"layout":"IPY_MODEL_c3a7c19abccc44cfb01a3f01f83e1f51","max":313,"min":0,"orientation":"horizontal","style":"IPY_MODEL_51f092b056674e2fbc8254737ab155aa","tabbable":null,"tooltip":null,"value":313}},"f7d0d367b22f426cbb06a23923f0a1f2":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_15e294c770c04bc8b517958485c16f47","placeholder":"​","style":"IPY_MODEL_bbf06f61005f4a748a20a5079dcc5658","tabbable":null,"tooltip":null,"value":" 313/313 [03:28&lt;00:00,  1.72it/s]"}}},"version_major":2,"version_minor":0}}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"f8845901","cell_type":"markdown","source":"# State Farm Distracted Driver Detection - Kaggle Submission Notebook\n\nThis notebook is optimized for Kaggle execution and produces a valid submission file at `/kaggle/working/submission.csv`.\n\nPipeline:\n1. Resolve dataset paths and validate files.\n2. Create leakage-safe train/validation split using `StratifiedGroupKFold` grouped by `subject`.\n3. Train an EfficientNet transfer-learning model on GPU.\n4. Apply early stopping and best checkpointing.\n5. Run test-time inference and generate Kaggle submission.\n","metadata":{}},{"id":"e1de2f13","cell_type":"code","source":"import gc\nimport os\nimport random\nfrom pathlib import Path\n\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nfrom tqdm.auto import tqdm\n\nimport torch\nfrom torch import nn\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import models, transforms\n\nfrom sklearn.metrics import accuracy_score, f1_score, log_loss\nfrom sklearn.model_selection import StratifiedGroupKFold\n\ndef seed_everything(seed: int = 42) -> None:\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = False\n\nseed_everything(42)\n\nIS_KAGGLE = Path('/kaggle').exists()\nuse_cuda = torch.cuda.is_available() and IS_KAGGLE\nif use_cuda:\n    major, minor = torch.cuda.get_device_capability(0)\n    if major < 7:\n        print(f\"Detected CUDA capability sm_{major}{minor} unsupported by current PyTorch build; falling back to CPU.\")\n        use_cuda = False\ndevice = torch.device('cuda' if use_cuda else 'cpu')\nprint(f\"Device: {device}\")\n","metadata":{"execution":{"iopub.status.busy":"2026-06-12T14:46:35.714726Z","iopub.execute_input":"2026-06-12T14:46:35.715390Z","iopub.status.idle":"2026-06-12T14:46:44.281800Z","shell.execute_reply.started":"2026-06-12T14:46:35.715357Z","shell.execute_reply":"2026-06-12T14:46:44.280993Z"},"trusted":true},"outputs":[],"execution_count":null},{"id":"b4452af0","cell_type":"code","source":"CANDIDATE_ROOTS = [\n    Path('/kaggle/input/competitions/state-farm-distracted-driver-detection'),\n    Path('/kaggle/input/state-farm-distracted-driver-detection'),\n    Path.cwd() / 'data' / 'raw',\n]\n\nDATA_ROOT = next((p for p in CANDIDATE_ROOTS if p.exists()), None)\nassert DATA_ROOT is not None, \"State Farm dataset directory not found.\"\n\nTRAIN_CSV = DATA_ROOT / 'driver_imgs_list.csv'\nSAMPLE_SUB_CSV = DATA_ROOT / 'sample_submission.csv'\nTRAIN_IMG_DIR = DATA_ROOT / 'imgs' / 'train'\nTEST_IMG_DIR = DATA_ROOT / 'imgs' / 'test'\n\nfor p in [TRAIN_CSV, SAMPLE_SUB_CSV, TRAIN_IMG_DIR, TEST_IMG_DIR]:\n    assert p.exists(), f\"Missing required path: {p}\"\n\nWORK_DIR = Path('/kaggle/working') if Path('/kaggle/working').exists() else Path.cwd()\nWORK_DIR.mkdir(parents=True, exist_ok=True)\n\nprint(f\"DATA_ROOT: {DATA_ROOT}\")\nprint(f\"WORK_DIR: {WORK_DIR}\")\n","metadata":{"execution":{"iopub.status.busy":"2026-06-12T14:46:44.283161Z","iopub.execute_input":"2026-06-12T14:46:44.283612Z","iopub.status.idle":"2026-06-12T14:46:44.295632Z","shell.execute_reply.started":"2026-06-12T14:46:44.283585Z","shell.execute_reply":"2026-06-12T14:46:44.295067Z"},"trusted":true},"outputs":[],"execution_count":null},{"id":"98265a4d","cell_type":"code","source":"meta = pd.read_csv(TRAIN_CSV)\nmeta['label'] = meta['classname'].str.replace('c', '', regex=False).astype(int)\nmeta['image_path'] = meta.apply(\n    lambda r: str(TRAIN_IMG_DIR / r['classname'] / r['img']),\n    axis=1,\n)\n\nassert meta['image_path'].map(lambda p: Path(p).exists()).all(), \"Some train images are missing.\"\n\nsgkf = StratifiedGroupKFold(n_splits=5, shuffle=True, random_state=42)\ntrain_idx, val_idx = next(sgkf.split(meta, y=meta['label'], groups=meta['subject']))\ntrain_df = meta.iloc[train_idx].reset_index(drop=True)\nval_df = meta.iloc[val_idx].reset_index(drop=True)\n\nprint(f\"Train rows: {len(train_df):,}\")\nprint(f\"Validation rows: {len(val_df):,}\")\nprint(f\"Train subjects: {train_df['subject'].nunique():,}\")\nprint(f\"Validation subjects: {val_df['subject'].nunique():,}\")\n\nIS_KAGGLE = Path('/kaggle').exists()\nif (not IS_KAGGLE) or (device.type != 'cuda'):\n    train_df = train_df.sample(min(8000, len(train_df)), random_state=42).reset_index(drop=True)\n    val_df = val_df.sample(min(2000, len(val_df)), random_state=42).reset_index(drop=True)\n    print('Sampling train/val rows for faster execution on non-GPU runtime.')\n","metadata":{"execution":{"iopub.status.busy":"2026-06-12T14:46:44.296377Z","iopub.execute_input":"2026-06-12T14:46:44.296672Z","iopub.status.idle":"2026-06-12T14:47:48.366989Z","shell.execute_reply.started":"2026-06-12T14:46:44.296650Z","shell.execute_reply":"2026-06-12T14:47:48.366241Z"},"trusted":true},"outputs":[],"execution_count":null},{"id":"0fb1658b","cell_type":"code","source":"class DriverDataset(Dataset):\n    def __init__(self, df: pd.DataFrame, transform=None, is_test: bool = False):\n        self.df = df.reset_index(drop=True)\n        self.transform = transform\n        self.is_test = is_test\n\n    def __len__(self) -> int:\n        return len(self.df)\n\n    def __getitem__(self, idx: int):\n        row = self.df.iloc[idx]\n        if self.is_test:\n            img_path = TEST_IMG_DIR / row['img']\n            image = Image.open(img_path).convert('RGB')\n            if self.transform is not None:\n                image = self.transform(image)\n            return image, row['img']\n\n        image = Image.open(row['image_path']).convert('RGB')\n        label = int(row['label'])\n        if self.transform is not None:\n            image = self.transform(image)\n        return image, label\n\nimagenet_mean = (0.485, 0.456, 0.406)\nimagenet_std = (0.229, 0.224, 0.225)\n\ntrain_tfms = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.RandomResizedCrop(224, scale=(0.8, 1.0)),\n    transforms.RandomHorizontalFlip(p=0.5),\n    transforms.ColorJitter(brightness=0.25, contrast=0.2, saturation=0.2, hue=0.05),\n    transforms.RandomRotation(degrees=10),\n    transforms.ToTensor(),\n    transforms.Normalize(imagenet_mean, imagenet_std),\n])\n\nvalid_tfms = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(imagenet_mean, imagenet_std),\n])\n\nBATCH_SIZE = 64 if device.type == 'cuda' else 16\nNUM_WORKERS = 4 if Path('/kaggle').exists() else 0\nEPOCHS = 5 if device.type == 'cuda' else 1\nPATIENCE = 2\n\ntrain_ds = DriverDataset(train_df, transform=train_tfms)\nval_ds = DriverDataset(val_df, transform=valid_tfms)\n\ntrain_loader = DataLoader(\n    train_ds,\n    batch_size=BATCH_SIZE,\n    shuffle=True,\n    num_workers=NUM_WORKERS,\n    pin_memory=(device.type == 'cuda'),\n)\nval_loader = DataLoader(\n    val_ds,\n    batch_size=BATCH_SIZE,\n    shuffle=False,\n    num_workers=NUM_WORKERS,\n    pin_memory=(device.type == 'cuda'),\n)\n\nprint(f\"Train batches: {len(train_loader)} | Val batches: {len(val_loader)}\")\n","metadata":{"execution":{"iopub.status.busy":"2026-06-12T14:47:48.368380Z","iopub.execute_input":"2026-06-12T14:47:48.368721Z","iopub.status.idle":"2026-06-12T14:47:48.380127Z","shell.execute_reply.started":"2026-06-12T14:47:48.368695Z","shell.execute_reply":"2026-06-12T14:47:48.379325Z"},"trusted":true},"outputs":[],"execution_count":null},{"id":"757a0c9f","cell_type":"code","source":"weights = models.EfficientNet_B0_Weights.DEFAULT\nmodel = models.efficientnet_b0(weights=weights)\nin_features = model.classifier[1].in_features\nmodel.classifier[1] = nn.Linear(in_features, 10)\nmodel = model.to(device)\n\ncriterion = nn.CrossEntropyLoss(label_smoothing=0.05)\noptimizer = torch.optim.AdamW(model.parameters(), lr=3e-4, weight_decay=1e-4)\nscheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=max(EPOCHS, 1))\n\ncheckpoint_path = WORK_DIR / 'best_efficientnet_b0_statefarm.pth'\n\ndef run_epoch(loader: DataLoader, is_train: bool):\n    model.train(is_train)\n    total_loss = 0.0\n    all_labels = []\n    all_preds = []\n    all_probs = []\n\n    pbar = tqdm(loader, total=len(loader), leave=False)\n    for batch in pbar:\n        if is_train:\n            images, labels = batch\n            images = images.to(device, non_blocking=True)\n            labels = labels.to(device, non_blocking=True)\n            optimizer.zero_grad(set_to_none=True)\n        else:\n            images, labels = batch\n            images = images.to(device, non_blocking=True)\n            labels = labels.to(device, non_blocking=True)\n\n        with torch.set_grad_enabled(is_train):\n            with torch.autocast(\n                device_type='cuda',\n                dtype=torch.float16,\n                enabled=(device.type == 'cuda'),\n            ):\n                logits = model(images)\n                loss = criterion(logits, labels)\n\n            if is_train:\n                loss.backward()\n                optimizer.step()\n\n        probs = torch.softmax(logits.detach(), dim=1)\n        preds = probs.argmax(dim=1)\n\n        total_loss += loss.item() * images.size(0)\n        all_labels.extend(labels.detach().cpu().numpy().tolist())\n        all_preds.extend(preds.detach().cpu().numpy().tolist())\n        all_probs.extend(probs.detach().cpu().numpy().tolist())\n\n    epoch_loss = total_loss / len(loader.dataset)\n    epoch_acc = accuracy_score(all_labels, all_preds)\n    epoch_f1 = f1_score(all_labels, all_preds, average='macro')\n    epoch_logloss = log_loss(all_labels, np.array(all_probs), labels=list(range(10)))\n    return epoch_loss, epoch_acc, epoch_f1, epoch_logloss\n\nhistory = []\nbest_val_logloss = float('inf')\npatience_left = PATIENCE\n\nfor epoch in range(1, EPOCHS + 1):\n    train_loss, train_acc, train_f1, train_logloss = run_epoch(train_loader, is_train=True)\n    val_loss, val_acc, val_f1, val_logloss = run_epoch(val_loader, is_train=False)\n    scheduler.step()\n\n    row = {\n        'epoch': epoch,\n        'train_loss': train_loss,\n        'train_acc': train_acc,\n        'train_f1_macro': train_f1,\n        'train_logloss': train_logloss,\n        'val_loss': val_loss,\n        'val_acc': val_acc,\n        'val_f1_macro': val_f1,\n        'val_logloss': val_logloss,\n    }\n    history.append(row)\n    print(row)\n\n    if val_logloss < best_val_logloss:\n        best_val_logloss = val_logloss\n        patience_left = PATIENCE\n        torch.save({'model_state_dict': model.state_dict()}, checkpoint_path)\n        print(f\"Saved best checkpoint: {checkpoint_path}\")\n    else:\n        patience_left -= 1\n        if patience_left <= 0:\n            print('Early stopping triggered.')\n            break\n\nhistory_df = pd.DataFrame(history)\ndisplay(history_df)\n","metadata":{"execution":{"iopub.status.busy":"2026-06-12T14:47:48.381185Z","iopub.execute_input":"2026-06-12T14:47:48.381597Z"},"trusted":true},"outputs":[],"execution_count":null},{"id":"3aa6bdd2","cell_type":"code","source":"ckpt = torch.load(checkpoint_path, map_location=device)\nmodel.load_state_dict(ckpt['model_state_dict'])\nmodel.eval()\n\nsample_submission = pd.read_csv(SAMPLE_SUB_CSV)\nif not IS_KAGGLE:\n    sample_submission = sample_submission.head(5000).copy()\n\ntest_ds = DriverDataset(sample_submission[['img']].copy(), transform=valid_tfms, is_test=True)\ntest_loader = DataLoader(\n    test_ds,\n    batch_size=BATCH_SIZE,\n    shuffle=False,\n    num_workers=NUM_WORKERS,\n    pin_memory=(device.type == 'cuda'),\n)\n\nall_img_names = []\nall_test_probs = []\n\nwith torch.no_grad():\n    for images, img_names in tqdm(test_loader, total=len(test_loader)):\n        images = images.to(device, non_blocking=True)\n        with torch.autocast(device_type='cuda', dtype=torch.float16, enabled=(device.type == 'cuda')):\n            logits = model(images)\n        probs = torch.softmax(logits, dim=1).cpu().numpy()\n        all_test_probs.append(probs)\n        all_img_names.extend(list(img_names))\n\ntest_probs = np.concatenate(all_test_probs, axis=0)\npred_df = pd.DataFrame(test_probs, columns=[f'c{i}' for i in range(10)])\nsubmission = pd.concat([pd.DataFrame({'img': all_img_names}), pred_df], axis=1)\n\nexpected_cols = ['img'] + [f'c{i}' for i in range(10)]\nsubmission = submission[expected_cols]\nsubmission = submission.sort_values('img').reset_index(drop=True)\n\nsample_sorted = sample_submission[['img']].sort_values('img').reset_index(drop=True)\nassert submission['img'].equals(sample_sorted['img']), 'Submission img order mismatch.'\n\nsubmission_path = WORK_DIR / 'submission.csv'\nsubmission.to_csv(submission_path, index=False)\n\nprint(f\"Saved submission to: {submission_path}\")\nprint(submission.head())\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}